diff --git a/Assets/PerfectWorld/Scene/Boostrap.unity b/Assets/PerfectWorld/Scene/Boostrap.unity index 3b2550c1df..011eb5b382 100644 --- a/Assets/PerfectWorld/Scene/Boostrap.unity +++ b/Assets/PerfectWorld/Scene/Boostrap.unity @@ -164,6 +164,114 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: _nextSceneName: LoginScene +--- !u!1 &428240946 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 428240950} + - component: {fileID: 428240949} + - component: {fileID: 428240948} + - component: {fileID: 428240947} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &428240947 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428240946} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &428240948 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428240946} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &428240949 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428240946} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &428240950 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428240946} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &506356661 PrefabInstance: m_ObjectHideFlags: 0 @@ -590,3 +698,4 @@ SceneRoots: - {fileID: 591506937} - {fileID: 105404091} - {fileID: 506356661} + - {fileID: 428240950} diff --git a/Assets/PerfectWorld/Scripts/MainFiles/CECGameRun.cs b/Assets/PerfectWorld/Scripts/MainFiles/CECGameRun.cs index 4f4a6eb598..a9c86dc519 100644 --- a/Assets/PerfectWorld/Scripts/MainFiles/CECGameRun.cs +++ b/Assets/PerfectWorld/Scripts/MainFiles/CECGameRun.cs @@ -1,4 +1,5 @@ using BrewMonster; +using BrewMonster.Scripts.World; using CSNetwork.GPDataType; using System; using UnityEngine; diff --git a/Assets/PerfectWorld/Scripts/MainFiles/EC_Game.cs b/Assets/PerfectWorld/Scripts/MainFiles/EC_Game.cs index dbec590394..d2839d51f7 100644 --- a/Assets/PerfectWorld/Scripts/MainFiles/EC_Game.cs +++ b/Assets/PerfectWorld/Scripts/MainFiles/EC_Game.cs @@ -1,5 +1,5 @@ using ModelRenderer.Scripts.GameData; -using PerfectWorld.Scripts.Task; +using BrewMonster.Scripts.Task; using UnityEngine; namespace BrewMonster.Network { diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs new file mode 100644 index 0000000000..e78f6de794 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs @@ -0,0 +1,545 @@ +using BrewMonster.Scripts.Player; +using CSNetwork.GPDataType; +using NUnit.Framework; +using PerfectWorld.Scripts.Player; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using ARectF = BrewMonster.Scripts.ARect; +using ARectI = BrewMonster.Scripts.ARect; +using BlockArray = System.Collections.Generic.List; +using WORD = System.UInt16; + +namespace BrewMonster.Scripts.World +{ + public class A3DTerrain2Block + { + // Trerrain2 vertex format when use lightmap + public struct A3DTRN2VERTEX1 + { + public float vPosX; // PositionX + public float vPosY; // PositionY + public float vPosZ; // PositionZ + public float vNormalX; // NormalX + public float vNormalY; // NormalY + public float vNormalZ; // NormalZ + public float u1, v1; // Texture coordinates project on xz + public float u2, v2; // Texture coordinates project on xy + public float u3, v3; // Texture coordinates project on yz + public float u4, v4; // Texture coordinate of layer mask + }; + + // Terrain2 vertex format when use vertex-light (not lightmap) + public struct A3DTRN2VERTEX2 + { + public float vPosX; // Position X + public float vPosY; // Position Y + public float vPosZ; // Position Z + public uint dwDiffuse; // Diffuse color + public uint dwSpecular; // Specular color + public float u1, v1; // Texture coordinates project on xz + public float u2, v2; // Texture coordinates project on xy + public float u3, v3; // Texture coordinates project on yz + public float u4, v4; // Texture coordinate of layer mask + }; + + public bool m_bDataLoaded = false; // Data loaded flag + public bool IsDataLoaded() { return m_bDataLoaded; } + public uint m_dwBlockFlags; // Block flags + public A3DAABB m_aabbBlock; // Block postion and size in whole world + public A3DTRN2VERTEX1[] m_aVertices1; // Vertex buffer, ps version + public A3DTRN2VERTEX2[] m_aVertices2; // Vertex buffer, non-ps version + public A3DTerrain2 m_pTerrain; // Terrain object + public int m_iBlockGrid; // Each block has m_iBlockGrid * m_iBlockGrid terrain grids + + // Get block's position and size in whole world + public A3DAABB GetBlockAABB() { return m_aabbBlock; } + // Get flag for this whole block unable for GetPosHeight + public bool IsNoPosHeight() + { + return (m_dwBlockFlags & Block_flags_masks.T2BKFLAG_NOPOSHEIGHT) != 0; + } + + // Get vertex + public A3DVECTOR3 GetVertexPos(int n) + { + if (m_aVertices1 != null && m_aVertices1.Length > n) + return new A3DVECTOR3(m_aVertices1[n].vPosX, m_aVertices1[n].vPosY, m_aVertices1[n].vPosZ); + else + { + //ASSERT(m_aVertices2); + return new A3DVECTOR3(m_aVertices2[n].vPosX, m_aVertices2[n].vPosY, m_aVertices2[n].vPosZ); + } + } + + /* Copy block vertices to destination buffer. This function works like BitBlt. + Copy vertex positions in a rectangle grid area to destination buffer, every + vertex is like a pixel in BitBlt; + + pDestBuf: destination vertex buffer + iWid, iHei: vertex rectangle area's size + iDestPitch: destination vertex buffer pitch in A3DVECTOR3 + sx, sy: grid rectangle area's left-top corner in block +*/ + public bool CopyVertexPos(ref A3DVECTOR3[] pDestBuf, int iWid, int iHei, + int iDestPitch, int sx, int sy) + { + WORD[] aIndexMaps = m_pTerrain.GetLODManager().GetIndexMaps(); + int pDestLine = 0; + int iSrcLine = sy * (m_iBlockGrid + 1) + sx; + + if (m_pTerrain.UseLightmapTech()) + { + //ASSERT(m_aVertices1); + + for (int i = 0; i < iHei; i++) + { + int destIndex = pDestLine; + int iSrc = iSrcLine; + pDestLine += iDestPitch; + iSrcLine += m_iBlockGrid + 1; + + for (int j = 0; j < iWid; j++, destIndex++, iSrc++) + { + // Note: here we map index + A3DTRN2VERTEX1 pSrc = m_aVertices1[aIndexMaps[iSrc]]; + + pDestBuf[destIndex].x = pSrc.vPosX; + pDestBuf[destIndex].y = pSrc.vPosY; + pDestBuf[destIndex].z = pSrc.vPosZ; + } + } + } + else + { + for (int i = 0; i < iHei; i++) + { + int pDest = pDestLine; + int iSrc = iSrcLine; + pDestLine += iDestPitch; + iSrcLine += m_iBlockGrid + 1; + + for (int j = 0; j < iWid; j++, pDest++, iSrc++) + { + var pSrc = m_aVertices2[aIndexMaps[iSrc]]; + + pDestBuf[pDest].x = pSrc.vPosX; + pDestBuf[pDest].y = pSrc.vPosY; + pDestBuf[pDest].z = pSrc.vPosZ; + } + } + } + + return true; + } + + /* Copy grid faces to destination buffer. This function works like BitBlt. + Copy face in a rectangle grid area to destination buffer, every face is + like a pixel in BitBlt; + + pDestVert: destination vertex buffer + pDestIdx: destination index buffer + iWid, iHei: grid rectangle area's size + iDstVertPitch: destination vertex buffer pitch in A3DVECTOR3 + iBaseVert: Index of left-top corner vertex in vertex buffer + sx, sy: grid rectangle area's left-top corner in block +*/ + public bool CopyFaces(ref A3DVECTOR3[] pDestVert, ref WORD[] pDestIdx, int iWid, int iHei, + int iDstVertPitch, int iBaseVert, int sx, int sy) + { + // Copy vertices at first. Notice the difference of iWid and iHei in this + // function and in CopyVertexPos() + CopyVertexPos(ref pDestVert, iWid + 1, iHei + 1, iDstVertPitch, sx, sy); + + // Build indices + int pIndices = 0; + + for (int i = 0; i < iHei; i++) + { + WORD v0 = (WORD)iBaseVert; + iBaseVert += iDstVertPitch; + + for (int j = 0; j < iWid; j++, pIndices += 6, v0++) + { + // v3 v0----v1 + // | \ \ | + // | \ \ | + // | \ \ | + // | \ \ | + // v5---v4 v2 + pDestIdx[pIndices] = v0; + pDestIdx[pIndices + 1] = (WORD)(v0 + 1); + pDestIdx[pIndices + 2] = (WORD)(v0 + iDstVertPitch + 1); + + pDestIdx[pIndices + 3] = v0; + pDestIdx[pIndices + 4] = (WORD)(v0 + iDstVertPitch + 1); + pDestIdx[pIndices + 5] = (WORD)(v0 + iDstVertPitch); + } + } + + // If this area contain block's right-top corner grid or left-bottom + // corner grid, then we have to adjust index so that they are in + // rendering order + if (sx == 0 && sy + iHei == m_iBlockGrid) + { + // Contain left-bottom corner grid + // v0----v1 + // | / | + // | / | + // | / | + // | / | + // v2----v3 + int offer = (iHei - 1) * iWid * 6; + WORD v0 = pDestIdx[offer]; + WORD v1 = pDestIdx[offer + 1]; + WORD v2 = pDestIdx[offer + 5]; + WORD v3 = pDestIdx[offer + 2]; + + pDestIdx[offer] = v0; + pDestIdx[offer + 1] = v1; + pDestIdx[offer + 2] = v2; + + pDestIdx[offer + 3] = v1; + pDestIdx[offer + 4] = v3; + pDestIdx[offer + 5] = v2; + } + + if (sx + iWid == m_iBlockGrid && sy == 0) + { + // Contain right-top corner grid + // v0----v1 + // | / | + // | / | + // | / | + // | / | + // v2----v3 + int offer = (iWid - 1) * 6; + WORD v0 = pDestIdx[offer]; + WORD v1 = pDestIdx[offer + 1]; + WORD v2 = pDestIdx[offer + 5]; + WORD v3 = pDestIdx[offer + 2]; + + pDestIdx[offer + 0] = v0; + pDestIdx[offer + 1] = v1; + pDestIdx[offer + 2] = v2; + + pDestIdx[offer + 3] = v1; + pDestIdx[offer + 4] = v3; + pDestIdx[offer + 5] = v2; + } + + return true; + } + } + + public class A3DTerrain2 + { + public ACTBLOCKS m_pCurActBlocks; // Currently active block array + public ARectF m_rcTerrain; // Whole terrain area in logic unit (metres) + public float m_fBlockSize = 0; // Block size (on x and z axis) in logic unit (metres) + public int m_iBlockGrid = 0; // Each block has m_iBlockGrid * m_iBlockGrid terrain grids + public float m_fGridSize; // Terrain grid size (on x and z axis) in logic unit (metres) + public A3DTerrain2LOD m_pLODMan; // LOD manager + public int m_iNumActBlockRow; // Row and column number of active blocks + public int m_iNumAllBlockRow = 0; // Row number of all blocks + public int m_iNumAllBlockCol = 0; // Column number of all blocks + public bool m_bVertexLight = false; // true, force to use vertex light rather than lightmap + public List m_lstMesh; + + // Check lightmap or vertex-light is used + public bool UseLightmapTech() { return !m_bVertexLight; } + + public A3DTerrain2LOD GetLODManager() { return m_pLODMan; } + + // Get grid faces of specified area + public bool GetFacesOfArea(A3DVECTOR3 vCenter, int iGridWid, int iGridLen, ref A3DVECTOR3[] pVertBuf, ref WORD[] pIdxBuf) + { + //if (m_pCurActBlocks.rcArea.IsEmpty()) + // return false; + if(m_lstMesh == null || m_lstMesh.Count == 0) + { + return false; + } + + float halfW = (iGridWid * m_fGridSize) / 2f; + float halfL = (iGridLen * m_fGridSize) / 2f; + Bounds area = new Bounds(EC_Utility.ToVector3(vCenter), new Vector3(halfW * 2, 1000f, halfL * 2)); + + float fInvGridSize = 1.0f / m_fGridSize; + + ARectI rcGrid = new ARectI(); + rcGrid.left = (int)((vCenter.x - m_rcTerrain.left) * fInvGridSize) - (iGridWid >> 1); + rcGrid.top = (int)((m_rcTerrain.top - vCenter.z) * fInvGridSize) - (iGridLen >> 1); + rcGrid.right = rcGrid.left + iGridWid; + rcGrid.bottom = rcGrid.top + iGridLen; + + return GetFacesOfArea(rcGrid, ref pVertBuf, ref pIdxBuf); + } + + public bool GetFacesOfArea(ARectI rcGridArea, ref A3DVECTOR3[] pVertBuf, ref WORD[] pIdxBuf) + { + if (m_pCurActBlocks.rcArea.IsEmpty()) + return false; + + float fInvGridSize = 1.0f / m_fGridSize; + + ARectI rcGrid = rcGridArea; + + int iMaxGrid = m_iNumAllBlockCol * m_iBlockGrid; + AAssist.a_Clamp(ref rcGrid.left, 0, iMaxGrid); + AAssist.a_Clamp(ref rcGrid.right, 0, iMaxGrid); + iMaxGrid = m_iNumAllBlockRow * m_iBlockGrid; + AAssist.a_Clamp(ref rcGrid.top, 0, iMaxGrid); + AAssist.a_Clamp(ref rcGrid.bottom, 0, iMaxGrid); + + if (rcGrid.IsEmpty()) + return false; + + ARectI rcBlock = new ARectI(); + rcBlock.left = rcGrid.left / m_iBlockGrid; + rcBlock.top = rcGrid.top / m_iBlockGrid; + rcBlock.right = (rcGrid.right - 1) / m_iBlockGrid; + rcBlock.bottom = (rcGrid.bottom - 1) / m_iBlockGrid; + + int r, c; + + // Ensure all blocks in active area and have been loaded + for (r = rcBlock.top; r <= rcBlock.bottom; r++) + { + for (c = rcBlock.left; c <= rcBlock.right; c++) + { + if (!m_pCurActBlocks.rcArea.PtInRect(c, r) || + m_pCurActBlocks.GetBlock(r, c, false) == null) + return false; + } + } + + int pDestIdx = 0; + A3DVECTOR3[] pVertDest = new A3DVECTOR3[0]; + WORD[] pIdxTemp = new WORD[0]; + + for (r = rcBlock.top; r <= rcBlock.bottom; r++) + { + ARectI rect = new ARectI(); + rect.left = rcBlock.left * m_iBlockGrid; + rect.top = r * m_iBlockGrid; + rect.right = rect.left + m_iBlockGrid; + rect.bottom = rect.top + m_iBlockGrid; + + for (c = rcBlock.left; c <= rcBlock.right; c++) + { + A3DTerrain2Block pBlock = m_pCurActBlocks.GetBlock(r, c, false); + //ASSERT(pBlock); + + ARectI rc = rcGrid & rect; + //ASSERT(!rc.IsEmpty()); + + int dx = rc.left - rcGrid.left; + int dy = rc.top - rcGrid.top; + int iBaseVert = dy * (rcGrid.Width() + 1) + dx; + + pVertDest = pVertBuf.Skip(iBaseVert).ToArray(); + pIdxTemp = pIdxBuf.Skip(pDestIdx).ToArray(); + int sx = rc.left - rect.left; + int sy = rc.top - rect.top; + + pBlock.CopyFaces(ref pVertDest, ref pIdxTemp, rc.Width(), rc.Height(), rcGrid.Width() + 1, iBaseVert, sx, sy); + + for (int i = iBaseVert; i < pVertBuf.Length; i++) + { + pVertBuf[i] = pVertDest[i - iBaseVert]; + } + for (int i = 0; i < pIdxBuf.Length; i++) + { + pIdxBuf[i] = pIdxTemp[i - pDestIdx]; + } + + pDestIdx += rc.Width() * rc.Height() * 6; + rect.left += m_iBlockGrid; + rect.right += m_iBlockGrid; + } + } + + return true; + } + + // Get height and normal of specified position + public float GetPosHeight(A3DVECTOR3 vPos, ref A3DVECTOR3 pvNormal) + { + // Give a default value to normal + if (pvNormal != null) + pvNormal.Clear(); + + if (m_pCurActBlocks.rcArea.IsEmpty()) + return 0.0f; + + // Currenly active area AABB + ARectF rcActive = new ARectF(); + rcActive.left = m_rcTerrain.left + m_pCurActBlocks.rcArea.left * m_fBlockSize; + rcActive.top = m_rcTerrain.top - m_pCurActBlocks.rcArea.top * m_fBlockSize; + rcActive.right = rcActive.left + m_pCurActBlocks.rcArea.Width() * m_fBlockSize; + rcActive.bottom = rcActive.top - m_pCurActBlocks.rcArea.Height() * m_fBlockSize; + + if (vPos.x < rcActive.left || vPos.x > rcActive.right || + vPos.z > rcActive.top || vPos.z < rcActive.bottom) + return 0.0f; + + // Get block this position is in + float fInvBlockSize = 1.0f / m_fBlockSize; + int iCol = (int)((vPos.x - rcActive.left) * fInvBlockSize); + int iRow = (int)(-(vPos.z - rcActive.top) * fInvBlockSize); + AAssist.a_Clamp(ref iCol, 0, m_pCurActBlocks.rcArea.Width() - 1); + AAssist.a_Clamp(ref iRow, 0, m_pCurActBlocks.rcArea.Height() - 1); + + int iBlock = iRow * m_pCurActBlocks.rcArea.Width() + iCol; + A3DTerrain2Block pBlock = m_pCurActBlocks.aBlocks[iBlock]; + if (pBlock == null || !pBlock.IsDataLoaded()) + return 0.0f; + + // If whole block is a hole, return as if there is no block here + if (pBlock.IsNoPosHeight()) + return 0.0f; + + // Get block's AABB + A3DAABB aabb = pBlock.GetBlockAABB(); + + // Get grid this position is in + float fInvGridSize = 1.0f / m_fGridSize; + iCol = (int)((vPos.x - aabb.Mins.x) * fInvGridSize); + iRow = (int)(-(vPos.z - aabb.Maxs.z) * fInvGridSize); + AAssist.a_Clamp(ref iCol, 0, m_iBlockGrid - 1); + AAssist.a_Clamp(ref iRow, 0, m_iBlockGrid - 1); + + int iGrid = iRow * m_iBlockGrid + iCol; + GRID Grid = m_pLODMan.GetGrids()[iGrid]; + + A3DVECTOR3 v0 = pBlock.GetVertexPos(Grid.v0); + A3DVECTOR3 v1 = pBlock.GetVertexPos(Grid.v1); + A3DVECTOR3 v2 = pBlock.GetVertexPos(Grid.v2); + A3DVECTOR3 v3 = pBlock.GetVertexPos(Grid.v3); + A3DVECTOR3 v4 = pBlock.GetVertexPos(Grid.v4); + A3DVECTOR3 v5 = pBlock.GetVertexPos(Grid.v5); + + A3DVECTOR3 vDest; + float dx, dz; + + if (iGrid == m_iBlockGrid - 1 || iGrid == m_iBlockGrid * (m_iBlockGrid - 1)) + { + // The grid is on right-top corner or left-bottom corner + dx = vPos.x - v2.x; + dz = vPos.z - v2.z; + + if (dx > dz) + { + vDest = v5 + (v4 - v5) * (dx / (v4.x - v5.x)); + vDest += (v3 - v4) * (dz / (v3.z - v4.z)); + + if (pvNormal != null) + { + pvNormal = A3DVECTOR3.CrossProduct(v4 - v3, v5 - v3); + pvNormal.Normalize(); + } + } + else + { + vDest = v2 + (v0 - v2) * (dz / (v0.z - v2.z)); + vDest += (v1 - v0) * (dx / (v1.x - v0.x)); + + if (pvNormal != null) + { + pvNormal = A3DVECTOR3.CrossProduct(v1 - v0, v2 - v0); + pvNormal.Normalize(); + } + } + } + else + { + dx = vPos.x - v0.x; + dz = vPos.z - v0.z; + + if (dx > -dz) + { + vDest = v0 + (v1 - v0) * (dx / (v1.x - v0.x)); + vDest += (v2 - v1) * (dz / (v2.z - v1.z)); + + if (pvNormal != null) + { + pvNormal = A3DVECTOR3.CrossProduct(v1 - v0, v2 - v0); + pvNormal.Normalize(); + } + } + else + { + vDest = v3 + (v5 - v3) * (dz / (v5.z - v3.z)); + vDest += (v4 - v5) * (dx / (v4.x - v5.x)); + + if (pvNormal != null) + { + pvNormal = A3DVECTOR3.CrossProduct(v4 - v3, v5 - v3); + pvNormal.Normalize(); + } + } + } + + return vDest.y; + } + } + + // Active blocks + public struct ACTBLOCKS + { + public ARectI rcArea; // Active area represented in blocks + public BlockArray aBlocks; // Active block array + + public ACTBLOCKS(ARectI rcArea, BlockArray aBlocks) + { + this.rcArea = rcArea; + this.aBlocks = aBlocks; + } + + // Get block object at specified row, column. + public A3DTerrain2Block GetBlock(int r, int c, bool bClear) + { + //ASSERT(rcArea.PtInRect(c, r)); + + int iIndex = GetBlockIndex(r, c); + A3DTerrain2Block pBlock = aBlocks[iIndex]; + + if (bClear) + aBlocks[iIndex] = null; + + return pBlock; + } + + // Set block object at specified row, column + void SetBlock(int r, int c, A3DTerrain2Block pBlock) + { + //ASSERT(rcArea.PtInRect(c, r)); + int iIndex = GetBlockIndex(r, c); + aBlocks[iIndex] = pBlock; + } + + // Get block index in aBlocks + int GetBlockIndex(int r, int c) + { + return (r - rcArea.top) * rcArea.Width() + c - rcArea.left; + } + }; + + // Block flags & masks + public class Block_flags_masks + { + public static uint T2BKFLAG_DEFAULT = 0x00, // The block flag default value + T2BKFLAG_NORENDER = 0x01, // The whole block is not rendered + T2BKFLAG_NOTRACE = 0x02, // The whole block is out of RayTrace + T2BKFLAG_NOPOSHEIGHT = 0x04, // The whole block is unable to GetPosHeight + T2BKFLAG_NORENDERWITHWATER = 0x08; // The whole block is not rendered with water + }; + + // Vertex indices in a terrain grid + public struct GRID + { + public int v0, v1, v2; // Face 1 + public int v3, v4, v5; // Face 2 + }; +} diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs.meta b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs.meta new file mode 100644 index 0000000000..1a18d55e91 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 828eeca29c5904541bdb0f5162832508 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs new file mode 100644 index 0000000000..2098bb2af6 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs @@ -0,0 +1,12 @@ +using BrewMonster.Scripts.World; +using WORD = System.UInt16; + +public class A3DTerrain2LOD +{ + public GRID[] m_aGrids; // Grid of a block + public WORD[] m_aIndexMaps; // Index map + + // Get grids + public GRID[] GetGrids() { return m_aGrids; } + public WORD[] GetIndexMaps() { return m_aIndexMaps; } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs.meta b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs.meta new file mode 100644 index 0000000000..adced35aa5 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DTerrain2LOD.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: ea4c2d97d77797548b9de5443e250290 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/ARect.cs b/Assets/PerfectWorld/Scripts/Managers/ARect.cs new file mode 100644 index 0000000000..48dff7a51f --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/ARect.cs @@ -0,0 +1,281 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace BrewMonster.Scripts +{ + public class ARect where T : IComparable + { + public T left, top, right, bottom; + + public ARect() + { + left = default(T); + top = default(T); + right = default(T); + bottom = default(T); + } + + public ARect(ARect rc) + { + left = rc.left; top = rc.top; right = rc.right; bottom = rc.bottom; + } + + public ARect(T left, T top, T right, T bottom) + { + this.left = left; + this.top = top; + this.right = right; + this.bottom = bottom; + } + + // == and != operator + public static bool operator !=(ARect rc1, ARect rc2) + { + return !(rc1 == rc2); + } + public static bool operator ==(ARect rc1, ARect rc2) + { + return EqualityComparer.Default.Equals(rc1.left, rc2.left) && + EqualityComparer.Default.Equals(rc1.top, rc2.top) && + EqualityComparer.Default.Equals(rc1.right, rc2.right) && + EqualityComparer.Default.Equals(rc1.bottom, rc2.bottom); + } + + // + and - operator + public static ARect operator +(ARect rc1, ARect rc2) + { + dynamic l = rc1.left, t = rc1.top, r = rc1.right, b = rc1.bottom; + dynamic l2 = rc2.left, t2 = rc2.top, r2 = rc2.right, b2 = rc2.bottom; + ARect result = new ARect(l + l2, t + t2, r + r2, b + b2); + return result; + } + public static ARect operator -(ARect rc1, ARect rc2) + { + return new ARect((dynamic)rc1.left - (dynamic)rc2.left, + (dynamic)rc1.top - (dynamic)rc2.top, + (dynamic)rc1.right - (dynamic)rc2.right, + (dynamic)rc1.bottom - (dynamic)rc2.bottom); + } + //public static ARect operator +(ARect rc1, APoint pt) + //{ + // return new ARect((dynamic)rc1.left + (dynamic)pt.x, + // (dynamic)rc1.top + (dynamic)pt.y, + // (dynamic)rc1.right + (dynamic)pt.x, + // (dynamic)rc1.bottom + (dynamic)pt.y); + //} + //public static ARect operator -(ARect rc1, APoint pt) + //{ + // return new ARect((dynamic)rc1.left - (dynamic)pt.x, + // (dynamic)rc1.top - (dynamic)pt.y, + // (dynamic)rc1.right - (dynamic)pt.x, + // (dynamic)rc1.bottom - (dynamic)pt.y); + //} + + // &= and |= operator + public ARect AndAssign(ARect rc) => this & rc; + public ARect OrAssign(ARect rc) => this | rc; + + public static ARect operator &(ARect rc1, ARect rc2) + { + if (rc1.IsEmpty() || rc2.IsEmpty()) + return new ARect(default, default, default, default); + + dynamic l1 = rc1.left, r1 = rc1.right, t1 = rc1.top, b1 = rc1.bottom; + dynamic l2 = rc2.left, r2 = rc2.right, t2 = rc2.top, b2 = rc2.bottom; + + if (l1 >= r2 || l2 >= r1 || + t1 >= b2 || t2 >= b1) + return new ARect(default, default, default, default); + + return new ARect(l1 > l2 ? l1 : l2, + t1 > t2 ? t1 : t2, + r1 < r2 ? r1 : r2, + b1 < b2 ? b1 : b2); + } + + public static ARect operator |(ARect rc1, ARect rc2) + { + if (rc1.IsEmpty()) + return rc2; + + if (rc2.IsEmpty()) + return rc1; + + dynamic l1 = rc1.left, r1 = rc1.right, t1 = rc1.top, b1 = rc1.bottom; + dynamic l2 = rc2.left, r2 = rc2.right, t2 = rc2.top, b2 = rc2.bottom; + + return new ARect(l1 < l2 ? l1 : l2, + t1 < t2 ? t1 : t2, + r1 > r2 ? r1 : r2, + b1 > b2 ? b1 : b2); + } + + public static ARect operator +(ARect rc) { return rc; } + public static ARect operator -(ARect rc) + { + return new ARect(-(dynamic)rc.left, -(dynamic)rc.top, -(dynamic)rc.right, -(dynamic)rc.bottom); + } + + // = operator + //public static ARect operator = (ARect rc) { left = rc.left; top = rc.top; right = rc.right; bottom = rc.bottom; return *this; } + + // += and -= operator + public ARect AdditionAssign(ARect rc) + { + left += (dynamic)rc.left; + top += (dynamic)rc.top; + right += (dynamic)rc.right; + bottom += (dynamic)rc.bottom; + return this; + } + public ARect SubtractionAssign(ARect rc) + { + left -= (dynamic)rc.left; + top -= (dynamic)rc.top; + right -= (dynamic)rc.right; + bottom -= (dynamic)rc.bottom; + return this; + } + //public ARect AdditionAssign(APoint pt) { left += pt.x; top += pt.y; right += pt.x; bottom += pt.y; return this; } + //public ARect SubtractionAssign(APoint pt) { left -= pt.x; top -= pt.y; right -= pt.x; bottom -= pt.y; return this; } + + // Get width of rectangle + public T Width() + { + return (dynamic)right - (dynamic)left; + } + // Get height of rectangle + public T Height() + { + return (dynamic)bottom - (dynamic)top; + } + // Get center point of rectangle + //public APoint CenterPoint() { return new APoint((left + right) / 2, (top + bottom) / 2); } + // Set rectangle value + public void SetRect(T _left, T _top, T _right, T _bottom) + { + left = _left; + top = _top; + right = _right; + bottom = _bottom; + } + + // Point in rectangle + public bool PtInRect(T x, T y) + { + dynamic valueX = x; + dynamic valueY = y; + return (valueX >= left && valueX < right && valueY >= top && valueY < bottom) ? true : false; + } + //public bool PtInRect(APoint pt) { return PtInRect(pt.x, pt.y); } + + // Normalize rectangle. Note: The following CRect member functions require + // normalized rectangles in order to work properly: Height, Width, Size, + // IsEmpty, PtInRect, SetUnion, SetIntersect, operator ==, operator !=, + // operator |, operator |=, operator &, and operator &= + void Normalize() + { + if ((dynamic)left > right) + a_Swap(left, right); + + if ((dynamic)top > bottom) + a_Swap(top, bottom); + } + + private void a_Swap(T lhs, T rhs) + { + T tmp; + tmp = lhs; + lhs = rhs; + rhs = tmp; + } + + // All members are 0 ? + public bool IsRectNull() + { + return ((dynamic)left == 0 && (dynamic)top == 0 && (dynamic)right == 0 && (dynamic)bottom == 0); + } + // Rectangle is empty ? + public bool IsEmpty() + { + return ((dynamic)Width() == 0 || (dynamic)Height() == 0); + } + // Set all members to 0 + public void Clear() + { + left = top = right = bottom = default(T); + } + // Deflate rectangle + public void Deflate(T x, T y) + { + left += (dynamic)x; + top += (dynamic)y; + right -= (dynamic)x; + bottom -= (dynamic)y; + } + public void Deflate(ARect rc) + { + left += (dynamic)rc.left; + top += (dynamic)rc.top; + right -= (dynamic)rc.right; + bottom -= (dynamic)rc.bottom; + } + public void Deflate(T l, T t, T r, T b) + { + left += (dynamic)l; + top += (dynamic)t; + right -= (dynamic)r; + bottom -= (dynamic)b; + } + // Inflate rectangle + public void Inflate(T x, T y) + { + left -= (dynamic)x; + top -= (dynamic)y; + right += (dynamic)x; + bottom += (dynamic)y; + } + public void Inflate(ARect rc) + { + left -= (dynamic)rc.left; + top -= (dynamic)rc.top; + right += (dynamic)rc.right; + bottom += (dynamic)rc.bottom; + } + public void Inflate(T l, T t, T r, T b) + { + left -= (dynamic)l; + top -= (dynamic)t; + right += (dynamic)r; + bottom += (dynamic)b; + } + // Offset rectangle + public void Offset(T x, T y) + { + left += (dynamic)x; + top += (dynamic)y; + right += (dynamic)x; + bottom += (dynamic)y; + } + //public void Offset(APoint pt) { this += pt; } + // Set rectangle as union result + public void SetUnion(ARect rc1, ARect rc2) + { + var result = rc1 | rc2; + left = result.left; + right = result.right; + bottom = result.bottom; + top = result.top; + } + // Set rectangle as intersect result + public void SetIntersect(ARect rc1, ARect rc2) + { + var result = rc1 & rc2; + left = result.left; + right = result.right; + bottom = result.bottom; + top = result.top; + } + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/ARect.cs.meta b/Assets/PerfectWorld/Scripts/Managers/ARect.cs.meta new file mode 100644 index 0000000000..66c5766867 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/ARect.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 00eedf309b0008346a58412f4aad4dec \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/CECAttacksMan.cs b/Assets/PerfectWorld/Scripts/Managers/CECAttacksMan.cs index b735ae4f59..01f531d566 100644 --- a/Assets/PerfectWorld/Scripts/Managers/CECAttacksMan.cs +++ b/Assets/PerfectWorld/Scripts/Managers/CECAttacksMan.cs @@ -1,4 +1,5 @@ using BrewMonster; +using BrewMonster.Managers; using CSNetwork.GPDataType; using System; using System.Collections; diff --git a/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs b/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs index 44130b85f5..386f98a88b 100644 --- a/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs +++ b/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs @@ -1,4 +1,5 @@ using BrewMonster; +using BrewMonster.Scripts.World; using CSNetwork; using CSNetwork.GPDataType; using DG.Tweening; diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs b/Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs new file mode 100644 index 0000000000..975631466f --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using System.Numerics; +using UnityEngine; +namespace BrewMonster.Scripts +{ + //@desc : using grid to manage the brushes. By Kuiwu[2/11/2005] + public class CBrushGrid + { + //public CBrushGrid(int iCellSize = 80, int iW = 11, int iH = 11); + + // void AddProvider(CBrushProvider* pProvider); + // bool RemoveProvider(CBrushProvider* pProvider); + // void Build(const A3DVECTOR3& vCenter, bool bForce = false); + public bool Trace(BrushTraceInfo pInfo, bool bCheckFlag = true) + { + return false; + } + +#if BMAN_VERBOSE_STAT + CBManStat * GetStat() + { + return &m_Stat; + } +#endif + + + // private int m_iCellSize; + // private int m_iW, m_iH; //in cell + // private short m_iCenterX, m_iCenterZ; + // private float m_fTraceRange2; + + // private CBrushCell m_pBrushCell; //as a brush cell buffer + // //@note : use hash table to accelerate searching cell buffer. By Kuiwu[2/11/2005] + // private Dictionary CellTable; + // private CellTable m_CellTbl; + + // private vector m_UnOrganizedProvider; //to be built. + // private vector m_OutOfRangeBrush; + + // private void _GetCellIndex(const A3DVECTOR3& vPos, short& x, short& z); + //private CBrushCell * _FindCell(short x, short z); + + // private bool _UpdateCenter(const A3DVECTOR3& vCenter, bool bForce); + // private bool _AddBrush(CCDBrush pBrush); +#if BMAN_VERBOSE_STAT + CBManStat m_Stat; +#endif + + } + + public class CECBrushMan + { + public CBrushGrid m_pBrushGrid; + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs.meta new file mode 100644 index 0000000000..1cc88f8059 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_BrushMan.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: dbb7777494908644db0a9f59f533162d \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs b/Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs new file mode 100644 index 0000000000..fcc9d97884 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs @@ -0,0 +1,714 @@ +using CSNetwork.GPDataType; +using PerfectWorld.Scripts.Player; +using System; + +namespace BrewMonster.Scripts +{ + using WorkList = System.Collections.Generic.List; + + public abstract class CECEPWorkMatcher + { + public abstract bool Match(CECEPWork work, int workType); + } + + // class CECEPWorkMelee + public class CECEPWorkMelee : CECEPWork + { + int m_iAttackTarget; + + public CECEPWorkMelee(CECEPWorkMan pWorkMan, int attackTarget) : base(EP_work_ID.WORK_HACKOBJECT, pWorkMan) + { + m_iAttackTarget = attackTarget; + } + public override void Start() + { + GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND; + GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_ATTACK_1 + UnityEngine.Random.Range(0, 3)); + GetPlayer().EnterFightState(); + } + public override void Tick(float dwDeltaTime) + { + GetPlayer().TurnFaceTo(m_iAttackTarget); + + // Slide to server position + A3DVECTOR3 vDir = GetPlayer().m_vServerPos - GetPlayer().GetPos(); + float fDist = vDir.Normalize(); + if (fDist > 0.0001f) + { + float fMoveDist = 10.0f * dwDeltaTime * 0.001f; + if (fMoveDist > fDist) + fMoveDist = fDist; + + GetPlayer().SetPos(GetPlayer().GetPos() + vDir * fMoveDist); + } + if (GetPlayer().m_FightCnt.IncCounter(dwDeltaTime)) + { + Finish(); + } + } + public override void Cancel() + { + GetPlayer().TurnFaceTo(0); + } + }; + + public class CECEPWorkIDMatcher : CECEPWorkMatcher + { + int m_workID; + public CECEPWorkIDMatcher(int workID) + { + m_workID = workID; + } + public override bool Match(CECEPWork work, int workType) + { + return work != null && work.GetWorkID() == m_workID; + } + } + + // class CECEPWorkCongregate + public class CECEPWorkCongregate : CECEPWork + { + int m_iType; + public CECEPWorkCongregate(CECEPWorkMan pWorkMan, int iType) : base(EP_work_ID.WORK_CONGREGATE, pWorkMan) + { + m_iType = iType; + } + public override void Start() + { + + } + public int GetType() + { + return m_iType; + } + } + + public class CECEPCongregateWorkMatcher : CECEPWorkMatcher + { + int m_iType; + public CECEPCongregateWorkMatcher(int iType) + { + m_iType = iType; + } + + public override bool Match(CECEPWork work, int workType) + { + if (work != null && work.GetWorkID() == CECEPWork.EP_work_ID.WORK_CONGREGATE) + { + CECEPWorkCongregate pCongregateWork = work as CECEPWorkCongregate; + return pCongregateWork.GetType() == m_iType; + } + return false; + } + } + + // class CECEPWorkIdle + public class CECEPWorkIdle : CECEPWork + { + int m_iType; + bool m_bOTCheck; + CECCounter m_OTCnt; + uint m_dwParam; + public CECEPWorkIdle(CECEPWorkMan pWorkMan, int iType, int iOTTime, uint dwParam) : base(EP_work_ID.WORK_IDLE, pWorkMan) + { + m_dwParam = dwParam; + m_iType = iType; + m_bOTCheck = iOTTime > 0 ? true : false; + + if (m_bOTCheck) + { + m_OTCnt.SetPeriod(iOTTime); + m_OTCnt.Reset(); + } + + switch (iType) + { + case Idle_work_type.IDLE_SITDOWN: + GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND; + + if (m_dwParam != 0) + GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SITDOWN_LOOP); + else + { + GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SITDOWN); + GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SITDOWN_LOOP, true, 200, true); + } + + break; + + case Idle_work_type.IDLE_REVIVE: + + GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_REVIVE); + break; + + case Idle_work_type.IDLE_BOOTH: + + GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND; + break; + } + } + public override void Tick(float dwDeltaTime) + { + base.Tick(dwDeltaTime); + } + public int GetType() + { + return m_iType; + } + } + + public class CECEPIdleWorkMatcher : CECEPWorkMatcher + { + int m_iType; + public CECEPIdleWorkMatcher(int iType) + { + m_iType = iType; + } + public override bool Match(CECEPWork work, int workType) + { + if (work != null && work.GetWorkID() == CECEPWork.EP_work_ID.WORK_IDLE) + { + CECEPWorkIdle pIdleWork = work as CECEPWorkIdle; + return pIdleWork.GetType() == m_iType; + } + return false; + } + } + + public class CECEPWork + { + public static class EP_work_ID + { + public const int WORK_INVALID = -1, + WORK_STAND = 0, // Stand and do nothing + WORK_MOVE = 1, // Move + WORK_HACKOBJECT = 2, // Hack specified object (NPC, player etc.) + WORK_SPELL = 3, // Spell magic + WORK_PICKUP = 4, // Pickup matter + WORK_DEAD = 5, // Dead + WORK_USEITEM = 6, // Use item + WORK_IDLE = 7, // Idle works + WORK_FLASHMOVE = 8, // Flash move + WORK_PASSIVEMOVE = 9, // Move controlled by server + WORK_CONGREGATE = 10, // Congregate reply + WORK_SKILLSTATEACT = 11, // skill buff action + NUM_WORK = 12; + } + + // Idle work type + public static class Idle_work_type + { + public const int IDLE_SITDOWN = 0, + IDLE_REVIVE = 1, + IDLE_BOOTH = 2; + } + + static string[] l_WorkName = new string[EP_work_ID.NUM_WORK] + { + "WORK_STAND", + "WORK_MOVE", + "WORK_HACKOBJECT", + "WORK_SPELL", + "WORK_PICKUP", + "WORK_DEAD", + "WORK_USEITEM", + "WORK_IDLE", + "WORK_FLASHMOVE", + "WORK_PASSIVEMOVE", + "WORK_CONGREGATE", + "WORK_SKILLSTATEACT", + }; + + + protected int m_iWorkID; + protected CECEPWorkMan m_pWorkMan; + protected bool m_bFinished; + protected EC_ElsePlayer GetPlayer() + { + return m_pWorkMan.GetPlayer(); + } + + + public CECEPWork(int iWorkID, CECEPWorkMan pWorkMan) + { + m_iWorkID = iWorkID; + m_pWorkMan = pWorkMan; + m_bFinished = false; + } + + + public static string GetWorkName(int iWork) + { + if (iWork >= EP_work_ID.WORK_STAND && iWork < l_WorkName.Length) + { + return l_WorkName[iWork]; + } + else + { + return "Invalid Work"; + } + } + + public string GetWorkName() + { + return GetWorkName(GetWorkID()); + } + public int GetWorkID() + { + return m_iWorkID; + } + public bool IsFinished() + { + return m_bFinished; + } + + public virtual void Start() { } + public virtual void Tick(float dwDeltaTime) { } + public virtual void Cancel() { } + public virtual void Finish() + { + m_bFinished = true; + } + static bool Validate(int iWork) + { + return iWork >= EP_work_ID.WORK_STAND && iWork < EP_work_ID.NUM_WORK; + } + } + + // class CECEPWorkSpell + public class CECEPWorkSpell : CECEPWork + { + CECCounter m_SkillCnt; + CECSkill m_pCurSkill; + int m_idCurSkillTarget; + + public CECEPWorkSpell(CECEPWorkMan pWorkMan, uint dwPeriod, CECSkill pSkill, int target) : base(CECEPWork.EP_work_ID.WORK_SPELL, pWorkMan) + { + m_pCurSkill = pSkill; + m_idCurSkillTarget = target; + m_SkillCnt.SetPeriod(dwPeriod); + m_SkillCnt.Reset(); + } + public override void Start() + { + GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND; + } + public override void Tick(float dwDeltaTime) + { + //TO DO: fix later + //GetPlayer().m_FightCnt.IncCounter(dwDeltaTime); + //int iRealTime = g_pGame.GetRealTickTime(); + //if (m_SkillCnt.IncCounter(iRealTime)) + //{ + // Finish(); + //} + //else + //{ + // if (m_idCurSkillTarget != 0) + // { + // GetPlayer().TurnFaceTo(m_idCurSkillTarget); + // } + // if (GetPlayer().IsPlayingMoveAction() && !GetPlayer().IsWorkMoveRunning()) + // { // 从移动施法到停止移动、会一直在持续播放移动动作,此处暂停 + // GetPlayer().PlayAction(CECPlayer::ACT_FIGHTSTAND); + // } + // if (!GetPlayer().IsPlayingAction()) + // { + // GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_FIGHTSTAND); // 技能动作播放完成后、播放战斗站立动作 + // } + //} + } + public override void Cancel() + { + //TO DO: fix later + //if (m_pCurSkill != null) + //{ + // m_pCurSkill = null; + //} + //m_idCurSkillTarget = 0; + //GetPlayer().StopSkillAttackAction(); + //GetPlayer().TurnFaceTo(0); + } + public CECSkill GetSkill() + { + return m_pCurSkill; + } + } + + public class CECEPWorkMan + { + public static class Work_type + { + public const int WT_NOTHING = 0, // Do thing + WT_NORMAL = 1, // Normal type work + WT_INTERRUPT = 2, // Interrupt type work + NUM_WORKTYPE = 3; + } + + private EC_ElsePlayer m_pElsePlayer; + private WorkList[] m_WorkStack = new WorkList[Work_type.NUM_WORKTYPE]; + private int m_iCurWorkType; + + public CECEPWorkMan(EC_ElsePlayer pElsePlayer) + { + m_pElsePlayer = pElsePlayer; + m_iCurWorkType = -1; + } + + public EC_ElsePlayer GetPlayer() + { + return m_pElsePlayer; + } + + public bool ValidateWorkType(int iWorkType) + { + return iWorkType >= 0 && iWorkType < Work_type.NUM_WORKTYPE; + } + + public bool FindWork(int iWorkType, int iWorkID) + { + if (!ValidateWorkType(iWorkType)) + { + return false; + } + WorkList workList = m_WorkStack[iWorkType]; + if (workList != null) + { + for (int i = 0; i < workList.Count; ++i) + { + if (iWorkID == workList[i].GetWorkID()) + { + return true; + } + } + } + return false; + } + + public void StartNormalWork(CECEPWork pWork) + { + StartWork(Work_type.WT_NORMAL, ref pWork); + } + + private bool CanRunSimultaneously(CECEPWork pWork1, CECEPWork pWork2) + { + if (pWork1.GetWorkID() == CECEPWork.EP_work_ID.WORK_MOVE && + pWork2.GetWorkID() == CECEPWork.EP_work_ID.WORK_SPELL) + { + return CanSpellWhileMoving(pWork2 as CECEPWorkSpell); + } + if (pWork2.GetWorkID() == CECEPWork.EP_work_ID.WORK_MOVE && + pWork1.GetWorkID() == CECEPWork.EP_work_ID.WORK_SPELL) + { + return CanSpellWhileMoving(pWork1 as CECEPWorkSpell); + } + return false; + } + + private bool CanReplace(CECEPWork pNewWork, CECEPWork pExistWork) + { + if (pNewWork.GetWorkID() == CECEPWork.EP_work_ID.WORK_SPELL && + pExistWork.GetWorkID() == CECEPWork.EP_work_ID.WORK_SPELL) + { + return CanSpellWhileMoving(pNewWork as CECEPWorkSpell) + && CanSpellWhileMoving(pExistWork as CECEPWorkSpell); + } + return false; + } + + private bool CanSpellWhileMoving(CECEPWorkSpell pWorkSpell) + { + return false; + // TO DO: fix later + // return pWorkSpell.GetSkill() + // && CECCastSkillWhenMove.Instance().IsSkillSupported(pWorkSpell.GetSkill().GetSkillID(), GetPlayer()); + } + + private bool CanMergeWithCurrentWork(int iWorkType, CECEPWork pWork) + { + if (!ValidateWorkType(iWorkType) || iWorkType != m_iCurWorkType) + { + return false; + } + WorkList workList = m_WorkStack[iWorkType]; + if (workList == null || workList.Count == 0) + { + return false; + } + for (int i = 0; i < workList.Count; ++i) + { + if (!CanRunSimultaneously(pWork, workList[i]) && // 要么同时共存 + !CanReplace(pWork, workList[i])) + { // 要么可以替换 + return false; + } + } + return true; + } + + private void KillWork(int iWorkType, int index) + { + if (!ValidateWorkType(iWorkType)) + { + //ASSERT(false); + return; + } + WorkList workList = m_WorkStack[iWorkType]; + if (index < 0 || index >= (int)workList.Count) + { + //ASSERT(false); + return; + } + CECEPWork pWork = workList[index]; + pWork.Cancel(); + //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::%s(%s) killed", pWork.GetWorkName(), GetWorkTypeName(iWorkType))); + //delete pWork; + pWork = null; + workList.RemoveAt(index); + } + + private void MergeWork(int iWorkType, CECEPWork pWork) + { + if (!CanMergeWithCurrentWork(iWorkType, pWork)) + { + //ASSERT(false); + return; + } + WorkList workList = m_WorkStack[iWorkType]; + for (int i = 0; i < workList.Count; ++i) + { + if (CanReplace(pWork, workList[i])) + { + //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::MergeWork %s replacing %s at %s", pWork.GetWorkName(), workList[i].GetWorkName(), GetWorkTypeName(iWorkType))); + KillWork(iWorkType, i); + workList.Insert(i, pWork); + return; + } + } + workList.Add(pWork); + //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::MergeWork %s appended to %s", pWork.GetWorkName(), GetWorkTypeName(iWorkType))); + } + + private void FinishWorkAtWorkType(int iWorkType) + { + if (!ValidateWorkType(iWorkType)) + { + //ASSERT(false); + return; + } + WorkList workList = m_WorkStack[iWorkType]; + while (workList != null && workList.Count != 0) + { + KillWork(iWorkType, 0); + } + if (m_iCurWorkType == iWorkType) + { + m_iCurWorkType = -1; + } + } + + private void AppendWork(int iWorkType, CECEPWork pWork) + { + if (!ValidateWorkType(iWorkType) || pWork == null) + { + //ASSERT(false); + return; + } + m_WorkStack[iWorkType].Add(pWork); + } + + private void CancelWorkAtWorkType(int iWorkType) + { + if (!ValidateWorkType(iWorkType)) + { + return; + } + WorkList workList = m_WorkStack[iWorkType]; + for (int i = 0; i < workList.Count; ++i) + { + CancelWork(workList[i]); + //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::%s(%s) cancelled", workList[i].GetWorkName(), GetWorkTypeName(iWorkType))); + } + } + + private void CancelWork(CECEPWork pWork) + { + if (pWork == null) + { + //ASSERT(false); + return; + } + pWork.Cancel(); + } + + public void StartWork(int iWorkType, ref CECEPWork pWork) + { + if (!ValidateWorkType(iWorkType)) + { + pWork = null; + return; + } + if (CanMergeWithCurrentWork(iWorkType, pWork)) + { + MergeWork(iWorkType, pWork); + } + else + { + if (pWork.GetWorkID() == CECEPWork.EP_work_ID.WORK_DEAD) + { + for (int i = iWorkType; i < Work_type.NUM_WORKTYPE; i++) + { + FinishWorkAtWorkType(i); + } + AppendWork(iWorkType, pWork); + m_iCurWorkType = iWorkType; + } + else + { + bool shouldStart = (iWorkType >= m_iCurWorkType); + FinishWorkAtWorkType(iWorkType); + AppendWork(iWorkType, pWork); + if (!shouldStart) + { + //LOG_DEBUG_INFO(AString().Format("CECEPWork::StartWork %s flushed %s", pWork.GetWorkName(), GetWorkTypeName(iWorkType))); + return; + } + if (iWorkType > m_iCurWorkType) + { + CancelWorkAtWorkType(m_iCurWorkType); + } + m_iCurWorkType = iWorkType; + } + } + pWork.Start(); + } + + private bool IsAnyWorkRunning() + { + return ValidateWorkType(m_iCurWorkType) && m_WorkStack != null && m_WorkStack[m_iCurWorkType] != null; + } + + private void StartAwaitingWorks() + { + if (ValidateWorkType(m_iCurWorkType)) + { + for (--m_iCurWorkType; m_iCurWorkType >= 0; --m_iCurWorkType) + { + WorkList workList = m_WorkStack[m_iCurWorkType]; + if (workList == null || workList.Count == 0) + { + continue; + } + for (int j = 0; j < workList.Count; ++j) + { + workList[j].Start(); + //LOG_DEBUG_INFO(AString().Format("CECElsePlayer::StartAwaitingWorks %s(%s) started by decrease priority", workList[j].GetWorkName(), GetWorkTypeName(m_iCurWorkType))); + } + break; + } + } + } + + public void Tick(float dwDeltaTime) + { + if (!IsAnyWorkRunning()) + { + return; + } + WorkList workList = m_WorkStack[m_iCurWorkType]; + if (workList != null) + { + for (int i = 0; i < workList.Count;) + { + CECEPWork pWork = workList[i]; + pWork.Tick(dwDeltaTime); + if (!pWork.IsFinished()) + { + ++i; + continue; + } + KillWork(m_iCurWorkType, i); + } + if (workList == null || workList.Count == 0) + { + StartAwaitingWorks(); + } + } + } + + public void FinishWork(CECEPWorkMatcher matcher) + { + bool bCurrentWorkFinished = false; + for (int i = Work_type.NUM_WORKTYPE - 1; i >= 0; --i) + { + WorkList workList = m_WorkStack[i]; + if (workList == null || workList.Count == 0) + { + continue; + } + for (int j = 0; j < workList.Count;) + { + if (!matcher.Match(workList[j], i)) + { + ++j; + continue; + } + KillWork(i, j); + if (i == m_iCurWorkType && (workList == null || workList.Count == 0)) + { + bCurrentWorkFinished = true; + } + } + } + if (bCurrentWorkFinished) + { + StartAwaitingWorks(); + } + } + public void FinishWork(int idWork) + { + FinishWork(new CECEPWorkIDMatcher(idWork)); + } + + public bool IsWorkRunning(int iWork) + { + return FindWork(m_iCurWorkType, iWork); + } + + public void FinishRunningWork(int idWork) + { + if (!IsWorkRunning(idWork)) + { + return; + } + WorkList workList = m_WorkStack[m_iCurWorkType]; + if (workList != null) + { + for (int i = 0; i < workList.Count;) + { + if (workList[i].GetWorkID() != idWork) + { + ++i; + continue; + } + //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::FinishRunningWork %s(%s)", workList[i].GetWorkName(), GetWorkTypeName(m_iCurWorkType))); + KillWork(m_iCurWorkType, i); + } + if (workList == null) + { + StartAwaitingWorks(); + } + } + } + public bool FinishIdleWork(int iType) + { + FinishWork(new CECEPIdleWorkMatcher(iType)); + return true; + } + public bool FinishCongregateWork(int iType) + { + FinishWork(new CECEPCongregateWorkMatcher(iType)); + return true; + } + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs.meta new file mode 100644 index 0000000000..27becec87a --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_EPWork.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9352b9911dad2d541b975297dcefa8d2 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs index 14f1895208..f8531917e2 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs @@ -1,100 +1,101 @@ +using BrewMonster.Scripts.Player; using System.Collections.Generic; -using System.Security.Cryptography; -using Unity.VisualScripting; -using WorkList = System.Collections.Generic.List; -public class CECHPWork : CECObjectWork +namespace BrewMonster.Scripts { - // Host work ID - public static class Host_work_ID + using WorkList = System.Collections.Generic.List; + public class CECHPWork : CECObjectWork { - public const int WORK_INVALID = -1, - WORK_STAND = 0, // Stand and do nothing - WORK_MOVETOPOS = 1, // Move to a destination terrain position - WORK_TRACEOBJECT = 2, // Trace specified object (NPC, player etc.) - WORK_HACKOBJECT = 3, // Hack specified object (NPC, player etc.) - WORK_SPELLOBJECT = 4, // Spell magic on specified object (NPC, player etc.) - WORK_USEITEM = 5, // Host use item - WORK_DEAD = 6, // Host is dead - WORK_FOLLOW = 7, // Follow some one else - WORK_FLYOFF = 8, // Fly off - WORK_FREEFALL = 9, // Free fall - WORK_SIT = 10, // Sit - WORK_PICKUP = 11, // Pickup item - WORK_CONCENTRATE = 12, // All concentrate work - WORK_REVIVE = 13, // Revive - WORK_FLASHMOVE = 14, // Flash move - WORK_BEBOUND = 15, // Be bound by buddy - WORK_PASSIVEMOVE = 16, // Passive movement (knock back / pull) - WORK_CONGREGATE = 17, // Congregate reply - WORK_SKILLSTATEACT = 18, // skill buff action - WORK_FORCENAVIGATEMOVE = 19, // force navigate move - NUM_WORK = 20; - } - - protected static class Work_mask - { - public const uint MASK_STAND = 0x0001, - MASK_MOVETOPOS = 0x0002, - MASK_TRACEOBJECT = 0x0004, - MASK_HACKOBJECT = 0x0008, - MASK_SPELLOBJECT = 0x0010, - MASK_USEITEM = 0x0020, - MASK_DEAD = 0x0040, - MASK_FOLLOW = 0x0080, - MASK_FLYOFF = 0x0100, - MASK_FREEFALL = 0x0200, - MASK_SIT = 0x0400, - MASK_PICKUP = 0x0800, - MASK_CONCENTRATE = 0x1000, - MASK_REVIVE = 0x2000, - MASK_FLASHMOVE = 0x4000, - MASK_BEBOUND = 0x8000, - MASK_CONGREGATE = 0x10000, - MASK_SKILLSTATEACT = 0x20000, - MASK_FORCENAVIGATE = 0x40000; - public const uint MASK_ALLWORK = 0xffffffff; - } - - protected CECHPWorkMan m_pWorkMan; // Work manager - protected CECHostPlayer m_pHost; // Host player object - - public CECHPWork(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID) - { - m_pWorkMan = pWorkMan; - m_pHost = pWorkMan.GetHostPlayer(); - } - - // Operations - // Override from CECObjectWork - public virtual void Cancel() - { - - } - // This work is do player moving ? - public virtual bool IsMoving() - { - return false; - } - // Copy work data - public virtual bool CopyData(CECHPWork pWork) - { - m_bFinished = pWork.m_bFinished; - m_bFirstTick = pWork.m_bFirstTick; - return true; - } - - public string GetWorkName() - { - return GetWorkName(GetWorkID()); - } - public static uint GetWorkMask(int iWorkID) - { - if (!Validate(iWorkID)) + // Host work ID + public static class Host_work_ID { - return 0; + public const int WORK_INVALID = -1, + WORK_STAND = 0, // Stand and do nothing + WORK_MOVETOPOS = 1, // Move to a destination terrain position + WORK_TRACEOBJECT = 2, // Trace specified object (NPC, player etc.) + WORK_HACKOBJECT = 3, // Hack specified object (NPC, player etc.) + WORK_SPELLOBJECT = 4, // Spell magic on specified object (NPC, player etc.) + WORK_USEITEM = 5, // Host use item + WORK_DEAD = 6, // Host is dead + WORK_FOLLOW = 7, // Follow some one else + WORK_FLYOFF = 8, // Fly off + WORK_FREEFALL = 9, // Free fall + WORK_SIT = 10, // Sit + WORK_PICKUP = 11, // Pickup item + WORK_CONCENTRATE = 12, // All concentrate work + WORK_REVIVE = 13, // Revive + WORK_FLASHMOVE = 14, // Flash move + WORK_BEBOUND = 15, // Be bound by buddy + WORK_PASSIVEMOVE = 16, // Passive movement (knock back / pull) + WORK_CONGREGATE = 17, // Congregate reply + WORK_SKILLSTATEACT = 18, // skill buff action + WORK_FORCENAVIGATEMOVE = 19, // force navigate move + NUM_WORK = 20; } - uint[] l_workMask = new uint[]{ + + protected static class Work_mask + { + public const uint MASK_STAND = 0x0001, + MASK_MOVETOPOS = 0x0002, + MASK_TRACEOBJECT = 0x0004, + MASK_HACKOBJECT = 0x0008, + MASK_SPELLOBJECT = 0x0010, + MASK_USEITEM = 0x0020, + MASK_DEAD = 0x0040, + MASK_FOLLOW = 0x0080, + MASK_FLYOFF = 0x0100, + MASK_FREEFALL = 0x0200, + MASK_SIT = 0x0400, + MASK_PICKUP = 0x0800, + MASK_CONCENTRATE = 0x1000, + MASK_REVIVE = 0x2000, + MASK_FLASHMOVE = 0x4000, + MASK_BEBOUND = 0x8000, + MASK_CONGREGATE = 0x10000, + MASK_SKILLSTATEACT = 0x20000, + MASK_FORCENAVIGATE = 0x40000; + public const uint MASK_ALLWORK = 0xffffffff; + } + + protected CECHPWorkMan m_pWorkMan; // Work manager + protected CECHostPlayer m_pHost; // Host player object + + public CECHPWork(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID) + { + m_pWorkMan = pWorkMan; + m_pHost = pWorkMan.GetHostPlayer(); + } + + // Operations + // Override from CECObjectWork + public override void Cancel() + { + + } + // This work is do player moving ? + public virtual bool IsMoving() + { + return false; + } + // Copy work data + public virtual bool CopyData(CECHPWork pWork) + { + m_bFinished = pWork.m_bFinished; + m_bFirstTick = pWork.m_bFirstTick; + return true; + } + + public string GetWorkName() + { + return GetWorkName(GetWorkID()); + } + public static uint GetWorkMask(int iWorkID) + { + if (!Validate(iWorkID)) + { + return 0; + } + uint[] l_workMask = new uint[]{ Work_mask.MASK_STAND, Work_mask.MASK_MOVETOPOS, Work_mask.MASK_TRACEOBJECT, @@ -115,17 +116,17 @@ public class CECHPWork : CECObjectWork Work_mask.MASK_SKILLSTATEACT, Work_mask.MASK_FORCENAVIGATE, }; - return l_workMask[iWorkID]; - } - public static bool Validate(int iWorkID) - { - return iWorkID >= 0 && iWorkID < Host_work_ID.NUM_WORK; - } - - public static string GetWorkName(int iWorkID) - { - string[] l_WorkName = new string[Host_work_ID.NUM_WORK] + return l_workMask[iWorkID]; + } + public static bool Validate(int iWorkID) { + return iWorkID >= 0 && iWorkID < Host_work_ID.NUM_WORK; + } + + public static string GetWorkName(int iWorkID) + { + string[] l_WorkName = new string[Host_work_ID.NUM_WORK] + { "WORK_STAND", "WORK_MOVETOPOS", "WORK_TRACEOBJECT", @@ -146,538 +147,539 @@ public class CECHPWork : CECObjectWork "WORK_CONGREGATE", "WORK_SKILLSTATEACT", "WORK_FORCENAVIGATEMOVE" - }; - if (Validate(iWorkID)) - { - return l_WorkName[iWorkID]; - } - else if (iWorkID == Host_work_ID.WORK_INVALID) - { - return "WORK_INVALID"; - } - else - { - return "Unknown"; - } - } -} - -/////////////////////////////////////////////////////////////////////////// -// -// Class CECHPWorkMan -// -/////////////////////////////////////////////////////////////////////////// -public class CECHPWorkMan -{ - // Work priority - public static class Work_priority - { - public const int PRIORITY_0 = 0, - PRIORITY_1 = 1, - PRIORITY_2 = 2, - NUM_PRIORITY = 3; - }; - - // Delayed work info. - public struct DELAYWORK - { - public int iPriority; - public CECHPWork pWork; - } - - private CECHostPlayer m_pHost; - private WorkList[] m_WorkStack = new WorkList[Work_priority.NUM_PRIORITY] { new List(), new List(), new List() }; - private int m_iCurPriority; - private DELAYWORK m_Delayed; - private CECHPWorkPostTickCommand m_pPostTickCommand; - - public CECHPWorkMan(CECHostPlayer pHost) - { - m_pHost = pHost; - m_iCurPriority = -1; - m_Delayed = new DELAYWORK - { - iPriority = 0, - pWork = null - }; - m_pPostTickCommand = null; - } - - public CECHPWork GetRunningWork(int iWorkID) - { - CECHPWork result = null; - if (ValidatePriority(m_iCurPriority)) - { - WorkList workList = m_WorkStack[m_iCurPriority]; - for (int i = 0; i < workList.Count; ++i) + }; + if (Validate(iWorkID)) { - if (iWorkID == workList[i].GetWorkID()) - { - result = workList[i]; - break; - } + return l_WorkName[iWorkID]; + } + else if (iWorkID == Host_work_ID.WORK_INVALID) + { + return "WORK_INVALID"; + } + else + { + return "Unknown"; } } - return result; } - public CECHPWork GetWork(int iWorkID, int iPriority = Work_priority.PRIORITY_1, bool bIncludeDelayedWork = false) + + /////////////////////////////////////////////////////////////////////////// + // + // Class CECHPWorkMan + // + /////////////////////////////////////////////////////////////////////////// + public class CECHPWorkMan { - CECHPWorkGeneralMatcher cECHPWork = new CECHPWorkGeneralMatcher(iWorkID, iPriority, bIncludeDelayedWork); - return GetWork(cECHPWork); - } - public CECHPWork GetWork(CECHPWorkMatcher matcher) - { - CECHPWork result = null; - for (int i = (Work_priority.NUM_PRIORITY - 1); i >= 0; --i) + // Work priority + public static class Work_priority { - WorkList workList = m_WorkStack[i]; - if (workList != null) + public const int PRIORITY_0 = 0, + PRIORITY_1 = 1, + PRIORITY_2 = 2, + NUM_PRIORITY = 3; + }; + + // Delayed work info. + public struct DELAYWORK + { + public int iPriority; + public CECHPWork pWork; + } + + private CECHostPlayer m_pHost; + private WorkList[] m_WorkStack = new WorkList[Work_priority.NUM_PRIORITY] { new List(), new List(), new List() }; + private int m_iCurPriority; + private DELAYWORK m_Delayed; + private CECHPWorkPostTickCommand m_pPostTickCommand; + + public CECHPWorkMan(CECHostPlayer pHost) + { + m_pHost = pHost; + m_iCurPriority = -1; + m_Delayed = new DELAYWORK { - for (int j = 0; j < workList.Count; ++j) + iPriority = 0, + pWork = null + }; + m_pPostTickCommand = null; + } + + public CECHPWork GetRunningWork(int iWorkID) + { + CECHPWork result = null; + if (ValidatePriority(m_iCurPriority)) + { + WorkList workList = m_WorkStack[m_iCurPriority]; + for (int i = 0; i < workList.Count; ++i) { - CECHPWork pWork = workList[j]; - if (matcher.Match(pWork, i, false)) + if (iWorkID == workList[i].GetWorkID()) { - result = pWork; + result = workList[i]; break; } } } + return result; } - if (result == null && GetDelayedWork() != null && matcher.Match(m_Delayed.pWork, m_Delayed.iPriority, true)) + public CECHPWork GetWork(int iWorkID, int iPriority = Work_priority.PRIORITY_1, bool bIncludeDelayedWork = false) { - result = GetDelayedWork(); + CECHPWorkGeneralMatcher cECHPWork = new CECHPWorkGeneralMatcher(iWorkID, iPriority, bIncludeDelayedWork); + return GetWork(cECHPWork); } - return result; - } - - bool InternallyStartWork(int iPriority, CECHPWork pWork) - { - bool bStarted = false; - if (CanRunSimultaneouslyWithCurrentWork(iPriority, pWork)) + public CECHPWork GetWork(CECHPWorkMatcher matcher) { - WorkList workList = m_WorkStack[iPriority]; - workList.Add(pWork); - bStarted = true; - //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started simultaneously, priority=%d", pWork->GetWorkName(), iPriority)); - } - else - { - if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_DEAD) + CECHPWork result = null; + for (int i = (Work_priority.NUM_PRIORITY - 1); i >= 0; --i) { - for (int i = iPriority; i < Work_priority.NUM_PRIORITY; i++) + WorkList workList = m_WorkStack[i]; + if (workList != null) { - FinishWorkAtPriority(i); + for (int j = 0; j < workList.Count; ++j) + { + CECHPWork pWork = workList[j]; + if (matcher.Match(pWork, i, false)) + { + result = pWork; + break; + } + } } - ClearDelayedWork(); + } + if (result == null && GetDelayedWork() != null && matcher.Match(m_Delayed.pWork, m_Delayed.iPriority, true)) + { + result = GetDelayedWork(); + } + return result; + } + + bool InternallyStartWork(int iPriority, CECHPWork pWork) + { + bool bStarted = false; + if (CanRunSimultaneouslyWithCurrentWork(iPriority, pWork)) + { WorkList workList = m_WorkStack[iPriority]; workList.Add(pWork); - m_iCurPriority = iPriority; bStarted = true; + //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started simultaneously, priority=%d", pWork->GetWorkName(), iPriority)); } else { - bool shouldStart = (iPriority >= m_iCurPriority); - FinishWorkAtPriority(iPriority); - WorkList workList = m_WorkStack[iPriority]; - workList.Add(pWork); - if (shouldStart) + if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_DEAD) { - if (iPriority > m_iCurPriority) + for (int i = iPriority; i < Work_priority.NUM_PRIORITY; i++) { - CancelWorkAtPriority(m_iCurPriority); + FinishWorkAtPriority(i); } + ClearDelayedWork(); + WorkList workList = m_WorkStack[iPriority]; + workList.Add(pWork); m_iCurPriority = iPriority; bStarted = true; } + else + { + bool shouldStart = (iPriority >= m_iCurPriority); + FinishWorkAtPriority(iPriority); + WorkList workList = m_WorkStack[iPriority]; + workList.Add(pWork); + if (shouldStart) + { + if (iPriority > m_iCurPriority) + { + CancelWorkAtPriority(m_iCurPriority); + } + m_iCurPriority = iPriority; + bStarted = true; + } + } + //if (bStarted) + //{ + // LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started, priority=%d", pWork->GetWorkName(), iPriority)); + //} + //else + //{ + // LOG_DEBUG_INFO(AString().Format("CECHPWork::%s add to priority queue %d", pWork->GetWorkName(), iPriority)); + //} } - //if (bStarted) - //{ - // LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started, priority=%d", pWork->GetWorkName(), iPriority)); - //} - //else - //{ - // LOG_DEBUG_INFO(AString().Format("CECHPWork::%s add to priority queue %d", pWork->GetWorkName(), iPriority)); - //} + return bStarted; } - return bStarted; - } - bool CanRunSimultaneouslyWithCurrentWork(int iPriority, CECHPWork pWork) - { - if (!ValidatePriority(iPriority) || iPriority != m_iCurPriority) + bool CanRunSimultaneouslyWithCurrentWork(int iPriority, CECHPWork pWork) { - return false; - } - WorkList workList = m_WorkStack[iPriority]; - if (workList == null || workList.Count == 0) - { - return false; - } - - foreach (var work in workList) - { - if (!CanRunSimultaneously(work, pWork)) + if (!ValidatePriority(iPriority) || iPriority != m_iCurPriority) { return false; } - } - return true; - } - bool CanRunSimultaneously(CECHPWork pWork1, CECHPWork pWork2) - { - if (pWork1.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS && - pWork2.GetWorkID() == CECHPWork.Host_work_ID.WORK_SPELLOBJECT) - { - return CanSpellWhileMoving(pWork2 as CECHPWorkSpell); - } - if (pWork2.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS && - pWork1.GetWorkID() == CECHPWork.Host_work_ID.WORK_SPELLOBJECT) - { - return CanSpellWhileMoving(pWork1 as CECHPWorkSpell); - } - return false; - } - bool CanSpellWhileMoving(CECHPWorkSpell pWorkSpell) - { - //return pWorkSpell.GetSkill() - // && CECCastSkillWhenMove::Instance().IsSkillSupported(pWorkSpell->GetSkill()->GetSkillID(), m_pHost); - return false; - } - void StartAwaitingWorks() - { - if (ValidatePriority(m_iCurPriority)) - { - for (--m_iCurPriority; m_iCurPriority >= 0; --m_iCurPriority) + WorkList workList = m_WorkStack[iPriority]; + if (workList == null || workList.Count == 0) { - WorkList workList = m_WorkStack[m_iCurPriority]; - if (workList == null || workList.Count == 0) - { - continue; - } - foreach (var work in workList) - { - work.OnWorkShift(); - //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started by decrease priority, priority=%d", workList[j]->GetWorkName(), m_iCurPriority)); - } - break; + return false; } - } - StartDelayedWork(); - } - void FinishWorkAtPriority(int iPriority) - { - if (!ValidatePriority(iPriority)) - { - return; - } - WorkList workList = m_WorkStack[iPriority]; - while ((workList != null && workList.Count > 0)) - { - KillWork(iPriority, 0); - } - if (m_iCurPriority == iPriority) - { - m_iCurPriority = -1; - } - } - - void KillWork(int iPriority, int index) - { - if (!ValidatePriority(iPriority)) - { - return; - } - WorkList workList = m_WorkStack[iPriority]; - if (index < 0 || index >= workList.Count) - { - return; - } - CECHPWork pWork = workList[index]; - KillWork(pWork); - //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s priority=%d killed", pWork->GetWorkName(), iPriority)); - //delete pWork; - workList.RemoveAt(index); - } - void KillWork(CECHPWork pWork) - { - if (pWork == null) - { - return; - } - if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS) - { - CECHPWorkMove pWorkMove = pWork as CECHPWorkMove; - if (pWorkMove != null) + foreach (var work in workList) { - if (pWorkMove.GetAutoMove()) - { - //pWorkMove.Finish(); - } - else - { - pWorkMove.Cancel(); - } - } - } - else - { - pWork.Cancel(); - } - } - - public void CancelWork(CECHPWork pWork) - { - - } - public void CancelWorkAtPriority(int iPriority) - { - - } - - public bool DelayWork(int iPriority, CECHPWork pWork) - { - return false; - } - public void StartDelayedWork() - { - - } - public void ClearDelayedWork() - { - - } - public CECHPWork GetDelayedWork() - { - return m_Delayed.pWork; - } - - public bool ValidatePriority(int iPriority) - { - return iPriority >= 0 && iPriority < Work_priority.NUM_PRIORITY; - } - - public bool StartWork(int iPriority, CECHPWork pWork, bool bNoDelay = false) - { - if (pWork == null) - { - return false; - } - if (!ValidatePriority(iPriority)) - { - return false; - } - //if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_TRACEOBJECT) - //{ - // if (g_pGame->GetGameRun()->GetHostInputFilter()->IsMoveUsagePressed()) - // { - // CECHPWorkTrace pWorkTrace = pWork as CECHPWorkTrace; - // if (!pWorkTrace.CanTouch()) - // { // 2014-8-16 当还在通过键盘操纵移动时、有条件忽略 CECHPWorkTrace, - // //delete pWorkTrace; // 否则会因 CECHPWorkTrace 中临时转向目标位置、而后又被键盘操纵调整移动方向导致方向瞬间抖动 - // return false; // 当 CECHPWorkTrace 中目标可立即接触时,不忽略 CECHPWorkTrace,以实现键盘控制移动中、对某怪应用技能时,立刻转向怪施放技能 - // } - // } - //} - if (!bNoDelay && DelayWork(iPriority, pWork)) - { - return true; - } - return InternallyStartWork(iPriority, pWork); - } - public bool StartWork_p0(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_0, pWork, bNoDelay); } - public bool StartWork_p1(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_1, pWork, bNoDelay); } - public bool StartWork_p2(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_2, pWork, bNoDelay); } - public CECHostPlayer GetHostPlayer() { return m_pHost; } - - public CECHPWork CreateWork(int idWork) - { - CECHPWork pWork = null; - - switch (idWork) - { - //case CECHPWork.Host_work_ID.WORK_STAND: pWork = new CECHPWorkStand(this); break; - case CECHPWork.Host_work_ID.WORK_MOVETOPOS: pWork = new CECHPWorkMove(this); break; - case CECHPWork.Host_work_ID.WORK_TRACEOBJECT: pWork = new CECHPWorkTrace(this); break; - case CECHPWork.Host_work_ID.WORK_HACKOBJECT: pWork = new CECHPWorkMelee(this); break; - case CECHPWork.Host_work_ID.WORK_SPELLOBJECT: pWork = new CECHPWorkSpell(this); break; - //case CECHPWork.Host_work_ID.WORK_USEITEM: pWork = new CECHPWorkUse(this); break; - //case CECHPWork.Host_work_ID.WORK_DEAD: pWork = new CECHPWorkDead(this); break; - //case CECHPWork.Host_work_ID.WORK_FOLLOW: pWork = new CECHPWorkFollow(this); break; - //case CECHPWork.Host_work_ID.WORK_FLYOFF: pWork = new CECHPWorkFly(this); break; - //case CECHPWork.Host_work_ID.WORK_FREEFALL: pWork = new CECHPWorkFall(this); break; - //case CECHPWork.Host_work_ID.WORK_SIT: pWork = new CECHPWorkSit(this); break; - //case CECHPWork.Host_work_ID.WORK_PICKUP: pWork = new CECHPWorkPick(this); break; - //case CECHPWork.Host_work_ID.WORK_CONCENTRATE: pWork = new CECHPWorkConcentrate(this); break; - //case CECHPWork.Host_work_ID.WORK_REVIVE: pWork = new CECHPWorkRevive(this); break; - //case CECHPWork.Host_work_ID.WORK_FLASHMOVE: pWork = new CECHPWorkFMove(this); break; - //case CECHPWork.Host_work_ID.WORK_BEBOUND: pWork = new CECHPWorkBeBound(this); break; - //case CECHPWork.Host_work_ID.WORK_PASSIVEMOVE: pWork = new CECHPWorkPassiveMove(this); break; - //case CECHPWork.Host_work_ID.WORK_CONGREGATE: pWork = new CECHPWorkCongregate(this); break; - //case CECHPWork.Host_work_ID.WORK_SKILLSTATEACT: pWork = new CECHPWorkSkillStateAction(this); break; - //case CECHPWork.Host_work_ID.WORK_FORCENAVIGATEMOVE: pWork = new CECHPWorkNavigate(this); break; - default: - return null; - } - - return pWork; - } - - public bool CanStartWork(int iWorkID, int iPriority = CECHPWorkMan.Work_priority.PRIORITY_1) - { - if (!ValidatePriority(iPriority)) - { - return false; - } - if (GetWork(iWorkID) != null) - { - return false; - } - if (!HasWorkOnPriority(iPriority)) - { - return true; - } - WorkList workList = m_WorkStack[iPriority]; - if (workList != null) - { - for (int i = 0; i < workList.Count; ++i) - { - if (!workList[i].CanTransferTo(CECHPWork.GetWorkMask(iWorkID))) + if (!CanRunSimultaneously(work, pWork)) { return false; } } + return true; } - return true; - } - - bool HasWorkOnPriority(int iPriority) - { - return ValidatePriority(iPriority) && m_WorkStack[iPriority] != null && m_WorkStack[iPriority].Count != 0; - } - - public void SetPostTickCommand(CECHPWorkPostTickCommand command) - { - m_pPostTickCommand = command; - } - - public bool HasWorkRunningOnPriority(int iPriority) - { - return HasWorkOnPriority(iPriority); - } - bool IsAnyWorkRunning() - { - return HasWorkRunningOnPriority(m_iCurPriority); - } - - public void Tick(float dwDeltaTime) - { - if (!IsAnyWorkRunning()) + bool CanRunSimultaneously(CECHPWork pWork1, CECHPWork pWork2) { - return; - } - WorkList workList = m_WorkStack[m_iCurPriority]; - for (int i = 0; i < workList.Count;) - { - CECHPWork pWork = workList[i]; - - SetPostTickCommand(null); - pWork.Tick(dwDeltaTime); - - if (m_pPostTickCommand == null) + if (pWork1.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS && + pWork2.GetWorkID() == CECHPWork.Host_work_ID.WORK_SPELLOBJECT) { - if (!pWork.IsFinished()) + return CanSpellWhileMoving(pWork2 as CECHPWorkSpell); + } + if (pWork2.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS && + pWork1.GetWorkID() == CECHPWork.Host_work_ID.WORK_SPELLOBJECT) + { + return CanSpellWhileMoving(pWork1 as CECHPWorkSpell); + } + return false; + } + bool CanSpellWhileMoving(CECHPWorkSpell pWorkSpell) + { + //return pWorkSpell.GetSkill() + // && CECCastSkillWhenMove::Instance().IsSkillSupported(pWorkSpell->GetSkill()->GetSkillID(), m_pHost); + return false; + } + void StartAwaitingWorks() + { + if (ValidatePriority(m_iCurPriority)) + { + for (--m_iCurPriority; m_iCurPriority >= 0; --m_iCurPriority) { - ++i; - continue; + WorkList workList = m_WorkStack[m_iCurPriority]; + if (workList == null || workList.Count == 0) + { + continue; + } + foreach (var work in workList) + { + work.OnWorkShift(); + //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started by decrease priority, priority=%d", workList[j]->GetWorkName(), m_iCurPriority)); + } + break; + } + } + StartDelayedWork(); + } + + void FinishWorkAtPriority(int iPriority) + { + if (!ValidatePriority(iPriority)) + { + return; + } + WorkList workList = m_WorkStack[iPriority]; + while ((workList != null && workList.Count > 0)) + { + KillWork(iPriority, 0); + } + if (m_iCurPriority == iPriority) + { + m_iCurPriority = -1; + } + } + + void KillWork(int iPriority, int index) + { + if (!ValidatePriority(iPriority)) + { + return; + } + WorkList workList = m_WorkStack[iPriority]; + if (index < 0 || index >= workList.Count) + { + return; + } + CECHPWork pWork = workList[index]; + KillWork(pWork); + //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s priority=%d killed", pWork->GetWorkName(), iPriority)); + //delete pWork; + workList.RemoveAt(index); + } + void KillWork(CECHPWork pWork) + { + if (pWork == null) + { + return; + } + if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS) + { + CECHPWorkMove pWorkMove = pWork as CECHPWorkMove; + if (pWorkMove != null) + { + if (pWorkMove.GetAutoMove()) + { + //pWorkMove.Finish(); + } + else + { + pWorkMove.Cancel(); + } } - KillWork(m_iCurPriority, i); } else { - m_pPostTickCommand.Run(this); - SetPostTickCommand(null); - break; // 不确定 m_pPostTickCommand 执行什么内容,此处跳出 + pWork.Cancel(); } } - if (workList.Count == 0) + + public void CancelWork(CECHPWork pWork) { - StartAwaitingWorks(); + } - } -} + public void CancelWorkAtPriority(int iPriority) + { -public abstract class CECHPWorkPostTickCommand -{ - public abstract bool Run(CECHPWorkMan pWorkMan); -}; + } -public abstract class CECHPWorkMatcher -{ - public abstract bool Match(CECHPWork pWork, int priority, bool isDelayWork); -}; - -public class CECHPWorkGeneralMatcher : CECHPWorkMatcher -{ - int m_workID; - int m_priority; - bool m_matchDelayedWork; - - public override bool Match(CECHPWork pWork, int priority, bool isDelayWork) - { - return pWork != null - && pWork.GetWorkID() == m_workID - && priority == m_priority - && isDelayWork == m_matchDelayedWork; - } - - public CECHPWorkGeneralMatcher(int workID, int priority, bool bIncludeDelayedWork) - { - m_workID = workID; - m_priority = priority; - m_matchDelayedWork = bIncludeDelayedWork; - } -} - -public class CECHPWorkPostTickRunWorkCommand : CECHPWorkPostTickCommand -{ - CECHPWork m_pWork; - int m_iPriority; - bool m_bNoDelay; - bool m_bShouldTick; - uint m_dwTickTime; - - // Constructor - public CECHPWorkPostTickRunWorkCommand( - CECHPWork pWork, - bool bNoDelay = false, - int iPriority = CECHPWorkMan.Work_priority.PRIORITY_1, - bool bShouldTick = false, - uint dwTickTime = 0) - { - m_pWork = pWork; - m_bNoDelay = bNoDelay; - m_iPriority = iPriority; - m_bShouldTick = bShouldTick; - m_dwTickTime = dwTickTime; - } - - public override bool Run(CECHPWorkMan pWorkMan) - { - if (m_pWork == null || pWorkMan == null) + public bool DelayWork(int iPriority, CECHPWork pWork) { return false; } - if (!pWorkMan.StartWork(m_iPriority, m_pWork, m_bNoDelay)) + public void StartDelayedWork() { + + } + public void ClearDelayedWork() + { + + } + public CECHPWork GetDelayedWork() + { + return m_Delayed.pWork; + } + + public bool ValidatePriority(int iPriority) + { + return iPriority >= 0 && iPriority < Work_priority.NUM_PRIORITY; + } + + public bool StartWork(int iPriority, CECHPWork pWork, bool bNoDelay = false) + { + if (pWork == null) + { + return false; + } + if (!ValidatePriority(iPriority)) + { + return false; + } + //if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_TRACEOBJECT) + //{ + // if (g_pGame->GetGameRun()->GetHostInputFilter()->IsMoveUsagePressed()) + // { + // CECHPWorkTrace pWorkTrace = pWork as CECHPWorkTrace; + // if (!pWorkTrace.CanTouch()) + // { // 2014-8-16 当还在通过键盘操纵移动时、有条件忽略 CECHPWorkTrace, + // //delete pWorkTrace; // 否则会因 CECHPWorkTrace 中临时转向目标位置、而后又被键盘操纵调整移动方向导致方向瞬间抖动 + // return false; // 当 CECHPWorkTrace 中目标可立即接触时,不忽略 CECHPWorkTrace,以实现键盘控制移动中、对某怪应用技能时,立刻转向怪施放技能 + // } + // } + //} + if (!bNoDelay && DelayWork(iPriority, pWork)) + { + return true; + } + return InternallyStartWork(iPriority, pWork); + } + public bool StartWork_p0(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_0, pWork, bNoDelay); } + public bool StartWork_p1(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_1, pWork, bNoDelay); } + public bool StartWork_p2(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_2, pWork, bNoDelay); } + public CECHostPlayer GetHostPlayer() { return m_pHost; } + + public CECHPWork CreateWork(int idWork) + { + CECHPWork pWork = null; + + switch (idWork) + { + //case CECHPWork.Host_work_ID.WORK_STAND: pWork = new CECHPWorkStand(this); break; + case CECHPWork.Host_work_ID.WORK_MOVETOPOS: pWork = new CECHPWorkMove(this); break; + case CECHPWork.Host_work_ID.WORK_TRACEOBJECT: pWork = new CECHPWorkTrace(this); break; + case CECHPWork.Host_work_ID.WORK_HACKOBJECT: pWork = new CECHPWorkMelee(this); break; + case CECHPWork.Host_work_ID.WORK_SPELLOBJECT: pWork = new CECHPWorkSpell(this); break; + //case CECHPWork.Host_work_ID.WORK_USEITEM: pWork = new CECHPWorkUse(this); break; + //case CECHPWork.Host_work_ID.WORK_DEAD: pWork = new CECHPWorkDead(this); break; + //case CECHPWork.Host_work_ID.WORK_FOLLOW: pWork = new CECHPWorkFollow(this); break; + //case CECHPWork.Host_work_ID.WORK_FLYOFF: pWork = new CECHPWorkFly(this); break; + //case CECHPWork.Host_work_ID.WORK_FREEFALL: pWork = new CECHPWorkFall(this); break; + //case CECHPWork.Host_work_ID.WORK_SIT: pWork = new CECHPWorkSit(this); break; + //case CECHPWork.Host_work_ID.WORK_PICKUP: pWork = new CECHPWorkPick(this); break; + //case CECHPWork.Host_work_ID.WORK_CONCENTRATE: pWork = new CECHPWorkConcentrate(this); break; + //case CECHPWork.Host_work_ID.WORK_REVIVE: pWork = new CECHPWorkRevive(this); break; + //case CECHPWork.Host_work_ID.WORK_FLASHMOVE: pWork = new CECHPWorkFMove(this); break; + //case CECHPWork.Host_work_ID.WORK_BEBOUND: pWork = new CECHPWorkBeBound(this); break; + //case CECHPWork.Host_work_ID.WORK_PASSIVEMOVE: pWork = new CECHPWorkPassiveMove(this); break; + //case CECHPWork.Host_work_ID.WORK_CONGREGATE: pWork = new CECHPWorkCongregate(this); break; + //case CECHPWork.Host_work_ID.WORK_SKILLSTATEACT: pWork = new CECHPWorkSkillStateAction(this); break; + //case CECHPWork.Host_work_ID.WORK_FORCENAVIGATEMOVE: pWork = new CECHPWorkNavigate(this); break; + default: + return null; + } + + return pWork; + } + + public bool CanStartWork(int iWorkID, int iPriority = CECHPWorkMan.Work_priority.PRIORITY_1) + { + if (!ValidatePriority(iPriority)) + { + return false; + } + if (GetWork(iWorkID) != null) + { + return false; + } + if (!HasWorkOnPriority(iPriority)) + { + return true; + } + WorkList workList = m_WorkStack[iPriority]; + if (workList != null) + { + for (int i = 0; i < workList.Count; ++i) + { + if (!workList[i].CanTransferTo(CECHPWork.GetWorkMask(iWorkID))) + { + return false; + } + } + } + return true; + } + + bool HasWorkOnPriority(int iPriority) + { + return ValidatePriority(iPriority) && m_WorkStack[iPriority] != null && m_WorkStack[iPriority].Count != 0; + } + + public void SetPostTickCommand(CECHPWorkPostTickCommand command) + { + m_pPostTickCommand = command; + } + + public bool HasWorkRunningOnPriority(int iPriority) + { + return HasWorkOnPriority(iPriority); + } + bool IsAnyWorkRunning() + { + return HasWorkRunningOnPriority(m_iCurPriority); + } + + public void Tick(float dwDeltaTime) + { + if (!IsAnyWorkRunning()) + { + return; + } + WorkList workList = m_WorkStack[m_iCurPriority]; + for (int i = 0; i < workList.Count;) + { + CECHPWork pWork = workList[i]; + + SetPostTickCommand(null); + pWork.Tick(dwDeltaTime); + + if (m_pPostTickCommand == null) + { + if (!pWork.IsFinished()) + { + ++i; + continue; + } + KillWork(m_iCurPriority, i); + } + else + { + m_pPostTickCommand.Run(this); + SetPostTickCommand(null); + break; // 不确定 m_pPostTickCommand 执行什么内容,此处跳出 + } + } + if (workList.Count == 0) + { + StartAwaitingWorks(); + } + } + } + + public abstract class CECHPWorkPostTickCommand + { + public abstract bool Run(CECHPWorkMan pWorkMan); + }; + + public abstract class CECHPWorkMatcher + { + public abstract bool Match(CECHPWork pWork, int priority, bool isDelayWork); + }; + + public class CECHPWorkGeneralMatcher : CECHPWorkMatcher + { + int m_workID; + int m_priority; + bool m_matchDelayedWork; + + public override bool Match(CECHPWork pWork, int priority, bool isDelayWork) + { + return pWork != null + && pWork.GetWorkID() == m_workID + && priority == m_priority + && isDelayWork == m_matchDelayedWork; + } + + public CECHPWorkGeneralMatcher(int workID, int priority, bool bIncludeDelayedWork) + { + m_workID = workID; + m_priority = priority; + m_matchDelayedWork = bIncludeDelayedWork; + } + } + + public class CECHPWorkPostTickRunWorkCommand : CECHPWorkPostTickCommand + { + CECHPWork m_pWork; + int m_iPriority; + bool m_bNoDelay; + bool m_bShouldTick; + uint m_dwTickTime; + + // Constructor + public CECHPWorkPostTickRunWorkCommand( + CECHPWork pWork, + bool bNoDelay = false, + int iPriority = CECHPWorkMan.Work_priority.PRIORITY_1, + bool bShouldTick = false, + uint dwTickTime = 0) + { + m_pWork = pWork; + m_bNoDelay = bNoDelay; + m_iPriority = iPriority; + m_bShouldTick = bShouldTick; + m_dwTickTime = dwTickTime; + } + + public override bool Run(CECHPWorkMan pWorkMan) + { + if (m_pWork == null || pWorkMan == null) + { + return false; + } + if (!pWorkMan.StartWork(m_iPriority, m_pWork, m_bNoDelay)) + { + m_pWork = null; + return false; + } + if (m_bShouldTick) + { + m_pWork.Tick(m_dwTickTime); + } m_pWork = null; - return false; + return true; } - if (m_bShouldTick) - { - m_pWork.Tick(m_dwTickTime); - } - m_pWork = null; - return true; - } -}; + }; +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs index a9f954569f..dcc50c915b 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs @@ -1,5 +1,7 @@ using BrewMonster; +using BrewMonster.Managers; using BrewMonster.Network; +using BrewMonster.Scripts; using CSNetwork.GPDataType; using PerfectWorld.Scripts.Managers; using PerfectWorld.Scripts.Player; diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs index 318949b4b4..14ad942f18 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs @@ -1,367 +1,370 @@ using CSNetwork.GPDataType; using UnityEngine; -public class CECHPWorkMove : CECHPWork +namespace BrewMonster.Scripts { - public static class Types + public class CECHPWorkMove : CECHPWork { - public const int DEST_2D = 0, - DEST_3D = 1, - DEST_DIR = 2, - DEST_PUSH = 3, - DEST_STANDJUMP = 4, - DEST_AUTOPF = 5; // Movement type - } - - protected A3DVECTOR3 m_vMoveDest; // Move destination position or direction - protected int m_iDestType; // Destination type - protected bool m_bHaveDest; // true, have destination - protected bool m_bMeetSlide; // true, meet slide - protected A3DVECTOR3 m_vCurDir; // Current move direction - protected bool m_bReadyCancel; // true, ready to cancel - protected bool m_bGliding; // glide - protected float m_fGlideTime; - protected float m_fGlideSpan; - protected float m_fGlideAng; - protected float m_fGlideVel; // glide angular vel - protected float m_fGlidePitch; // glide pitch angle - protected float m_fCurPitch; - protected float m_fPushPitch; - protected float m_fPushLean; - - protected bool m_bUseAutoMoveDialog; // Auto move - protected float m_fAutoHeight; // Height of auto moving destination - protected bool m_bAutoLand; // Auto land when arrive at destination - protected bool m_bAutoFly; // Auto fly - protected bool m_bReachedHeight;// Player reached specified height - protected bool m_bAutoFlyPending; // Mark whether a fly command had been executed - - protected int m_iNPCTempleId; - protected int m_iTaskId; - protected bool m_bSwitchTo2D; - - protected bool m_bResetAutoPF; - - public CECHPWorkMove(CECHPWorkMan pWorkMan) : base (Host_work_ID.WORK_MOVETOPOS, pWorkMan) - { - m_dwMask = Work_mask.MASK_MOVETOPOS; - m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_TRACEOBJECT | Work_mask.MASK_FOLLOW; - Reset(); - } - - public CECHPWorkMove(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan) - { - } - - // Set destination position or direction - public void SetDestination(int iDestType, A3DVECTOR3 vMoveDest) - { - m_iDestType = iDestType; - m_vMoveDest = vMoveDest; - m_bHaveDest = true; - m_bGliding = false; - //m_pHost->SetAdjustOrient(false); // 2014-9-10 徐文彬:在 CECHPWorkMove 创建的时候都会调用此函数,会导致其它时机通过 SetDestDirAndUp 调用对人物的朝向调整失效。 - // 重现方法为:月仙“望月咏”技能释放后、马上按住'A'或'D'等移动键并摁住不放,将导致人物施法方向偏离目标而朝向移动方向(需多次尝试) - - //清空任务信息 - m_iTaskId = 0; - m_iNPCTempleId = 0; - ResetUseAutoPF(); - - if (iDestType == Types.DEST_DIR) + public static class Types { - m_vCurDir = vMoveDest; - if (m_bUseAutoMoveDialog) + public const int DEST_2D = 0, + DEST_3D = 1, + DEST_DIR = 2, + DEST_PUSH = 3, + DEST_STANDJUMP = 4, + DEST_AUTOPF = 5; // Movement type + } + + protected A3DVECTOR3 m_vMoveDest; // Move destination position or direction + protected int m_iDestType; // Destination type + protected bool m_bHaveDest; // true, have destination + protected bool m_bMeetSlide; // true, meet slide + protected A3DVECTOR3 m_vCurDir; // Current move direction + protected bool m_bReadyCancel; // true, ready to cancel + protected bool m_bGliding; // glide + protected float m_fGlideTime; + protected float m_fGlideSpan; + protected float m_fGlideAng; + protected float m_fGlideVel; // glide angular vel + protected float m_fGlidePitch; // glide pitch angle + protected float m_fCurPitch; + protected float m_fPushPitch; + protected float m_fPushLean; + + protected bool m_bUseAutoMoveDialog; // Auto move + protected float m_fAutoHeight; // Height of auto moving destination + protected bool m_bAutoLand; // Auto land when arrive at destination + protected bool m_bAutoFly; // Auto fly + protected bool m_bReachedHeight;// Player reached specified height + protected bool m_bAutoFlyPending; // Mark whether a fly command had been executed + + protected int m_iNPCTempleId; + protected int m_iTaskId; + protected bool m_bSwitchTo2D; + + protected bool m_bResetAutoPF; + + public CECHPWorkMove(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_MOVETOPOS, pWorkMan) + { + m_dwMask = Work_mask.MASK_MOVETOPOS; + m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_TRACEOBJECT | Work_mask.MASK_FOLLOW; + Reset(); + } + + public CECHPWorkMove(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan) + { + } + + // Set destination position or direction + public void SetDestination(int iDestType, A3DVECTOR3 vMoveDest) + { + m_iDestType = iDestType; + m_vMoveDest = vMoveDest; + m_bHaveDest = true; + m_bGliding = false; + //m_pHost->SetAdjustOrient(false); // 2014-9-10 徐文彬:在 CECHPWorkMove 创建的时候都会调用此函数,会导致其它时机通过 SetDestDirAndUp 调用对人物的朝向调整失效。 + // 重现方法为:月仙“望月咏”技能释放后、马上按住'A'或'D'等移动键并摁住不放,将导致人物施法方向偏离目标而朝向移动方向(需多次尝试) + + //清空任务信息 + m_iTaskId = 0; + m_iNPCTempleId = 0; + ResetUseAutoPF(); + + if (iDestType == Types.DEST_DIR) { - m_bUseAutoMoveDialog = false; - m_bAutoLand = false; - m_fAutoHeight = -1.0f; - m_bAutoFly = false; - m_bReachedHeight = true; - m_bAutoFlyPending = false; + m_vCurDir = vMoveDest; + if (m_bUseAutoMoveDialog) + { + m_bUseAutoMoveDialog = false; + m_bAutoLand = false; + m_fAutoHeight = -1.0f; + m_bAutoFly = false; + m_bReachedHeight = true; + m_bAutoFlyPending = false; + } } - } - else if (iDestType == Types.DEST_2D || iDestType == Types.DEST_3D) - { - m_vCurDir = vMoveDest - new A3DVECTOR3(m_pHost.transform.position.x, m_pHost.transform.position.y, m_pHost.transform.position.z); - m_vCurDir.y = 0.0f; - m_vCurDir.Normalize(); - } - else if (IsAutoPF()) - { + else if (iDestType == Types.DEST_2D || iDestType == Types.DEST_3D) + { + m_vCurDir = vMoveDest - new A3DVECTOR3(m_pHost.transform.position.x, m_pHost.transform.position.y, m_pHost.transform.position.z); + m_vCurDir.y = 0.0f; + m_vCurDir.Normalize(); + } + else if (IsAutoPF()) + { + // TO DO: fix later + //m_vCurDir = CECIntelligentRoute::Instance().GetCurDest() - m_pHost->GetPos(); + //m_vCurDir.y = 0.0f; + //m_vCurDir.Normalize(); + //if (m_bUseAutoMoveDialog) + //{ + // // 此处禁用 m_bUseAutoMoveDialog,见 SetUseAutoMoveDialog 中说明 + // m_bUseAutoMoveDialog = false; + // m_bAutoLand = false; + // m_fAutoHeight = -1.0f; + // m_bAutoFly = false; + // m_bReachedHeight = true; + // m_bAutoFlyPending = false; + //} + } + // TO DO: fix later - //m_vCurDir = CECIntelligentRoute::Instance().GetCurDest() - m_pHost->GetPos(); - //m_vCurDir.y = 0.0f; - //m_vCurDir.Normalize(); - //if (m_bUseAutoMoveDialog) + //if (m_pHost.m_pMoveTargetGFX) //{ - // // 此处禁用 m_bUseAutoMoveDialog,见 SetUseAutoMoveDialog 中说明 - // m_bUseAutoMoveDialog = false; - // m_bAutoLand = false; - // m_fAutoHeight = -1.0f; - // m_bAutoFly = false; - // m_bReachedHeight = true; - // m_bAutoFlyPending = false; + // if (iDestType != DEST_PUSH) + // m_pHost.m_pMoveTargetGFX.Stop(); //} } - // TO DO: fix later - //if (m_pHost.m_pMoveTargetGFX) - //{ - // if (iDestType != DEST_PUSH) - // m_pHost.m_pMoveTargetGFX.Stop(); - //} - } + void ResetUseAutoPF() + { + m_bResetAutoPF = true; + } - void ResetUseAutoPF() - { - m_bResetAutoPF = true; - } + // Tick routine + public virtual bool Tick(float dwDeltaTime) + { + //UpdateResetUseAutoPF(); + //if (m_bSwitchTo2D) + //{ + // SwitchToDest2D(); + // m_bSwitchTo2D = false; + // return true; + //} + //if (IsAutoPF()) + //{ + // if (CECIntelligentRoute::Instance().IsIdle()) + // { + // // 智能寻路模式未成功时,等待下个 Tick 切换到 DEST_2D 模式 + // return true; + // } + // if (m_pHost.IsFlying()) + // { + // // 中途切换到飞行模式时,切换到 DEST_2D 模式 + // CECIntelligentRoute::Instance().ResetSearch(); + // m_bSwitchTo2D = true; + // return true; + // } + //} - // Tick routine - public virtual bool Tick(float dwDeltaTime) - { - //UpdateResetUseAutoPF(); - //if (m_bSwitchTo2D) - //{ - // SwitchToDest2D(); - // m_bSwitchTo2D = false; - // return true; - //} - //if (IsAutoPF()) - //{ - // if (CECIntelligentRoute::Instance().IsIdle()) - // { - // // 智能寻路模式未成功时,等待下个 Tick 切换到 DEST_2D 模式 - // return true; - // } - // if (m_pHost.IsFlying()) - // { - // // 中途切换到飞行模式时,切换到 DEST_2D 模式 - // CECIntelligentRoute::Instance().ResetSearch(); - // m_bSwitchTo2D = true; - // return true; - // } - //} + //base.Tick(dwDeltaTime); - //base.Tick(dwDeltaTime); + //if (m_pHost.IsRooting()) + // return true; - //if (m_pHost.IsRooting()) - // return true; + //if (m_bUseAutoMoveDialog) + //{ + // if (m_pHost.IsFlying()) + // { + // m_bAutoFly = false; + // m_bAutoFlyPending = false; + // } - //if (m_bUseAutoMoveDialog) - //{ - // if (m_pHost.IsFlying()) - // { - // m_bAutoFly = false; - // m_bAutoFlyPending = false; - // } + // if (m_bAutoFly && !m_bAutoFlyPending && !m_pHost.IsFlying()) + // { + // if (m_pHost.CmdFly()) + // { + // m_bAutoFly = false; + // m_bAutoFlyPending = true; + // } + // } + //} + //else + //{ + // // Make sure 'Win_AutoPlay' dialog doesn't show up + // CECGameUIMan pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan(); + // pGameUI.AutoMoveShowDialog(false); + //} - // if (m_bAutoFly && !m_bAutoFlyPending && !m_pHost.IsFlying()) - // { - // if (m_pHost.CmdFly()) - // { - // m_bAutoFly = false; - // m_bAutoFlyPending = true; - // } - // } - //} - //else - //{ - // // Make sure 'Win_AutoPlay' dialog doesn't show up - // CECGameUIMan pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan(); - // pGameUI.AutoMoveShowDialog(false); - //} + ////寻路过程中找到NPC对象转为WorkTrace状态 + //if ((m_vMoveDest - m_pHost.GetPos()).MagnitudeH() <= 5.0f) + //{ + // if (m_iNPCTempleId) + // { + // CECNPC pNPC = g_pGame.GetGameRun().GetWorld().GetNPCMan().FindNPCByTempleID(m_iNPCTempleId); + // if (pNPC && m_pHost.SelectTarget(pNPC->GetNPCID())) + // { + // CECHPWorkTrace pWork = m_pWorkMan.CreateNPCTraceWork(pNPC, m_iTaskId); + // if (pWork) + // { + // m_bAutoLand = false; //防止飞行状态寻路结束,转到worktrace之前自动着陆,进入workfall。 + // Finish(); + // m_pWorkMan.SetPostTickCommand(new CECHPWorkPostTickRunWorkCommand(pWork, true)); + // return true; + // } + // } + // } + //} - ////寻路过程中找到NPC对象转为WorkTrace状态 - //if ((m_vMoveDest - m_pHost.GetPos()).MagnitudeH() <= 5.0f) - //{ - // if (m_iNPCTempleId) - // { - // CECNPC pNPC = g_pGame.GetGameRun().GetWorld().GetNPCMan().FindNPCByTempleID(m_iNPCTempleId); - // if (pNPC && m_pHost.SelectTarget(pNPC->GetNPCID())) - // { - // CECHPWorkTrace pWork = m_pWorkMan.CreateNPCTraceWork(pNPC, m_iTaskId); - // if (pWork) - // { - // m_bAutoLand = false; //防止飞行状态寻路结束,转到worktrace之前自动着陆,进入workfall。 - // Finish(); - // m_pWorkMan.SetPostTickCommand(new CECHPWorkPostTickRunWorkCommand(pWork, true)); - // return true; - // } - // } - // } - //} + //float fDeltaTime = dwDeltaTime; + //if (m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_GROUND || + // m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_WATER && m_pHost.IsJumping() && (m_pHost.m_CDRInfo.vAbsVelocity.y > 0 || m_pHost.m_CDRInfo.fYVel > 0)) + //{ + // // Play appropriate actions + // if (!m_pHost.IsJumping() && !m_pHost.IsPlayingAction(CECPlayer::ACT_TRICK_RUN) && + // m_pHost.m_iMoveMode != CECPlayer::MOVE_SLIDE && !m_bMeetSlide) + // { + // int iAction = m_pHost->GetMoveStandAction(true); + // m_pHost.PlayAction(iAction, false); + // } - //float fDeltaTime = dwDeltaTime; - //if (m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_GROUND || - // m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_WATER && m_pHost.IsJumping() && (m_pHost.m_CDRInfo.vAbsVelocity.y > 0 || m_pHost.m_CDRInfo.fYVel > 0)) - //{ - // // Play appropriate actions - // if (!m_pHost.IsJumping() && !m_pHost.IsPlayingAction(CECPlayer::ACT_TRICK_RUN) && - // m_pHost.m_iMoveMode != CECPlayer::MOVE_SLIDE && !m_bMeetSlide) - // { - // int iAction = m_pHost->GetMoveStandAction(true); - // m_pHost.PlayAction(iAction, false); - // } + // Tick_Walk(fDeltaTime); + //} + //else // (m_pHost->m_iMoveEnv == CECPlayer::MOVEENV_AIR || m_pHost->m_iMoveEnv == CECPlayer::MOVEENV_WATER) + //{ + // m_pHost->ResetJump(); - // Tick_Walk(fDeltaTime); - //} - //else // (m_pHost->m_iMoveEnv == CECPlayer::MOVEENV_AIR || m_pHost->m_iMoveEnv == CECPlayer::MOVEENV_WATER) - //{ - // m_pHost->ResetJump(); + // // Play appropriate actions + // if (!m_bGliding) + // { + // int iAction = m_pHost.GetMoveStandAction(true); + // m_pHost.PlayAction(iAction, false); + // } - // // Play appropriate actions - // if (!m_bGliding) - // { - // int iAction = m_pHost.GetMoveStandAction(true); - // m_pHost.PlayAction(iAction, false); - // } + // Tick_FlySwim(fDeltaTime); + //} - // Tick_FlySwim(fDeltaTime); - //} + return true; + } + // Reset work + public virtual void Reset() + { - return true; - } - // Reset work - public virtual void Reset() - { + } + // Work is cancel + public virtual void Cancel() + { + + } + + // This work is do player moving ? + public virtual bool IsMoving() { return true; } + // Copy work data + public virtual bool CopyData(CECHPWork pWork) + { + return true; + } + + // Play move target effect + public void PlayMoveTargetGFX(A3DVECTOR3 vPos, A3DVECTOR3 vNormal) + { + + } + + // User press cancel button + public void PressCancel() { m_bReadyCancel = true; } + + public void SetUseAutoMoveDialog(bool bUseAutoMoveDialog) + { + + } + public bool GetUseAutoMoveDialog() { return m_bUseAutoMoveDialog; } + public bool GetAutoMove() + { + return true; + } + + void SetAutoLand(bool bAutoLand) { m_bAutoLand = bAutoLand; } + bool GetAutoLand() { return m_bAutoLand; } + + void SetAutoHeight(float fHeight) { m_fAutoHeight = fHeight; m_bAutoFly = true; m_bReachedHeight = false; } + float GetAutoHeight() { return m_fAutoHeight; } + bool IsAutoFly() { return m_bAutoFly; } + + bool IsAutoPF() { return m_iDestType == Types.DEST_AUTOPF; } + + // Finish work + void Finish() + { + + } + + void SetTaskNPCInfo(int tid, int taskid) + { + + } + + void SwitchToDest2D() + { + //int tid, taskid; + //tid = m_iNPCTempleId; + //taskid = m_iTaskId; + //CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan(); + //pGameUI->SetAutoMoveShowDialogTarget((int)m_vMoveDest.x, (int)m_vMoveDest.z); + //SetDestination(CECHPWorkMove::DEST_2D, m_vMoveDest); + //SetTaskNPCInfo(tid, taskid); + //SetUseAutoMoveDialog(true); + } + // On first tick + protected virtual void OnFirstTick() + { + + } + + // Tick routine of walking on ground + protected bool Tick_Walk(float fDeltaTime) + { + return true; + } + // Tick routine of flying or swimming + protected bool Tick_FlySwim(float fDeltaTime) + { + return true; + } + // Start gliding + protected void Glide(float fMoveTime, A3DVECTOR3 vMoveDirH, float fDeltaTime, bool bFly) + { + + } + + // Calculate vertical speed when fly or swim + protected float CalcFlySwimVertSpeed(float fSpeed1, float fPushDir, float fPushAccel, float fDeltaTime) + { + return 0; + } + + protected void ClearResetUseAutoPF() + { + + } + protected void UpdateResetUseAutoPF() + { + // if (!m_bResetAutoPF) + // { + // return; + // } + // CECIntelligentRoute::Instance().SetUsage(CECIntelligentRoute::enumUsageWorkMove); + // CECIntelligentRoute::Instance().ResetSearch(); + // if (m_iDestType == DEST_2D || m_iDestType == DEST_3D) + // { + //# ifdef SHOW_AUTOMOVE_FOOTPRINTS + // g_AutoPFFollowPoints.clear(); + // g_AutoPFPathPoints.clear(); + //#endif + // } + // else if (IsAutoPF()) + // { + // bool bSwitchTo2D(true); + // while (true) + // { + // if (m_pHost->IsFlying()) + // { + // break; + // } + // CECHostBrushTest brushTester(m_pHost->GetPos(), m_pHost->m_CDRInfo.vExtent, m_pHost->m_CDRInfo.fStepHeight); + // if (CECIntelligentRoute::Instance().Search(m_pHost->GetPos(), m_vMoveDest, &brushTester) != CECIntelligentRoute::enumSearchSuccess) + // { + // break; + // } + // bSwitchTo2D = false; + // break; + // } + // if (bSwitchTo2D) + // { + // m_bSwitchTo2D = true; + // } + // } + // ClearResetUseAutoPF(); + } } - // Work is cancel - public virtual void Cancel() - { - - } - - // This work is do player moving ? - public virtual bool IsMoving() { return true; } - // Copy work data - public virtual bool CopyData(CECHPWork pWork) - { - return true; - } - - // Play move target effect - public void PlayMoveTargetGFX(A3DVECTOR3 vPos, A3DVECTOR3 vNormal) - { - - } - - // User press cancel button - public void PressCancel() { m_bReadyCancel = true; } - - public void SetUseAutoMoveDialog(bool bUseAutoMoveDialog) - { - - } - public bool GetUseAutoMoveDialog() { return m_bUseAutoMoveDialog; } - public bool GetAutoMove() - { - return true; - } - - void SetAutoLand(bool bAutoLand) { m_bAutoLand = bAutoLand; } - bool GetAutoLand() { return m_bAutoLand; } - - void SetAutoHeight(float fHeight) { m_fAutoHeight = fHeight; m_bAutoFly = true; m_bReachedHeight = false; } - float GetAutoHeight() { return m_fAutoHeight; } - bool IsAutoFly() { return m_bAutoFly;} - - bool IsAutoPF(){ return m_iDestType == Types.DEST_AUTOPF; } - - // Finish work - void Finish() - { - - } - - void SetTaskNPCInfo(int tid, int taskid) - { - - } - - void SwitchToDest2D() - { - //int tid, taskid; - //tid = m_iNPCTempleId; - //taskid = m_iTaskId; - //CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan(); - //pGameUI->SetAutoMoveShowDialogTarget((int)m_vMoveDest.x, (int)m_vMoveDest.z); - //SetDestination(CECHPWorkMove::DEST_2D, m_vMoveDest); - //SetTaskNPCInfo(tid, taskid); - //SetUseAutoMoveDialog(true); - } - // On first tick - protected virtual void OnFirstTick() - { - - } - - // Tick routine of walking on ground - protected bool Tick_Walk(float fDeltaTime) - { - return true; - } - // Tick routine of flying or swimming - protected bool Tick_FlySwim(float fDeltaTime) - { - return true; - } - // Start gliding - protected void Glide(float fMoveTime, A3DVECTOR3 vMoveDirH, float fDeltaTime, bool bFly) - { - - } - - // Calculate vertical speed when fly or swim - protected float CalcFlySwimVertSpeed(float fSpeed1, float fPushDir, float fPushAccel, float fDeltaTime) - { - return 0; - } - - protected void ClearResetUseAutoPF() - { - - } - protected void UpdateResetUseAutoPF() - { -// if (!m_bResetAutoPF) -// { -// return; -// } -// CECIntelligentRoute::Instance().SetUsage(CECIntelligentRoute::enumUsageWorkMove); -// CECIntelligentRoute::Instance().ResetSearch(); -// if (m_iDestType == DEST_2D || m_iDestType == DEST_3D) -// { -//# ifdef SHOW_AUTOMOVE_FOOTPRINTS -// g_AutoPFFollowPoints.clear(); -// g_AutoPFPathPoints.clear(); -//#endif -// } -// else if (IsAutoPF()) -// { -// bool bSwitchTo2D(true); -// while (true) -// { -// if (m_pHost->IsFlying()) -// { -// break; -// } -// CECHostBrushTest brushTester(m_pHost->GetPos(), m_pHost->m_CDRInfo.vExtent, m_pHost->m_CDRInfo.fStepHeight); -// if (CECIntelligentRoute::Instance().Search(m_pHost->GetPos(), m_vMoveDest, &brushTester) != CECIntelligentRoute::enumSearchSuccess) -// { -// break; -// } -// bSwitchTo2D = false; -// break; -// } -// if (bSwitchTo2D) -// { -// m_bSwitchTo2D = true; -// } -// } -// ClearResetUseAutoPF(); - } - } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs index 96368a98b4..6efffdd379 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs @@ -1,75 +1,78 @@ using UnityEngine; -/////////////////////////////////////////////////////////////////////////// -// -// Class CECHPWorkSpell -// -/////////////////////////////////////////////////////////////////////////// -public class CECHPWorkSpell : CECHPWork +namespace BrewMonster.Scripts { - public static class Spell_magic_state + /////////////////////////////////////////////////////////////////////////// + // + // Class CECHPWorkSpell + // + /////////////////////////////////////////////////////////////////////////// + public class CECHPWorkSpell : CECHPWork { - public const int ST_INCANT = 0, - ST_SPELL = 1; - } + public static class Spell_magic_state + { + public const int ST_INCANT = 0, + ST_SPELL = 1; + } - public CECHPWorkSpell(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_SPELLOBJECT, pWorkMan) - { - m_dwMask = Work_mask.MASK_SPELLOBJECT; - m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_TRACEOBJECT; - Reset(); - } + public CECHPWorkSpell(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_SPELLOBJECT, pWorkMan) + { + m_dwMask = Work_mask.MASK_SPELLOBJECT; + m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_TRACEOBJECT; + Reset(); + } - public CECHPWorkSpell(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan) - { - } + public CECHPWorkSpell(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan) + { + } - protected CECSkill m_pSkill; // Skill object - protected CECCounter m_OverTimeCnt; // Over time counter - protected int m_iState; - protected int m_idTarget; // Target id + protected CECSkill m_pSkill; // Skill object + protected CECCounter m_OverTimeCnt; // Over time counter + protected int m_iState; + protected int m_idTarget; // Target id - // On first tick - protected virtual void OnFirstTick() - { - //m_pHost.m_iMoveMode = CECHostPlayer::MOVE_STAND; - } - // Prepare cast - public void PrepareCast(int idTarget, CECSkill pSkill, int iIncantTime) - { + // On first tick + protected virtual void OnFirstTick() + { + //m_pHost.m_iMoveMode = CECHostPlayer::MOVE_STAND; + } + // Prepare cast + public void PrepareCast(int idTarget, CECSkill pSkill, int iIncantTime) + { - } - // Change state - public void ChangeState(int iState) - { + } + // Change state + public void ChangeState(int iState) + { - } - // Get state - public int GetState() - { - return m_iState; - } - public CECSkill GetSkill() - { - return m_pSkill; - } + } + // Get state + public int GetState() + { + return m_iState; + } + public CECSkill GetSkill() + { + return m_pSkill; + } - // Tick routine - public virtual bool Tick(uint dwDeltaTime) - { - return false; - } - // Reset work - public virtual void Reset() - { + // Tick routine + public virtual bool Tick(uint dwDeltaTime) + { + return false; + } + // Reset work + public virtual void Reset() + { - } - // Copy work data - public virtual bool CopyData(CECHPWork pWork) - { - return false; - } - // Cancel work - public virtual void Cancel() - { + } + // Copy work data + public virtual bool CopyData(CECHPWork pWork) + { + return false; + } + // Cancel work + public virtual void Cancel() + { + } } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs index 31e56cc2d4..d1b38189aa 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs @@ -1,5 +1,7 @@ using BrewMonster; +using BrewMonster.Managers; using BrewMonster.Network; +using BrewMonster.Scripts; using CSNetwork.GPDataType; using PerfectWorld.Scripts.Player; using System; diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs index b270df64ee..62f9ceb5df 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using UnityEngine; -namespace PerfectWorld.Scripts.Managers +namespace BrewMonster.Scripts.Managers { public static class EC_Inventory diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs b/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs index 205716958a..57b1d882e8 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_InventoryUI.cs @@ -7,7 +7,7 @@ using BrewMonster.Network; using BrewMonster; using ModelRenderer.Scripts.GameData; -namespace PerfectWorld.Scripts.Managers +namespace BrewMonster.Scripts.Managers { public class EC_InventoryUI : MonoBehaviour { diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem.cs index a814e47d16..091c87edec 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrItem.cs @@ -8,7 +8,7 @@ using ModelRenderer.Scripts.Common; using ModelRenderer.Scripts.GameData; using UnityEngine; -namespace PerfectWorld.Scripts.Managers +namespace BrewMonster.Scripts.Managers { public class InventoryItemData { diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrType.cs b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrType.cs index 17919062e5..29e9ad3938 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_IvtrType.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_IvtrType.cs @@ -3,7 +3,7 @@ using UnityEngine; using ModelRenderer.Scripts.GameData; using BrewMonster; -namespace PerfectWorld.Scripts.Managers +namespace BrewMonster.Scripts.Managers { public enum IndexOfIteminEquipmentInventory : byte { diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs index 0648b0ed31..b2d1402019 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs @@ -52,6 +52,7 @@ namespace PerfectWorld.Scripts.Managers break; } case int value when value == EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY: + case int value1 when value1 == EC_MsgDef.MSG_PM_PLAYERATKRESULT: Debug.Log("EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY"); TransmitMessage(Msg); break; @@ -437,7 +438,10 @@ namespace PerfectWorld.Scripts.Managers else cid = ((cmd_object_landing)msg.dwParam1).object_id; break;*/ - + case long value when value == EC_MsgDef.MSG_PM_PLAYERATKRESULT: + cmd_object_atk_result pCmdAtk = GPDataTypeHelper.FromBytes((byte[])msg.dwParam1); + cid = pCmdAtk.attacker_id; + break; // 鈿狅笍 C谩c case kh谩c c农ng t瓢啤ng t峄, ch峄 vi峄嘽 l岷 ra 膽煤ng tr瓢峄漬g id / caster / user ... // Do qu谩 d脿i n锚n b岷 c贸 th峄 copy d岷 t峄玭g case t峄 C++ sang. @@ -446,7 +450,7 @@ namespace PerfectWorld.Scripts.Managers return false; } - /* if (cid == 0) + if (cid == 0) { System.Diagnostics.Debug.Assert(false, "cid = 0"); return false; @@ -461,7 +465,7 @@ namespace PerfectWorld.Scripts.Managers var elsePlayer = SeekOutElsePlayer(cid); if (elsePlayer != null) elsePlayer.ProcessMessage(msg); - }*/ + } return true; } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs index 9d525548d2..b77e8ed28b 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs @@ -1,4 +1,5 @@ using BrewMonster; +using BrewMonster.Managers; using CSNetwork.GPDataType; using CSNetwork.Protocols; using UnityEngine; diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs index 77a4e6cde8..0a899d2cf7 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs @@ -1,64 +1,67 @@ using UnityEngine; -public class CECObjectWork +namespace BrewMonster.Scripts { - // Attributes - protected int m_iWorkID; // Work ID - protected bool m_bFinished; // true, Work is finished - protected uint m_dwMask; // Mask of this work - protected uint m_dwTransMask; // Work transfer masks - protected bool m_bFirstTick; - // Constructor - public CECObjectWork(int iWorkID) + public class CECObjectWork { - m_iWorkID = iWorkID; - m_bFinished = false; - m_dwMask = 0; - m_dwTransMask = 0; - m_bFinished = true; - } - - public virtual bool Tick(float dwDeltaTime) - { - if (m_bFirstTick) + // Attributes + protected int m_iWorkID; // Work ID + protected bool m_bFinished; // true, Work is finished + protected uint m_dwMask; // Mask of this work + protected uint m_dwTransMask; // Work transfer masks + protected bool m_bFirstTick; + // Constructor + public CECObjectWork(int iWorkID) { - m_bFirstTick = false; - OnFirstTick(); + m_iWorkID = iWorkID; + m_bFinished = false; + m_dwMask = 0; + m_dwTransMask = 0; + m_bFinished = true; } - return true; + + public virtual bool Tick(float dwDeltaTime) + { + if (m_bFirstTick) + { + m_bFirstTick = false; + OnFirstTick(); + } + return true; + } + + // Reset work + public virtual void Reset() + { + m_bFinished = false; + m_bFirstTick = true; + } + + // Work is cancel + public virtual void Cancel() { } + + // Can work transfer to another work with specified mask + public virtual bool CanTransferTo(uint dwMask) + { + return (m_dwTransMask & dwMask) != 0; + } + + // On work shift to + public virtual void OnWorkShift() { } + + // Get work ID + public int GetWorkID() => m_iWorkID; + + // Is work finished? + public bool IsFinished() => m_bFinished; + + // Get work mask + public uint GetWorkMask() => m_dwMask; + + // Get work transfer works + public uint GetTransferMask() => m_dwTransMask; + + // On first tick + protected virtual void OnFirstTick() { } } - - // Reset work - public virtual void Reset() - { - m_bFinished = false; - m_bFirstTick = true; - } - - // Work is cancel - public virtual void Cancel() { } - - // Can work transfer to another work with specified mask - public virtual bool CanTransferTo(uint dwMask) - { - return (m_dwTransMask & dwMask) != 0; - } - - // On work shift to - public virtual void OnWorkShift() { } - - // Get work ID - public int GetWorkID() => m_iWorkID; - - // Is work finished? - public bool IsFinished() => m_bFinished; - - // Get work mask - public uint GetWorkMask() => m_dwMask; - - // Get work transfer works - public uint GetTransferMask() => m_dwTransMask; - - // On first tick - protected virtual void OnFirstTick() { } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs b/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs new file mode 100644 index 0000000000..8315be2ff5 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs @@ -0,0 +1,99 @@ +using CSNetwork.GPDataType; +using UnityEngine; + +namespace BrewMonster.Scripts.Ornament +{ + public class CECOrnamentMan + { + CECBrushMan m_pBrushMan; + // Trace for CD + public virtual bool TraceWithBrush(ref BrushTraceInfo pInfo) + { + bool bCollide = false; + //TO DO: fix later + //save original result + //bool bStartSolid = pInfo.bStartSolid; // Collide something at start point + //bool bAllSolid = pInfo.bAllSolid; // All in something + //int iClipPlane = pInfo.iClipPlane; // Clip plane's index + //float fFraction = 100.0f; // Fraction + //A3DVECTOR3 vNormal = pInfo.ClipPlane.GetNormal(); //clip plane normal + //float fDist = pInfo.ClipPlane.GetDist(); //clip plane dist + + //if (m_pBrushMan != null && m_pBrushMan.Trace(pInfo) + // && (pInfo.fFraction < fFraction)) + //{ + // fFraction = pInfo.fFraction; + // bAllSolid = pInfo.bAllSolid; + // bStartSolid = pInfo.bStartSolid; + // iClipPlane = pInfo.iClipPlane; + // vNormal = pInfo.ClipPlane.GetNormal(); + // fDist = pInfo.ClipPlane.GetDist(); + // bCollide = true; + //} + + //HomeOnmtTable::iterator it1 = m_HomeOrnamentTab.begin(); + //for (; it1 != m_HomeOrnamentTab.end(); ++it1) + //{ + // CECHomeOrnament* pHomeOrnament = *it1.value(); + // if (!pHomeOrnament.IsLoaded()) + // continue; + + // CELBuildingWithBrush* pBuildingWithBrush = pHomeOrnament.GetBuildingWithBrush(); + // if (pBuildingWithBrush && pBuildingWithBrush.TraceWithBrush(pInfo) && (pInfo.fFraction < fFraction)) + // { + // fFraction = pInfo.fFraction; + // bAllSolid = pInfo.bAllSolid; + // bStartSolid = pInfo.bStartSolid; + // iClipPlane = pInfo.iClipPlane; + // vNormal = pInfo.ClipPlane.GetNormal(); + // fDist = pInfo.ClipPlane.GetDist(); + // bCollide = true; + // } + //} + + //// now see if collide with forest + //CELForest* pForest = g_pGame.GetGameRun().GetWorld().GetForest(); + //if ((fFraction > 0.0f) && pForest + // && pForest.TraceWithBrush(pInfo) + // && (pInfo.fFraction < fFraction)) + //{ + // fFraction = pInfo.fFraction; + // bAllSolid = pInfo.bAllSolid; + // bStartSolid = pInfo.bStartSolid; + // iClipPlane = pInfo.iClipPlane; + // vNormal = pInfo.ClipPlane.GetNormal(); + // fDist = pInfo.ClipPlane.GetDist(); + // bCollide = true; + //} + + //// now see if collide with dynamic scene building + //ECModelTable::iterator it = m_ECModelTab.begin(); + //for (; it != m_ECModelTab.end(); ++it) + //{ + // ECMODELNODE* pNode = *it.value(); + // if ((fFraction > 0.0f) && pNode + // && pNode.TraceWithBrush(pInfo) + // && (pInfo.fFraction < fFraction)) + // { + // fFraction = pInfo.fFraction; + // bAllSolid = pInfo.bAllSolid; + // bStartSolid = pInfo.bStartSolid; + // iClipPlane = pInfo.iClipPlane; + // vNormal = pInfo.ClipPlane.GetNormal(); + // fDist = pInfo.ClipPlane.GetDist(); + // bCollide = true; + // } + //} + + ////set back + //pInfo.fFraction = fFraction; + //pInfo.bStartSolid = bStartSolid; + //pInfo.bAllSolid = bAllSolid; + //pInfo.iClipPlane = iClipPlane; + //pInfo.ClipPlane.SetNormal(vNormal); + //pInfo.ClipPlane.SetD(fDist); + return bCollide; + + } + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs.meta new file mode 100644 index 0000000000..4448024055 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_OrnamentMan.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 90848592c1c53d04e87291f2c1bfafdb \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_World.cs b/Assets/PerfectWorld/Scripts/Managers/EC_World.cs new file mode 100644 index 0000000000..91d9f27bb0 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_World.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +//public class CECWorld +//{ + +//} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_World.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_World.cs.meta new file mode 100644 index 0000000000..b08d5372e0 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_World.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4f8b18d59a72e044fbcf236fe5b2991c \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs b/Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs new file mode 100644 index 0000000000..42933fa251 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs @@ -0,0 +1,166 @@ +using CSNetwork.GPDataType; +using System; +using UnityEngine; +using UnityEngine.UIElements; + +namespace BrewMonster.Scripts +{ + public class CHalfSpace + { + public static float DistThresh; //空间一顶点到halfspace平面的距离阈值,作为判断是在半空间内部、外部,or 边界上 + //该阈值属于整个类而不是某一个对象,因此定义为静态成员 + //根据三个顶点构造平面及半空间区域 + //Attributes + public const float HS_DEFAULT_DISTTHRESH = 0.000001f; //距离差的阈值,作为判断是在半空间内部or边界上 + + protected A3DVECTOR3 m_vNormal; + protected float m_d; + + public void Set(A3DVECTOR3 v1, A3DVECTOR3 v2) + { + m_vNormal = A3DVECTOR3.CrossProduct(v2 - v1, new A3DVECTOR3(0.0f, 0.0f, 1.0f)); + m_vNormal.Normalize(); + m_d = A3DVECTOR3.DotProduct(v1, m_vNormal); + } + public void Set(A3DVECTOR3 v1, A3DVECTOR3 v2, A3DVECTOR3 v3) + { + m_vNormal = A3DVECTOR3.CrossProduct(v2 - v1, v3 - v1); + m_vNormal.Normalize(); + m_d = A3DVECTOR3.DotProduct(v1, m_vNormal); + } + + //直接设置法向 + public void SetNormal(A3DVECTOR3 n) { m_vNormal = n; m_vNormal.Normalize(); } + + public float GetDist() { return m_d; } + + //直接设置距离d + public void SetD(float d) { m_d = d; } + + public CHalfSpace(A3DVECTOR3 v1, A3DVECTOR3 v2, A3DVECTOR3 v3) + { + Set(v1, v2, v3); + + } + //根据两个顶点构造平行于Z轴的平面及半空间区域 + public CHalfSpace(A3DVECTOR3 v1, A3DVECTOR3 v2) + { + Set(v1, v2); + } + public CHalfSpace() + { + + } + + public CHalfSpace(CHalfSpace hs) + { + m_vNormal = hs.m_vNormal; + m_d = hs.m_d; + } + + // 对决定Halfspace的平面进行变换!变换矩阵为mtxTrans + public virtual void Transform(A3DMATRIX4 mtxTrans) + { + //从mtxTrans分解出Scale,Rotate,Translate分量 + A3DVECTOR3 vTranslate = mtxTrans.GetRow(3); + float fScale = mtxTrans.GetCol(0).Magnitude(); + + // 与mtxTrans一样,仍定义为右乘矩阵 + A3DMATRIX3 mtx3Rotate = new A3DMATRIX3(); + mtx3Rotate.m = new float[3 * 3]; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + mtx3Rotate.m[(i * 3) + j] = mtxTrans.m[(i * 4) + j] / fScale; + + //对于平面方程N.X=D的变换(s,R,t)如下: + + // N'=NR + SetNormal(m_vNormal * mtx3Rotate); + + //D'=s*D+N'.t + SetD(fScale * m_d + A3DVECTOR3.DotProduct(m_vNormal, vTranslate)); + } + + public void Translate(float Delta) { m_d += Delta; } //沿法线方向作一个平移 + public void Inverse() { m_d = -m_d; m_vNormal = -m_vNormal; } //翻转半空间的正反方向 + + //点v到半空间定义平面的距离,此距离带符号! + public float DistV2Plane(A3DVECTOR3 v) + { + float d = A3DVECTOR3.DotProduct(v, m_vNormal); + return (d - m_d); + } + + //与线段求交 + public int IntersectLineSeg(A3DVECTOR3 v1, A3DVECTOR3 v2, A3DVECTOR3 vIntersection) + { + vIntersection = new A3DVECTOR3(0.0f, 0.0f, 0.0f); + //先处理在平面上的情况 + bool v1InPlane = OnPlane(v1); + bool v2InPlane = OnPlane(v2); + if (v1InPlane && v2InPlane) return 3; + if (v1InPlane) return 1; + if (v2InPlane) return 2; + + if (Outside(v1) ^ Outside(v2)) + { + //两顶点分别在两侧,计算交点 + A3DVECTOR3 vd = v2 - v1; + float t = m_d - A3DVECTOR3.DotProduct(m_vNormal, v1); + t /= A3DVECTOR3.DotProduct(m_vNormal, vd); + //assert(t < 1.0f && t > 0.0f); + vIntersection = v1 + t * vd; + + return 4; + } + else + return 0; + } + + //////////////////////////////////////////////////////////// + // 判断一个三维点是否处于半空间内部,或者说处于平面的一侧 + // 注意halfspace的OutSide,Inside定义方式 + // /\ + // /||\ + // || + // || normal (Outside) + //------------------------------------------Plane + // (Inside) + // + public bool Inside(A3DVECTOR3 v) + { + float d = A3DVECTOR3.DotProduct(v, m_vNormal); + bool bInside = (m_d - d > DistThresh); + return (bInside); + } + public bool Outside(A3DVECTOR3 v) + { + float d = A3DVECTOR3.DotProduct(v, m_vNormal); + bool bOutside = (d - m_d > DistThresh); + return (bOutside); + } + public bool OnPlane(A3DVECTOR3 v) + { + float d = A3DVECTOR3.DotProduct(v, m_vNormal); + bool bOnPlane = (Math.Abs(m_d - d) <= DistThresh); + return bOnPlane; + } + + //set && get operations + public static void SetDistThresh(float DThresh = HS_DEFAULT_DISTTHRESH) //并设定一个缺省值 + { + DistThresh = DThresh; + } + + public A3DVECTOR3 GetNormal() { return m_vNormal; } + + //点法式 + public void SetNV(A3DVECTOR3 n, A3DVECTOR3 v) + { + m_vNormal = n; + m_vNormal.Normalize(); + m_d = A3DVECTOR3.DotProduct(m_vNormal, v); + } + + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs.meta b/Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs.meta new file mode 100644 index 0000000000..30fbbcd701 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 495f51cd9612ff441a012f1aea98974d \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/NPCManager.cs b/Assets/PerfectWorld/Scripts/Managers/NPCManager.cs index 3f80cd6492..25b591664a 100644 --- a/Assets/PerfectWorld/Scripts/Managers/NPCManager.cs +++ b/Assets/PerfectWorld/Scripts/Managers/NPCManager.cs @@ -1,6 +1,6 @@ using UnityEngine; -namespace PerfectWorld.Scripts.Managers +namespace BrewMonster.Scripts.Managers { public class NPCManager : MonoBehaviour { diff --git a/Assets/PerfectWorld/Scripts/Managers/aabbcd.cs b/Assets/PerfectWorld/Scripts/Managers/aabbcd.cs new file mode 100644 index 0000000000..33c2b0852c --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/aabbcd.cs @@ -0,0 +1,67 @@ +using CSNetwork.GPDataType; +using BrewMonster.Scripts.Player; +using PerfectWorld.Scripts.Player; + +namespace BrewMonster.Scripts +{ + ////////////////////////////////////////////////////////////////////////// + // define a new compact Convex Hull data type which is used in ElementClient! + ////////////////////////////////////////////////////////////////////////// + public class BrushTraceInfo + { + ////////////////////////////////////////////////////////////////////////// + // In + ////////////////////////////////////////////////////////////////////////// + // aabb's info + public A3DVECTOR3 vStart; // Start point + public A3DVECTOR3 vDelta; // Move delta + public A3DVECTOR3 vExtents; + public A3DAABB BoundAABB; + // Dist Epsilon + public float fDistEpsilon; // Dist Epsilon + public bool bIsPoint; //raytrace + ////////////////////////////////////////////////////////////////////////// + // Out + ////////////////////////////////////////////////////////////////////////// + public bool bStartSolid; // Collide something at start point + public bool bAllSolid; // All in something + public CHalfSpace ClipPlane; // Clip plane + public int iClipPlane; // Clip plane's index + public float fFraction; // Fraction + public uint dwUser1; // User defined data 1 + public uint dwUser2; // User defined data 2 + + public void Init(A3DVECTOR3 start, A3DVECTOR3 delta, A3DVECTOR3 ext, bool bRay = false, float epsilon = 0.03125f) + { + + vStart = start; + vDelta = delta; + vExtents = ext; + fDistEpsilon = epsilon; + fFraction = 100.0f; + bIsPoint = bRay; + bStartSolid = false; + bAllSolid = false; + dwUser1 = 0; + dwUser2 = 0; + if (!bIsPoint) + { + BoundAABB.Clear(); + BoundAABB.AddVertex(vStart); + BoundAABB.AddVertex(vStart + vExtents); + BoundAABB.AddVertex(vStart - vExtents); + BoundAABB.AddVertex(vStart + vDelta); + BoundAABB.AddVertex(vStart + vDelta + vExtents); + BoundAABB.AddVertex(vStart + vDelta - vExtents); + BoundAABB.CompleteCenterExts(); + } + + else + { + //@note : it cheats the caller. By Kuiwu[25/8/2005] + //@todo : refine me. By Kuiwu[25/8/2005] + fDistEpsilon = 1E-5f; + } + } + }; +} diff --git a/Assets/PerfectWorld/Scripts/Managers/aabbcd.cs.meta b/Assets/PerfectWorld/Scripts/Managers/aabbcd.cs.meta new file mode 100644 index 0000000000..69fc874090 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/aabbcd.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2ac2c48a14ff7e1478eb76c24ead3cc3 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Move/CECHostMove.cs b/Assets/PerfectWorld/Scripts/Move/CECHostMove.cs index 3589a2b441..46e401f0b8 100644 --- a/Assets/PerfectWorld/Scripts/Move/CECHostMove.cs +++ b/Assets/PerfectWorld/Scripts/Move/CECHostMove.cs @@ -1,4 +1,5 @@ 锘縰sing BrewMonster.Network; +using BrewMonster.Scripts; using CSNetwork; using CSNetwork.C2SCommand; using CSNetwork.GPDataType; diff --git a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs index e3bdd76483..6a420dc0fb 100644 --- a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs @@ -1,6 +1,7 @@ using Animancer; -using Animancer.Editor; using BrewMonster; +using BrewMonster.Managers; +using BrewMonster.Scripts.Managers; using CSNetwork.GPDataType; using ModelRenderer.Scripts.GameData; using PerfectWorld.Scripts.Managers; diff --git a/Assets/PerfectWorld/Scripts/Move/EC_CDR.cs b/Assets/PerfectWorld/Scripts/Move/EC_CDR.cs index e6e29eb985..b1991728a5 100644 --- a/Assets/PerfectWorld/Scripts/Move/EC_CDR.cs +++ b/Assets/PerfectWorld/Scripts/Move/EC_CDR.cs @@ -1,251 +1,560 @@ -锘縰sing CSNetwork.GPDataType; +锘縰sing BrewMonster.Scripts.Ornament; +using BrewMonster.Scripts.Player; +using BrewMonster.Scripts.World; +using CSNetwork.GPDataType; using System; -using TMPro; -using Unity.VisualScripting; using UnityEngine; -public static class EC_CDR +using WORD = System.UInt16; + +namespace BrewMonster.Scripts { - // Cho ph茅p CECHostMove g谩n mask theo scene (gi峄 linh ho岷 nh瓢ng kh么ng ph谩 c岷 tr煤c) - public static LayerMask BrushMask { get; set; } = ~0; - public static LayerMask TerrainMask { get; set; } = ~0; - - static LayerMask UsedMask_Ground() => BrushMask | TerrainMask; - - // == Thay CollideWithEnv (C++) b岷眓g BoxCast == - static bool CollideWithEnv_BoxCast(Vector3 vStart, Vector3 vDelta, Vector3 vExt, - LayerMask mask, - out RaycastHit hit, out float fFraction, out Vector3 vHitNormal, out bool bStartSolid, - float skin = 0.01f) + public static class EC_CDR { - hit = default; - vHitNormal = Vector3.up; - bStartSolid = false; - fFraction = 1.0f; + // Cho ph茅p CECHostMove g谩n mask theo scene (gi峄 linh ho岷 nh瓢ng kh么ng ph谩 c岷 tr煤c) + public static LayerMask BrushMask { get; set; } = ~0; + public static LayerMask TerrainMask { get; set; } = ~0; - float dist = vDelta.magnitude; - if (dist <= 1e-6f) return false; - - // start-in-solid - var overlapped = Physics.OverlapBox(vStart, vExt - Vector3.one * skin, Quaternion.identity, mask, QueryTriggerInteraction.Ignore); - if (overlapped != null && overlapped.Length > 0) + const float LOCAL_EPSILON = 1e-5f; + //[Flags] + public class CDR_EVN { - bStartSolid = true; - return true; + public const int CDR_BRUSH = 0x1, + CDR_TERRAIN = 0x2, + CDR_WATER = 0x4; } - // sweep AABB - Vector3 dir = vDelta / Mathf.Max(dist, 1e-6f); - if (Physics.BoxCast(vStart, vExt - Vector3.one * skin, dir, out hit, Quaternion.identity, dist, mask, QueryTriggerInteraction.Ignore)) + static LayerMask UsedMask_Ground() => BrushMask | TerrainMask; + + static bool CollideWithEnv(env_trace_t pEnvTrc) { - fFraction = Mathf.Clamp01(hit.distance / Mathf.Max(dist, 1e-6f)); - vHitNormal = hit.normal; - return true; - } - return false; - } - - // == Thay RetrieveSupportPlane (C++) b岷眓g Raycast xu峄憂g == - static bool DoGroundProbe(Vector3 vStart, Vector3 vExt, float fDeltaY, LayerMask mask, - out Vector3 vEnd, out Vector3 vHitNormal, out bool bSupport, - float skin = 0.01f) - { - vEnd = vStart; - vHitNormal = Vector3.up; - bSupport = false; - - float dist = Mathf.Max(fDeltaY, 0f) + vExt.y + skin + 0.05f; - Vector3 origin = vStart + Vector3.up * 0.05f; - - if (Physics.Raycast(origin, Vector3.down, out RaycastHit hit, dist, mask, QueryTriggerInteraction.Ignore)) - { - vHitNormal = hit.normal; - vEnd = new Vector3(vStart.x, hit.point.y + vExt.y + skin, vStart.z); - bSupport = (vHitNormal.y >= 0f); - return true; - } - return true; // kh么ng th岷 ground 鈫 bSupport=false - } - - // ======= STATIC OnGroundMove 鈥 GI峄 NGUY脢N VAI TR脪 TO脌N C峄 (C API) ======= - public static void OnGroundMove(ref CDR_INFO CDRInfo) - { - const float VEL_EPSILON = 1e-4f; - const float DIST_EPSILON = 1e-4f; - const float NORMAL_EPSILON = 1e-2f; - const float VEL_MAX_SPEED = 200f; - const float VEL_REFLECT = 0.3f; - - CDRInfo.fMoveDist = 0.0f; - - bool bFreeFall = (CDRInfo.vTPNormal.y < CDRInfo.fSlopeThresh); - if (Mathf.Abs(CDRInfo.fYVel) < VEL_EPSILON && Mathf.Abs(CDRInfo.fSpeed) < VEL_EPSILON && !bFreeFall) - return; - - float fYVel = CDRInfo.fYVel; - bool bJump = (fYVel > 0.5f); - - Vector3 vVelocity = CDRInfo.fSpeed * new Vector3(CDRInfo.vXOZVelDir.x, 0f, CDRInfo.vXOZVelDir.z) + fYVel * Vector3.up; - if (bFreeFall) - { - vVelocity += -CDRInfo.fGravityAccel * CDRInfo.t * Vector3.up; - fYVel += -CDRInfo.fGravityAccel * CDRInfo.t; - } - - Vector3 vVelDir = vVelocity; - float fVelSpeed = vVelDir.magnitude; - if (fVelSpeed > 1e-6f) vVelDir /= fVelSpeed; else vVelDir = Vector3.zero; - if (!bFreeFall) fVelSpeed = Mathf.Min(fVelSpeed, VEL_MAX_SPEED); - vVelocity = vVelDir * fVelSpeed; - - float dtp = Vector3.Dot(vVelDir, CDRInfo.vTPNormal); - if (dtp < 0f || !bJump) - { - vVelocity = (vVelDir - CDRInfo.vTPNormal * dtp - CDRInfo.vTPNormal * dtp * 0.01f) * fVelSpeed; - } - - CDRInfo.vAbsVelocity = vVelocity; - - Vector3 vStart = CDRInfo.vCenter; - Vector3 vExt = CDRInfo.vExtent; - float fTime = CDRInfo.t; - - Vector3 vDelta, vNormal = Vector3.up, vFinalPos = vStart; - bool bPull = false; - bool bTryPull = false; - - int nTry = 0; - LayerMask mask = UsedMask_Ground(); - - while (nTry < 4) - { - vDelta = vVelocity * fTime; - float fDeltaDist = vDelta.magnitude; - if (fDeltaDist < DIST_EPSILON) break; - - bool hasHit = CollideWithEnv_BoxCast(vStart, vDelta, vExt, mask, - out RaycastHit hit, out float fFraction, out Vector3 hitNormal, out bool bStartSolid); - - nTry++; - - if (bStartSolid) + pEnvTrc.fFraction = 100.0f; + pEnvTrc.bStartSolid = false; + pEnvTrc.dwClsFlag = 0; + if ((pEnvTrc.dwCheckFlag & CDR_EVN.CDR_BRUSH) == CDR_EVN.CDR_BRUSH) { - CDRInfo.fMoveDist = 0f; - if (CDRInfo.vTPNormal.y < CDRInfo.fSlopeThresh) CDRInfo.vTPNormal = Vector3.up; + BrushTraceInfo bruInfo = new BrushTraceInfo(); + bruInfo.Init(pEnvTrc.vStart, pEnvTrc.vDelta, pEnvTrc.vExt); + if (AABBCollideWithBrush(ref bruInfo)) + { + pEnvTrc.fFraction = bruInfo.fFraction; + pEnvTrc.vHitNormal = bruInfo.ClipPlane.GetNormal(); + pEnvTrc.bStartSolid = bruInfo.bStartSolid; + pEnvTrc.dwClsFlag = CDR_EVN.CDR_BRUSH; + } + } + if ((pEnvTrc.dwCheckFlag & CDR_EVN.CDR_TERRAIN) == CDR_EVN.CDR_TERRAIN) + { + float fFraction = 0f; + A3DVECTOR3 vTerNormal = new A3DVECTOR3(); + bool bStart = false; + if (CollideWithTerrain(pEnvTrc.vTerStart, pEnvTrc.vDelta, ref fFraction, ref vTerNormal, ref bStart) + && (fFraction < pEnvTrc.fFraction)) + { + //assert(fFraction >= 0.0f); + //pEnvTrc.fFraction = a_Max(0.0f, fFraction - 1E-4f); + pEnvTrc.fFraction = fFraction; + pEnvTrc.vHitNormal = vTerNormal; + pEnvTrc.bStartSolid = bStart; + pEnvTrc.dwClsFlag = CDR_EVN.CDR_TERRAIN; + } + + } + + if ((pEnvTrc.dwCheckFlag & CDR_EVN.CDR_WATER) == CDR_EVN.CDR_WATER) + { + float fFraction = 0f; + A3DVECTOR3 vWatNormal = new A3DVECTOR3(); + bool bStart = false; + //@todo : TBD: use center or foot? By Kuiwu[10/10/2005] + //if (CollideWithWater(pEnvTrc.vWatStart, pEnvTrc.vDelta, pEnvTrc.bWaterSolid, ref fFraction, ref vWatNormal, ref bStart) + // && fFraction < pEnvTrc.fFraction) + //{ + // pEnvTrc.fFraction = fFraction; + // pEnvTrc.vHitNormal = vWatNormal; + // pEnvTrc.bStartSolid = bStart; + // pEnvTrc.dwClsFlag = CDR_EVN.CDR_WATER; + // //# ifdef CDR_DEBUG + // // A3DVECTOR3 vHitPos(pEnvTrc.vWatStart +pEnvTrc.vDelta * fFraction); + // // sprintf(msg, "collide water, fraction %f pos %f %f %f \n", fFraction, vHitPos.x, vHitPos.y, vHitPos.z); + // // OUTPUT_DEBUG_INFO(msg); + // //#endif + + //} + } + + return (pEnvTrc.fFraction < 1.0f + 1E-4f); + } + + // == Thay CollideWithEnv (C++) b岷眓g BoxCast == + static bool CollideWithEnv_BoxCast(Vector3 vStart, Vector3 vDelta, Vector3 vExt, + LayerMask mask, + out RaycastHit hit, out float fFraction, out Vector3 vHitNormal, out bool bStartSolid, + float skin = 0.01f) + { + hit = default; + vHitNormal = Vector3.up; + bStartSolid = false; + fFraction = 1.0f; + + float dist = vDelta.magnitude; + if (dist <= 1e-6f) return false; + + // start-in-solid + var overlapped = Physics.OverlapBox(vStart, vExt - Vector3.one * skin, Quaternion.identity, mask, QueryTriggerInteraction.Ignore); + if (overlapped != null && overlapped.Length > 0) + { + bStartSolid = true; + return true; + } + + // sweep AABB + Vector3 dir = vDelta / Mathf.Max(dist, 1e-6f); + if (Physics.BoxCast(vStart, vExt - Vector3.one * skin, dir, out hit, Quaternion.identity, dist, mask, QueryTriggerInteraction.Ignore)) + { + fFraction = Mathf.Clamp01(hit.distance / Mathf.Max(dist, 1e-6f)); + vHitNormal = hit.normal; + return true; + } + return false; + } + + // == Thay RetrieveSupportPlane (C++) b岷眓g Raycast xu峄憂g == + static bool DoGroundProbe(Vector3 vStart, Vector3 vExt, float fDeltaY, LayerMask mask, + out Vector3 vEnd, out Vector3 vHitNormal, out bool bSupport, + float skin = 0.01f) + { + vEnd = vStart; + vHitNormal = Vector3.up; + bSupport = false; + + float dist = Mathf.Max(fDeltaY, 0f) + vExt.y + skin + 0.05f; + Vector3 origin = vStart + Vector3.up * 0.05f; + + if (Physics.Raycast(origin, Vector3.down, out RaycastHit hit, dist, mask, QueryTriggerInteraction.Ignore)) + { + vHitNormal = hit.normal; + vEnd = new Vector3(vStart.x, hit.point.y + vExt.y + skin, vStart.z); + bSupport = (vHitNormal.y >= 0f); + return true; + } + return true; // kh么ng th岷 ground 鈫 bSupport=false + } + + // ======= STATIC OnGroundMove 鈥 GI峄 NGUY脢N VAI TR脪 TO脌N C峄 (C API) ======= + public static void OnGroundMove(ref CDR_INFO CDRInfo) + { + const float VEL_EPSILON = 1e-4f; + const float DIST_EPSILON = 1e-4f; + const float NORMAL_EPSILON = 1e-2f; + const float VEL_MAX_SPEED = 200f; + const float VEL_REFLECT = 0.3f; + + CDRInfo.fMoveDist = 0.0f; + + bool bFreeFall = (CDRInfo.vTPNormal.y < CDRInfo.fSlopeThresh); + if (Mathf.Abs(CDRInfo.fYVel) < VEL_EPSILON && Mathf.Abs(CDRInfo.fSpeed) < VEL_EPSILON && !bFreeFall) return; + + float fYVel = CDRInfo.fYVel; + bool bJump = (fYVel > 0.5f); + + Vector3 vVelocity = CDRInfo.fSpeed * new Vector3(CDRInfo.vXOZVelDir.x, 0f, CDRInfo.vXOZVelDir.z) + fYVel * Vector3.up; + if (bFreeFall) + { + vVelocity += -CDRInfo.fGravityAccel * CDRInfo.t * Vector3.up; + fYVel += -CDRInfo.fGravityAccel * CDRInfo.t; } - if (!hasHit) + Vector3 vVelDir = vVelocity; + float fVelSpeed = vVelDir.magnitude; + if (fVelSpeed > 1e-6f) vVelDir /= fVelSpeed; else vVelDir = Vector3.zero; + if (!bFreeFall) fVelSpeed = Mathf.Min(fVelSpeed, VEL_MAX_SPEED); + vVelocity = vVelDir * fVelSpeed; + + float dtp = Vector3.Dot(vVelDir, CDRInfo.vTPNormal); + if (dtp < 0f || !bJump) { - vFinalPos = vStart + vDelta; - CDRInfo.fMoveDist += fDeltaDist; - break; + vVelocity = (vVelDir - CDRInfo.vTPNormal * dtp - CDRInfo.vTPNormal * dtp * 0.01f) * fVelSpeed; } - vStart += vDelta * fFraction; - CDRInfo.fMoveDist += (fDeltaDist * fFraction); - fTime -= fTime * fFraction; - vNormal = hitNormal; + CDRInfo.vAbsVelocity = vVelocity; - // Step-up (gi峄 tinh th岷 b岷 g峄慶) - if (!bFreeFall && !bTryPull && !bJump) + Vector3 vStart = CDRInfo.vCenter; + Vector3 vExt = CDRInfo.vExtent; + float fTime = CDRInfo.t; + + Vector3 vDelta, vNormal = Vector3.up, vFinalPos = vStart; + bool bPull = false; + bool bTryPull = false; + + int nTry = 0; + LayerMask mask = UsedMask_Ground(); + + while (nTry < 4) { - float skin = 0.01f; - Vector3 vStartUp = vStart + new Vector3(0f, CDRInfo.fStepHeight, 0f); - bool upBlocked = Physics.CheckBox(vStartUp, vExt - Vector3.one * skin, Quaternion.identity, mask, QueryTriggerInteraction.Ignore); - if (!upBlocked) + vDelta = vVelocity * fTime; + float fDeltaDist = vDelta.magnitude; + if (fDeltaDist < DIST_EPSILON) break; + + // TO DO: fix later beacuse logic in CollideWithEnv_BoxCast is wrong + //bool hasHit = CollideWithEnv_BoxCast(vStart, vDelta, vExt, mask, + // out RaycastHit hit, out float fFraction, out Vector3 hitNormal, out bool bStartSolid); + bool hasHit = false, bStartSolid = false; + float fFraction = 0f; + Vector3 hitNormal = Vector3.zero; + nTry++; + + if (bStartSolid) { - Vector3 vDelta2 = vVelocity; - bool hasHit2 = CollideWithEnv_BoxCast(vStartUp, vDelta2, vExt, mask, - out RaycastHit hit2, out float frac2, out Vector3 hitNormal2, out bool bStartSolid2); - if (hasHit2) vDelta2 *= frac2; + CDRInfo.fMoveDist = 0f; + if (CDRInfo.vTPNormal.y < CDRInfo.fSlopeThresh) CDRInfo.vTPNormal = Vector3.up; + return; + } - if (vDelta2.sqrMagnitude >= (vExt.x * vExt.x * 4f)) + if (!hasHit) + { + vFinalPos = vStart + vDelta; + CDRInfo.fMoveDist += fDeltaDist; + break; + } + + vStart += vDelta * fFraction; + CDRInfo.fMoveDist += (fDeltaDist * fFraction); + fTime -= fTime * fFraction; + vNormal = hitNormal; + + // Step-up (gi峄 tinh th岷 b岷 g峄慶) + if (!bFreeFall && !bTryPull && !bJump) + { + float skin = 0.01f; + Vector3 vStartUp = vStart + new Vector3(0f, CDRInfo.fStepHeight, 0f); + bool upBlocked = Physics.CheckBox(vStartUp, vExt - Vector3.one * skin, Quaternion.identity, mask, QueryTriggerInteraction.Ignore); + if (!upBlocked) { - vStart = vStartUp; - vDelta = vDelta2; + Vector3 vDelta2 = vVelocity; + bool hasHit2 = CollideWithEnv_BoxCast(vStartUp, vDelta2, vExt, mask, + out RaycastHit hit2, out float frac2, out Vector3 hitNormal2, out bool bStartSolid2); + if (hasHit2) vDelta2 *= frac2; - float distAll = vVelocity.magnitude; - float distMoved = vDelta.magnitude; - if (distAll > 1e-6f) fTime *= Mathf.Clamp01(distMoved / Mathf.Max(distAll, 1e-6f)); + if (vDelta2.sqrMagnitude >= (vExt.x * vExt.x * 4f)) + { + vStart = vStartUp; + vDelta = vDelta2; - bPull = true; + float distAll = vVelocity.magnitude; + float distMoved = vDelta.magnitude; + if (distAll > 1e-6f) fTime *= Mathf.Clamp01(distMoved / Mathf.Max(distAll, 1e-6f)); + + bPull = true; + } + } + bTryPull = true; + } + + if (!bPull) + { + if (vVelocity.sqrMagnitude > 1e-12f) + { + vVelDir = vVelocity.normalized; + fVelSpeed = vVelocity.magnitude * (1f - nTry * 0.1f); + + dtp = Vector3.Dot(vNormal, vVelDir); + float fRelSpeed = Mathf.Min(fVelSpeed, 5.0f); + + if (dtp >= 0f && dtp < 1e-4f) + { + vVelocity += vNormal * VEL_REFLECT * fRelSpeed; + } + else + { + vVelocity = (vVelDir - vNormal * dtp) * fVelSpeed - vNormal * dtp * VEL_REFLECT * fRelSpeed; + } + } + + if (fYVel > VEL_EPSILON) + { + if (vNormal.y >= CDRInfo.fSlopeThresh || vNormal.y < -NORMAL_EPSILON) fYVel = 0f; + } + else if (fYVel < -VEL_EPSILON) + { + if (vNormal.y >= CDRInfo.fSlopeThresh) fYVel = 0f; } } - bTryPull = true; } - if (!bPull) + // 鈥渧ertical ground trace鈥 鈥 thay RetrieveSupportPlane + Vector3 vTPNormal = Vector3.zero; + Vector3 vFinal = vFinalPos; + + float downDist = 0.3f; + if (bPull) downDist = CDRInfo.fStepHeight + 0.1f; + if (bJump) downDist = 0.0f; + + if (downDist > 0f) { - if (vVelocity.sqrMagnitude > 1e-12f) + if (!DoGroundProbe(vFinalPos, vExt, downDist, mask, out Vector3 vEnd, out Vector3 groundNormal, out bool bSupport)) { - vVelDir = vVelocity.normalized; - fVelSpeed = vVelocity.magnitude * (1f - nTry * 0.1f); - - dtp = Vector3.Dot(vNormal, vVelDir); - float fRelSpeed = Mathf.Min(fVelSpeed, 5.0f); - - if (dtp >= 0f && dtp < 1e-4f) - { - vVelocity += vNormal * VEL_REFLECT * fRelSpeed; - } - else - { - vVelocity = (vVelDir - vNormal * dtp) * fVelSpeed - vNormal * dtp * VEL_REFLECT * fRelSpeed; - } + CDRInfo.fMoveDist = 0f; + CDRInfo.vTPNormal = Vector3.up; + return; } - if (fYVel > VEL_EPSILON) + if (bSupport) { - if (vNormal.y >= CDRInfo.fSlopeThresh || vNormal.y < -NORMAL_EPSILON) fYVel = 0f; - } - else if (fYVel < -VEL_EPSILON) - { - if (vNormal.y >= CDRInfo.fSlopeThresh) fYVel = 0f; + vFinal = vEnd; + if (!bJump) vTPNormal = groundNormal; } } + + if ((vTPNormal.y >= CDRInfo.fSlopeThresh && fYVel < 0.0f) || (!bJump && fYVel > 0.0f)) + fYVel = 0.0f; + + CDRInfo.vCenter = vFinal; + CDRInfo.fYVel = fYVel; + if (vTPNormal != Vector3.zero) CDRInfo.vTPNormal = vTPNormal; } - // 鈥渧ertical ground trace鈥 鈥 thay RetrieveSupportPlane - Vector3 vTPNormal = Vector3.zero; - Vector3 vFinal = vFinalPos; - - float downDist = 0.3f; - if (bPull) downDist = CDRInfo.fStepHeight + 0.1f; - if (bJump) downDist = 0.0f; - - if (downDist > 0f) + static bool SegmentTriangleIntersect(A3DVECTOR3 vStart, A3DVECTOR3 vDelta, A3DVECTOR3[] vert, ref float fFraction, bool bCull) { - if (!DoGroundProbe(vFinalPos, vExt, downDist, mask, out Vector3 vEnd, out Vector3 groundNormal, out bool bSupport)) + float dist = 0f; + A3DVECTOR3 vDir = new A3DVECTOR3(vDelta); + + dist = vDir.Normalize(); + if (dist < 1E-5f) { - CDRInfo.fMoveDist = 0f; - CDRInfo.vTPNormal = Vector3.up; - return; + //assert(0 && "too small dist!"); + fFraction = 0.0f; + return true; } - if (bSupport) + float t = 0f, u = 0f, v = 0f; + + if (RayTriangleIntersect(vStart, vDir, vert, ref t, ref u, ref v, bCull) && (t >= 0.0f) && (t <= dist)) { - vFinal = vEnd; - if (!bJump) vTPNormal = groundNormal; + //fFraction = t/dist; + //fFraction = a_Max( 0.0f, fFraction -1E-4f); //put back + fFraction = (t - 5E-4f) / dist; + AAssist.a_ClampFloor(ref fFraction, 0.0f); + return true; } + + return false; } - if ((vTPNormal.y >= CDRInfo.fSlopeThresh && fYVel < 0.0f) || (!bJump && fYVel > 0.0f)) - fYVel = 0.0f; + /* + * ray: origin + t* dir, triangle: p(u,v) = (1-u -v)vert[0] + u*vert[1] + v*vert[2] + * @desc : + * @param vDir: normalized direction + * @param bCull: cull back face if true + * @return : + * @note: + * @todo: + * @author: kuiwu [8/10/2005] + * @ref: Tomas Moller's JGT code + */ + static bool RayTriangleIntersect(A3DVECTOR3 vOrigin, A3DVECTOR3 vDir, A3DVECTOR3[] vert, ref float t, ref float u, ref float v, bool bCull) + { + // find vectors for two edges sharing vert0 + A3DVECTOR3 edge1 = vert[1] - vert[0]; + A3DVECTOR3 edge2 = vert[2] - vert[0]; + // begin calculating determinant - also used to calculate U parameter + A3DVECTOR3 pvec = A3DVECTOR3.CrossProduct(vDir, edge2); + // if determinant is near zero, ray lies in plane of triangle + float det = A3DVECTOR3.DotProduct(edge1, pvec); + if (bCull) + { + if (det < LOCAL_EPSILON) + return false; + // From here, det is > 0. + // Calculate distance from vert0 to ray origin + A3DVECTOR3 tvec = vOrigin - vert[0]; + // Calculate U parameter and test bounds + u = A3DVECTOR3.DotProduct(tvec, pvec); + if ((u < 0.0f) || (u > det)) + return false; - CDRInfo.vCenter = vFinal; - CDRInfo.fYVel = fYVel; - if (vTPNormal != Vector3.zero) CDRInfo.vTPNormal = vTPNormal; + // prepare to test V parameter + A3DVECTOR3 qvec = A3DVECTOR3.CrossProduct(tvec, edge1); + // calculate V parameter and test bounds + v = A3DVECTOR3.DotProduct(vDir, qvec); + if ((v < 0.0f) || (u + v > det)) + return false; + + // calculate t, ray intersects triangle + t = A3DVECTOR3.DotProduct(edge2, qvec); + // Det > 0 so we can early exit here + // Intersection point is valid if distance is positive + // (else it can just be a face behind the orig point) + if (t < 0.0f) + { + return false; + } + + float OneOverDet = 1.0f / det; + + + t *= OneOverDet; + u *= OneOverDet; + v *= OneOverDet; + } + + else + { + if (det > -LOCAL_EPSILON && det < LOCAL_EPSILON) + return false; + float OneOverDet = 1.0f / det; + // Calculate distance from vert0 to ray origin + A3DVECTOR3 tvec = vOrigin - vert[0]; + // calculate U parameter and test bounds + u = A3DVECTOR3.DotProduct(tvec, pvec) * OneOverDet; + if ((u < 0.0f) || (u > 1.0f)) + return false; + // prepare to test V parameter + A3DVECTOR3 qvec = A3DVECTOR3.CrossProduct(tvec, edge1); + // calculate V parameter and test bounds + v = A3DVECTOR3.DotProduct(vDir, qvec) * OneOverDet; + if ((v < 0.0f) || (u + v > 1.0f)) + return false; + // calculate t, ray intersects triangle + t = A3DVECTOR3.DotProduct(edge2, qvec) * OneOverDet; + } + + return true; + } + + public static bool CollideWithTerrain(A3DVECTOR3 vStart, A3DVECTOR3 vDelta, ref float fFraction, ref A3DVECTOR3 vHitNormal, ref bool bStart) + { + + CECWorld pWorld = CECWorld.Instance; //g_pGame.GetGameRun().GetWorld(); + A3DTerrain2 pTerrain = pWorld.GetTerrain(); + bStart = false; + float h1 = pTerrain.GetPosHeight(vStart, ref vHitNormal); + if (h1 > vStart.y + 1E-4f) + {//start under terrain + bStart = true; + fFraction = 0.0f; + return true; + } + + int nWid, nHei; // in grid, 2 meters + float fMag = vDelta.Magnitude(); + + nWid = (int)Math.Ceiling(fMag / 2.0f); + nWid = Math.Max(3, nWid); + nHei = nWid; + int nTriangles = nWid * nHei * 2; + A3DVECTOR3[] pVerts = new A3DVECTOR3[(nWid + 1) * (nHei + 1)]; + //assert(pVerts != NULL); + //memset(pVerts, 0, sizeof(A3DVECTOR3)* (nWid + 1) * (nHei + 1)); + WORD[] pIndices = new WORD[nTriangles * 3]; + //assert(pIndices != NULL); + //memset(pIndices, 0, sizeof(WORD)* nTriangles * 3); + if (!pTerrain.GetFacesOfArea(vStart, nWid, nHei, ref pVerts, ref pIndices)) + { + //a_freetemp(pVerts); + // a_freetemp(pIndices); + return false; + } + int i; + A3DVECTOR3[] vert = new A3DVECTOR3[3]; + //@note : Here init the fraction. By Kuiwu[9/10/2005] + fFraction = 100.0f; + float tmpFraction = fFraction; + + for (i = 0; i < nTriangles; i++) + { + vert[0] = pVerts[pIndices[i * 3]]; + vert[1] = pVerts[pIndices[i * 3 + 1]]; + vert[2] = pVerts[pIndices[i * 3 + 2]]; + //A3DVECTOR3 vPt; + + //@note: Tomas Moller's JGT code : By Kuiwu[9/10/2005] + //@note: discard the engine version because it put back the hit point too much. By Kuiwu[13/10/2005] + // if(CLS_RayToTriangle(vStart, vDelta, *vert[0], *vert[1], *vert[2], vPt, true, &tmpFraction) + // && (tmpFraction <= 1.0f) && (tmpFraction < fFraction)) + if (SegmentTriangleIntersect(vStart, vDelta, vert, ref tmpFraction, true) && (tmpFraction < fFraction)) + { + //get the triangle normal + A3DVECTOR3 vEdge1 = vert[1] - vert[0]; + A3DVECTOR3 vEdge2 = vert[2] - vert[0]; + vHitNormal = A3DVECTOR3.CrossProduct(vEdge1, vEdge2); + vHitNormal.Normalize(); + + //@note : may be redundant, but to assure. By Kuiwu[17/10/2005] + A3DVECTOR3 vDir = new A3DVECTOR3(); + A3DVECTOR3.Normalize(vDelta, out vDir); + if (A3DVECTOR3.DotProduct(vHitNormal, vDir) > 0.01f) + {//leave the hit plane + //assert(0 && "hit a plane with same direction!"); + continue; + } + + fFraction = Math.Max(0.0f, tmpFraction); + } + + } + //a_freetemp(pVerts); + // a_freetemp(pIndices); + + return (fFraction <= 1.0f); + + } + + public static bool AABBCollideWithBrush(ref BrushTraceInfo pInfo) + { + //TO DO: fix later + return false; + //CECWorld pWorld = CECWorld.Instance; //g_pGame.GetGameRun().GetWorld(); + + //CECOrnamentMan pOrnMan = pWorld.GetOrnamentMan(); + //bool bBrush = pOrnMan.TraceWithBrush(ref pInfo); + + //BrushTraceInfo info = pInfo; + //CECMatterMan pMatterMan = pWorld.GetMatterMan(); + //if (pMatterMan.TraceWithBrush(ref info) && info.fFraction < pInfo.fFraction) + //{ + // pInfo = info; + // bBrush = true; + //} + + //info = pInfo; + //CECNPCMan pNPCMan = pWorld.GetNPCMan(); + //if (pNPCMan.TraceWithBrush(ref info) && info.fFraction < pInfo.fFraction) + //{ + // pInfo = info; + // bBrush = true; + //} + + //return bBrush; + } } + public struct OtherPlayer_Move_Info + { + // Bounding sphere of avator + public A3DVECTOR3 vCenter; + public A3DVECTOR3 vExts; + public float fStepHeight; + public A3DVECTOR3 vVelocity; + public float t; + public bool bTraceGround; // Whether trace the ground + public bool bTestTrnOnly; // Trace terrain only + public A3DVECTOR3 vecGroundNormal; // if bTraceGround is true, this will contain the ground normal when returned + }; + + //@desc :used to trace the environment, brush&terrain&water By Kuiwu[8/10/2005] + public struct env_trace_t + { + public A3DVECTOR3 vStart; // brush start + public A3DVECTOR3 vExt; + public A3DVECTOR3 vDelta; + public A3DVECTOR3 vTerStart; + public A3DVECTOR3 vWatStart; + public uint dwCheckFlag; + public bool bWaterSolid; + + public float fFraction; + public A3DVECTOR3 vHitNormal; + public bool bStartSolid; //start in solid + public uint dwClsFlag; //collision flag + }; } -public struct OtherPlayer_Move_Info -{ - // Bounding sphere of avator - public A3DVECTOR3 vCenter; - public A3DVECTOR3 vExts; - public float fStepHeight; - public A3DVECTOR3 vVelocity; - public float t; - public bool bTraceGround; // Whether trace the ground - public bool bTestTrnOnly; // Trace terrain only - public A3DVECTOR3 vecGroundNormal; // if bTraceGround is true, this will contain the ground normal when returned -}; \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs b/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs index a2630332f0..c496ec362f 100644 --- a/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs +++ b/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs @@ -1,15 +1,13 @@ using Animancer; using BrewMonster; +using BrewMonster.Managers; +using BrewMonster.Scripts; using CSNetwork; using CSNetwork.GPDataType; using ModelRenderer.Scripts.Common; using System; using System.IO; -using System.Text; -using Unity.VisualScripting; -using UnityEditor.Playables; using UnityEngine; -using static CECPlayer; public class CECNPC : CECObject { diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs index f9938234e0..255b59ce30 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs @@ -15,6 +15,8 @@ using System.Numerics; using CSNetwork.C2SCommand; using CSNetwork.GPDataType; using BrewMonster; +using BrewMonster.Managers; +using BrewMonster.Scripts.Player; namespace CSNetwork { @@ -415,12 +417,13 @@ namespace CSNetwork EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_HURTRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); break; case CommandID.OBJECT_ATTACK_RESULT: - int id = GPDataTypeHelper.FromBytes(pDataBuf); - BMLogger.LogError($"OBJECT_ATTACK_RESULT: npc ? " + ISNPCID(id)); + //int id = GPDataTypeHelper.FromBytes(pDataBuf); + cmd_object_atk_result pCmdAtk = GPDataTypeHelper.FromBytes(pDataBuf); + //BMLogger.LogError($"OBJECT_ATTACK_RESULT: npc ? " + ISNPCID(id)); - if (ISPLAYERID(id)) + if (ISPLAYERID(pCmdAtk.attacker_id)) EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERATKRESULT, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - else if (ISNPCID(id)) + else if (ISNPCID(pCmdAtk.attacker_id)) EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCATKRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); break; case CommandID.HOST_ATTACKRESULT: diff --git a/Assets/PerfectWorld/Scripts/Network/EC_ManMessageMono.cs b/Assets/PerfectWorld/Scripts/Network/EC_ManMessageMono.cs index 3fa4d0d8b3..ea4f28f9f1 100644 --- a/Assets/PerfectWorld/Scripts/Network/EC_ManMessageMono.cs +++ b/Assets/PerfectWorld/Scripts/Network/EC_ManMessageMono.cs @@ -1,12 +1,11 @@ using System; using UnityEngine; using CSNetwork; -using PerfectWorld.Scripts.Managers.BrewMonster.Managers; -using BrewMonster.Network; -using UnityEngine.SceneManagement; using CSNetwork.GPDataType; +using BrewMonster.Scripts.Player; +using PerfectWorld.Scripts.Managers.BrewMonster.Managers; -namespace BrewMonster +namespace BrewMonster.Managers { [Serializable] public class EC_ManMessageMono : MonoBehaviour diff --git a/Assets/PerfectWorld/Scripts/PlayerState/PlayerIdleState.cs b/Assets/PerfectWorld/Scripts/PlayerState/PlayerIdleState.cs index 00f87ae540..1d95133c92 100644 --- a/Assets/PerfectWorld/Scripts/PlayerState/PlayerIdleState.cs +++ b/Assets/PerfectWorld/Scripts/PlayerState/PlayerIdleState.cs @@ -1,3 +1,4 @@ +using BrewMonster.Scripts.Player; using UnityEngine; using static CECPlayer; diff --git a/Assets/PerfectWorld/Scripts/PlayerState/PlayerMoveState.cs b/Assets/PerfectWorld/Scripts/PlayerState/PlayerMoveState.cs index b46ef1e484..66c69102c7 100644 --- a/Assets/PerfectWorld/Scripts/PlayerState/PlayerMoveState.cs +++ b/Assets/PerfectWorld/Scripts/PlayerState/PlayerMoveState.cs @@ -1,3 +1,4 @@ +using BrewMonster.Scripts.Player; using UnityEngine; using static CECPlayer; diff --git a/Assets/PerfectWorld/Scripts/PlayerState/PlayerState.cs b/Assets/PerfectWorld/Scripts/PlayerState/PlayerState.cs index 6ce5c03a59..e9fc80c320 100644 --- a/Assets/PerfectWorld/Scripts/PlayerState/PlayerState.cs +++ b/Assets/PerfectWorld/Scripts/PlayerState/PlayerState.cs @@ -1,13 +1,16 @@ using UnityEngine; -public abstract class PlayerState +namespace BrewMonster.Scripts.Player { - protected readonly CECHostPlayer _characterCtrl; - public PlayerState(CECHostPlayer characterCtrl) + public abstract class PlayerState { - _characterCtrl = characterCtrl; + protected readonly CECHostPlayer _characterCtrl; + public PlayerState(CECHostPlayer characterCtrl) + { + _characterCtrl = characterCtrl; + } + public abstract void Enter(); + public abstract void Exit(); + public abstract void Update(); } - public abstract void Enter(); - public abstract void Exit(); - public abstract void Update(); } diff --git a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs index 0b38d13122..ed6c7af21d 100644 --- a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs +++ b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs @@ -1,4 +1,6 @@ using BrewMonster; +using BrewMonster.Managers; +using BrewMonster.Scripts; using CSNetwork; using CSNetwork.GPDataType; using CSNetwork.Protocols.RPCData; @@ -10,7 +12,7 @@ namespace PerfectWorld.Scripts.Player public class EC_ElsePlayer : CECPlayer { A3DVECTOR3 m_vMoveDir; // Player's velocity - A3DVECTOR3 m_vServerPos; // Player's real position on server + public A3DVECTOR3 m_vServerPos; // Player's real position on server A3DVECTOR3 m_vStopDir; // The direction when player stop moving // 鏄惁鏄緷闄勮 = Is it a dependent/attacher? bool m_bHangerOn; @@ -24,10 +26,13 @@ namespace PerfectWorld.Scripts.Player OtherPlayer_Move_Info m_cdr = new OtherPlayer_Move_Info(); float m_fDistToHost = 0f; // Distance to host player float m_fDistToHostH = 0f; // Horizontal distance to host player - CECCounter m_FightCnt; + public CECCounter m_FightCnt; + CECEPWorkMan m_pEPWorkMan; + CECHostPlayer pHost => EC_ManMessageMono.Instance?.GetECManPlayer?.GetHostPlayer(); public void Init(RoleInfo roleInfo, info_player_1 Info) { + m_pEPWorkMan = new CECEPWorkMan(this); m_iProfession = roleInfo.occupation; m_iGender = roleInfo.gender; @@ -69,7 +74,7 @@ namespace PerfectWorld.Scripts.Player { BrewMonster.BMLogger.Log("HoangDev : fDist >= MAX_LAGDIST"); SetPos(Cmd.dest); - //m_pEPWorkMan->FinishWork(CECEPWork::WORK_MOVE); + //m_pEPWorkMan.FinishWork(CECEPWork::WORK_MOVE); return; } @@ -348,15 +353,16 @@ namespace PerfectWorld.Scripts.Player private void Update() { MovingTo(Time.deltaTime); - CECHostPlayer pHost = EC_ManMessageMono.Instance.GetECManPlayer.GetHostPlayer(); - if (pHost != null /*&& pHost->IsSkeletonReady()*/) + + if (pHost != null /*&& pHost.IsSkeletonReady()*/) { m_fDistToHost = CalcDist(pHost.GetPos(), true); m_fDistToHostH = CalcDist(pHost.GetPos(), false); } + m_pEPWorkMan?.Tick(Time.deltaTime); } - private void SetPos(A3DVECTOR3 vPos) + public void SetPos(A3DVECTOR3 vPos) { Vector3 vector = new Vector3(); vector.x = vPos.x; @@ -382,6 +388,152 @@ namespace PerfectWorld.Scripts.Player // Get player's real position on server public A3DVECTOR3 GetServerPos() { return m_vServerPos; } + public bool ProcessMessage(ECMSG Msg) + { + switch (Msg.dwMsg) + { + case long value when value == EC_MsgDef.MSG_PM_PLAYERATKRESULT: + OnMsgPlayerAtkResult(Msg); + break; + } + return true; + } + + void OnMsgPlayerAtkResult(ECMSG Msg) + { + + cmd_object_atk_result pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1); + //ASSERT(pCmd && pCmd.attacker_id == m_PlayerInfo.cid); + + // Face to target + TurnFaceTo(pCmd.target_id); + + // TO DO: fix later + //PlayAttackEffect(pCmd.target_id, 0, 0, -1, pCmd.attack_flag, pCmd.speed* 50); + + if (!m_pEPWorkMan.FindWork(CECEPWorkMan.Work_type.WT_NORMAL, CECEPWork.EP_work_ID.WORK_HACKOBJECT)){ + m_pEPWorkMan.StartNormalWork(new CECEPWorkMelee(m_pEPWorkMan, pCmd.target_id)); + } + + // Enter fight state + EnterFightState(); + } + + // Play an attack effect + //void PlayAttackEffect(int idTarget, int idSkill, int skillLevel, int nDamage, + // uint dwModifier, int nAttackSpeed, int[] piAttackTime/* NULL */, int nSection) + //{ + // if (!IsAllResReady()) + // return; + + // if (idSkill == 0) + // { + // int idWeapon = IsShapeChanged() ? 0 : GetWeaponID(); + + // int nTimeFly = 10; + // if (idWeapon != 0) + // { + // // 驴麓驴麓脢脟虏禄脢脟脭露鲁脤脦盲脝梅 + // DATA_TYPE dt; + // WEAPON_ESSENCE pWeapon = (WEAPON_ESSENCE)g_pGame.GetElementDataMan().get_data_ptr(idWeapon, ID_SPACE_ESSENCE, dt); + // //ASSERT(dt == DT_WEAPON_ESSENCE); + + // if (dt == DT_WEAPON_ESSENCE && pWeapon && pWeapon.require_projectile) + // { + // nTimeFly = 700; + + // if (m_aEquips[EQUIPIVTR_PROJECTILE]) + // idWeapon = m_aEquips[EQUIPIVTR_PROJECTILE]; // set weapon to the projectile + // } + // } + + // if (g_pGame.GetGameRun().GetWorld().GetAttacksMan().FindAttackByAttacker(GetPlayerInfo().cid)) + // { + // // signal early attack event + // ClearComActFlagAllRankNodes(true); + // } + + // // melee attack + // CECAttackEvent pAttack = g_pGame.GetGameRun().GetWorld().GetAttacksMan().AddMeleeAttack( + // GetPlayerInfo().cid, idTarget, idWeapon, dwModifier, nDamage, nTimeFly); + + // if (pAttack != null) + // { + // if (!IsDead() && (dwModifier & CECAttackEvent::MOD_RETORT) == 0 + // && (dwModifier & CECAttackEvent::MOD_ATTACK_AURA) == 0 + // && PlayAttackAction(nAttackSpeed, piAttackTime, &pAttack.m_bSignaled) + // && (dwModifier & CECAttackEvent::MOD_BEAT_BACK) == 0) + // { + // } + // else + // { + // pAttack.m_bSignaled = true; + // } + // } + // } + // else + // { + // if (skillLevel == 0) + // { + // if (m_pCurSkill) + // skillLevel = m_pCurSkill.GetSkillLevel(); + // else + // skillLevel = 1; + // } + + // CECAttackEvent pAttack = null; + + // // first try to find if there is already a skill attack event in attackman + // CECAttackerEvents attackerEvents = g_pGame.GetGameRun().GetWorld().GetAttacksMan().FindAttackByAttacker(GetPlayerInfo().cid); + // if (attackerEvents) + // { + // CECAttackEvent pAttack = attackerEvents.Find(idSkill, nSection); + // if (() != null) + // { + // // 脙忙鹿楼禄梅碌脛路脟碌脷脪禄麓脦脡脣潞娄脧没脧垄 + // pAttack.AddTarget(idTarget, dwModifier, nDamage); + // goto EXIT; + // } + // else + // { + // attackerEvents.Signal(); + // } + // } + // if (GNET::ElementSkill::IsGoblinSkill(idSkill) && + // GNET::ElementSkill::GetType(idSkill) == 2) + // { + // pAttack = g_pGame.GetGameRun().GetWorld().GetAttacksMan().AddSkillAttack( + // GetPlayerInfo().cid, GetPlayerInfo().cid, idTarget, GetWeaponID(), idSkill, skillLevel, dwModifier, nDamage); + // } + // else + // { + // // begin a skill attack + // pAttack = g_pGame.GetGameRun().GetWorld().GetAttacksMan().AddSkillAttack( + // GetPlayerInfo().cid, m_idCurSkillTarget, idTarget, GetWeaponID(), idSkill, skillLevel, dwModifier, nDamage); + // } + + // if (pAttack) + // { + // pAttack.SetSkillSection(nSection); + // if (!IsDead() && (dwModifier & CECAttackEvent::MOD_RETORT) == 0 + // && (dwModifier & CECAttackEvent::MOD_ATTACK_AURA) == 0 + // && PlaySkillAttackAction(idSkill, nAttackSpeed, NULL, nSection, &pAttack.m_bSignaled) + // && (dwModifier & CECAttackEvent::MOD_BEAT_BACK) == 0) + // { + // } + // else + // { + // pAttack.m_bSignaled = true; + // } + // } + + // EXIT: + // // For skill attacking, time is always set to 0 + // if (piAttackTime) + // *piAttackTime = 0; + // } + //} + //public A3DVECTOR3 GetPos() //{ // return new A3DVECTOR3(transform.position.x, transform.position.y, transform.position.z); diff --git a/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs b/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs index a7981b970f..c49991ccf9 100644 --- a/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs +++ b/Assets/PerfectWorld/Scripts/Task/ATaskTemplMan.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.IO; using UnityEngine; -namespace PerfectWorld.Scripts.Task +namespace BrewMonster.Scripts.Task { public class ATaskTemplMan { diff --git a/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs b/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs index 461bb9622a..38be64a5b1 100644 --- a/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs +++ b/Assets/PerfectWorld/Scripts/Task/CECTaskInterface.cs @@ -1,8 +1,9 @@ using BrewMonster.Network; +using BrewMonster.Scripts.Player; using System.Collections.Generic; using UnityEngine; -namespace PerfectWorld.Scripts.Task +namespace BrewMonster.Scripts.Task { public class CECTaskInterface : TaskInterface { diff --git a/Assets/PerfectWorld/Scripts/Task/TaskExpAnalyser.cs b/Assets/PerfectWorld/Scripts/Task/TaskExpAnalyser.cs index fb05f704bf..e7101b9a2b 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskExpAnalyser.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskExpAnalyser.cs @@ -1,4 +1,4 @@ -锘縩amespace PerfectWorld.Scripts.Task +锘縩amespace BrewMonster.Scripts.Task { public struct TASK_EXPRESSION { diff --git a/Assets/PerfectWorld/Scripts/Task/TaskInterface.cs b/Assets/PerfectWorld/Scripts/Task/TaskInterface.cs index 242ccd320f..084574cd72 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskInterface.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskInterface.cs @@ -1,4 +1,4 @@ -namespace PerfectWorld.Scripts.Task +namespace BrewMonster.Scripts.Task { public interface TaskInterface { diff --git a/Assets/PerfectWorld/Scripts/Task/TaskProcess.cs b/Assets/PerfectWorld/Scripts/Task/TaskProcess.cs index 24230b2a9e..9491d3c884 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskProcess.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskProcess.cs @@ -1,6 +1,6 @@ using System; using System.Runtime.InteropServices; -using PerfectWorld.Scripts.Task; +using BrewMonster.Scripts.Task; using UnityEngine; public class TaskProcess diff --git a/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs b/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs index 9c28eae2d6..89bd3962b6 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskTempl.cs @@ -3,7 +3,7 @@ using System.IO; using System.Runtime.InteropServices; -namespace PerfectWorld.Scripts.Task +namespace BrewMonster.Scripts.Task { public sealed class TaskConstant { diff --git a/Assets/PerfectWorld/Scripts/Task/TaskTest.cs b/Assets/PerfectWorld/Scripts/Task/TaskTest.cs index 2fca9f1774..a8af4ffd46 100644 --- a/Assets/PerfectWorld/Scripts/Task/TaskTest.cs +++ b/Assets/PerfectWorld/Scripts/Task/TaskTest.cs @@ -2,7 +2,7 @@ using System.IO; using UnityEngine; -namespace PerfectWorld.Scripts.Task +namespace BrewMonster.Scripts.Task { public class TaskTest : MonoBehaviour { diff --git a/Assets/PerfectWorld/Scripts/UI/pickupItem.cs b/Assets/PerfectWorld/Scripts/UI/pickupItem.cs index 71d870b8fc..09a5b06cc9 100644 --- a/Assets/PerfectWorld/Scripts/UI/pickupItem.cs +++ b/Assets/PerfectWorld/Scripts/UI/pickupItem.cs @@ -7,6 +7,8 @@ using CSNetwork.GPDataType; using System.Collections.Generic; using BrewMonster; using TMPro; +using BrewMonster.Managers; +using BrewMonster.Scripts.Managers; public class pickupItem : MonoBehaviour { diff --git a/Assets/PerfectWorld/Scripts/World/CECWorld.cs b/Assets/PerfectWorld/Scripts/World/CECWorld.cs index 779918373f..fb4e33b65c 100644 --- a/Assets/PerfectWorld/Scripts/World/CECWorld.cs +++ b/Assets/PerfectWorld/Scripts/World/CECWorld.cs @@ -1,9 +1,27 @@ using BrewMonster; +using BrewMonster.Scripts.Ornament; using UnityEngine; -public class CECWorld : MonoSingleton -{ - uint m_dwBornStamp = 0; - public uint GetBornStamp() { return m_dwBornStamp++; } +namespace BrewMonster.Scripts.World +{ + public class CECWorld : MonoSingleton + { + protected A3DTerrain2 m_pA3DTerrain; // Terrain object + CECOrnamentMan m_pOnmtMan; + uint m_dwBornStamp = 0; + + public uint GetBornStamp() { return m_dwBornStamp++; } + + // Get terrain object + public A3DTerrain2 GetTerrain() + { + return m_pA3DTerrain; + } + + public CECOrnamentMan GetOrnamentMan() + { + return m_pOnmtMan; + } + } } diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index 716a778ddf..439e54fe96 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -1,5 +1,9 @@ using BrewMonster; +using BrewMonster.Managers; using BrewMonster.Network; +using BrewMonster.Scripts; +using BrewMonster.Scripts.Managers; +using BrewMonster.Scripts.Player; using CSNetwork; using CSNetwork.Common; using CSNetwork.GPDataType; @@ -9,14 +13,12 @@ using NUnit.Framework; using PerfectWorld.Scripts.Managers; using PerfectWorld.Scripts.Managers.BrewMonster.Managers; using PerfectWorld.Scripts.Player; -using PerfectWorld.Scripts.Task; using System; using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using System.Text; using TMPro; -using UnityEditor.Experimental.GraphView; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; @@ -598,7 +600,7 @@ public class CECHostPlayer : CECPlayer Debug.Log("[Inventory] OWN_ITEM_INFO received"); var data = Msg.dwParam1 as byte[]; int hostId = Convert.ToInt32(Msg.dwParam3); - PerfectWorld.Scripts.Managers.EC_Inventory.LogInventoryPacket("OWN_ITEM_INFO", data, hostId); + EC_Inventory.LogInventoryPacket("OWN_ITEM_INFO", data, hostId); break; } @@ -614,20 +616,20 @@ public class CECHostPlayer : CECPlayer { case CommandID.OWN_IVTR_DATA: { - PerfectWorld.Scripts.Managers.EC_Inventory.LogInventoryPacket("OWN_IVTR_DATA", data, hostId); + EC_Inventory.LogInventoryPacket("OWN_IVTR_DATA", data, hostId); break; } case CommandID.OWN_IVTR_DETAIL_DATA: { - PerfectWorld.Scripts.Managers.EC_Inventory.LogInventoryPacket("OWN_IVTR_DETAIL_DATA", data, hostId); + EC_Inventory.LogInventoryPacket("OWN_IVTR_DETAIL_DATA", data, hostId); // Parse and store if (data != null && data.Length >= 6) { byte byPackage = data[0]; byte ivtrSize = data[1]; - if (PerfectWorld.Scripts.Managers.EC_IvtrItem.TryParseInventoryDetail(data, out var pkg, out var size, out var items)) + if (EC_IvtrItem.TryParseInventoryDetail(data, out var pkg, out var size, out var items)) { - PerfectWorld.Scripts.Managers.EC_Inventory.UpdatePack(pkg, size, items); + EC_Inventory.UpdatePack(pkg, size, items); } } break; diff --git a/Assets/Scripts/CanvasController.cs b/Assets/Scripts/CanvasController.cs index ae5585106f..a63b381e24 100644 --- a/Assets/Scripts/CanvasController.cs +++ b/Assets/Scripts/CanvasController.cs @@ -1,47 +1,50 @@ using BrewMonster.UI; using CSNetwork.Protocols.RPCData; -using PerfectWorld.Scripts.Managers; +using BrewMonster.Scripts.Managers; using System.Collections.Generic; using System.Threading; using UnityEngine; -public class CanvasController : MonoBehaviour +namespace BrewMonster.Managers { - [SerializeField] private ScreenLogin screenLogin; - [SerializeField] private SelecScreenCharacter screenCharacter; - [SerializeField] private GameObject bgr; - [SerializeField] private GameController gameController; - - GameObject screenLoginOb; - GameObject screenCharacterOb; - private SynchronizationContext context; - - // Start is called once before the first execution of Update after the MonoBehaviour is created - void Start() + public class CanvasController : MonoBehaviour { - bgr.gameObject.SetActive(true); - screenLogin.gameObject.SetActive(true); - screenCharacter.gameObject.SetActive(false); - context = SynchronizationContext.Current; - } + [SerializeField] private ScreenLogin screenLogin; + [SerializeField] private SelecScreenCharacter screenCharacter; + [SerializeField] private GameObject bgr; + [SerializeField] private GameController gameController; - public void ShowScreenSelectCharacter(List roleInfos) - { - context.Post(_ => + GameObject screenLoginOb; + GameObject screenCharacterOb; + private SynchronizationContext context; + + // Start is called once before the first execution of Update after the MonoBehaviour is created + void Start() { - screenLogin.gameObject.SetActive(false); - screenCharacter.gameObject.SetActive(true); - screenCharacter.InitScreen(roleInfos, OnClickSelectChacter); - }, null); - } + bgr.gameObject.SetActive(true); + screenLogin.gameObject.SetActive(true); + screenCharacter.gameObject.SetActive(false); + context = SynchronizationContext.Current; + } - private void OnClickSelectChacter(RoleInfo roleInfo) - { - - } + public void ShowScreenSelectCharacter(List roleInfos) + { + context.Post(_ => + { + screenLogin.gameObject.SetActive(false); + screenCharacter.gameObject.SetActive(true); + screenCharacter.InitScreen(roleInfos, OnClickSelectChacter); + }, null); + } - private void OnDestroy() - { - + private void OnClickSelectChacter(RoleInfo roleInfo) + { + + } + + private void OnDestroy() + { + + } } } diff --git a/Assets/Scripts/Move.meta b/Assets/Scripts/Move.meta new file mode 100644 index 0000000000..478ced574a --- /dev/null +++ b/Assets/Scripts/Move.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0bc278a5921e8bc49ae3adc91a46e33c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/PlayerStateMachine.cs b/Assets/Scripts/PlayerStateMachine.cs index da9131e4e7..8d7528e566 100644 --- a/Assets/Scripts/PlayerStateMachine.cs +++ b/Assets/Scripts/PlayerStateMachine.cs @@ -1,41 +1,44 @@ using UnityEngine; -public class PlayerStateMachine +namespace BrewMonster.Scripts.Player { - PlayerState _state; - CECHostPlayer _characterCtrl; - - public PlayerState State { get => _state; } - - public void InitState(PlayerState state) + public class PlayerStateMachine { - if (_state != null) - { - Debug.LogWarning("_state is already inited"); - return; - } - _state = state; - _state.Enter(); - } + PlayerState _state; + CECHostPlayer _characterCtrl; - public void ChangeState(PlayerState state) - { - if (_state == null ) - { - Debug.LogError("you need to init state first "); - return; - } - if (_state == state) - { - Debug.LogWarning("Unchanged state"); - } - _state.Exit(); - _state = state; - _state.Enter(); - } - public void UpdateState() - { - _state.Update(); - } + public PlayerState State { get => _state; } + public void InitState(PlayerState state) + { + if (_state != null) + { + Debug.LogWarning("_state is already inited"); + return; + } + _state = state; + _state.Enter(); + } + + public void ChangeState(PlayerState state) + { + if (_state == null) + { + Debug.LogError("you need to init state first "); + return; + } + if (_state == state) + { + Debug.LogWarning("Unchanged state"); + } + _state.Exit(); + _state = state; + _state.Enter(); + } + public void UpdateState() + { + _state.Update(); + } + + } } diff --git a/Assets/Scripts/ScreenLogin.cs b/Assets/Scripts/ScreenLogin.cs index 06314e2205..1d05f569fe 100644 --- a/Assets/Scripts/ScreenLogin.cs +++ b/Assets/Scripts/ScreenLogin.cs @@ -4,35 +4,38 @@ using UnityEngine.UI; using System.Collections.Generic; using CSNetwork.Protocols.RPCData; -public class ScreenLogin : MonoBehaviour +namespace BrewMonster.Managers { - [SerializeField] private TMP_InputField ifUsername; - [SerializeField] private TMP_InputField ifPassword; - [SerializeField] private TMP_Dropdown ip; - [SerializeField] private Button btnLogin; - [SerializeField] private CanvasController canvasController; - - private void Start() + public class ScreenLogin : MonoBehaviour { - btnLogin.onClick.AddListener(OnClickBtnLogin); - } + [SerializeField] private TMP_InputField ifUsername; + [SerializeField] private TMP_InputField ifPassword; + [SerializeField] private TMP_Dropdown ip; + [SerializeField] private Button btnLogin; + [SerializeField] private CanvasController canvasController; - private void OnClickBtnLogin() - { - string _username = ifUsername.text; - string _password = ifPassword.text; - string _ip = ip.options[ip.value].text; - Debug.LogError("Login..."); - } + private void Start() + { + btnLogin.onClick.AddListener(OnClickBtnLogin); + } - private void HandleLoginComplete(List roleInfos) - { - Debug.LogError("Success"); - canvasController.ShowScreenSelectCharacter(roleInfos); - } + private void OnClickBtnLogin() + { + string _username = ifUsername.text; + string _password = ifPassword.text; + string _ip = ip.options[ip.value].text; + Debug.LogError("Login..."); + } - private void HandleLoginFaile(string reslut) - { - Debug.LogError(reslut); + private void HandleLoginComplete(List roleInfos) + { + Debug.LogError("Success"); + canvasController.ShowScreenSelectCharacter(roleInfos); + } + + private void HandleLoginFaile(string reslut) + { + Debug.LogError(reslut); + } } } diff --git a/Assets/StarterAssets/ThirdPersonController/Scripts/ThirdPersonController.cs b/Assets/StarterAssets/ThirdPersonController/Scripts/ThirdPersonController.cs index 855dea1336..3068a8777f 100644 --- a/Assets/StarterAssets/ThirdPersonController/Scripts/ThirdPersonController.cs +++ b/Assets/StarterAssets/ThirdPersonController/Scripts/ThirdPersonController.cs @@ -1,4 +1,5 @@ -锘 using UnityEngine; +锘縰sing BrewMonster.Scripts.Player; +using UnityEngine; #if ENABLE_INPUT_SYSTEM using UnityEngine.InputSystem; #endif