Merge remote-tracking branch 'origin/develop' into feature/HostAttack_Hoang
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BrewMonster;
|
||||
using BrewMonster.Scripts.World;
|
||||
using CSNetwork.GPDataType;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using ModelRenderer.Scripts.GameData;
|
||||
using PerfectWorld.Scripts.Task;
|
||||
using BrewMonster.Scripts.Task;
|
||||
using UnityEngine;
|
||||
namespace BrewMonster.Network
|
||||
{
|
||||
|
||||
@@ -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<float>;
|
||||
using ARectI = BrewMonster.Scripts.ARect<int>;
|
||||
using BlockArray = System.Collections.Generic.List<BrewMonster.Scripts.World.A3DTerrain2Block>;
|
||||
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<MeshFilter> 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
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 828eeca29c5904541bdb0f5162832508
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea4c2d97d77797548b9de5443e250290
|
||||
@@ -0,0 +1,281 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BrewMonster.Scripts
|
||||
{
|
||||
public class ARect<T> where T : IComparable<T>
|
||||
{
|
||||
public T left, top, right, bottom;
|
||||
|
||||
public ARect()
|
||||
{
|
||||
left = default(T);
|
||||
top = default(T);
|
||||
right = default(T);
|
||||
bottom = default(T);
|
||||
}
|
||||
|
||||
public ARect(ARect<T> 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<T> rc1, ARect<T> rc2)
|
||||
{
|
||||
return !(rc1 == rc2);
|
||||
}
|
||||
public static bool operator ==(ARect<T> rc1, ARect<T> rc2)
|
||||
{
|
||||
return EqualityComparer<T>.Default.Equals(rc1.left, rc2.left) &&
|
||||
EqualityComparer<T>.Default.Equals(rc1.top, rc2.top) &&
|
||||
EqualityComparer<T>.Default.Equals(rc1.right, rc2.right) &&
|
||||
EqualityComparer<T>.Default.Equals(rc1.bottom, rc2.bottom);
|
||||
}
|
||||
|
||||
// + and - operator
|
||||
public static ARect<T> operator +(ARect<T> rc1, ARect<T> 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<T> result = new ARect<T>(l + l2, t + t2, r + r2, b + b2);
|
||||
return result;
|
||||
}
|
||||
public static ARect<T> operator -(ARect<T> rc1, ARect<T> rc2)
|
||||
{
|
||||
return new ARect<T>((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<T> operator +(ARect<T> rc1, APoint<T> pt)
|
||||
//{
|
||||
// return new ARect<T>((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<T> operator -(ARect<T> rc1, APoint<T> pt)
|
||||
//{
|
||||
// return new ARect<T>((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<T> AndAssign(ARect<T> rc) => this & rc;
|
||||
public ARect<T> OrAssign(ARect<T> rc) => this | rc;
|
||||
|
||||
public static ARect<T> operator &(ARect<T> rc1, ARect<T> rc2)
|
||||
{
|
||||
if (rc1.IsEmpty() || rc2.IsEmpty())
|
||||
return new ARect<T>(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<T>(default, default, default, default);
|
||||
|
||||
return new ARect<T>(l1 > l2 ? l1 : l2,
|
||||
t1 > t2 ? t1 : t2,
|
||||
r1 < r2 ? r1 : r2,
|
||||
b1 < b2 ? b1 : b2);
|
||||
}
|
||||
|
||||
public static ARect<T> operator |(ARect<T> rc1, ARect<T> 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<T>(l1 < l2 ? l1 : l2,
|
||||
t1 < t2 ? t1 : t2,
|
||||
r1 > r2 ? r1 : r2,
|
||||
b1 > b2 ? b1 : b2);
|
||||
}
|
||||
|
||||
public static ARect<T> operator +(ARect<T> rc) { return rc; }
|
||||
public static ARect<T> operator -(ARect<T> rc)
|
||||
{
|
||||
return new ARect<T>(-(dynamic)rc.left, -(dynamic)rc.top, -(dynamic)rc.right, -(dynamic)rc.bottom);
|
||||
}
|
||||
|
||||
// = operator
|
||||
//public static ARect<T> operator = (ARect<T> rc) { left = rc.left; top = rc.top; right = rc.right; bottom = rc.bottom; return *this; }
|
||||
|
||||
// += and -= operator
|
||||
public ARect<T> AdditionAssign(ARect<T> rc)
|
||||
{
|
||||
left += (dynamic)rc.left;
|
||||
top += (dynamic)rc.top;
|
||||
right += (dynamic)rc.right;
|
||||
bottom += (dynamic)rc.bottom;
|
||||
return this;
|
||||
}
|
||||
public ARect<T> SubtractionAssign(ARect<T> rc)
|
||||
{
|
||||
left -= (dynamic)rc.left;
|
||||
top -= (dynamic)rc.top;
|
||||
right -= (dynamic)rc.right;
|
||||
bottom -= (dynamic)rc.bottom;
|
||||
return this;
|
||||
}
|
||||
//public ARect<T> AdditionAssign(APoint<T> pt) { left += pt.x; top += pt.y; right += pt.x; bottom += pt.y; return this; }
|
||||
//public ARect<T> SubtractionAssign(APoint<T> 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<T> CenterPoint() { return new APoint<T>((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<T> 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<T> 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<T> 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<T> pt) { this += pt; }
|
||||
// Set rectangle as union result
|
||||
public void SetUnion(ARect<T> rc1, ARect<T> 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<T> rc1, ARect<T> rc2)
|
||||
{
|
||||
var result = rc1 & rc2;
|
||||
left = result.left;
|
||||
right = result.right;
|
||||
bottom = result.bottom;
|
||||
top = result.top;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00eedf309b0008346a58412f4aad4dec
|
||||
@@ -1,4 +1,5 @@
|
||||
using BrewMonster;
|
||||
using BrewMonster.Managers;
|
||||
using CSNetwork.GPDataType;
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BrewMonster;
|
||||
using BrewMonster.Scripts.World;
|
||||
using CSNetwork;
|
||||
using CSNetwork.GPDataType;
|
||||
using DG.Tweening;
|
||||
|
||||
@@ -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<CBrushCell , uint> CellTable;
|
||||
// private CellTable m_CellTbl;
|
||||
|
||||
// private vector<CBrushProvider*> m_UnOrganizedProvider; //to be built.
|
||||
// private vector<CCDBrush*> 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dbb7777494908644db0a9f59f533162d
|
||||
@@ -0,0 +1,714 @@
|
||||
using CSNetwork.GPDataType;
|
||||
using PerfectWorld.Scripts.Player;
|
||||
using System;
|
||||
|
||||
namespace BrewMonster.Scripts
|
||||
{
|
||||
using WorkList = System.Collections.Generic.List<CECEPWork>;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9352b9911dad2d541b975297dcefa8d2
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using BrewMonster;
|
||||
using BrewMonster.Managers;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using CSNetwork.GPDataType;
|
||||
using PerfectWorld.Scripts.Player;
|
||||
using System;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ using UnityEngine;
|
||||
using ModelRenderer.Scripts.GameData;
|
||||
using BrewMonster;
|
||||
|
||||
namespace PerfectWorld.Scripts.Managers
|
||||
namespace BrewMonster.Scripts.Managers
|
||||
{
|
||||
public enum IndexOfIteminEquipmentInventory : byte
|
||||
{
|
||||
|
||||
@@ -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<cmd_object_atk_result>((byte[])msg.dwParam1);
|
||||
cid = pCmdAtk.attacker_id;
|
||||
break;
|
||||
// ⚠️ Các case khác cũng tương tự, chỉ việc lấy ra đúng trường id / caster / user ...
|
||||
// Do quá dài nên bạn có thể copy dần từng 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;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BrewMonster;
|
||||
using BrewMonster.Managers;
|
||||
using CSNetwork.GPDataType;
|
||||
using CSNetwork.Protocols;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -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() { }
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90848592c1c53d04e87291f2c1bfafdb
|
||||
@@ -0,0 +1,6 @@
|
||||
using UnityEngine;
|
||||
|
||||
//public class CECWorld
|
||||
//{
|
||||
|
||||
//}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f8b18d59a72e044fbcf236fe5b2991c
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 495f51cd9612ff441a012f1aea98974d
|
||||
@@ -1,6 +1,6 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace PerfectWorld.Scripts.Managers
|
||||
namespace BrewMonster.Scripts.Managers
|
||||
{
|
||||
public class NPCManager : MonoBehaviour
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ac2c48a14ff7e1478eb76c24ead3cc3
|
||||
@@ -1,4 +1,5 @@
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using CSNetwork;
|
||||
using CSNetwork.C2SCommand;
|
||||
using CSNetwork.GPDataType;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,251 +1,560 @@
|
||||
using CSNetwork.GPDataType;
|
||||
using 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ạt nhưng không phá cấu 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ằng 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ạt nhưng không phá cấu 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ằng Raycast xuống ==
|
||||
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ấy ground → bSupport=false
|
||||
}
|
||||
|
||||
// ======= STATIC OnGroundMove – GIỮ NGUYÊN VAI TRÒ TOÀN CỤ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ằng 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ằng Raycast xuống ==
|
||||
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ấy ground → bSupport=false
|
||||
}
|
||||
|
||||
// ======= STATIC OnGroundMove – GIỮ NGUYÊN VAI TRÒ TOÀN CỤ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ần bản gốc)
|
||||
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ần bản gốc)
|
||||
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)
|
||||
// “vertical 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;
|
||||
}
|
||||
|
||||
// “vertical 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
|
||||
};
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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<int>(pDataBuf);
|
||||
BMLogger.LogError($"OBJECT_ATTACK_RESULT: npc ? " + ISNPCID(id));
|
||||
//int id = GPDataTypeHelper.FromBytes<int>(pDataBuf);
|
||||
cmd_object_atk_result pCmdAtk = GPDataTypeHelper.FromBytes<cmd_object_atk_result>(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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using BrewMonster.Scripts.Player;
|
||||
using UnityEngine;
|
||||
using static CECPlayer;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using BrewMonster.Scripts.Player;
|
||||
using UnityEngine;
|
||||
using static CECPlayer;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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<cmd_object_atk_result>((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)
|
||||
// {
|
||||
// // ¿´¿´ÊDz»ÊÇÔ¶³ÌÎäÆ÷
|
||||
// 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);
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PerfectWorld.Scripts.Task
|
||||
namespace BrewMonster.Scripts.Task
|
||||
{
|
||||
public class ATaskTemplMan
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PerfectWorld.Scripts.Task
|
||||
namespace BrewMonster.Scripts.Task
|
||||
{
|
||||
public struct TASK_EXPRESSION
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PerfectWorld.Scripts.Task
|
||||
namespace BrewMonster.Scripts.Task
|
||||
{
|
||||
public interface TaskInterface
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using PerfectWorld.Scripts.Task;
|
||||
using BrewMonster.Scripts.Task;
|
||||
using UnityEngine;
|
||||
|
||||
public class TaskProcess
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace PerfectWorld.Scripts.Task
|
||||
namespace BrewMonster.Scripts.Task
|
||||
{
|
||||
public sealed class TaskConstant
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@ using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace PerfectWorld.Scripts.Task
|
||||
namespace BrewMonster.Scripts.Task
|
||||
{
|
||||
public class TaskTest : MonoBehaviour
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -1,9 +1,27 @@
|
||||
using BrewMonster;
|
||||
using BrewMonster.Scripts.Ornament;
|
||||
using UnityEngine;
|
||||
|
||||
public class CECWorld : MonoSingleton<CECWorld>
|
||||
{
|
||||
uint m_dwBornStamp = 0;
|
||||
|
||||
public uint GetBornStamp() { return m_dwBornStamp++; }
|
||||
namespace BrewMonster.Scripts.World
|
||||
{
|
||||
public class CECWorld : MonoSingleton<CECWorld>
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<RoleInfo> 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<RoleInfo> 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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0bc278a5921e8bc49ae3adc91a46e33c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<RoleInfo> 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<RoleInfo> roleInfos)
|
||||
{
|
||||
Debug.LogError("Success");
|
||||
canvasController.ShowScreenSelectCharacter(roleInfos);
|
||||
}
|
||||
|
||||
private void HandleLoginFaile(string reslut)
|
||||
{
|
||||
Debug.LogError(reslut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using BrewMonster.Scripts.Player;
|
||||
using UnityEngine;
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user