diff --git a/Assets/NetworkLib.meta b/Assets/NetworkLib.meta deleted file mode 100644 index 5b4e6dc27e..0000000000 --- a/Assets/NetworkLib.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 95c82a23114631b428b9fff51c373a39 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/NetworkLib/Debug.meta b/Assets/NetworkLib/Debug.meta deleted file mode 100644 index a8ef706c49..0000000000 --- a/Assets/NetworkLib/Debug.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: bac3638b875256b479fb1e463c6e213d -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/NetworkLib/Debug/netstandard2.1.meta b/Assets/NetworkLib/Debug/netstandard2.1.meta deleted file mode 100644 index d87e17ade3..0000000000 --- a/Assets/NetworkLib/Debug/netstandard2.1.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 464b57f0bb61a1143a27580c5fe83dca -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/NetworkLib/Debug/netstandard2.1/CSNetwork.dll b/Assets/NetworkLib/Debug/netstandard2.1/CSNetwork.dll deleted file mode 100644 index f9fc2fd74b..0000000000 Binary files a/Assets/NetworkLib/Debug/netstandard2.1/CSNetwork.dll and /dev/null differ diff --git a/Assets/PerfectWorld/Scripts/Common/CECObject.cs b/Assets/PerfectWorld/Scripts/Common/CECObject.cs index d67bce471d..008c401e0a 100644 --- a/Assets/PerfectWorld/Scripts/Common/CECObject.cs +++ b/Assets/PerfectWorld/Scripts/Common/CECObject.cs @@ -1,49 +1,43 @@ using CSNetwork.GPDataType; using UnityEngine; -public class CECObject : MonoBehaviour -{ - protected uint m_dwBornStamp; - protected bool m_bBornInSight; - protected bool m_bSelectable; - protected int m_iCID; +//public class CECObject : MonoBehaviour +//{ +// protected uint m_dwBornStamp; +// protected bool m_bBornInSight; +// protected bool m_bSelectable; +// protected int m_iCID; - public virtual void SetUpCECObject() - { - m_dwBornStamp = 0; - m_bBornInSight = false; - m_bSelectable = false; - m_iCID = (int)ClassID.OCID_OBJECT; - } - public void SetBornStamp(uint dwStamp) { m_dwBornStamp = dwStamp; } - public void SetBornInSight(bool bFlag) { m_bBornInSight = bFlag; } - public void SetSelectable(bool bSelectable) { m_bSelectable = bSelectable; } - public enum ClassID - { - OCID_OBJECT = 0, - OCID_PLAYER, - OCID_HOSTPLAYER, - OCID_ELSEPLAYER, - OCID_LOGINPLAYER, - OCID_NPC, - OCID_MONSTER, - OCID_SERVER, - OCID_MATTER, - OCID_PET, - OCID_CLONED_PLAYER, // 复制角色模型 - OCID_HOST_NAVIGATER, // 纯客户端player类,用于强制移动 - OCID_NPCCLONED_MASTER, // NPC 复制的角色模型 - }; - public enum EnviromentMoveType - { - MOVEENV_GROUND = 0, // Move on ground - MOVEENV_WATER, - MOVEENV_AIR, - } - protected void TurnFaceTo(int idTarget, float dwTime) - { - // Face to target - A3DVECTOR3 vTarget; - - } -} \ No newline at end of file +// public virtual void SetUpCECObject() +// { +// m_dwBornStamp = 0; +// m_bBornInSight = false; +// m_bSelectable = false; +// m_iCID = (int)ClassID.OCID_OBJECT; +// } +// public void SetBornStamp(uint dwStamp) { m_dwBornStamp = dwStamp; } +// public void SetBornInSight(bool bFlag) { m_bBornInSight = bFlag; } +// public void SetSelectable(bool bSelectable) { m_bSelectable = bSelectable; } +// public enum ClassID +// { +// OCID_OBJECT = 0, +// OCID_PLAYER, +// OCID_HOSTPLAYER, +// OCID_ELSEPLAYER, +// OCID_LOGINPLAYER, +// OCID_NPC, +// OCID_MONSTER, +// OCID_SERVER, +// OCID_MATTER, +// OCID_PET, +// OCID_CLONED_PLAYER, // 复制角色模型 +// OCID_HOST_NAVIGATER, // 纯客户端player类,用于强制移动 +// OCID_NPCCLONED_MASTER, // NPC 复制的角色模型 +// }; +// public enum EnviromentMoveType +// { +// MOVEENV_GROUND = 0, // Move on ground +// MOVEENV_WATER, +// MOVEENV_AIR, +// } +//} \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DFuncs.cs b/Assets/PerfectWorld/Scripts/Managers/A3DFuncs.cs new file mode 100644 index 0000000000..e5d905547c --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DFuncs.cs @@ -0,0 +1,15 @@ +using CSNetwork.GPDataType; +using UnityEngine; + +public class A3DFuncs +{ + // Returns vector with same direction and unit length + public static A3DVECTOR3 a3d_Normalize(A3DVECTOR3 v) + { + float mag = v.Magnitude(); + if (mag< 1e-12 && mag> -1e-12) + return new A3DVECTOR3(0.0f); + else + return v / mag; + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DFuncs.cs.meta b/Assets/PerfectWorld/Scripts/Managers/A3DFuncs.cs.meta new file mode 100644 index 0000000000..2120447e7f --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DFuncs.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a1b54a25c0c92e64d8292ea30bf4f1ee \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DMatrix.cs b/Assets/PerfectWorld/Scripts/Managers/A3DMatrix.cs new file mode 100644 index 0000000000..3cd2c426eb --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DMatrix.cs @@ -0,0 +1,808 @@ +using CSNetwork.GPDataType; +using System; +using UnityEngine; + +/////////////////////////////////////////////////////////////////////////// +// +// class A3DMATRIX3 +// +/////////////////////////////////////////////////////////////////////////// + +public struct A3DMATRIX3 +{ + // Construct flag + public enum CONSTRUCT + { + IDENTITY = 0, // Construct a identity matrix + CLEARED, // Construct a cleared matrix + } + + //float _11, _12, _13; + //float _21, _22, _23; + //float _31, _32, _33; + + public float[] m; + //{ + // get + // { + // return new float[9] { + // _11, _12, _13, + // _21, _22, _23, + // _31, _32, _33 + // }; + // } + // set + // { + // if (value.Length != 9 ) + // throw new ArgumentException("Matrix must be 9"); + // _11 = value[0]; _12 = value[1]; _13 = value[2]; + // _21 = value[3]; _22 = value[lenght]; _23 = value[5]; + // _31 = value[6]; _32 = value[7]; _33 = value[8]; + // } + //} + + //public A3DMATRIX3() { } + + public A3DMATRIX3(CONSTRUCT c) + { + if (c == CONSTRUCT.IDENTITY) + { + m = new float[9]{ + 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f + }; + } + else/* if (c == CONSTRUCT.CLEARED)*/ + { + m = new float[9]{ + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f + }; + } + } + + public A3DMATRIX3(float[,] arr) + { + m = new float[9]{ + arr[0, 0], arr[0, 1], arr[0, 2], + arr[1, 0], arr[1, 1], arr[1, 2], + arr[2, 0], arr[2, 1], arr[2, 2] + }; + } + + public A3DMATRIX3(A3DMATRIX3 rkMatrix) + { + m = new float[9]{ + rkMatrix.m[0], rkMatrix.m[1], rkMatrix.m[2], + rkMatrix.m[3], rkMatrix.m[4], rkMatrix.m[5], + rkMatrix.m[6], rkMatrix.m[7], rkMatrix.m[8] + }; + } + + public A3DMATRIX3(float fEntry00, float fEntry01, float fEntry02, + float fEntry10, float fEntry11, float fEntry12, + float fEntry20, float fEntry21, float fEntry22) + { + m = new float[9]{ + fEntry00, fEntry01, fEntry02, + fEntry10, fEntry11, fEntry12, + fEntry20, fEntry21, fEntry22 + }; + } + // Operations + + public A3DVECTOR3 GetRow(int i) { int row = i * 3; return new A3DVECTOR3(m[row + 0], m[row + 1], m[row + 2]); } + public A3DVECTOR3 GetCol(int i) { return new A3DVECTOR3(m[i + (0 * 3)], m[i + (1 * 3)], m[i + (2 * 3)]); } + + // * operator + public static A3DVECTOR3 operator *(A3DVECTOR3 v, A3DMATRIX3 mat) + { + return new A3DVECTOR3(v.x * mat.m[0] + v.y * mat.m[3] + v.z * mat.m[6], + v.x * mat.m[1] + v.y * mat.m[4] + v.z * mat.m[7], + v.x * mat.m[2] + v.y * mat.m[5] + v.z * mat.m[8]); + } + public static A3DVECTOR3 operator *(A3DMATRIX3 mat, A3DVECTOR3 v) + { + return new A3DVECTOR3(v.x * mat.m[0] + v.y * mat.m[3] + v.z * mat.m[6], + v.x * mat.m[1] + v.y * mat.m[4] + v.z * mat.m[7], + v.x * mat.m[2] + v.y * mat.m[5] + v.z * mat.m[8]); + } + public static A3DMATRIX3 operator *(A3DMATRIX3 mat1, A3DMATRIX3 mat2) + { + A3DMATRIX3 matRet = new A3DMATRIX3(); + int lenght = 3; + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + for (int k = 0; k < 3; k++) + matRet.m[(i * lenght) + j] += mat1.m[(i * lenght) + k] * mat2.m[(k * lenght) + j]; + } + } + return matRet; + } + + // *= operator + public A3DMATRIX3 MultiplyAssign(A3DMATRIX3 mat) + { + A3DMATRIX3 temp = this * mat; + Array.Copy(temp.m, this.m, temp.m.Length); + return this; + } + + void Transpose() + { + float t; + t = m[1]; m[1] = m[3]; m[3] = t; + t = m[2]; m[2] = m[6]; m[6] = t; + t = m[5]; m[5] = m[7]; m[7] = t; + } + + // Clear all elements to zero + void Clear() + { + m = new float[9]{ + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f + }; + } + // Set matrix to identity matrix + void Identity() + { + m = new float[9] { + 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f + }; + } + + // Build matrix to be translation and rotation matrix + void Translate(float x, float y) + { + Identity(); + m[6] = x; + m[7] = y; + } + void Rotate(float fRad) + { + Identity(); + m[4] = m[0] = (float)Math.Cos(fRad); + m[1] = (float)Math.Cos(fRad); + m[3] = -m[1]; + } +} + +public struct D3DXVECTOR3 +{ + public float X; + public float Y; + public float Z; + + // Constructors + public D3DXVECTOR3(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + } + + public D3DXVECTOR3(float[] v) + { + if (v == null || v.Length < 3) throw new ArgumentException("Array must have at least 3 elements."); + X = v[0]; + Y = v[1]; + Z = v[2]; + } + + public D3DXVECTOR3(D3DXVECTOR3 v) + { + X = v.X; + Y = v.Y; + Z = v.Z; + } + + // Unary operators + public static D3DXVECTOR3 operator +(D3DXVECTOR3 v) => v; + public static D3DXVECTOR3 operator -(D3DXVECTOR3 v) => new D3DXVECTOR3(-v.X, -v.Y, -v.Z); + + // Binary operators + public static D3DXVECTOR3 operator +(D3DXVECTOR3 a, D3DXVECTOR3 b) => + new D3DXVECTOR3(a.X + b.X, a.Y + b.Y, a.Z + b.Z); + + public static D3DXVECTOR3 operator -(D3DXVECTOR3 a, D3DXVECTOR3 b) => + new D3DXVECTOR3(a.X - b.X, a.Y - b.Y, a.Z - b.Z); + + public static D3DXVECTOR3 operator *(D3DXVECTOR3 v, float s) => + new D3DXVECTOR3(v.X * s, v.Y * s, v.Z * s); + + public static D3DXVECTOR3 operator *(float s, D3DXVECTOR3 v) => v * s; + + public static D3DXVECTOR3 operator /(D3DXVECTOR3 v, float s) + { + if (s == 0f) throw new DivideByZeroException(); + return new D3DXVECTOR3(v.X / s, v.Y / s, v.Z / s); + } + + // Assignment-style operators + public static D3DXVECTOR3 Add(ref D3DXVECTOR3 a, D3DXVECTOR3 b) + { + a.X += b.X; a.Y += b.Y; a.Z += b.Z; + return a; + } + + public static D3DXVECTOR3 Subtract(ref D3DXVECTOR3 a, D3DXVECTOR3 b) + { + a.X -= b.X; a.Y -= b.Y; a.Z -= b.Z; + return a; + } + + public static D3DXVECTOR3 Multiply(ref D3DXVECTOR3 v, float s) + { + v.X *= s; v.Y *= s; v.Z *= s; + return v; + } + + public static D3DXVECTOR3 Divide(ref D3DXVECTOR3 v, float s) + { + if (s == 0f) throw new DivideByZeroException(); + v.X /= s; v.Y /= s; v.Z /= s; + return v; + } + + // Comparison operators + public static bool operator ==(D3DXVECTOR3 a, D3DXVECTOR3 b) => + a.X == b.X && a.Y == b.Y && a.Z == b.Z; + + public static bool operator !=(D3DXVECTOR3 a, D3DXVECTOR3 b) => + !(a == b); + + public override bool Equals(object obj) + { + if (obj is D3DXVECTOR3 v) return this == v; + return false; + } + + public override int GetHashCode() => HashCode.Combine(X, Y, Z); + + // Magnitude and Normalize + public float Magnitude() => (float)Math.Sqrt(X * X + Y * Y + Z * Z); + + public D3DXVECTOR3 Normalize() + { + float mag = Magnitude(); + if (Math.Abs(mag) < 1e-12f) return new D3DXVECTOR3(0f, 0f, 0f); + return this / mag; + } +} + + +/////////////////////////////////////////////////////////////////////////// +// +// class A3DMATRIX4 +// +/////////////////////////////////////////////////////////////////////////// + +public struct A3DMATRIX4 +{ + // Construct flag + public enum CONSTRUCT + { + IDENTITY = 0, // Construct a identity matrix + } + + //float _11, _12, _13, _14; + //float _21, _22, _23, _24; + //float _31, _32, _33, _34; + //float _41, _42, _43, _44; + + public float[] m; + //{ + // get + // { + // return new float[16] { + // _11, _12, _13, _14, + // _21, _22, _23, _24, + // _31, _32, _33, _34, + // _41, _42, _43, _44 + // }; + // } + // set + // { + // if (value.Length != 16) + // throw new ArgumentException("Matrix must be range 16"); + // _11 = value[0]; _12 = value[1]; _13 = value[2]; _14 = value[3]; + // _21 = value[4]; _22 = value[5]; _23 = value[6]; _24 = value[7]; + // _31 = value[8]; _32 = value[9]; _33 = value[10]; _34 = value[11]; + // _41 = value[12]; _42 = value[13]; _43 = value[14]; _44 = value[15]; + // } + //} + + // Constructions and Destructions + + public A3DMATRIX4(float[] v) + { + m = new float[16]; + for (int i = 0; i < 16; i++) + { + m[i] = v[i]; + } + } + + public A3DMATRIX4(A3DMATRIX4 mat) + { + float _11 = mat.m[0], _12 = mat.m[1], _13 = mat.m[2], _14 = mat.m[3]; + float _21 = mat.m[4], _22 = mat.m[5], _23 = mat.m[6], _24 = mat.m[7]; + float _31 = mat.m[8], _32 = mat.m[9], _33 = mat.m[10], _34 = mat.m[11]; + float _41 = mat.m[12], _42 = mat.m[13], _43 = mat.m[14], _44 = mat.m[15]; + m = new float[16] { + _11, _12, _13, _14, + _21, _22, _23, _24, + _31, _32, _33, _34, + _41, _42, _43, _44 + }; + } + + public A3DMATRIX4(CONSTRUCT c) + { + m = new float[16] { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + public A3DMATRIX4(float fEntry00, float fEntry01, float fEntry02, float fEntry03, + float fEntry10, float fEntry11, float fEntry12, float fEntry13, + float fEntry20, float fEntry21, float fEntry22, float fEntry23, + float fEntry30, float fEntry31, float fEntry32, float fEntry33) + { + m = new float[16] { + fEntry00, fEntry01, fEntry02, fEntry03, + fEntry10, fEntry11, fEntry12, fEntry13, + fEntry20, fEntry21, fEntry22, fEntry23, + fEntry30, fEntry31, fEntry32, fEntry33 + }; + } + // Operaitons + + // Get row and column + public A3DVECTOR3 GetRow(int i) { int row = i * 4; return new A3DVECTOR3(m[row + 0], m[row + 1], m[row + 2]); } + public A3DVECTOR3 GetCol(int i) { return new A3DVECTOR3(m[(0 * 4) + i], m[(1 * 4) + i], m[(2 * 4) + i]); } + // Set row and column + public void SetRow(int i, A3DVECTOR3 v) { int row = i * 4; m[row + 0] = v.x; m[row + 1] = v.y; m[row + 2] = v.z; } + public void SetCol(int i, A3DVECTOR3 v) { m[(0 * 3) + i] = v.x; m[(1 * 3) + i] = v.y; m[(2 * 3) + i] = v.z; } + + // * operator + public static A3DVECTOR3 operator *(A3DVECTOR3 v, A3DMATRIX4 mat) + { + A3DVECTOR3 vRet = new A3DVECTOR3(v.x * mat.m[0] + v.y * mat.m[4] + v.z * mat.m[8] + mat.m[12], + v.x * mat.m[1] + v.y * mat.m[5] + v.z * mat.m[9] + mat.m[13], + v.x * mat.m[2] + v.y * mat.m[6] + v.z * mat.m[10] + mat.m[14]); + float w = 1.0f / (v.x * mat.m[3] + v.y * mat.m[7] + v.z * mat.m[11] + mat.m[15]); + return vRet *= w; + } + public static A3DVECTOR3 operator *(A3DMATRIX4 mat, A3DVECTOR3 v) + { + A3DVECTOR3 vRet = new A3DVECTOR3(v.x * mat.m[0] + v.y * mat.m[4] + v.z * mat.m[8] + mat.m[12], + v.x * mat.m[1] + v.y * mat.m[5] + v.z * mat.m[9] + mat.m[13], + v.x * mat.m[2] + v.y * mat.m[6] + v.z * mat.m[10] + mat.m[14]); + float w = 1.0f / (v.x * mat.m[3] + v.y * mat.m[7] + v.z * mat.m[11] + mat.m[15]); + return vRet *= w; + } + + + public static A3DVECTOR4 operator *(A3DVECTOR4 v, A3DMATRIX4 mat) + { + return new A3DVECTOR4(v.m[0] * mat.m[0] + v.m[1] * mat.m[4] + v.m[2] * mat.m[8] + v.m[3] * mat.m[12], + v.m[0] * mat.m[1] + v.m[1] * mat.m[5] + v.m[2] * mat.m[9] + v.m[3] * mat.m[13], + v.m[0] * mat.m[2] + v.m[1] * mat.m[6] + v.m[2] * mat.m[10] + v.m[0] * mat.m[14], + v.m[0] * mat.m[3] + v.m[1] * mat.m[7] + v.m[2] * mat.m[11] + v.m[3] * mat.m[15]); + } + public static A3DVECTOR4 operator *(A3DMATRIX4 mat, A3DVECTOR4 v) + { + return new A3DVECTOR4(v.m[0] * mat.m[0] + v.m[1] * mat.m[4] + v.m[2] * mat.m[8] + v.m[3] * mat.m[12], + v.m[0] * mat.m[1] + v.m[1] * mat.m[5] + v.m[2] * mat.m[9] + v.m[3] * mat.m[13], + v.m[0] * mat.m[2] + v.m[1] * mat.m[6] + v.m[2] * mat.m[10] + v.m[3] * mat.m[14], + v.m[0] * mat.m[3] + v.m[1] * mat.m[7] + v.m[2] * mat.m[11] + v.m[3] * mat.m[15]); + } + public static A3DMATRIX4 operator *(A3DMATRIX4 mat1, A3DMATRIX4 mat2) + { + A3DMATRIX4 matRet = new A3DMATRIX4(); + int lenght = 4; + for (int i = 0; i < lenght; i++) + { + for (int j = 0; j < lenght; j++) + { + for (int k = 0; k < lenght; k++) + //matRet.m[i,j] += mat1.m[i,k] * mat2.m[k,j]; + matRet.m[(i * lenght) + j] += mat1.m[(i * lenght) + k] * mat2.m[(k * lenght) + j]; + + } + } + return matRet; + } + + // Scale matrix + public static A3DMATRIX4 operator *(A3DMATRIX4 mat, float s) + { + A3DMATRIX4 matRet = new A3DMATRIX4(); + int lenght = 4; + for (int i = 0; i < lenght; i++) + { + for (int j = 0; j < lenght; j++) + matRet.m[(i * lenght) + j] = mat.m[(i * lenght) + j] * s; + } + + return matRet; + } + public static A3DMATRIX4 operator *(float s, A3DMATRIX4 mat) { return mat * s; } + public static A3DMATRIX4 operator /(A3DMATRIX4 mat, float s) { return mat * (1.0f / s); } + + // *= operator + public A3DMATRIX4 MultiplyAssign(A3DMATRIX4 mat) + { + A3DMATRIX4 temp = this * mat; + Array.Copy(temp.m, this.m, temp.m.Length); + return this; + } + public A3DMATRIX4 MultiplyAssign(float s) + { + A3DMATRIX4 temp = this; + int lenght = 4; + for (int i = 0; i < lenght; i++) + { + for (int j = 0; j < lenght; j++) + m[(i * lenght) + j] *= s; + } + Array.Copy(temp.m, this.m, temp.m.Length); + return this; + } + // /= operator + public A3DMATRIX4 DivisionAssign(float s) { return MultiplyAssign(1.0f / s); } + + // == operator + public static bool operator ==(A3DMATRIX4 mat1, A3DMATRIX4 mat2) + { + int lenght = 4; + for (int i = 0; i < lenght; i++) + { + for (int j = 0; j < lenght; j++) + { + if (mat1.m[(i * lenght) + j] != mat2.m[(i * lenght) + j]) + return false; + } + } + return true; + } + + // != operator + public static bool operator !=(A3DMATRIX4 mat1, A3DMATRIX4 mat2) + { + int lenght = 4; + for (int i = 0; i < lenght; i++) + { + for (int j = 0; j < lenght; j++) + { + if (mat1.m[(i * lenght) + j] != mat2.m[(i * lenght) + j]) + return true; + } + } + return false; + } + + // + operator + public static A3DMATRIX4 operator +(A3DMATRIX4 mat1, A3DMATRIX4 mat2) + { + A3DMATRIX4 matRet = new A3DMATRIX4(); + int lenght = 4; + for (int i = 0; i < lenght; i++) + { + for (int j = 0; j < lenght; j++) + matRet.m[(i * lenght) + j] = mat1.m[(i * lenght) + j] + mat2.m[(i * lenght) + j]; + } + return matRet; + } + // - operator + public static A3DMATRIX4 operator -(A3DMATRIX4 mat1, A3DMATRIX4 mat2) + { + int lenght = 4; + A3DMATRIX4 matRet = new A3DMATRIX4(); + for (int i = 0; i < lenght; i++) + { + for (int j = 0; j < lenght; j++) + matRet.m[(i * lenght) + j] = mat1.m[(i * lenght) + j] - mat2.m[(i * lenght) + j]; + } + + return matRet; + } + // += operator + public A3DMATRIX4 AdditionAssign(A3DMATRIX4 mat) + { + int lenght = 4; + A3DMATRIX4 temp = this; + for (int i = 0; i < lenght; i++) + { + for (int j = 0; j < lenght; j++) + m[(i * lenght) + j] += mat.m[(i * lenght) + j]; + } + Array.Copy(temp.m, this.m, temp.m.Length); + return this; + } + // -= operator + public A3DMATRIX4 SubtractionAssign(A3DMATRIX4 mat) + { + int lenght = 4; + A3DMATRIX4 temp = this; + for (int i = 0; i < lenght; i++) + { + for (int j = 0; j < lenght; j++) + m[(i * lenght) + j] -= mat.m[(i * lenght) + j]; + } + Array.Copy(temp.m, this.m, temp.m.Length); + return this; + } + + // Clear all elements to zero + public void Clear() + { + m = new float[16] { + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f + }; + } + // Set matrix to identity matrix + public void Identity() + { + m = new float[16] { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + // Transpose matrix + public void Transpose() + { + float t = 0f; + t = m[1]; m[1] = m[4]; m[4] = t; + t = m[2]; m[2] = m[8]; m[8] = t; + t = m[3]; m[3] = m[12]; m[2] = t; + t = m[6]; m[6] = m[9]; m[9] = t; + t = m[7]; m[7] = m[13]; m[3] = t; + t = m[11]; m[11] = m[4]; m[4] = t; + } + // Get transpose matrix of this matrix + public A3DMATRIX4 GetTranspose() + { + int lenght = 4; + A3DMATRIX4 matRet = new A3DMATRIX4(); + for (int i = 0; i < lenght; i++) + { + for (int j = 0; j < lenght; j++) + matRet.m[(i * lenght) + j] = m[(j * lenght) + i]; + } + + return matRet; + } + // Inverse matrix + // void Inverse() { *this = GetInverse(); } + // Get inverse matrix of this matrix + // A3DMATRIX4 GetInverse() const; + // Inverse matrix (used only by transform matrix) + public void InverseTM() + { + A3DMATRIX4 temp = GetInverseTM(); + Array.Copy(temp.m, this.m, temp.m.Length); + } + // Get inverse matrix (used only by transform matrix) + public A3DMATRIX4 GetInverseTM() + { + float _11 = m[0], _12 = m[1], _13 = m[2], _14 = m[3]; + float _21 = m[4], _22 = m[5], _23 = m[6], _24 = m[7]; + float _31 = m[8], _32 = m[9], _33 = m[10], _34 = m[11]; + float _41 = m[12], _42 = m[13], _43 = m[14], _44 = m[15]; + + float fDet = 1.0f / Det3x3(_11, _12, _13, _21, _22, _23, _31, _32, _33); + + A3DMATRIX4 mat = new A3DMATRIX4(); + + mat.m[0] = fDet * Det3x3(_22, _23, _24, _32, _33, _34, _42, _43, _44); + mat.m[1] = -fDet * Det3x3(_12, _13, _14, _32, _33, _34, _42, _43, _44); + mat.m[2] = fDet * Det3x3(_12, _13, _14, _22, _23, _24, _42, _43, _44); + mat.m[3] = -fDet * Det3x3(_12, _13, _14, _22, _23, _24, _32, _33, _34); + + mat.m[4] = -fDet * Det3x3(_21, _23, _24, _31, _33, _34, _41, _43, _44); + mat.m[5] = fDet * Det3x3(_11, _13, _14, _31, _33, _34, _41, _43, _44); + mat.m[6] = -fDet * Det3x3(_11, _13, _14, _21, _23, _24, _41, _43, _44); + mat.m[7] = fDet * Det3x3(_11, _13, _14, _21, _23, _24, _31, _33, _34); + + mat.m[8] = fDet * Det3x3(_21, _22, _24, _31, _32, _34, _41, _42, _44); + mat.m[9] = -fDet * Det3x3(_11, _12, _14, _31, _32, _34, _41, _42, _44); + mat.m[10] = fDet * Det3x3(_11, _12, _14, _21, _22, _24, _41, _42, _44); + mat.m[11] = -fDet * Det3x3(_11, _12, _14, _21, _22, _24, _31, _32, _34); + + mat.m[12] = -fDet * Det3x3(_21, _22, _23, _31, _32, _33, _41, _42, _43); + mat.m[13] = fDet * Det3x3(_11, _12, _13, _31, _32, _33, _41, _42, _43); + mat.m[14] = -fDet * Det3x3(_11, _12, _13, _21, _22, _23, _41, _42, _43); + mat.m[15] = fDet * Det3x3(_11, _12, _13, _21, _22, _23, _31, _32, _33); + + return mat; + } + // Get determinant of this matrix + public float Determinant() + { + float _11 = m[0], _12 = m[1], _13 = m[2], _14 = m[3]; + float _21 = m[4], _22 = m[5], _23 = m[6], _24 = m[7]; + float _31 = m[8], _32 = m[9], _33 = m[10], _34 = m[11]; + float _41 = m[12], _42 = m[13], _43 = m[14], _44 = m[15]; + + float fDet = 0f; + fDet = _11 * _22 * _33 * _44; + fDet += _21 * _32 * _43 * _14; + fDet += _31 * _42 * _13 * _24; + fDet += _41 * _12 * _23 * _34; + fDet -= _41 * _32 * _23 * _14; + fDet -= _42 * _33 * _24 * _11; + fDet -= _43 * _34 * _21 * _12; + fDet -= _44 * _31 * _22 * _13; + return fDet; + } + + // Build matrix to be translation and rotation matrix + public void Translate(float x, float y, float z) + { + Identity(); + m[12] = x; + m[13] = y; + m[14] = z; + } + public void RotateX(float fRad) + { + Identity(); + m[10] = m[5] = Mathf.Cos(fRad); + m[6] = Mathf.Sin(fRad); + m[9] = -m[6]; + } + public void RotateY(float fRad) + { + Identity(); + m[10] = m[0] = Mathf.Cos(fRad); + m[8] = Mathf.Sin(fRad); + m[2] = -m[8]; + } + public void RotateZ(float fRad) + { + Identity(); + m[5] = m[0] = Mathf.Cos(fRad); + m[1] = Mathf.Sin(fRad); + m[4] = -m[1]; + } + public void RotateAxis(A3DVECTOR3 v, float fRad) + { + float fCos = Mathf.Cos(fRad); + float fSin = Mathf.Sin(fRad); + + m[0] = (v.x * v.x) * (1.0f - fCos) + fCos; + m[4] = (v.x * v.y) * (1.0f - fCos) - (v.z * fSin); + m[8] = (v.x * v.x) * (1.0f - fCos) + (v.y * fSin); + + m[1] = (v.y * v.y) * (1.0f - fCos) + (v.z * fSin); + m[5] = (v.y * v.y) * (1.0f - fCos) + fCos; + m[9] = (v.y * v.z) * (1.0f - fCos) - (v.x * fSin); + + m[2] = (v.z * v.x) * (1.0f - fCos) - (v.y * fSin); + m[6] = (v.z * v.y) * (1.0f - fCos) + (v.x * fSin); + m[10] = (v.z * v.z) * (1.0f - fCos) + fCos; + + m[3] = m[7] = m[11] = 0.0f; + m[12] = m[13] = m[14] = 0.0f; + m[15] = 1.0f; + } + public void RotateAxis(A3DVECTOR3 vPos, A3DVECTOR3 vAxis, float fRad) + { + Translate(-vPos.x, -vPos.y, -vPos.z); + + A3DMATRIX4 mat = new A3DMATRIX4(); + mat.RotateAxis(vAxis, fRad); + MultiplyAssign(mat); + mat.Translate(vPos.x, vPos.y, vPos.z); + MultiplyAssign(mat); + } + public void Scale(float sx, float sy, float sz) + { + Clear(); + m[0] = sx; + m[5] = sy; + m[10] = sz; + m[15] = 1.0f; + } + + + // Calcualte determinant of a 3x3 matrix + public float Det3x3(float a11, float a12, float a13, float a21, float a22, float a23, + float a31, float a32, float a33) + { + return a11 * a22 * a33 + a21 * a32 * a13 + a31 * a12 * a23 - + a13 * a22 * a31 - a23 * a32 * a11 - a33 * a12 * a21; + } + +} +////////////////////////////////////////////////////////////////////////// +// +// class A3DVECTOR4 +// +/////////////////////////////////////////////////////////////////////////// + +public struct A3DVECTOR4 +{ + float x; + float y; + float z; + float w; + + public float[] m; + //{ + // get => new float[] { x, y, z, w }; + // set + // { + // if (value == null || value.Length < 4) + // throw new ArgumentException("Array must have at least 4 elements."); + // x = value[0]; + // y = value[1]; + // z = value[2]; + // w = value[3]; + // } + //} + + // Constructors and Destructors + public A3DVECTOR4(float _x, float _y, float _z, float _w) + { + x = _x; + y = _y; + z = _z; + w = _w; + m = new float[] { x, y, z, w }; + } + public A3DVECTOR4(float f) + { + x = y = z = w = f; + m = new float[] { x, y, z, w }; + } + public A3DVECTOR4(float[] f) + { + if (f == null || f.Length < 4) + throw new ArgumentException("Array must have at least 4 elements."); + x = f[0]; y = f[1]; z = f[2]; w = f[3]; + m = new float[] { x, y, z, w }; + } + public A3DVECTOR4(A3DVECTOR4 v) + { + x = v.x; y = v.y; z = v.z; w = v.w; + m = new float[] { x, y, z, w }; + } + public A3DVECTOR4(A3DVECTOR3 v) + { + x = v.x; y = v.y; z = v.z; w = 1.0f; + m = new float[] { x, y, z, w }; + } + + // Operations + + // = operator + public A3DVECTOR4 assignment(A3DVECTOR4 v) + { + x = v.x; y = v.y; z = v.z; w = v.w; return this; + } + public A3DVECTOR4 assignment(A3DVECTOR3 v) { x = v.x; y = v.y; z = v.z; w = 1.0f; return this; } + + public void Set(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } + public void Clear() { x = y = z = w = 0.0f; } +}; + + diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DMatrix.cs.meta b/Assets/PerfectWorld/Scripts/Managers/A3DMatrix.cs.meta new file mode 100644 index 0000000000..1d6dee9aac --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DMatrix.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: cc8e1e1d27a1f8f4e8995615fba55f2b \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs b/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs index 33def69a3f..4e25d1fc29 100644 --- a/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs +++ b/Assets/PerfectWorld/Scripts/Managers/CECNPCMan.cs @@ -7,9 +7,6 @@ using System.Buffers.Binary; using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine; -using UnityEngine.LightTransport; -using static CECNPC; -using static CECObject; public class CECNPCMan : CECObject, IMsgHandler { @@ -21,7 +18,7 @@ public class CECNPCMan : CECObject, IMsgHandler public CECNPCMan() { m_vServerPos = Vector3.zero; - m_iCID = (int)ClassID.OCID_MONSTER; + m_iCID = (int)Class_ID.OCID_MONSTER; } public bool ProcessMessage(ECMSG Msg) { diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs new file mode 100644 index 0000000000..12da223e03 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs @@ -0,0 +1,674 @@ +using System.Security.Cryptography; +using Unity.VisualScripting; +using WorkList = System.Collections.Generic.List; + +public class CECHPWork : CECObjectWork +{ + // Host work ID + public static class Host_work_ID + { + public const int WORK_INVALID = -1, + WORK_STAND = 0, // Stand and do nothing + WORK_MOVETOPOS = 1, // Move to a destination terrain position + WORK_TRACEOBJECT = 2, // Trace specified object (NPC, player etc.) + WORK_HACKOBJECT = 3, // Hack specified object (NPC, player etc.) + WORK_SPELLOBJECT = 4, // Spell magic on specified object (NPC, player etc.) + WORK_USEITEM = 5, // Host use item + WORK_DEAD = 6, // Host is dead + WORK_FOLLOW = 7, // Follow some one else + WORK_FLYOFF = 8, // Fly off + WORK_FREEFALL = 9, // Free fall + WORK_SIT = 10, // Sit + WORK_PICKUP = 11, // Pickup item + WORK_CONCENTRATE = 12, // All concentrate work + WORK_REVIVE = 13, // Revive + WORK_FLASHMOVE = 14, // Flash move + WORK_BEBOUND = 15, // Be bound by buddy + WORK_PASSIVEMOVE = 16, // Passive movement (knock back / pull) + WORK_CONGREGATE = 17, // Congregate reply + WORK_SKILLSTATEACT = 18, // skill buff action + WORK_FORCENAVIGATEMOVE = 19, // force navigate move + NUM_WORK = 20; + } + + protected static class Work_mask + { + public const uint MASK_STAND = 0x0001, + MASK_MOVETOPOS = 0x0002, + MASK_TRACEOBJECT = 0x0004, + MASK_HACKOBJECT = 0x0008, + MASK_SPELLOBJECT = 0x0010, + MASK_USEITEM = 0x0020, + MASK_DEAD = 0x0040, + MASK_FOLLOW = 0x0080, + MASK_FLYOFF = 0x0100, + MASK_FREEFALL = 0x0200, + MASK_SIT = 0x0400, + MASK_PICKUP = 0x0800, + MASK_CONCENTRATE = 0x1000, + MASK_REVIVE = 0x2000, + MASK_FLASHMOVE = 0x4000, + MASK_BEBOUND = 0x8000, + MASK_CONGREGATE = 0x10000, + MASK_SKILLSTATEACT = 0x20000, + MASK_FORCENAVIGATE = 0x40000; + public const uint MASK_ALLWORK = 0xffffffff; + } + + protected CECHPWorkMan m_pWorkMan; // Work manager + protected CECHostPlayer m_pHost; // Host player object + + public CECHPWork(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID) + { + m_pWorkMan = pWorkMan; + m_pHost = pWorkMan.GetHostPlayer(); + } + + // Operations + // Override from CECObjectWork + public virtual void Cancel() + { + + } + // This work is do player moving ? + public virtual bool IsMoving() + { + return false; + } + // Copy work data + public virtual bool CopyData(CECHPWork pWork) + { + m_bFinished = pWork.m_bFinished; + m_bFirstTick = pWork.m_bFirstTick; + return true; + } + + public string GetWorkName() + { + return GetWorkName(GetWorkID()); + } + public static uint GetWorkMask(int iWorkID) + { + if (!Validate(iWorkID)) + { + return 0; + } + uint[] l_workMask = new uint[]{ + Work_mask.MASK_STAND, + Work_mask.MASK_MOVETOPOS, + Work_mask.MASK_TRACEOBJECT, + Work_mask.MASK_HACKOBJECT, + Work_mask.MASK_SPELLOBJECT, + Work_mask.MASK_USEITEM, + Work_mask.MASK_DEAD, + Work_mask.MASK_FOLLOW, + Work_mask.MASK_FLYOFF, + Work_mask.MASK_FREEFALL, + Work_mask.MASK_SIT, + Work_mask.MASK_PICKUP, + Work_mask.MASK_CONCENTRATE, + Work_mask.MASK_REVIVE, + Work_mask.MASK_FLASHMOVE, + Work_mask.MASK_BEBOUND, + Work_mask.MASK_CONGREGATE, + Work_mask.MASK_SKILLSTATEACT, + Work_mask.MASK_FORCENAVIGATE, + }; + return l_workMask[iWorkID]; + } + public static bool Validate(int iWorkID) + { + return iWorkID >= 0 && iWorkID < Host_work_ID.NUM_WORK; + } + + public static string GetWorkName(int iWorkID) + { + string[] l_WorkName = new string[Host_work_ID.NUM_WORK] + { + "WORK_STAND", + "WORK_MOVETOPOS", + "WORK_TRACEOBJECT", + "WORK_HACKOBJECT", + "WORK_SPELLOBJECT", + "WORK_USEITEM", + "WORK_DEAD", + "WORK_FOLLOW", + "WORK_FLYOFF", + "WORK_FREEFALL", + "WORK_SIT", + "WORK_PICKUP", + "WORK_CONCENTRATE", + "WORK_REVIVE", + "WORK_FLASHMOVE", + "WORK_BEBOUND", + "WORK_PASSIVEMOVE", + "WORK_CONGREGATE", + "WORK_SKILLSTATEACT", + "WORK_FORCENAVIGATEMOVE" + }; + if (Validate(iWorkID)) + { + return l_WorkName[iWorkID]; + } + else if (iWorkID == Host_work_ID.WORK_INVALID) + { + return "WORK_INVALID"; + } + else + { + return "Unknown"; + } + } +} + +/////////////////////////////////////////////////////////////////////////// +// +// Class CECHPWorkMan +// +/////////////////////////////////////////////////////////////////////////// +public class CECHPWorkMan +{ + // Work priority + public static class Work_priority + { + public const int PRIORITY_0 = 0, + PRIORITY_1 = 1, + PRIORITY_2 = 2, + NUM_PRIORITY = 3; + }; + + // Delayed work info. + public struct DELAYWORK + { + public int iPriority; + public CECHPWork pWork; + } + + private CECHostPlayer m_pHost; + private WorkList[] m_WorkStack = new WorkList[Work_priority.NUM_PRIORITY]; + private int m_iCurPriority; + private DELAYWORK m_Delayed; + private CECHPWorkPostTickCommand m_pPostTickCommand; + + public CECHPWorkMan(CECHostPlayer pHost) + { + m_pHost = pHost; + m_iCurPriority = -1; + m_Delayed = new DELAYWORK + { + iPriority = 0, + pWork = null + }; + m_pPostTickCommand = null; + } + + public CECHPWork GetRunningWork(int iWorkID) + { + CECHPWork result = null; + if (ValidatePriority(m_iCurPriority)) + { + WorkList workList = m_WorkStack[m_iCurPriority]; + for (int i = 0; i < workList.Count; ++i) + { + if (iWorkID == workList[i].GetWorkID()) + { + result = workList[i]; + break; + } + } + } + return result; + } + public CECHPWork GetWork(int iWorkID, int iPriority = Work_priority.PRIORITY_1, bool bIncludeDelayedWork = false) + { + CECHPWorkGeneralMatcher cECHPWork = new CECHPWorkGeneralMatcher(iWorkID, iPriority, bIncludeDelayedWork); + return GetWork(cECHPWork); + } + public CECHPWork GetWork(CECHPWorkMatcher matcher) + { + CECHPWork result = null; + for (int i = (Work_priority.NUM_PRIORITY - 1); i >= 0; --i) + { + WorkList workList = m_WorkStack[i]; + for (int j = 0; j < workList.Count; ++j) + { + CECHPWork pWork = workList[j]; + if (matcher.Match(pWork, i, false)) + { + result = pWork; + break; + } + } + } + if (result == null && GetDelayedWork() != null && matcher.Match(m_Delayed.pWork, m_Delayed.iPriority, true)) + { + result = GetDelayedWork(); + } + return result; + } + + bool InternallyStartWork(int iPriority, CECHPWork pWork) + { + bool bStarted = false; + if (CanRunSimultaneouslyWithCurrentWork(iPriority, pWork)) + { + WorkList workList = m_WorkStack[iPriority]; + workList.Add(pWork); + bStarted = true; + //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started simultaneously, priority=%d", pWork->GetWorkName(), iPriority)); + } + else + { + if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_DEAD) + { + for (int i = iPriority; i < Work_priority.NUM_PRIORITY; i++) + { + FinishWorkAtPriority(i); + } + ClearDelayedWork(); + WorkList workList = m_WorkStack[iPriority]; + workList.Add(pWork); + m_iCurPriority = iPriority; + bStarted = true; + } + else + { + bool shouldStart = (iPriority >= m_iCurPriority); + FinishWorkAtPriority(iPriority); + WorkList workList = m_WorkStack[iPriority]; + workList.Add(pWork); + if (shouldStart) + { + if (iPriority > m_iCurPriority) + { + CancelWorkAtPriority(m_iCurPriority); + } + m_iCurPriority = iPriority; + bStarted = true; + } + } + //if (bStarted) + //{ + // LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started, priority=%d", pWork->GetWorkName(), iPriority)); + //} + //else + //{ + // LOG_DEBUG_INFO(AString().Format("CECHPWork::%s add to priority queue %d", pWork->GetWorkName(), iPriority)); + //} + } + return bStarted; + } + bool CanRunSimultaneouslyWithCurrentWork(int iPriority, CECHPWork pWork) + { + if (!ValidatePriority(iPriority) || iPriority != m_iCurPriority) + { + return false; + } + WorkList workList = m_WorkStack[iPriority]; + if (workList == null || workList.Count == 0) + { + return false; + } + + foreach (var work in workList) + { + if (!CanRunSimultaneously(work, pWork)) + { + return false; + } + } + return true; + } + bool CanRunSimultaneously(CECHPWork pWork1, CECHPWork pWork2) + { + if (pWork1.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS && + pWork2.GetWorkID() == CECHPWork.Host_work_ID.WORK_SPELLOBJECT) + { + return CanSpellWhileMoving(pWork2 as CECHPWorkSpell); + } + if (pWork2.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS && + pWork1.GetWorkID() == CECHPWork.Host_work_ID.WORK_SPELLOBJECT) + { + return CanSpellWhileMoving(pWork1 as CECHPWorkSpell); + } + return false; + } + bool CanSpellWhileMoving(CECHPWorkSpell pWorkSpell) + { + //return pWorkSpell.GetSkill() + // && CECCastSkillWhenMove::Instance().IsSkillSupported(pWorkSpell->GetSkill()->GetSkillID(), m_pHost); + return false; + } + void StartAwaitingWorks() + { + if (ValidatePriority(m_iCurPriority)) + { + for (--m_iCurPriority; m_iCurPriority >= 0; --m_iCurPriority) + { + WorkList workList = m_WorkStack[m_iCurPriority]; + if (workList == null || workList.Count == 0) + { + continue; + } + foreach (var work in workList) + { + work.OnWorkShift(); + //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started by decrease priority, priority=%d", workList[j]->GetWorkName(), m_iCurPriority)); + } + break; + } + } + StartDelayedWork(); + } + + void FinishWorkAtPriority(int iPriority) + { + if (!ValidatePriority(iPriority)) + { + return; + } + WorkList workList = m_WorkStack[iPriority]; + while ((workList != null && workList.Count > 0)) + { + KillWork(iPriority, 0); + } + if (m_iCurPriority == iPriority) + { + m_iCurPriority = -1; + } + } + + void KillWork(int iPriority, int index) + { + if (!ValidatePriority(iPriority)) + { + return; + } + WorkList workList = m_WorkStack[iPriority]; + if (index < 0 || index >= workList.Count) + { + return; + } + CECHPWork pWork = workList[index]; + KillWork(pWork); + //LOG_DEBUG_INFO(AString().Format("CECHPWork::%s priority=%d killed", pWork->GetWorkName(), iPriority)); + //delete pWork; + workList.RemoveAt(index); + } + void KillWork(CECHPWork pWork) + { + if (pWork == null) + { + return; + } + if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS) + { + CECHPWorkMove pWorkMove = pWork as CECHPWorkMove; + if (pWorkMove != null) + { + if (pWorkMove.GetAutoMove()) + { + //pWorkMove.Finish(); + } + else + { + pWorkMove.Cancel(); + } + } + } + else + { + pWork.Cancel(); + } + } + + public void CancelWork(CECHPWork pWork) + { + + } + public void CancelWorkAtPriority(int iPriority) + { + + } + + public bool DelayWork(int iPriority, CECHPWork pWork) + { + return false; + } + public void StartDelayedWork() + { + + } + public void ClearDelayedWork() + { + + } + public CECHPWork GetDelayedWork() + { + return m_Delayed.pWork; + } + + public bool ValidatePriority(int iPriority) + { + return iPriority >= 0 && iPriority < Work_priority.NUM_PRIORITY; + } + + public bool StartWork(int iPriority, CECHPWork pWork, bool bNoDelay = false) + { + if (pWork == null) + { + return false; + } + if (!ValidatePriority(iPriority)) + { + return false; + } + //if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_TRACEOBJECT) + //{ + // if (g_pGame->GetGameRun()->GetHostInputFilter()->IsMoveUsagePressed()) + // { + // CECHPWorkTrace pWorkTrace = pWork as CECHPWorkTrace; + // if (!pWorkTrace.CanTouch()) + // { // 2014-8-16 当还在通过键盘操纵移动时、有条件忽略 CECHPWorkTrace, + // //delete pWorkTrace; // 否则会因 CECHPWorkTrace 中临时转向目标位置、而后又被键盘操纵调整移动方向导致方向瞬间抖动 + // return false; // 当 CECHPWorkTrace 中目标可立即接触时,不忽略 CECHPWorkTrace,以实现键盘控制移动中、对某怪应用技能时,立刻转向怪施放技能 + // } + // } + //} + if (!bNoDelay && DelayWork(iPriority, pWork)) + { + return true; + } + return InternallyStartWork(iPriority, pWork); + } + public bool StartWork_p0(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_0, pWork, bNoDelay); } + public bool StartWork_p1(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_1, pWork, bNoDelay); } + public bool StartWork_p2(CECHPWork pWork, bool bNoDelay = false) { return StartWork(Work_priority.PRIORITY_2, pWork, bNoDelay); } + public CECHostPlayer GetHostPlayer() { return m_pHost; } + + public CECHPWork CreateWork(int idWork) + { + CECHPWork pWork = null; + + switch (idWork) + { + //case CECHPWork.Host_work_ID.WORK_STAND: pWork = new CECHPWorkStand(this); break; + case CECHPWork.Host_work_ID.WORK_MOVETOPOS: pWork = new CECHPWorkMove(this); break; + case CECHPWork.Host_work_ID.WORK_TRACEOBJECT: pWork = new CECHPWorkTrace(this); break; + case CECHPWork.Host_work_ID.WORK_HACKOBJECT: pWork = new CECHPWorkMelee(this); break; + case CECHPWork.Host_work_ID.WORK_SPELLOBJECT: pWork = new CECHPWorkSpell(this); break; + //case CECHPWork.Host_work_ID.WORK_USEITEM: pWork = new CECHPWorkUse(this); break; + //case CECHPWork.Host_work_ID.WORK_DEAD: pWork = new CECHPWorkDead(this); break; + //case CECHPWork.Host_work_ID.WORK_FOLLOW: pWork = new CECHPWorkFollow(this); break; + //case CECHPWork.Host_work_ID.WORK_FLYOFF: pWork = new CECHPWorkFly(this); break; + //case CECHPWork.Host_work_ID.WORK_FREEFALL: pWork = new CECHPWorkFall(this); break; + //case CECHPWork.Host_work_ID.WORK_SIT: pWork = new CECHPWorkSit(this); break; + //case CECHPWork.Host_work_ID.WORK_PICKUP: pWork = new CECHPWorkPick(this); break; + //case CECHPWork.Host_work_ID.WORK_CONCENTRATE: pWork = new CECHPWorkConcentrate(this); break; + //case CECHPWork.Host_work_ID.WORK_REVIVE: pWork = new CECHPWorkRevive(this); break; + //case CECHPWork.Host_work_ID.WORK_FLASHMOVE: pWork = new CECHPWorkFMove(this); break; + //case CECHPWork.Host_work_ID.WORK_BEBOUND: pWork = new CECHPWorkBeBound(this); break; + //case CECHPWork.Host_work_ID.WORK_PASSIVEMOVE: pWork = new CECHPWorkPassiveMove(this); break; + //case CECHPWork.Host_work_ID.WORK_CONGREGATE: pWork = new CECHPWorkCongregate(this); break; + //case CECHPWork.Host_work_ID.WORK_SKILLSTATEACT: pWork = new CECHPWorkSkillStateAction(this); break; + //case CECHPWork.Host_work_ID.WORK_FORCENAVIGATEMOVE: pWork = new CECHPWorkNavigate(this); break; + default: + return null; + } + + return pWork; + } + + public bool CanStartWork(int iWorkID, int iPriority = CECHPWorkMan.Work_priority.PRIORITY_1) + { + if (!ValidatePriority(iPriority)) + { + return false; + } + if (GetWork(iWorkID) != null) + { + return false; + } + if (!HasWorkOnPriority(iPriority)) + { + return true; + } + WorkList workList = m_WorkStack[iPriority]; + for (int i = 0; i < workList.Count; ++i) + { + if (!workList[i].CanTransferTo(CECHPWork.GetWorkMask(iWorkID))) + { + return false; + } + } + return true; + } + + bool HasWorkOnPriority(int iPriority) + { + return ValidatePriority(iPriority) && m_WorkStack[iPriority].Count != 0; + } + + public void SetPostTickCommand(CECHPWorkPostTickCommand command) + { + m_pPostTickCommand = command; + } + + bool HasWorkRunningOnPriority(int iPriority){ + return HasWorkOnPriority(iPriority); +} +bool IsAnyWorkRunning(){ + return HasWorkRunningOnPriority(m_iCurPriority); +} + +public void Tick(float dwDeltaTime) + { + if (!IsAnyWorkRunning()) + { + return; + } + WorkList workList = m_WorkStack[m_iCurPriority]; + for (int i = 0; i < workList.Count;) + { + CECHPWork pWork = workList[i]; + + SetPostTickCommand(null); + pWork.Tick(dwDeltaTime); + + if (m_pPostTickCommand == null) + { + if (!pWork.IsFinished()) + { + ++i; + continue; + } + KillWork(m_iCurPriority, i); + } + else + { + m_pPostTickCommand.Run(this); + SetPostTickCommand(null); + break; // 不确定 m_pPostTickCommand 执行什么内容,此处跳出 + } + } + if (workList.Count == 0) + { + StartAwaitingWorks(); + } + } +} + +public abstract class CECHPWorkPostTickCommand +{ + public abstract bool Run(CECHPWorkMan pWorkMan); +}; + +public abstract class CECHPWorkMatcher +{ + public abstract bool Match(CECHPWork pWork, int priority, bool isDelayWork); +}; + +public class CECHPWorkGeneralMatcher : CECHPWorkMatcher +{ + int m_workID; + int m_priority; + bool m_matchDelayedWork; + + public override bool Match(CECHPWork pWork, int priority, bool isDelayWork) + { + return pWork != null + && pWork.GetWorkID() == m_workID + && priority == m_priority + && isDelayWork == m_matchDelayedWork; + } + + public CECHPWorkGeneralMatcher(int workID, int priority, bool bIncludeDelayedWork) + { + m_workID = workID; + m_priority = priority; + m_matchDelayedWork = bIncludeDelayedWork; + } +} + +public class CECHPWorkPostTickRunWorkCommand : CECHPWorkPostTickCommand +{ + CECHPWork m_pWork; + int m_iPriority; + bool m_bNoDelay; + bool m_bShouldTick; + uint m_dwTickTime; + + // Constructor + public CECHPWorkPostTickRunWorkCommand( + CECHPWork pWork, + bool bNoDelay = false, + int iPriority = CECHPWorkMan.Work_priority.PRIORITY_1, + bool bShouldTick = false, + uint dwTickTime = 0) + { + m_pWork = pWork; + m_bNoDelay = bNoDelay; + m_iPriority = iPriority; + m_bShouldTick = bShouldTick; + m_dwTickTime = dwTickTime; + } + + public override bool Run(CECHPWorkMan pWorkMan) + { + if (m_pWork == null || pWorkMan == null) + { + return false; + } + if (!pWorkMan.StartWork(m_iPriority, m_pWork, m_bNoDelay)) + { + m_pWork = null; + return false; + } + if (m_bShouldTick) + { + m_pWork.Tick(m_dwTickTime); + } + m_pWork = null; + return true; + } +}; diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs.meta new file mode 100644 index 0000000000..f8f30555d7 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: de7b8e482be7d8347b45ab9751adae44 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs new file mode 100644 index 0000000000..713bd01136 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs @@ -0,0 +1,155 @@ +using BrewMonster; +using BrewMonster.Network; +using CSNetwork.GPDataType; +using PerfectWorld.Scripts.Managers; +using PerfectWorld.Scripts.Player; +using UnityEngine; + +class CECHPWorkPostTickCommand1 : CECHPWorkPostTickRunWorkCommand +{ + public CECHPWorkPostTickCommand1(CECHPWork pWork) : base(pWork, true) + { + } + public virtual bool Run(CECHPWorkMan pWorkMan) + { + if (!base.Run(pWorkMan)) + { + return false; + } + //AP_ActionEvent(AP_EVENT_MELEEOUTOFRANGE); + return true; + } +}; + +/////////////////////////////////////////////////////////////////////////// +// +// Class CECHPWorkMelee +// +/////////////////////////////////////////////////////////////////////////// + +class CECHPWorkMelee : CECHPWork +{ + protected int m_idTarget; // Target id + protected int m_iIdleTime; // Idle time + protected int m_iIdleTimeCnt; // Idle time counter + + // Constructor and Destructor + public CECHPWorkMelee(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_HACKOBJECT, pWorkMan) + { + m_dwMask = Work_mask.MASK_HACKOBJECT; + m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_TRACEOBJECT; + Reset(); + } + + // Tick routine + public virtual bool Tick(float dwDeltaTime) + { + base.Tick(dwDeltaTime); + + if (m_idTarget != 0 || m_idTarget == m_pHost.m_PlayerInfo.cid) + { + m_bFinished = true; + return true; + } + + // If target turn to be un-attackable, cancel action + if (m_pHost.AttackableJudge(m_idTarget, true) == 0) + { + UnityGameSession.c2s_CmdCancelAction(); + //g_pGame.GetGameSession().c2s_CmdCancelAction(); + m_bFinished = true; + return true; + } + + if (m_iIdleTimeCnt < m_iIdleTime) + { + m_iIdleTimeCnt += (int)dwDeltaTime; + if (m_iIdleTimeCnt < m_iIdleTime) + return true; + + m_iIdleTimeCnt = m_iIdleTime; + } + + // Face to target + //m_pHost.TurnFaceTo(m_idTarget); + + int idTraceTarget = 0; + + if (GPDataTypeHelper.ISPLAYERID(m_idTarget)) + { + EC_ElsePlayer pPlayer = EC_ManMessageMono.Instance.GetECManPlayer.GetElsePlayer(m_idTarget); + if (!pPlayer || pPlayer.IsDead()) // Taget has missed ? + return true; + + // if (!m_pHost.CanTouchTarget(pPlayer.GetServerPos(), pPlayer.GetTouchRadius(), 1, 0.8f)) + if (!m_pHost.CanTouchTarget(pPlayer.GetPos(), pPlayer.GetTouchRadius(), 1)) + idTraceTarget = m_idTarget; + } + else if (GPDataTypeHelper.ISNPCID(m_idTarget)) + { + CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(m_idTarget); + if (!pNPC || pNPC.IsDead()) // Taget has missed ? + return true; + + if (!m_pHost.CanTouchTarget(pNPC.GetPos(), pNPC.GetTouchRadius(), 1)) + idTraceTarget = m_idTarget; + } + + if (idTraceTarget != 0 && !m_pHost.IsRooting()) + { + CECHPWorkTrace pWork = (CECHPWorkTrace)m_pWorkMan.CreateWork(Host_work_ID.WORK_TRACEOBJECT); + pWork.SetTraceTarget(pWork.CreatTraceTarget(idTraceTarget, CECHPWorkTrace.Trace_reason.TRACE_ATTACK)); + m_pWorkMan.SetPostTickCommand(new CECHPWorkPostTickCommand1(pWork)); + return true; + } + return true; + } + // Reset work + public virtual void Reset() + { + base.Reset(); + + m_idTarget = 0; + m_iIdleTime = 0; + m_iIdleTimeCnt = 0; + } +// Copy work data +public virtual bool CopyData(CECHPWork pWork) +{ + if (!base.CopyData(pWork)) + return false; + + CECHPWorkMelee pSrc = (CECHPWorkMelee)pWork; + + m_idTarget = pSrc.m_idTarget; + m_iIdleTime = pSrc.m_iIdleTime; + m_iIdleTimeCnt = pSrc.m_iIdleTimeCnt; + + return true; +} +public virtual void Cancel() +{ + // TO DO: fix later + //m_pHost.TurnFaceTo(0); +} + +// Get attack target +public int GetTarget() { return m_idTarget; } +// Set idle time +public void SetIdleTime(int iTime) +{ + m_iIdleTime = iTime; + m_iIdleTimeCnt = 0; +} +// Get idle time +public int GetIdleTime() { return m_iIdleTime; } + +// On first tick +protected virtual void OnFirstTick() +{ + m_pHost.m_iMoveMode = (int)MoveMode.MOVE_STAND; + m_pHost.PlayAction((int)EC_Player.PLAYER_ACTION_TYPE.ACT_ATTACK_1 + Random.Range(0, 3), true, 200, false); + + m_idTarget = m_pHost.m_idSelTarget; +} +}; diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs.meta new file mode 100644 index 0000000000..11d81cd485 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 387c716aaa1c40b4cb343fa662a973e2 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs new file mode 100644 index 0000000000..318949b4b4 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs @@ -0,0 +1,367 @@ +using CSNetwork.GPDataType; +using UnityEngine; + +public class CECHPWorkMove : CECHPWork +{ + public static class Types + { + 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_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()) + { + // 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 + //if (m_pHost.m_pMoveTargetGFX) + //{ + // if (iDestType != DEST_PUSH) + // m_pHost.m_pMoveTargetGFX.Stop(); + //} + } + + 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; + // } + //} + + //base.Tick(dwDeltaTime); + + //if (m_pHost.IsRooting()) + // return true; + + //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); + //} + + ////寻路过程中找到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); + // } + + // 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); + // } + + // Tick_FlySwim(fDeltaTime); + //} + + 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(); + } + +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs.meta new file mode 100644 index 0000000000..708b27c87b --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMove.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d03d31e6920c13745a437cff8cfe4572 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs new file mode 100644 index 0000000000..96368a98b4 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs @@ -0,0 +1,75 @@ +using UnityEngine; +/////////////////////////////////////////////////////////////////////////// +// +// Class CECHPWorkSpell +// +/////////////////////////////////////////////////////////////////////////// +public class CECHPWorkSpell : CECHPWork +{ + 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(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 + + // 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) + { + + } + // 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() + { + + } + // Copy work data + public virtual bool CopyData(CECHPWork pWork) + { + return false; + } + // Cancel work + public virtual void Cancel() + { + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs.meta new file mode 100644 index 0000000000..5c0946c956 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkSpell.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c82fffc45c6f0534e9a668a8ce937e1a \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs new file mode 100644 index 0000000000..d4a70c39fb --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs @@ -0,0 +1,994 @@ +using BrewMonster; +using BrewMonster.Network; +using CSNetwork.GPDataType; +using PerfectWorld.Scripts.Player; +using System; +using System.Runtime.ConstrainedExecution; +using UnityEngine; + +/////////////////////////////////////////////////////////////////////////// +// +// Class CECHPWorkTrace +// +/////////////////////////////////////////////////////////////////////////// + +public static class TraceObjectType +{ + public const int TRACE_NONE = 0, + TRACE_PLAYER = 1, + TRACE_MATTER = 2, + TRACE_NPC = 3, + TRACE_TASKNPC = 4; +} + +public abstract class CECTracedObject +{ + //friend CECHPWorkTrace; + protected int m_iTraceType; + protected int m_iObjectId; + protected int m_iReason; + protected bool m_bMoreClose; + protected CECHostPlayer m_pHost; + + public CECTracedObject(int type, int id, CECHostPlayer pHost, int ireason) + { + m_iTraceType = type; + m_iObjectId = id; + m_iReason = ireason; + m_pHost = pHost; + m_bMoreClose = false; + } + public CECTracedObject(CECTracedObject rhs) + { + m_iTraceType = rhs.m_iTraceType; + m_iObjectId = rhs.m_iObjectId; + m_iReason = rhs.m_iReason; + m_bMoreClose = rhs.m_bMoreClose; + m_pHost = rhs.m_pHost; + } + + public abstract bool OnTargetMissing(); + public abstract A3DVECTOR3 GetTargetPos(); + public abstract bool OnTouched(); + public abstract CECTracedObject Clone(); + + public virtual bool IsTargetMissing() + { + if (m_iObjectId != 0) + { + CECObject pObj = EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); + if (pObj) + { + return false; + } + } + return true; + } + + public A3DVECTOR3? GetMovePos() + { + A3DVECTOR3 vMovePos; + CECObject pObject = EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); + if (pObject) + { + if (GPDataTypeHelper.ISPLAYERID(m_iObjectId)) + { + if (m_iObjectId == m_pHost.GetCharacterID()) + { + vMovePos = m_pHost.GetPos(); + } + else + { + vMovePos = (pObject as EC_ElsePlayer).GetServerPos(); + } + } + else if (GPDataTypeHelper.ISNPCID(m_iObjectId)) + { + vMovePos = (pObject as CECNPC).GetServerPos(); + } + else + { + vMovePos = pObject.GetPos(); + } + return vMovePos; + } + return null; + } + + public int GetObjectID() + { + return m_iObjectId; + } + public bool CanTouchMoreClose() + { + return m_bMoreClose; + } + public void SetMoveCloseFlag(bool bMoveClode) + { + m_bMoreClose = bMoveClode; + } + public int GetTraceReason() + { + return m_iReason; + } + public bool CanTouchFrom(A3DVECTOR3 vHostPos) + { + while (m_iObjectId != 0) + { + A3DVECTOR3 vTargetPos = new A3DVECTOR3(0f, 0f, 0f); + vTargetPos = GetTargetPos(); + + int iTouchReason = 0; + if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) + iTouchReason = 1; + else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) + iTouchReason = 2; + else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_TALK) + iTouchReason = 3; + + float fMaxCut = m_bMoreClose ? -1.0f : 1.0f; + + CECObject pObject = EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); + + float fTouchRadius = 0.0f; + if (GPDataTypeHelper.ISPLAYERID(m_iObjectId)) + { + if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_TALK) + { + fTouchRadius = 0.0f; + } + else + { + EC_Player pPlayer = pObject.GetComponent(); + fTouchRadius = pPlayer.GetTouchRadius(); + } + return m_pHost.CanTouchTarget(vHostPos, vTargetPos, fTouchRadius, iTouchReason, fMaxCut); + } + else if (GPDataTypeHelper.ISNPCID(m_iObjectId)) + { + CECNPC pNPC = pObject as CECNPC; + fTouchRadius = pNPC.GetTouchRadius(); + return m_pHost.CanTouchTarget(vHostPos, vTargetPos, fTouchRadius, iTouchReason, fMaxCut); + } + //else if (GPDataTypeHelper.ISMATTERID(m_iObjectId)) + //{ + // CECMatter pMatter = (pObject) as CECMatter; + // return pMatter.CalcDist(vHostPos, true) < pMatter.GetGatherDist(); + //} + break; + } + return false; + } + public int GetTraceType() + { + return m_iTraceType; + } + public CECObject GetTargetObject() + { + return EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); + } +}; + +public class CECTracedNPC : CECTracedObject +{ + protected bool m_bForceAttack; + + public CECTracedNPC(int type, int id, CECHostPlayer pHost, int ireason, bool bForceAttack = false) : base(type, id, pHost, ireason) + { + m_bForceAttack = bForceAttack; + } + public CECTracedNPC(CECTracedNPC rhs) : base(rhs) + { + m_bForceAttack = rhs.m_bForceAttack; + } + + public override bool OnTargetMissing() + { + bool bRet = false; + + if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) + { + bRet = true; + } + //else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) + //{ + // CECSkill pSkill = m_pHost.m_pPrepSkill; + // if (pSkill == null || pSkill.GetTargetType() != 2) + // { + // bRet = true; + // m_pHost.m_pPrepSkill = null; + // } + //} + return bRet; + } + + public override A3DVECTOR3 GetTargetPos() + { + return (GetTargetObject() as CECNPC).GetServerPos(); + } + + public override bool OnTouched() + { + bool bActionDone = false; + + if (GPDataTypeHelper.ISNPCID(m_iObjectId)) + { + CECNPC pNPC = (CECNPC)GetTargetObject(); + + if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_TALK) + { + if ((!m_pHost.IsInBattle() || m_pHost.InSameBattleCamp(pNPC)) /*&& + !g_pGame.GetGameRun().GetUIManager().GetInGameUIMan().GetDialog("Win_SkillAction").IsShow()*/) + { + UnityGameSession.c2s_CmdNPCSevHello(m_iObjectId); + bActionDone = true; + //a_LogOutput(1, "[NormalATK]- CECTracedNPC- OnTouched- TRACE_TALK"); + } + } + else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) + { + if (m_iObjectId == m_pHost.m_idSelTarget && + m_pHost.AttackableJudge(m_iObjectId, m_bForceAttack) == 1) + { + byte byPVPMask = EC_Utility.glb_BuildPVPMask(m_bForceAttack); + UnityGameSession.c2s_CmdNormalAttack(byPVPMask); + m_pHost.m_bPrepareFight = true; + bActionDone = true; + //a_LogOutput(1, "[NormalATK]- CECTracedNPC- OnTouched- TRACE_ATTACK"); + } + } + //else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) + //{ + // //a_LogOutput(1, "[NormalATK]- CECTracedNPC- OnTouched- TRACE_SPELL"); + // if (!m_pHost.CannotAttack()) + // { + // if (m_pHost.CastSkill(m_iObjectId, m_bForceAttack)) + // bActionDone = true; + // } + // else + // m_pHost.m_pPrepSkill = null; + //} + } + return bActionDone; + } + + public override CECTracedObject Clone() + { + return new CECTracedNPC(this); + } + + public override bool IsTargetMissing() + { + if (base.IsTargetMissing()) + { + return true; + } + CECNPC pNPC = GetTargetObject() as CECNPC; + if (pNPC.IsDead()) + { + return true; + } + return false; + } +} + +public class CECTracedPlayer : CECTracedObject +{ + protected bool m_bForceAttack; + public CECTracedPlayer(int type, int id, CECHostPlayer pHost, int ireason, bool bForceAttack = false) : base(type, id, pHost, ireason) + { + m_bForceAttack = bForceAttack; + } + public CECTracedPlayer(CECTracedPlayer rhs) : base(rhs) + { + m_bForceAttack = rhs.m_bForceAttack; + } + + public override bool OnTargetMissing() + { + bool bRet = false; + + if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) + { + bRet = true; + } + //else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) + //{ + // CECSkill pSkill = m_pHost.m_pPrepSkill; + // if (pSkill == null || pSkill.GetTargetType() != 2) + // { + // bRet = true; + // m_pHost.m_pPrepSkill = null; + // } + //} + return bRet; + } + + public override A3DVECTOR3 GetTargetPos() + { + CECObject pObject = EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0); + if (m_iObjectId == m_pHost.GetCharacterID()) + { + return m_pHost.GetPos(); + } + else + { + return (pObject as EC_ElsePlayer).GetServerPos(); + } + } + + public override bool OnTouched() + { + bool bActionDone = false; + if (GPDataTypeHelper.ISPLAYERID(m_iObjectId)) + { + if (m_iObjectId == 0 || m_iObjectId == m_pHost.GetCharacterID()) + { + // Handle special case + //ASSERT(m_iReason == CECHPWorkTrace::TRACE_SPELL); + //if (!m_pHost.CannotAttack()) + //{ + // if (m_pHost.CastSkill(m_iObjectId, m_bForceAttack, null)) + // bActionDone = true; + //} + //else + //{ + // m_pHost.m_pPrepSkill = null; + //} + //a_LogOutput(1, "[NormalATK]- CECTracedPlayer- OnTouched- special case- TRACE_SPELL"); + return bActionDone; + } + if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK) + { + if (m_iObjectId == m_pHost.m_idSelTarget && + m_pHost.AttackableJudge(m_iObjectId, m_bForceAttack) == 1) + { + byte byPVPMask = EC_Utility.glb_BuildPVPMask(m_bForceAttack); + UnityGameSession.c2s_CmdNormalAttack(byPVPMask); + m_pHost.m_bPrepareFight = true; + bActionDone = true; + //a_LogOutput(1, "[NormalATK]- CECTracedPlayer- OnTouched- TRACE_ATTACK"); + } + } + //else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) + //{ + // //a_LogOutput(1, "[NormalATK]- CECTracedPlayer- OnTouched- TRACE_SPELL"); + // if (!m_pHost.CastSkill(m_iObjectId, m_bForceAttack, GetTargetObject())) + // { + // m_pHost.m_pPrepSkill = null; + // } + // else + // { + // bActionDone = true; + // } + //} + else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_TALK) + { + // Visite other's booth, send hello message to him + //a_LogOutput(1, "[NormalATK]- CECTracedPlayer- OnTouched- TRACE_TALK"); + UnityGameSession.c2s_CmdNPCSevHello(m_iObjectId); + bActionDone = true; + } + } + return bActionDone; + } + + public override CECTracedObject Clone() + { + return new CECTracedPlayer(this); + } + + public override bool IsTargetMissing() + { + if (base.IsTargetMissing()) + { + return true; + } + EC_Player pPlayer = GetTargetObject() as EC_Player; + if (pPlayer.IsElsePlayer()) + { + if (pPlayer.IsDead()) + { + //if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_SPELL) + //{ + // CECSkill pSkill = m_pHost.m_pPrepSkill; + // if (pSkill && pSkill.GetTargetType() == 2) + // { + // return false; + // } + //} + return true; + } + } + return false; + } +}; + +public class CECTracedMatter : CECTracedObject +{ + + public CECTracedMatter(int type, int id, CECHostPlayer pHost, int ireason) : base(type, id, pHost, ireason) + { + + } + public CECTracedMatter(CECTracedMatter rhs) : base(rhs) + { + + } + + public override bool OnTargetMissing() + { + return false; + } + + public override A3DVECTOR3 GetTargetPos() + { + return GetTargetObject().GetPos(); + } + + public override bool OnTouched() + { + bool bActionDone = false; + //if (GPDataTypeHelper.ISMATTERID(m_iObjectId)) + //{ + // if (m_pHost.GetProfession() == PROF_GHOST && m_pHost.IsInvisible()) + // { + // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_CANNOT_USE_WHEN_INVISIBLE); + // return bActionDone; + // } + // CECMatter* pMatter = (CECMatter*)GetTargetObject(); + + // if (m_iReason == CECHPWorkTrace::TRACE_PICKUP) + // { + // // Check whether we have enougth place to hold this item or money + // a_LogOutput(1, "[NormalATK]- CECTracedMatter- OnTouched- TRACE_PICKUP"); + // if (m_pHost.CanTakeItem(pMatter.GetTemplateID(), 1)) + // { + // // Send pickup asking and wait response command + // g_pGame.GetGameSession().c2s_CmdPickup(m_iObjectId, pMatter.GetTemplateID()); + // bActionDone = true; + // } + // else + // { + // // Print a notify message + // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_PACKISFULL); + // } + // } + // else + // { // m_iReason == TRACE_GATHER + // int tidMatter = pMatter.GetTemplateID(); + // a_LogOutput(1, "[NormalATK]- CECTracedMatter- OnTouched- TRACE_GATHER"); + // // Check mine level requirement + // if (m_pHost.GetBasicProps().iLevel < pMatter.GetLevelReq()) + // { + // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_LEVELTOOLOW); + // return bActionDone; + // } + + // // Check whether we have a mine tool + // int iPack, iIndex, idTool; + // if (m_pHost.FindMineTool(tidMatter, &iPack, &iIndex, &idTool)) + // { + // DATA_TYPE DataType; + // const MINE_ESSENCE* pData = (const MINE_ESSENCE*)g_pGame.GetElementDataMan().get_data_ptr(pMatter.GetTemplateID(), ID_SPACE_ESSENCE, DataType); + // if (DataType != DT_MINE_ESSENCE) + // { + // ASSERT(DataType == DT_MINE_ESSENCE); + // return bActionDone; + // } + + // if (m_pHost.GetCoolTime(GP_CT_PLAYER_GATHER)) + // { + // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_CMD_INCOOLTIME); + // } + // else + // { + // // Send gather asking and wait response command + // g_pGame.GetGameSession().c2s_CmdGatherMaterial(m_iObjectId, iPack, iIndex, idTool, pData.task_in); + // } + // } + // else + // { + // g_pGame.GetGameRun().AddFixedMessage(FIXMSG_NEEDTOOL); + // } + // } + //} + return bActionDone; + } + + public override CECTracedObject Clone() + { + return new CECTracedMatter(this); + } +}; +public class CECHPWorkTrace : CECHPWork +{ + // Trace reason + public static class Trace_reason + { + public const int TRACE_NONE = -1, + TRACE_ATTACK = 0, // Normal attack + TRACE_PICKUP = 1, // Pickup object + TRACE_TALK = 2, // Go to talk + TRACE_SPELL = 3, // Cast magic + TRACE_GATHER = 4; // Gather object + } + // Constructor and Destructor + public CECHPWorkTrace(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_TRACEOBJECT, pWorkMan) + { + m_dwMask = Work_mask.MASK_TRACEOBJECT; + m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_FLYOFF | Work_mask.MASK_FREEFALL | + Work_mask.MASK_FOLLOW | Work_mask.MASK_USEITEM; + + Reset(); + } + + // Change trace target + //void ChangeTarget(int idTarget, int iReason, bool bUseAutoPF=false); + // 设定traceobject + public void SetTraceTarget(CECTracedObject pTraceObj, bool bUseAutoPF = false) + { + ResetUseAutoPF(bUseAutoPF); + if (!pTraceObj.GetTargetObject() || pTraceObj.GetObjectID() == m_pHost.GetCharacterID()) + { + // This is special case + ReplaceTarget(pTraceObj); + return; + } + int idTarget = pTraceObj.GetObjectID(); + if (!GPDataTypeHelper.ISPLAYERID(idTarget) && !GPDataTypeHelper.ISNPCID(idTarget) && !GPDataTypeHelper.ISMATTERID(idTarget)) + { + return; + } + CECObject pObject = pTraceObj.GetTargetObject(); + if (!pObject) + { + //delete pTraceObj; + return; + } + ReplaceTarget(pTraceObj); + if (m_pTraceObject.GetTargetObject()) + { + A3DVECTOR3 vDirH = pTraceObj.GetTargetPos() - m_pHost.GetPos(); + vDirH.y = 0.0f; + vDirH.Normalize(); + m_vCurDirH = !vDirH.IsZero() ? vDirH : m_vCurDirH = GPDataTypeHelper.g_vAxisZ; + } + } + + public CECTracedObject CreatTraceTarget(int iTraceObjId, int iReason, bool bForceAttack = false) + { + if (GPDataTypeHelper.ISPLAYERID(iTraceObjId)) + { + return new CECTracedPlayer(TraceObjectType.TRACE_PLAYER, iTraceObjId, m_pHost, iReason, bForceAttack); + } + else if (GPDataTypeHelper.ISNPCID(iTraceObjId)) + { + return new CECTracedNPC(TraceObjectType.TRACE_NPC, iTraceObjId, m_pHost, iReason, bForceAttack); + } + //else if (GPDataTypeHelper.ISMATTERID(iTraceObjId)) + //{ + // return new CECTracedMatter(TraceObjectType.TRACE_MATTER, iTraceObjId, m_pHost, iReason); + //} + return null; + } + + // Tick routine + public virtual bool Tick(float dwDeltaTime) + { + base.Tick(dwDeltaTime); + + CheckPrepSkill(); + + UpdateResetUseAutoPF(); + UpdateUseAutoPF(); + + // m_bFinished flag may be set both in OnFirstTick() and CheckPrepSkill(), + // so check it here ! + if (m_bFinished) + { + return true; + } + if (m_pTraceObject.IsTargetMissing()) + { + OnTargetMissing(); + return true; + } + + if (m_bCheckTouch) + { + if (IsGoodTimeToTouch()) + { + if (m_pTraceObject.CanTouchFrom(m_pHost.GetPos())) + { + OnTouchTarget(); + return true; + } + } + } + m_bCheckTouch = true; + + if (!m_pHost.IsRooting()) + { + // Continue tracing object + float fDeltaTime = dwDeltaTime /** 0.001f*/; + if (m_pHost.m_iMoveEnv == EC_Player.Move_environment.MOVEENV_GROUND) + { + // Play appropriate actions + if (!m_pHost.IsJumping() && !m_pHost.IsPlayingAction((int)EC_Player.PLAYER_ACTION_TYPE.ACT_TRICK_RUN) && + m_pHost.m_iMoveMode != (int)MoveMode.MOVE_SLIDE) + { + int iAction = m_pHost.GetMoveStandAction(true); + m_pHost.PlayAction(iAction, false, 200, false); + } + + Trace_Walk(fDeltaTime); + } + else // (m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_AIR || m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_WATER) + { + m_pHost.ResetJump(); + + // Play appropriate actions + int iAction = m_pHost.GetMoveStandAction(true); + m_pHost.PlayAction(iAction, false, 200, false); + + Trace_FlySwim(fDeltaTime); + } + + m_bHaveMoved = true; + } + + return true; + } + // Reset work + public override void Reset() + { + base.Reset(); + + m_bHaveMoved = false; + m_bMeetSlide = false; + m_bCheckTouch = true; + m_bReadyCancel = false; + m_bMoreClose = false; + //m_pPrepSkill = null; + m_bForceAttack = false; + m_bActionDone = false; + ClearResetUseAutoPF(); + m_bUseAutoPF = false; + m_dwAutoPFNextCheckTime = 0; + m_pTraceObject = null; + } + // Work is cancel + public override void Cancel() + { + //if (m_pHost.m_pPrepSkill && m_pTraceObject.GetTraceReason() == Trace_reason.TRACE_SPELL) + // m_pHost.m_pPrepSkill = null; + + ClearResetUseAutoPF(); + if (GetUseAutoPF()) + { + SetUseAutoPF(false); + } + //m_pHost.StopModelMove(); + base.Cancel(); + + //AP_ActionEvent(m_bActionDone ? AP_EVENT_TRACEOK : AP_EVENT_MOVEFINISHED, m_pTraceObject.GetTraceReason()); + } + + // This work is do player moving ? + public override bool IsMoving() { return true; } + // Copy work data + public override bool CopyData(CECHPWork pWork) + { + if (!base.CopyData(pWork)) + return false; + + CECHPWorkTrace pSrc = (CECHPWorkTrace)pWork; + + m_bHaveMoved = pSrc.m_bHaveMoved; + m_bMeetSlide = pSrc.m_bMeetSlide; + m_bCheckTouch = pSrc.m_bCheckTouch; + m_bReadyCancel = pSrc.m_bReadyCancel; + m_bMoreClose = pSrc.m_bMoreClose; + m_vCurDirH = pSrc.m_vCurDirH; + //m_pPrepSkill = pSrc.m_pPrepSkill; + m_bForceAttack = pSrc.m_bForceAttack; + m_bActionDone = pSrc.m_bActionDone; + m_bShouldResetUseAutoPF = pSrc.m_bShouldResetUseAutoPF; + m_bUseAutoPFResetValue = pSrc.m_bUseAutoPFResetValue; + m_bUseAutoPF = pSrc.m_bUseAutoPF; + m_dwAutoPFNextCheckTime = pSrc.m_dwAutoPFNextCheckTime; + + //delete m_pTraceObject; + m_pTraceObject = pSrc.m_pTraceObject.Clone(); + + return true; + } + + // User press cancel button + public void PressCancel() + { + m_bReadyCancel = true; + //if (m_pTraceObject.GetTraceReason() == TRACE_SPELL) + // m_pHost.m_pPrepSkill = NULL; + } + // Set move close flag + public void SetMoveCloseFlag(bool bMoveClose) { m_pTraceObject.SetMoveCloseFlag(bMoveClose); } + + // Set / Get force attack flag + public void SetForceAttack(bool bTrue) { m_bForceAttack = bTrue; } + public bool GetForceAttack() { return m_bForceAttack; } + // Set / Get prepared skill + public void SetPrepSkill(CECSkill pSkill) { /*m_pPrepSkill = pSkill;*/ } + public CECSkill GetPrepSkill() { /*return m_pPrepSkill;*/ return null; } + // Get target ID + public int GetTarget() { return m_pTraceObject.GetObjectID(); } + // Get trace reason + public int GetTraceReason() { return m_pTraceObject.GetTraceReason(); } + // AutoPF + public void SetUseAutoPF(bool bUse) + { + m_bUseAutoPF = bUse; + //if (!m_bUseAutoPF && CECIntelligentRoute.Instance().IsUsageTrace()) + //{ + // CECIntelligentRoute.Instance().ResetSearch(); + //} + } + public bool GetUseAutoPF() + { + return m_bUseAutoPF; + } + public bool IsAutoPF() + { + return false; + } + + public void SetActionDone(bool bActionDone) { m_bActionDone = bActionDone; } + + public void OnTargetMissing() + { + StopMove(true); + if ((m_pTraceObject.GetTraceType() == TraceObjectType.TRACE_NPC) || (m_pTraceObject.GetTraceType() == TraceObjectType.TRACE_PLAYER)) + { + m_pTraceObject.OnTargetMissing(); + } + //else if (m_pTraceObject.GetTraceReason() == Trace_reason.TRACE_SPELL) + //{ + // m_pHost.m_pPrepSkill = null; + //} + } + + public void OnTouchTarget() + { + StopMove(true); + m_bActionDone = m_pTraceObject.OnTouched(); + } + public bool CanTouch() + { + //CECSkill pPrepSkill = m_pHost.m_pPrepSkill; + CheckPrepSkill(); + bool result = m_pTraceObject.CanTouchFrom(m_pHost.GetPos()); + //m_pHost.m_pPrepSkill = pPrepSkill; + return result; + } + // Attributes + + protected bool m_bHaveMoved; // Have moved flag + protected bool m_bMeetSlide; // true, meet slide + protected bool m_bCheckTouch; // Check whether touch target in this frame + protected A3DVECTOR3 m_vCurDirH; // Current move direction + protected bool m_bReadyCancel; // true, ready to cancel + protected bool m_bMoreClose; // Move close flag + protected bool m_bForceAttack; // Force attack flag + protected CECSkill m_pPrepSkill; // Skill prepared to be casted + protected bool m_bActionDone; // 目标行为成功发出 + protected bool m_bShouldResetUseAutoPF; + protected bool m_bUseAutoPFResetValue; + protected bool m_bUseAutoPF; // Use CECIntelligentRoute::Search + protected uint m_dwAutoPFNextCheckTime; // 下次检查时间 + + protected CECTracedObject m_pTraceObject; // 定义trace目标对象 + + // Operations + + // On first tick + protected virtual void OnFirstTick() + { + m_pHost.m_iMoveMode = (int)MoveMode.MOVE_MOVE; + m_bHaveMoved = false; + } + + // Trace on ground + protected bool Trace_Walk(float fDeltaTime) + { + A3DVECTOR3 vCurPos = m_pHost.GetPos(); + A3DVECTOR3 vTargetPos = GetCurMovingDest(); + CDR_INFO cdr = m_pHost.m_CDRInfo; + + if (m_pHost.m_iMoveMode == (int)MoveMode.MOVE_SLIDE) + { + m_pHost.PlayAction((int)EC_Player.PLAYER_ACTION_TYPE.ACT_JUMP_LOOP, false, 200, false); + + // This will cause stop moming after we slide down. + A3DVECTOR3 vDir = vTargetPos - vCurPos; + vDir.y = 0; + vDir.Normalize(); + + float fMaxSpeedV = 0f; + m_bMeetSlide = m_pHost.m_MoveCtrl.MeetSlope(vDir, fMaxSpeedV); + EC_Utility.a_ClampFloor(cdr.fYVel, -fMaxSpeedV); + + if (!vDir.IsZero()) + m_vCurDirH = vDir; + + vCurPos = m_pHost.m_MoveCtrl.GroundMove(m_vCurDirH, m_pHost.GetGroundSpeed(), fDeltaTime); + if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3) + { + m_pHost.m_MoveCtrl.SetSlideLock(true); + m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), m_pHost.GetGroundSpeed(), (int)GPMoveMode.GP_MOVE_SLIDE); + m_bFinished = true; + } + else + { + m_pHost.SetPos(EC_Utility.ToVector3(vCurPos)); + //if (GetUseAutoPF() && CECIntelligentRoute::Instance().IsMoveOn()) + //{ + // CECIntelligentRoute::Instance().OnPlayerPosChange(vCurPos); + //} + m_pHost.m_MoveCtrl.SendMoveCmd(vCurPos, 2, GPDataTypeHelper.g_vOrigin, EC_Utility.ToA3DVECTOR3(cdr.vAbsVelocity), (int)GPMoveMode.GP_MOVE_SLIDE); + } + } + else if (!m_bMeetSlide) + { + int iMoveMode = m_pHost.m_bWalkRun ? (int)GPMoveMode.GP_MOVE_RUN : (int)GPMoveMode.GP_MOVE_WALK; + if (m_pHost.IsJumping()) + iMoveMode = (int)GPMoveMode.GP_MOVE_JUMP; + else if (!m_pHost.m_GndInfo.bOnGround) + iMoveMode = (int)GPMoveMode.GP_MOVE_FALL; + + if (m_pHost.m_GndInfo.bOnGround) + { + if (m_bReadyCancel) + { + StopMove(true); + return true; + } + + // Ajust direction only when player on ground + A3DVECTOR3 vDirH = vTargetPos - vCurPos; + A3DVECTOR3 v = A3DFuncs.a3d_Normalize(vDirH); + if (Math.Abs(v.y) > 0.9848f) + { + PressCancel(); + return true; + } + + vDirH.y = 0.0f; + vDirH.Normalize(); + if (!vDirH.IsZero()) + m_vCurDirH = vDirH; + } + + vCurPos = m_pHost.m_MoveCtrl.GroundMove(m_vCurDirH, m_pHost.GetGroundSpeed(), fDeltaTime, m_pHost.m_fVertSpeed); + m_pHost.SetPos(EC_Utility.ToVector3(vCurPos)); + //if (GetUseAutoPF() && CECIntelligentRoute::Instance().IsMoveOn()) + //{ + // CECIntelligentRoute::Instance().OnPlayerPosChange(vCurPos); + //} + + if (cdr.vTPNormal == Vector3.zero) + m_bCheckTouch = false; + + //if (!m_vCurDirH.IsZero()) + //{ + // m_pHost.StartModelMove(m_vCurDirH, g_vAxisY, 0); + //} + + if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3) + { + // m_pHost.m_MoveCtrl.SendStopMoveCmd(vCurPos, m_pHost.GetGroundSpeed(), iMoveMode); + PressCancel(); + } + else + m_pHost.m_MoveCtrl.SendMoveCmd(vCurPos, 0, vTargetPos, EC_Utility.ToA3DVECTOR3(cdr.vAbsVelocity), iMoveMode); + } + else // m_bMeetSlide == true + { + if (m_bHaveMoved) + m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), m_pHost.GetGroundSpeed(), (int)GPMoveMode.GP_MOVE_SLIDE); + + m_bFinished = true; + } + return true; + } + // Trace in air and water + public bool Trace_FlySwim(float fDeltaTime) + { + return true; + } + + // Stop move when touch target + public void StopMove(bool bFinish) + { + // If 'trace' work was transfered from a work which + // needs moving (such as 'move to' work) and we touch the target + // immediately (m_bHaveMoved = false), we must need to send 'stop move' + // command + if (m_bHaveMoved || !m_pHost.m_MoveCtrl.IsStop()) + m_pHost.m_MoveCtrl.SendStopMoveCmd(); + + m_pHost.m_vVelocity.Clear(); + //m_pHost.StopModelMove(); + + if (bFinish) + { + m_bFinished = true; + } + } + // Handle the case that target died when host is tracing it + public bool OnTargetDied(CECObject pTarget) + { + return true; + } + // Is valid time to touch target ? + public bool IsGoodTimeToTouch() + { + if (m_pHost.IsJumping()) + { + return false; + } + return true; + } + // Check prepare skill + public void CheckPrepSkill() + { + + } + public bool GetTargetCurPos(A3DVECTOR3 pos) + { + return true; + } + public A3DVECTOR3 GetCurMovingDest() + { + return new A3DVECTOR3(); + } + public void UpdateUseAutoPF() + { + + } + + public void ReplaceTarget(CECTracedObject ptraceobj) + { + //if (m_pTraceObject) + //{ + // delete m_pTraceObject; + //} + m_pTraceObject = ptraceobj; + } + + public void ResetUseAutoPF(bool bUseAutoPF) + { + m_bShouldResetUseAutoPF = true; + m_bUseAutoPFResetValue = bUseAutoPF; + } + public void UpdateResetUseAutoPF() + { + if (!m_bShouldResetUseAutoPF) + { + return; + } + //# ifdef SHOW_AUTOMOVE_FOOTPRINTS + // g_AutoPFFollowPoints.clear(); + // g_AutoPFPathPoints.clear(); + //#endif + //CECIntelligentRoute::Instance().SetUsage(CECIntelligentRoute::enumUsageWorkTrace); + //CECIntelligentRoute::Instance().ResetSearch(); + SetUseAutoPF(m_bUseAutoPFResetValue); + ClearResetUseAutoPF(); + } + public void ClearResetUseAutoPF() + { + m_bShouldResetUseAutoPF = false; + m_bUseAutoPFResetValue = false; + } +}; \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs.meta new file mode 100644 index 0000000000..fa9daf2a66 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 8cd5ac42b14a07f459a8c68c35d38af6 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs index 825d93d228..0db2223156 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs @@ -23,6 +23,7 @@ namespace PerfectWorld.Scripts.Managers Dictionary m_UkPlayerTab = new Dictionary(); Dictionary m_PlayerTab = new Dictionary(); private readonly object m_csPlayerTab = new object(); + CECHostPlayer m_pHostPlayer; public int HandlerId => (int)MANAGER_INDEX.MAN_PLAYER; public bool ProcessMessage(ECMSG Msg) { @@ -468,6 +469,20 @@ namespace PerfectWorld.Scripts.Managers return true; } + // Get a player (may be host or else player) by id + public EC_Player GetPlayer(int cid, uint dwBornStamp = 0) + { + CECHostPlayer pHost = GetHostPlayer(); + if (pHost && pHost.GetCharacterID() == cid) + return pHost; + else + return GetElsePlayer(cid, dwBornStamp); + } + + public CECHostPlayer GetHostPlayer() + { + return GameController.Instance.GetHostPlayer(); + } } } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs new file mode 100644 index 0000000000..f6f58bbfb4 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs @@ -0,0 +1,245 @@ +using CSNetwork.GPDataType; +using CSNetwork.Protocols; +using UnityEngine; + +/////////////////////////////////////////////////////////////////////////// +// +// Class CECObject +// +/////////////////////////////////////////////////////////////////////////// + +public class CECObject : MonoBehaviour +{ + // Class ID + public static class Class_ID + { + public const int OCID_OBJECT = 0, + OCID_PLAYER = 1, + OCID_HOSTPLAYER = 2, + OCID_ELSEPLAYER = 3, + OCID_LOGINPLAYER = 4, + OCID_NPC = 5, + OCID_MONSTER = 6, + OCID_SERVER = 7, + OCID_MATTER = 8, + OCID_PET = 9, + OCID_CLONED_PLAYER = 10, // 复制角色模型 + OCID_HOST_NAVIGATER = 11, // 纯客户端player类,用于强制移动 + OCID_NPCCLONED_MASTER = 12; // NPC 复制的角色模型 + } + + // Render flag + public static class Render_flag + { + public const int RD_NORMAL = 0, + RD_REFRACT = 1, + RD_REFLECT = 2; + } + + // Move environment + public static class Move_environment + { + public const int MOVEENV_GROUND = 0, // Move on ground + MOVEENV_WATER = 1, + MOVEENV_AIR = 2; + } + + // Constructor and Destructor + public CECObject() + { + m_iCID = Class_ID.OCID_OBJECT; + m_bAdjustOrient = false; + m_bVisible = true; + m_bBornInSight = false; + m_dwBornStamp = 0; + + m_bUseGroundNormal = false; + m_vecGroundNormal = new A3DVECTOR3(0.0f, 1.0f, 0.0f); + m_vecGroundNormalSet = new A3DVECTOR3(0.0f, 1.0f, 0.0f); + + m_bSelectable = true; + } + + public virtual void SetUpCECObject() + { + m_dwBornStamp = 0; + m_bBornInSight = false; + m_bSelectable = false; + m_iCID = (int)Class_ID.OCID_OBJECT; + } + + public void SetSelectable(bool bSelectable) { m_bSelectable = bSelectable; } + + // Tick routine + public bool Tick(float dwDeltaTime) + { + if (m_bAdjustOrient) + AdjustOrientation(dwDeltaTime); + + m_vecGroundNormal = Normalize(m_vecGroundNormal * 0.85f + m_vecGroundNormalSet * 0.15f); + return true; + } + + // Set absolute forward and up direction + public virtual void SetDirAndUp(A3DVECTOR3 vDir, A3DVECTOR3 vUp) + { + //if (m_bUseGroundNormal) + //{ + // A3DVECTOR3 vecRight = Normalize(CrossProduct(g_vAxisY, vDir)); + // A3DVECTOR3 vecNormal = m_vecGroundNormal - DotProduct(m_vecGroundNormal, vecRight) * vecRight; + // A3DVECTOR3 vecNewDir = Normalize(CrossProduct(vecRight, vecNormal)); + // A3DCoordinate::SetDirAndUp(vecNewDir, vecNormal); + //} + //else + // A3DCoordinate::SetDirAndUp(vDir, vUp); + + // Stop orientation adjusting + m_bAdjustOrient = false; + } + // Set destination orientation of model + public void SetDestDirAndUp(A3DVECTOR3 vDir, A3DVECTOR3 vUp, float dwTime) + { + m_bAdjustOrient = true; + m_dwOrientTime = dwTime; + m_dwOrientTimeCnt = 0; + + //// Calculate start orientation + //A3DMATRIX4 mat = a3d_TransformMatrix(GetDir(), GetUp(), g_vOrigin); + //m_quOrientStart.ConvertFromMatrix(mat); + + //// Calculate end orientation + //if (m_bUseGroundNormal) + //{ + // A3DVECTOR3 vecRight = Normalize(CrossProduct(g_vAxisY, vDir)); + // A3DVECTOR3 vecNormal = m_vecGroundNormal - DotProduct(m_vecGroundNormal, vecRight) * vecRight; + // A3DVECTOR3 vecNewDir = Normalize(CrossProduct(vecRight, vecNormal)); + // mat = a3d_TransformMatrix(vecNewDir, vecNormal, g_vOrigin); + //} + //else + //{ + // mat = a3d_TransformMatrix(vDir, vUp, g_vOrigin); + //} + + //m_quOrientEnd.ConvertFromMatrix(mat); + } + + // Calculate distance between this object and specified position + public float CalcDist(A3DVECTOR3 vPos, bool b3D) + { + A3DVECTOR3 vDelta = GetPos() - vPos; + return b3D ? vDelta.Magnitude() : vDelta.MagnitudeH(); + } + + private A3DVECTOR3 Normalize(A3DVECTOR3 v) + { + float mag = v.Magnitude(); + if (mag < 1e-12 && mag > -1e-12) + return new A3DVECTOR3(0.0f); + else + return v / mag; + } + + public A3DVECTOR3 GetPos() + { + return new A3DVECTOR3(transform.position.x, transform.position.y, transform.position.z); + } + + // Turn around object and face to specified object + public virtual void TurnFaceTo(int idTarget, float dwTime = 200) + { + + } + + // Set / Get visible flag + public void SetVisible(bool bVisible) + { + m_bVisible = bVisible; + } + public bool GetVisible() + { + return m_bVisible; + } + + // Get object class ID + public int GetClassID() { return m_iCID; } + public bool IsPlayer() { return m_iCID == Class_ID.OCID_HOSTPLAYER || m_iCID == Class_ID.OCID_ELSEPLAYER || m_iCID == Class_ID.OCID_LOGINPLAYER; } + public bool IsHostPlayer() { return m_iCID == Class_ID.OCID_HOSTPLAYER; } + public bool IsElsePlayer() { return m_iCID == Class_ID.OCID_ELSEPLAYER; } + public bool IsLoginPlayer(){ return m_iCID == Class_ID.OCID_LOGINPLAYER; } + public bool IsNPC() { return m_iCID == Class_ID.OCID_MONSTER || m_iCID == Class_ID.OCID_SERVER; } + public bool IsMonsterNPC() { return m_iCID == Class_ID.OCID_MONSTER; } + public bool IsServerNPC() { return m_iCID == Class_ID.OCID_SERVER; } + public bool IsMatter() { return m_iCID == Class_ID.OCID_MATTER; } + public bool IsSelectable() { return m_bSelectable; } + // Set / Get object born stamp + public uint GetBornStamp() { return m_dwBornStamp; } + public void SetBornStamp(uint dwStamp) { m_dwBornStamp = dwStamp; } + // Set / Get born in sight flag + public bool GetBornInSight() { return m_bBornInSight; } + public void SetBornInSight(bool bFlag) { m_bBornInSight = bFlag; } + + // Get object id + public static int GetObjectID(CECObject pObject) + { + if (!pObject) + return 0; + + if (pObject.IsPlayer()) + return ((EC_Player)pObject).GetCharacterID(); + else if (pObject.IsNPC()) + return ((CECNPC)pObject).GetNPCID(); + //else if (pObject.IsMatter()) + // return ((CECMatter*)pObject)->GetMatterID(); + else + return 0; + } + + protected int m_iCID; // Class ID + protected bool m_bAdjustOrient; // Is adjusting orientation + //protected A3DQUATERNION m_quOrientStart; // Orientation start + //protected A3DQUATERNION m_quOrientEnd; // Orientation end + protected float m_dwOrientTime; // Orientation adjusting time counter + protected uint m_dwOrientTimeCnt; // Orientation adjusting time counter + + protected bool m_bBornInSight; // Born in my sight + protected uint m_dwBornStamp; // Born time stamp + protected bool m_bVisible; // Render flag + + protected bool m_bUseGroundNormal; // flag indicates whether we use a ground normal as up + protected A3DVECTOR3 m_vecGroundNormal; // current ground normal + protected A3DVECTOR3 m_vecGroundNormalSet; // ground normal set + + protected bool m_bSelectable; // whether the object can be selected + + public A3DVECTOR3 GetGroundNormal(){ return m_vecGroundNormal; } + public bool GetUseGroundNormal(){ return m_bUseGroundNormal; } + + public void SetUseGroundNormal(bool bFlag) + { + //if (m_bUseGroundNormal == bFlag) + // return; + + //m_bUseGroundNormal = bFlag; + //if (m_bUseGroundNormal) + //{ + // // now reset dir and up to make the object show correct pose + // SetDirAndUp(GetDir(), GetUp()); + //} + //else + //{ + // // now reset dir and up to make the player show correct pose + // A3DVECTOR3 vLeft = CrossProduct(GetDir(), g_vAxisY); + // A3DVECTOR3 vDir = Normalize(CrossProduct(g_vAxisY, vLeft)); + // SetDirAndUp(vDir, g_vAxisY); + //} + } + public void SetGroundNormal(A3DVECTOR3 vecNormal) + { + m_vecGroundNormalSet = vecNormal; + } + + protected void AdjustOrientation(float dwDeltaTime) + { + + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs.meta new file mode 100644 index 0000000000..2faf36d1ae --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c36b379029c2c70458f3cb8d204f53d8 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs new file mode 100644 index 0000000000..77a4e6cde8 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs @@ -0,0 +1,64 @@ +using UnityEngine; + +public class CECObjectWork +{ + // 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_iWorkID = iWorkID; + m_bFinished = false; + m_dwMask = 0; + m_dwTransMask = 0; + m_bFinished = 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() { } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs.meta new file mode 100644 index 0000000000..2073381e0f --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_ObjectWork.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 8d658d501be8b9f45be5ed066a6efc23 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_RoleTypes.cs b/Assets/PerfectWorld/Scripts/Managers/EC_RoleTypes.cs new file mode 100644 index 0000000000..423543ee84 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_RoleTypes.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public class EC_RoleTypes +{ + +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_RoleTypes.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_RoleTypes.cs.meta new file mode 100644 index 0000000000..7323269a1f --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_RoleTypes.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2a00af48d21485d46bf5bae22e8b09f9 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Skill.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Skill.cs new file mode 100644 index 0000000000..be17af68ef --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_Skill.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +public class CECSkill +{ + +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Skill.cs.meta b/Assets/PerfectWorld/Scripts/Managers/EC_Skill.cs.meta new file mode 100644 index 0000000000..0596a7d863 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_Skill.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a33568a349c4ee9488a562e2c67002e7 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/NPC/CECMonster.cs b/Assets/PerfectWorld/Scripts/NPC/CECMonster.cs index a1f7ed3433..56109ec3c7 100644 --- a/Assets/PerfectWorld/Scripts/NPC/CECMonster.cs +++ b/Assets/PerfectWorld/Scripts/NPC/CECMonster.cs @@ -13,7 +13,7 @@ public class CECMonster : CECNPC public override void SetUpCECNPC(CECNPCMan pNPCMan) { base.SetUpCECNPC(pNPCMan); - m_iCID = (int)ClassID.OCID_MONSTER; + m_iCID = (int)Class_ID.OCID_MONSTER; m_pDBEssence = default; } public override bool Init(int tid, in info_npc info, ReadOnlySpan packet, int infoOffset) diff --git a/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs b/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs index 3db4c9a8cc..ddabd9d792 100644 --- a/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs +++ b/Assets/PerfectWorld/Scripts/NPC/CECNPC.cs @@ -23,7 +23,7 @@ public class CECNPC : CECObject protected float m_fDistToHost; protected float m_fDistToHostH; protected OtherPlayer_Move_Info m_cdr; - protected float m_fTouchRad; + protected float m_fTouchRad = 1f; protected ROLEBASICPROP m_BasicProps; protected Vector3 m_vMoveDir; protected int m_iPassiveMove; @@ -47,11 +47,12 @@ public class CECNPC : CECObject protected static CECStringTab m_ActionNames; + public virtual void SetUpCECNPC(CECNPCMan pNPCMan) { base.SetUpCECObject(); m_vServerPos = new Vector3(); - m_iCID = (int)ClassID.OCID_NPC; + m_iCID = (int)Class_ID.OCID_NPC; } public virtual bool Init(int tid, in info_npc info, ReadOnlySpan packet, int infoOffset) { @@ -76,9 +77,9 @@ public class CECNPC : CECObject _characterController = GetComponent(); - m_iMoveEnv = (int)((info.state & PlayerNPCState.GP_STATE_NPC_FLY) != 0 ? EnviromentMoveType.MOVEENV_AIR - : (info.state & PlayerNPCState.GP_STATE_NPC_SWIM) != 0 ? EnviromentMoveType.MOVEENV_WATER - : EnviromentMoveType.MOVEENV_GROUND); + m_iMoveEnv = (int)((info.state & PlayerNPCState.GP_STATE_NPC_FLY) != 0 ? Move_environment.MOVEENV_AIR + : (info.state & PlayerNPCState.GP_STATE_NPC_SWIM) != 0 ? Move_environment.MOVEENV_WATER + : Move_environment.MOVEENV_GROUND); var npcVisual = GetComponent(); m_pNPCModelPolicy.SetNpcVisual(npcVisual); @@ -853,8 +854,10 @@ public class CECNPC : CECObject } } bool IsMonsterOrPet() { return IsMonsterNPC() || IsPetNPC(); } - bool IsMonsterNPC() { return (int)ClassID.OCID_MONSTER == m_iCID; } - bool IsPetNPC() { return (int)ClassID.OCID_PET == m_iCID; } + bool IsMonsterNPC() { return (int)Class_ID.OCID_MONSTER == m_iCID; } + bool IsPetNPC() { return (int)Class_ID.OCID_PET == m_iCID; } + + public bool IsDead(){ return (m_dwStates & PlayerNPCState.GP_STATE_CORPSE) != 0; } public void PlayMoveAction(int iMoveMode) { BrewMonster.BMLogger.LogError($"HoangDev: PlayMoveAction {iMoveMode}"); @@ -906,6 +909,8 @@ public class CECNPC : CECObject } bool IsDisappearing() { return m_DisappearCnt == 0 ? true : false; } + public float GetTouchRadius() { return m_fTouchRad; } + bool IsLag(float fDist) { return m_iPassiveMove == 0 && fDist > MAX_LAGDIST; @@ -919,6 +924,41 @@ public class CECNPC : CECObject public int vis_tid;// template id for shape }; public const float MAX_LAGDIST = 25.0f; + + // Get NPC's real position on server + public A3DVECTOR3 GetServerPos() + { + return EC_Utility.ToA3DVECTOR3(m_vServerPos); + } + + // Get master id + public int GetMasterID() { return m_idMaster; } + // Is monster in invader camp in battle ? + public virtual bool IsInBattleInvaderCamp() { return false; } + // Is monster in defender camp in battle ? + public virtual bool IsInBattleDefenderCamp() { return false; } + // Get role in battle + public virtual int GetRoleInBattle() { return 0; } + public int GetOwnerFaction(){ return m_idOwnerFaction; } + + public bool IsFactionPVPMineCar() + { + //if (const MONSTER_ESSENCE* pMonsterEssence = GetMonsterEssence()){ + // return (pMonsterEssence.faction & (1 << 19)) != 0; + //} + return false; + } + + public bool IsFactionPVPMineBase() + { + //if (const MONSTER_ESSENCE *pMonsterEssence = GetMonsterEssence()){ + // return (pMonsterEssence->faction & (1 << 20)) != 0; + //} + return false; + } + + // Get NPC ID + public int GetNPCID() { return m_NPCInfo.nid; } } public enum WorkType { diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs index 623cac9385..1c95c8594f 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs @@ -1323,6 +1323,16 @@ namespace CSNetwork.S2CCommand // public byte size; // public char data[1]; //}; + + public struct cmd_sevnpc_hello + { + public int id; + }; + + public struct cmd_normal_attack + { + public byte pvp_mask; + }; } // Player and NPC state \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs index 9d2c624942..c6759f9d89 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs @@ -403,5 +403,28 @@ namespace CSNetwork.C2SCommand // Serialize the command and return the serialized data return SerializeCommand(CommandID.GET_ALL_DATA, cmd); } + + public static Octets CreateNPCSevHelloDataCommand(int iD) + { + var cmd = new cmd_sevnpc_hello + { + id = iD + }; + return SerializeCommand(CommandID.SEVNPC_HELLO, cmd); + } + + public static Octets CreateNormalAttackDataCmd(byte byPVPMask) + { + var cmd = new cmd_normal_attack + { + pvp_mask = byPVPMask + }; + return SerializeCommand(CommandID.NORMAL_ATTACK, cmd); + } + + public static Octets CreateNakeCmd(CommandID iCmd) + { + return SerializeCommand(iCmd); + } } } diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/CSNetwork.csproj.meta b/Assets/PerfectWorld/Scripts/Network/CSNetwork/CSNetwork.csproj.meta deleted file mode 100644 index 333a9b1482..0000000000 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/CSNetwork.csproj.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: d0c06c588e2a6442488a3542551fb243 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs index 2d8f7303d7..90ea6ed814 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GPDataType.cs @@ -892,7 +892,7 @@ namespace CSNetwork.GPDataType public byte index_equip; public uint amount; }; - + [StructLayout(LayoutKind.Sequential, Pack = 1)] struct cmd_player_drop_item { @@ -912,9 +912,9 @@ namespace CSNetwork.GPDataType [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct cmd_matter_enter_world { - public info_matter Info; + public info_matter Info; }; - + [StructLayout(LayoutKind.Sequential, Pack = 1)] struct cmd_pickup_item { @@ -1075,9 +1075,33 @@ namespace CSNetwork.GPDataType Marshal.FreeHGlobal(ptr); } } + + public static bool ISPLAYERID(int id) + { + return id != 0 && (id & 0x80000000) == 0; + } + public static bool ISNPCID(int id) + { + return (id & 0x80000000) != 0 && (id & 0x40000000) == 0; + } + + public static bool ISMATTERID(int id) + { + return (id & 0xC0000000) == 0xC0000000; + } + + public static A3DVECTOR3 g_vOrigin = new A3DVECTOR3(0.0f); + public static A3DVECTOR3 g_vAxisX = new A3DVECTOR3(1.0f, 0.0f, 0.0f); + public static A3DVECTOR3 g_vAxisY = new A3DVECTOR3(0.0f, 1.0f, 0.0f); + public static A3DVECTOR3 g_vAxisZ = new A3DVECTOR3(0.0f, 0.0f, 1.0f); + + // Move length minimum threshold + public const float MIN_MOVELEN_IN_AIR_WATER = 0.5f; + public const float MIN_MOVELEN_ON_GROUND = 0.5f; + public const float MIN_MOVELEN_FOR_DETECT_VIBRATION = 0.05f; } -[StructLayout(LayoutKind.Sequential, Pack = 1)] + [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct cmd_npc_info_list { public ushort count; @@ -1121,10 +1145,10 @@ namespace CSNetwork.GPDataType }; public struct cmd_npc_info_00 { - public int idNPC; - public int iHP; - public int iMaxHP; - public int iTargetID; + public int idNPC; + public int iHP; + public int iMaxHP; + public int iTargetID; }; [StructLayout(LayoutKind.Sequential, Pack = 1)] // sizeof = 36 v峄沬 padding 1 byte sau dir public struct info_npc @@ -1216,5 +1240,30 @@ namespace CSNetwork.GPDataType { OBJECT_EXT_STATE_COUNT = 6, // 脥忙录脪/NPC 脡铆脡脧脳麓脤卢鹿芒脨搂 DWORD 赂枚脢媒 }; + + // Player camp in battle + public static class Player_camp_in_battle + { + public const int GP_BATTLE_CAMP_NONE = 0, + GP_BATTLE_CAMP_INVADER = 1, + GP_BATTLE_CAMP_DEFENDER = 2; + }; + + // PVP mask + [Flags] + public enum PVP_mask : byte + { + GP_PVPMASK_FORCE = 0x0001, // 脟驴脕娄鹿楼禄梅 + GP_PVPMASK_NOMAFIA = 0x0002, + GP_PVPMASK_NOWHITE = 0x0004, + GP_PVPMASK_NOALLIANCE = 0x0008, + GP_PVPMASK_NOFORCE = 0x0010,//虏禄鹿楼禄梅脥卢脢脝脕娄碌脛 + + GP_BLSMASK_NORED = 0x0008, + GP_BLSMASK_NOMAFIA = 0x0010, + GP_BLSMASK_SELF = 0x0020, + GP_BLSMASK_NOALLIANCE = 0x0040, + GP_BLSMASK_NOFORCE = 0x0080 // 脢脝脕娄脝脕卤脦 + }; } diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs index ed9c2a4e25..7ec3dfbe0f 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs @@ -727,5 +727,26 @@ namespace CSNetwork _logger.Log(LogType.Warning, $"[Dat]- SendCmdGetAllData {byPack},{byEquip},{byTask}"); SendProtocol(gamedatasend); } + + public void c2s_SendCmdNPCSevHello(int nid) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevHelloDataCommand(nid); + SendProtocol(gamedatasend); + } + + public void c2s_CmdNormalAttack(byte byPVPMask) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNormalAttackDataCmd(byPVPMask); + SendProtocol(gamedatasend); + } + + public void c2s_CmdCancelAction() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(CSNetwork.C2SCommand.CommandID.CANCEL_ACTION); + SendProtocol(gamedatasend); + } } } diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/obj/Debug/netstandard2.1/CSNetwork.dll b/Assets/PerfectWorld/Scripts/Network/CSNetwork/obj/Debug/netstandard2.1/CSNetwork.dll deleted file mode 100644 index 3f28de2e06..0000000000 Binary files a/Assets/PerfectWorld/Scripts/Network/CSNetwork/obj/Debug/netstandard2.1/CSNetwork.dll and /dev/null differ diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/obj/Debug/netstandard2.1/CSNetwork.dll.meta b/Assets/PerfectWorld/Scripts/Network/CSNetwork/obj/Debug/netstandard2.1/CSNetwork.dll.meta deleted file mode 100644 index 73df0221aa..0000000000 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/obj/Debug/netstandard2.1/CSNetwork.dll.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: e3cf084cf53b24fe7a6bffb17846d608 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Network/EC_ManMessageMono.cs b/Assets/PerfectWorld/Scripts/Network/EC_ManMessageMono.cs index 623e51ecb1..57599c37b2 100644 --- a/Assets/PerfectWorld/Scripts/Network/EC_ManMessageMono.cs +++ b/Assets/PerfectWorld/Scripts/Network/EC_ManMessageMono.cs @@ -2,6 +2,9 @@ using System; using UnityEngine; using CSNetwork; using PerfectWorld.Scripts.Managers.BrewMonster.Managers; +using BrewMonster.Network; +using UnityEngine.SceneManagement; +using CSNetwork.GPDataType; namespace BrewMonster { @@ -50,5 +53,35 @@ namespace BrewMonster { EC_ManMessage.Tick(); } + + // Get object by specified ID + // iAliveFlag: 0, both alive and dead; 1, must be alive; 2, must be dead + public CECObject GetObject(int idObject, int iAliveFlag) + { + CECObject pObject = null; + + if (GPDataTypeHelper.ISNPCID(idObject)) + { + if (!(pObject = _CECNPCMan.GetNPC(idObject))) + return null; + + if ((iAliveFlag == 1 && (pObject as CECNPC).IsDead()) || + (iAliveFlag == 2 && !(pObject as CECNPC).IsDead())) + return null; + } + else if (GPDataTypeHelper.ISPLAYERID(idObject)) + { + if (!(pObject = EC_ManPlayer.GetPlayer(idObject))) + return null; + + if ((iAliveFlag == 1 && (pObject as EC_Player).IsDead()) || + (iAliveFlag == 2 && !(pObject as EC_Player).IsDead())) + return null; + } + //else if (GPDataTypeHelper.ISMATTERID(idObject)) + // pObject = GetMatterMan()->GetMatter(idObject); + + return pObject; + } } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs index 0964581efa..1b6f0c5cbd 100644 --- a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs @@ -180,6 +180,21 @@ namespace BrewMonster.Network } } + public static void c2s_CmdNPCSevHello(int nid) + { + Instance._gameSession.c2s_SendCmdNPCSevHello(nid); + } + + public static void c2s_CmdNormalAttack(byte byPVPMask) + { + Instance._gameSession.c2s_CmdNormalAttack(byPVPMask); + } + + public static void c2s_CmdCancelAction() + { + Instance._gameSession.c2s_CmdCancelAction(); + } + #region Task public static void c2s_CmdGetAllData(bool byPack, bool byEquip, bool byTask) { diff --git a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs index 43a07b88b9..58c64ecb0d 100644 --- a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs +++ b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs @@ -30,9 +30,9 @@ namespace PerfectWorld.Scripts.Player int m_iGender; // Gender float m_fScaleBySkill = 1f; MOVECONST m_MoveConst; // Const used when moving control - int m_iMoveEnv; // Move environment - bool m_bWalkRun; // Walk-run switch, 0-walk, 1-run - int m_iMoveMode; // Player's move mode + //int m_iMoveEnv; // Move environment + //bool m_bWalkRun; // Walk-run switch, 0-walk, 1-run + //int m_iMoveMode; // Player's move mode public MOVECONST[] aMoveConsts = new MOVECONST[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER] { @@ -445,7 +445,7 @@ namespace PerfectWorld.Scripts.Player m_aabbServer.CompleteMinsMaxs(); } - private A3DVECTOR3 GetPos() + public A3DVECTOR3 GetPos() { A3DVECTOR3 result = new A3DVECTOR3(); result.x = transform.position.x; @@ -454,70 +454,13 @@ namespace PerfectWorld.Scripts.Player return result; } - private int GetMoveStandAction(bool bMove, bool bFight = false) - { - int iMoveEnv = m_iMoveEnv; - //if (m_AttachMode != enumAttachNone) - //{ - // bFight = false; - // if (m_bHangerOn) - // iMoveEnv = MOVEENV_GROUND; - //} + // Get player's real position on server + public A3DVECTOR3 GetServerPos() { return m_vServerPos; } - int iAction = (int)PLAYER_ACTION_TYPE.ACT_STAND; - - if (bMove) - { - // Play appropriate actions - if (iMoveEnv == (int)MoveEnvironment.MOVEENV_GROUND) - { - if (m_bWalkRun) - iAction = (int)PLAYER_ACTION_TYPE.ACT_RUN; - else - iAction = (int)PLAYER_ACTION_TYPE.ACT_WALK; - } - //else if (iMoveEnv == MOVEENV_AIR) - //{ - // //if (/*UsingWing()*/ m_wingType == WINGTYPE_WING) - // // iAction = ACT_FLY; - // //else - // // iAction = ACT_FLY_SWORD; - //} - //else if (iMoveEnv == MOVEENV_WATER) - //{ - // //if (CanCombineWithMoveForSkill()) - // //{ - // // iAction = ACT_SWIM_FOR_MOVESKILL; - // //} - // //else - // //{ - // // iAction = ACT_SWIM; - // //} - //} - } - else - { - // Play appropriate actions - if (iMoveEnv == (int)MoveEnvironment.MOVEENV_GROUND) - { - if (bFight) - iAction = (int)PLAYER_ACTION_TYPE.ACT_FIGHTSTAND; - else - iAction = (int)PLAYER_ACTION_TYPE.ACT_STAND; - } - //else if (iMoveEnv == MOVEENV_AIR) - //{ - // if (/*UsingWing()*/ m_wingType == WINGTYPE_WING) - // iAction = ACT_HANGINAIR; - // else - // iAction = ACT_HANGINAIR_SWORD; - //} - //else if (iMoveEnv == MOVEENV_WATER) - // iAction = ACT_HANGINWATER; - } - - return iAction; - } + //public A3DVECTOR3 GetPos() + //{ + // return new A3DVECTOR3(transform.position.x, transform.position.y, transform.position.z); + //} } // Player appear flag diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index 7d0ca1c17a..96adbccb93 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -1,16 +1,17 @@ -锘縰sing BrewMonster.Network; +锘縰sing BrewMonster; +using BrewMonster.Network; using CSNetwork; using CSNetwork.GPDataType; using CSNetwork.Protocols; using CSNetwork.Protocols.RPCData; using PerfectWorld.Scripts.Managers; +using PerfectWorld.Scripts.Player; using PerfectWorld.Scripts.Task; using System; using System.IO; using System.Runtime.InteropServices; using System.Text; using TMPro; -using Unity.VisualScripting; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; @@ -30,7 +31,18 @@ public class CECHostPlayer : EC_Player PlayerStateMachine _playerStateMachine; PlayerMoveState _moveState; PlayerIdleState _idleState; - CECHostMove m_MoveCtrl; + public CECHostMove m_MoveCtrl; + + CECHPWorkMan m_pWorkMan; // Host work manager + uint m_dwLIES; // Logic-influence extend states + FACTION_FORTRESS_ENTER m_fortressEnter; // 陆酶脠毛禄霉碌脴脨脜脧垄 + PVPINFO m_pvp; // pvp information + bool m_bInSanctuary = false; // true, player is in sanctuary + int m_idFaction = 0; // ID of player's faction + public bool m_bPrepareFight = false; // true, prepare to fight + int m_iJumpCount = 0; + bool m_bJumpInWater = false; + public A3DVECTOR3 m_vVelocity; // Velocity float playerSpeed = 5.0f; float jumpHeight = 1.5f; @@ -40,6 +52,9 @@ public class CECHostPlayer : EC_Player bool isGrounded = false; bool isRun = false; Vector3 m_vLastSevPos; + public CDR_INFO m_CDRInfo; + public GNDINFO m_GndInfo; + public float m_fVertSpeed = 0f; // ====== Ground cast config ====== [Header("Ground Cast")] @@ -214,7 +229,7 @@ public class CECHostPlayer : EC_Player case int value when value == EC_MsgDef.MSG_HST_TASKDATA: { OnMsgHstTaskData(Msg); - Debug.Log("[Dat]- OnMsgHstTaskData"); + Debug.LogError("[Dat]- OnMsgHstTaskData"); break; } case int value when value == EC_MsgDef.MSG_HST_ITEMOPERATION: @@ -331,34 +346,34 @@ public class CECHostPlayer : EC_Player break; } case CommandID.EQUIP_ITEM: - { + { byte index_inv = data[0]; byte index_equip = data[1]; - // Update client-side data: move item between PACK_INVENTORY and PACK_EQUIPMENT - var invItem = EC_Inventory.GetItem(EC_Inventory.PACK_INVENTORY, index_inv, true); - var equipItem = EC_Inventory.GetItem(EC_Inventory.PACK_EQUIPMENT, index_equip, true); - if (invItem != null) - { - invItem.Package = EC_Inventory.PACK_EQUIPMENT; - invItem.Slot = index_equip; - EC_Inventory.SetItem(EC_Inventory.PACK_EQUIPMENT, index_equip, invItem); - } - if (equipItem != null) - { - equipItem.Package = EC_Inventory.PACK_INVENTORY; - equipItem.Slot = index_inv; - EC_Inventory.SetItem(EC_Inventory.PACK_INVENTORY, index_inv, equipItem); - } + // Update client-side data: move item between PACK_INVENTORY and PACK_EQUIPMENT + var invItem = EC_Inventory.GetItem(EC_Inventory.PACK_INVENTORY, index_inv, true); + var equipItem = EC_Inventory.GetItem(EC_Inventory.PACK_EQUIPMENT, index_equip, true); + if (invItem != null) + { + invItem.Package = EC_Inventory.PACK_EQUIPMENT; + invItem.Slot = index_equip; + EC_Inventory.SetItem(EC_Inventory.PACK_EQUIPMENT, index_equip, invItem); + } + if (equipItem != null) + { + equipItem.Package = EC_Inventory.PACK_INVENTORY; + equipItem.Slot = index_inv; + EC_Inventory.SetItem(EC_Inventory.PACK_INVENTORY, index_inv, equipItem); + } - // Trigger UI refresh if an EC_InventoryUI is present in scene - var ui = GameObject.FindObjectOfType(); - if (ui != null) - { - ui.RefreshAll(); - } + // Trigger UI refresh if an EC_InventoryUI is present in scene + var ui = GameObject.FindObjectOfType(); + if (ui != null) + { + ui.RefreshAll(); + } - break; - } + break; + } } } public void OnMsgHstOwnItemInfo(ECMSG Msg) @@ -428,7 +443,7 @@ public class CECHostPlayer : EC_Player } - private void SetPos(Vector3 pos) + public void SetPos(Vector3 pos) { transform.position = pos; } @@ -461,6 +476,13 @@ public class CECHostPlayer : EC_Player { visual.InitHostPlayerEventDoneHandler(); } + + // Create work manager + m_pWorkMan = new CECHPWorkMan(this); + if (m_pWorkMan == null) + { + return; + } } private void JoystickStartDrag(JoystickPressEvent joystickPressEvent) @@ -497,7 +519,7 @@ public class CECHostPlayer : EC_Player //cmd_task_data* pCmd = (cmd_task_data*)Msg.dwParam1; //ASSERT(pCmd); - //int iActiveListSize = (int)pCmd->active_list_size; + //int iActiveListSize = (int)pCmd.active_list_size; //BYTE* pData = (BYTE*)pCmd + sizeof(size_t); //void* pActiveListbuf = pData; //pData += iActiveListSize; @@ -523,30 +545,30 @@ public class CECHostPlayer : EC_Player //pData += iStorageTasksListSize; //A3DRELEASE(m_pTaskInterface); - - return; - var m_pTaskInterface = new CECTaskInterface(this); - if (!m_pTaskInterface.Init(null, 0, null, 0, - null, 0, null, 0, null, 0)) - { - //a_LogOutput(1, "CECHostPlayer::OnMsgHstTaskData, failed to initialize task interface"); - return; - } + //todo + //var m_pTaskInterface = new CECTaskInterface(this); - m_pTaskInterface.CheckPQEnterWorldInit(); + //if (!m_pTaskInterface.Init(null, 0, null, 0, + // null, 0, null, 0, null, 0)) + //{ + // //a_LogOutput(1, "CECHostPlayer::OnMsgHstTaskData, failed to initialize task interface"); + // return; + //} + + //m_pTaskInterface.CheckPQEnterWorldInit(); //// check if player has equipped goblin - //if (m_pEquipPack->GetItem(EQUIPIVTR_GOBLIN) != NULL) + //if (m_pEquipPack.GetItem(EQUIPIVTR_GOBLIN) != NULL) //{ - // CECIvtrGoblin* pIvtrGoblin = (CECIvtrGoblin*)m_pEquipPack->GetItem(EQUIPIVTR_GOBLIN); + // CECIvtrGoblin* pIvtrGoblin = (CECIvtrGoblin*)m_pEquipPack.GetItem(EQUIPIVTR_GOBLIN); // m_pGoblin = new CECHostGoblin(); - // m_pGoblin->Init(pIvtrGoblin->GetTemplateID(), pIvtrGoblin, this); + // m_pGoblin.Init(pIvtrGoblin.GetTemplateID(), pIvtrGoblin, this); //} //// Note: this command now is also used as the end flag of responding //// for GET_ALL_DATA request - //g_pGame->GetGameSession()->LoadConfigData(); + //g_pGame.GetGameSession().LoadConfigData(); //// 赂霉戮脻脳掳卤赂掳眉鹿眉赂眉脨脗脳掳卤赂录录脛脺碌陆录录脛脺脕脨卤铆 //if (UpdateEquipSkills()) @@ -557,12 +579,357 @@ public class CECHostPlayer : EC_Player //cmd_task_var_data* pCmd = (cmd_task_var_data*)Msg.dwParam1; //ASSERT(pCmd); //if (m_pTaskInterface) - // OnServerNotify(m_pTaskInterface, pCmd->data, pCmd->size); + // OnServerNotify(m_pTaskInterface, pCmd.data, pCmd.size); //else // ASSERT(m_pTaskInterface); } } #endregion + + private bool NormalAttackObject(int idTarget, bool bForceAttack, bool bMoreClose = false) + { + if (idTarget == 0 || idTarget == m_PlayerInfo.cid) + { + // We should have check target isn't dead + return false; + } + //if (!EC_Game.GetGameRun().GetWorld().GetObject(idTarget, 1)) + // return false; + bool bStartNewWork = false; + + bool bUseAutoPF = false; + //CECPlayerWrapper* pWrapper = CECAutoPolicy::GetInstance().GetPlayerWrapper(); + //if (CECAutoPolicy::GetInstance().IsAutoPolicyEnabled() && pWrapper.GetAttackError() >= 2) + bUseAutoPF = true; + + CECHPWorkTrace pWorkTrace = null; + CECHPWork pWork = null; + if ((pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT)) != null) + { + pWorkTrace = pWork as CECHPWorkTrace; + } + else if ((pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_HACKOBJECT)) != null) + { + if ((pWork as CECHPWorkMelee).GetTarget() == idTarget) + return false; // Host is attacking the target + + pWorkTrace = (CECHPWorkTrace)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT); + bStartNewWork = true; + } + else if (m_pWorkMan.CanStartWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT)) + { + pWorkTrace = (CECHPWorkTrace)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT); + bStartNewWork = true; + } + + if (pWorkTrace != null) + { + pWorkTrace.SetTraceTarget(pWorkTrace.CreatTraceTarget(idTarget, CECHPWorkTrace.Trace_reason.TRACE_ATTACK, bForceAttack), bUseAutoPF); + pWorkTrace.SetMoveCloseFlag(bMoreClose); + + if (bStartNewWork) + m_pWorkMan.StartWork_p1(pWorkTrace); + return true; + } + return false; + } + + public int AttackableJudge(int idTarget, bool bForceAttack) + { + if (CannotAttack()) + return 0; + + //if (CDlgAutoHelp::IsAutoHelp()) + // return 0; + + if (idTarget == 0 || idTarget == m_PlayerInfo.cid) + return -1; + + CECObject pObject = EC_ManMessageMono.Instance.GetObject(idTarget, 1); + if (!pObject) + return -1; + + // If target is pet, it's attacked possibility depends on it's monster + if (GPDataTypeHelper.ISNPCID(idTarget)) + { + CECNPC pNPC = (CECNPC)pObject; + int idMaster = pNPC.GetMasterID(); + if (idMaster != 0) + { + // master驴脡脛脺脢脟hostplayer + if (idMaster == m_PlayerInfo.cid) + return 0; + + //// Follow pet cannot be attacked + //if (pNPC.IsPetNPC() && ((CECPet)pNPC).IsFollowPet()) + // return 0; + + idTarget = idMaster; + pObject = EC_ManMessageMono.Instance.GetObject(idTarget, 1); + if (!pObject) + return -1; + } + } + + int iRet = 0; + + if (GPDataTypeHelper.ISNPCID(idTarget)) + { + CECNPC pNPC = (CECNPC)pObject; + + // If this npc is host's pet, cannot be attacked + //if (pNPC.GetMasterID() == m_PlayerInfo.cid) + // return 0; + + // If it's a pet and can not be attacked, pet can be attacked only if it's a fighting pet + //if (pNPC.IsPetNPC() && !((CECPet)pNPC).CanBeAttacked()) + // return 0; + + if (IsInBattle()) // Host is in battle + { + if (InSameBattleCamp(pNPC)) + iRet = 0; + else + { + if (pNPC.IsMonsterNPC()) + iRet = 1; + else if (pNPC.IsServerNPC() && (IsInFortress() || pNPC.GetRoleInBattle() == 8)) // 露脭路镁脦帽脨脥NPC碌脛鹿楼禄梅拢卢掳茂脜脡禄霉碌脴禄貌鲁脟脮陆脢卤驴脡脫脙 + iRet = 1; + else + iRet = 0; + } + } + else if (pNPC.IsServerNPC()) + { + // In sanctuary we cannot attack NPCs + if (!IsPVPOpen() || m_bInSanctuary || !bForceAttack) + iRet = 0; + else + iRet = 1; + } + else // Is monster + { + iRet = 1; + } + if (iRet == 1 && pNPC.GetOwnerFaction() > 0) + { + // 脮毛露脭掳茂脜脡 PVP 脮陆脮霉脰脨陆没脰鹿虏驴路脰鹿楼禄梅 + if (GetFactionID() == pNPC.GetOwnerFaction() || // 虏禄鹿楼禄梅脥卢掳茂鹿脰 + pNPC.IsFactionPVPMineCar() && !CanAttackFactionPVPMineCar() || // 脦脼路篓脭脵鹿楼禄梅脣没掳茂驴贸鲁碌脟茅驴枚 + pNPC.IsFactionPVPMineBase() && !CanAttackFactionPVPMineBase()) + { // 脦脼路篓脭脵鹿楼禄梅脣没掳茂麓忙驴贸碌茫脟茅驴枚 + iRet = 0; + } + } + } + // TO DO: fix later + //else if (GPDataTypeHelper.ISPLAYERID(idTarget)) + //{ + // // Check duel at first + // if (m_pvp.iDuelState == Duel_state.DUEL_ST_INDUEL && m_pvp.idDuelOpp == idTarget) + // return 1; + // else if (m_pvp.iDuelState == Duel_state.DUEL_ST_STOPPING && m_pvp.idDuelOpp == idTarget) + // return 0; + + // // In sanctuary we cannot attack other players + // if (m_bInSanctuary) + // return 0; + + // //ASSERT(pObject.GetClassID() == CECObject::OCID_ELSEPLAYER); + // EC_ElsePlayer pPlayer = (EC_ElsePlayer)pObject; + // ROLEBASICPROP bp = pPlayer.GetBasicProps(); + // EC_GAME_SETTING gs = g_pGame.GetConfigs().GetGameSettings(); + + // if (m_pvp.bFreePVP) + // { + // if (IsTeamMember(idTarget)) + // return 0; + + // // In free pvp mode, for example, host is in arena. + // if (bForceAttack) + // iRet = 1; + // else if (gs.bAtk_NoMafia && IsFactionMember(pPlayer.GetFactionID())) + // iRet = 0; + // else if (gs.bAtk_NoWhite && !pPlayer.IsInvader() && !pPlayer.IsPariah()) + // iRet = 0; + // else if (gs.bAtk_NoAlliance && g_pGame.GetFactionMan().IsFactionAlliance(pPlayer.GetFactionID())) + // iRet = 0; + // else if (gs.bAtk_NoForce && GetForce() > 0 && GetForce() == pPlayer.GetForce()) + // iRet = 0; + // else + // iRet = 1; + // } + // else if (m_iBattleCamp != GP_BATTLE_CAMP_NONE) + // { + // // Host is in battle + // int iCamp = pPlayer.GetBattleCamp(); + // if (iCamp != GP_BATTLE_CAMP_NONE && iCamp != m_iBattleCamp) + // iRet = 1; + // else + // iRet = 0; + // } + // else // Normal mode + // { + // if (IsTeamMember(idTarget)) + // return 0; + + // if (!IsPVPOpen() || !pPlayer.IsPVPOpen() || m_BasicProps.iLevel < EC_MAXNOPKLEVEL || bp.iLevel < EC_MAXNOPKLEVEL) + // iRet = 0; + // else if (bForceAttack) + // iRet = 1; + // else if (!gs.bAtk_Player) + // iRet = 0; + // else if (gs.bAtk_NoMafia && IsFactionMember(pPlayer.GetFactionID())) + // iRet = 0; + // else if (gs.bAtk_NoWhite && !pPlayer.IsInvader() && !pPlayer.IsPariah()) + // iRet = 0; + // else if (gs.bAtk_NoAlliance && g_pGame.GetFactionMan().IsFactionAlliance(pPlayer.GetFactionID())) + // iRet = 0; + // else if (gs.bAtk_NoForce && GetForce() > 0 && GetForce() == pPlayer.GetForce()) + // iRet = 0; + // else + // iRet = 1; + // } + //} + else + { + return -1; + } + + return iRet; + } + + private float A3d_Magnitude(A3DVECTOR3 v) + { + return Mathf.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); + } + + public int GetCharacterID(){ return m_PlayerInfo.cid; } + + public bool CannotAttack() { return (m_dwLIES & (uint)Logic_Influence_Extned_states.LIES_DISABLEFIGHT) != 0; } + + public bool CanTouchTarget(A3DVECTOR3 vHostPos, A3DVECTOR3 vTargetPos, float fTargetRad, int iReason, float fMaxCut = 1.0f) + { + float fDist = A3d_Magnitude(vTargetPos - vHostPos); + switch (iReason) + { + case 1: // melee + { + float fRange; + if (fMaxCut >= 0.0f) + { + float fCutDist = m_ExtProps.ak.AttackRange * 0.3f; + if (fCutDist > fMaxCut) + fCutDist = fMaxCut; + + fRange = m_ExtProps.ak.AttackRange - fCutDist; + } + + else + fRange = m_ExtProps.ak.AttackRange * 0.7f; + + if (fDist - fTargetRad <= fRange) + return true; + + break; + } + //case 2: // cast magic + //{ + // if (m_pPrepSkill) + // { + // float fRange = m_pPrepSkill->GetCastRange(m_ExtProps.ak.AttackRange, GetPrayDistancePlus()); + // if (fRange > 0.0f) + // { + // if (fDist - fTargetRad <= fRange) + // return true; + // } + // else + // return true; + // } + + // break; + //} + case 3: // talk + { + if (fDist - fTargetRad <= 5.0f) + return true; + + break; + } + default: // no special reason + { + if (fDist < (fTargetRad + m_fTouchRad) * 3.0f) + return true; + + break; + } + } + + return false; + } + + public bool CanTouchTarget(A3DVECTOR3 vTargetPos, float fTargetRad, int iReason, float fMaxCut = 1.0f) + { + A3DVECTOR3 vector = new A3DVECTOR3(gameObject.transform.position.x, gameObject.transform.position.y, gameObject.transform.position.z); + return CanTouchTarget(vector, vTargetPos, fTargetRad, iReason, fMaxCut); + } + public bool IsRooting() { + var mask = (uint)(Logic_Influence_Extned_states.LIES_ROOT + | Logic_Influence_Extned_states.LIES_SLEEP + | Logic_Influence_Extned_states.LIES_STUN); + return (m_dwLIES & mask) != 0; } + + bool IsInFortress() { return m_fortressEnter.role_in_war != 0; } + + bool IsPVPOpen() { return m_pvp.bEnable; } + // Get faction ID + int GetFactionID(){ return m_idFaction; } + + public bool IsJumping() { return m_iJumpCount > 0; } + + public bool IsPlayingAction(int iAction) + { + if (iAction == (int)PLAYER_ACTION_TYPE.ACT_WALK && _playerStateMachine.State is PlayerMoveState) + { + return true; + } + if (iAction == (int)PLAYER_ACTION_TYPE.ACT_STAND && _playerStateMachine.State is PlayerIdleState) + { + return true; + } + return false; + } + + public void ResetJump() { m_iJumpCount = 0; m_bJumpInWater = false; } + // Get move speed + public float GetFlySpeed() { return m_ExtProps.mv.flight_speed; } + public float GetSwimSpeed() { return m_ExtProps.mv.swim_speed; } + + //public float GetSwimSpeedSev() + //{ + // float fSpeedSev = GetSwimSpeed(); + // while (true) + // { + // if (!IsUnderWater()) break; + // //CECWorld* pWorld = g_pGame->GetGameRun()->GetWorld(); + // //if (!pWorld) break; + + // const A3DVECTOR3 vPos = GetPos(); + // float fTerrainHeight = pWorld->GetTerrainHeight(vPos); + // float fWaterHeight = pWorld->GetWaterHeight(vPos); + // if (fWaterHeight <= fTerrainHeight) break; + + // float fBorderLine = fWaterHeight - 2.0f; + // if (vPos.y <= fBorderLine) break; + + // // 路镁脦帽脝梅露脣陆芦脣庐脙忙脪脭脧脗2脙脳脪脭脡脧麓娄脌铆脦陋 run_speed拢篓脫脨脦脢脤芒拢漏 + // // 碌芦脦麓脢鹿脫脙录脫脣脵录录脛脺脢卤 swim_speed 脨隆脫脷 run_speed拢卢 + // // 驴脡脪脭脭脷脣庐脙忙脪脭脧脗2脙脳脪脭脡脧禄帽脠隆鲁卢鹿媒 swim_speed 碌脛脣脵露脠拢卢脪貌麓脣拢卢麓脣麓娄脠隆脕陆脮脽陆脧脨隆脰碌脦陋潞脧脌铆脳枚路篓 + // fSpeedSev = min(m_ExtProps.mv.run_speed, fSpeedSev); + // break; + // } + // return fSpeedSev; + //} } public enum StateAnim @@ -572,3 +939,54 @@ public enum StateAnim Run = 3, Jump = 4 } + +// Mask of some special extend states which will influence host game logic. +// Logic Influence Extned states +[Flags] +public enum Logic_Influence_Extned_states +{ + LIES_SLEEP = 0x0001, + LIES_STUN = 0x0002, + LIES_ROOT = 0x0004, + LIES_NOFGIHT = 0x0008, + + LIES_DISABLEFIGHT = 0x000B, +} + +// 陆酶脠毛禄霉碌脴脨脜脧垄 +public struct FACTION_FORTRESS_ENTER +{ + public int faction_id; + public int role_in_war; // 0 : 脰脨脕垄禄貌虏禄脭脷禄霉碌脴 1:鹿楼路陆 2: 脢脴路陆 + public int end_time; + + public FACTION_FORTRESS_ENTER(int faction_id, int role_in_war, int end_time) + { + this.faction_id = faction_id; + this.role_in_war = role_in_war; + this.end_time = end_time; + } +} + +// PVP infomation +public struct PVPINFO +{ + public bool bEnable; // PVP switch + public uint dwCoolTime; + public uint dwMaxCoolTime; + public bool bFreePVP; // Free PVP flag, ignore bEnable flag + public bool bInPVPCombat; // true, in PVP combat + public int iDuelState; // Duel state + public int idDuelOpp; // Duel opponent + public int iDuelTimeCnt; // Duel time counter + public int iDuelRlt; // Duel result. 0, no defined; 1-win; 2-lose; 3-draw +}; + +// Current ground information +public struct GNDINFO +{ + public float fGndHei; // Ground height + public float fWaterHei; // Water height + public A3DVECTOR3 vGndNormal; // Terrain normal + public bool bOnGround; // On ground flag +}; \ No newline at end of file diff --git a/Assets/Scripts/EC_Utility.cs b/Assets/Scripts/EC_Utility.cs index f238ff39ab..d1ef9f4cfb 100644 --- a/Assets/Scripts/EC_Utility.cs +++ b/Assets/Scripts/EC_Utility.cs @@ -86,4 +86,45 @@ public static class EC_Utility return $"{prefix}_{suffix}"; } + + // Build pvp mask + public static byte glb_BuildPVPMask(bool bForceAttack) + { + byte byMask = 0; + if (bForceAttack) + byMask |= (byte)PVP_mask.GP_PVPMASK_FORCE; + //else + //{ + // CECConfigs* pConfigs = g_pGame->GetConfigs(); + + // if (pConfigs->GetGameSettings().bAtk_Player) + // { + // byMask |= GP_PVPMASK_FORCE; + + // if (pConfigs->GetGameSettings().bAtk_NoMafia) + // byMask |= GP_PVPMASK_NOMAFIA; + + // if (pConfigs->GetGameSettings().bAtk_NoWhite) + // byMask |= GP_PVPMASK_NOWHITE; + + // if (pConfigs->GetGameSettings().bAtk_NoAlliance) + // byMask |= GP_PVPMASK_NOALLIANCE; + + // if (pConfigs->GetGameSettings().bAtk_NoForce) + // byMask |= GP_PVPMASK_NOFORCE; + // } + //} + + return byMask; + } + + public static T a_ClampFloor(T x, T min) where T : IComparable + { + return (x.CompareTo(min) < 0) ? min : x; + } + + public static T a_Min(T x, T y) where T : IComparable + { + return (y.CompareTo(x) < 0) ? y : x; + } } diff --git a/Assets/Scripts/Move/CECHostMove.cs b/Assets/Scripts/Move/CECHostMove.cs index 706c6293ea..5c1803db59 100644 --- a/Assets/Scripts/Move/CECHostMove.cs +++ b/Assets/Scripts/Move/CECHostMove.cs @@ -1,9 +1,12 @@ 锘縰sing BrewMonster.Network; +using CSNetwork; using CSNetwork.C2SCommand; using CSNetwork.GPDataType; +using CSNetwork.Protocols; using System; using System.Collections.Generic; using System.Runtime.ConstrainedExecution; +using System.Security.Cryptography; using System.Text; using UnityEngine; using CSNetwork.Protocols; @@ -24,7 +27,12 @@ public class CECHostMove ulong m_dwLastTime; Vector3 m_vLastPos; float m_fAverSpeedH; - + int m_iBlockedCnt; // Move blocked counter + bool m_bSlideLock; // Locked when slide + float m_fBlockTime; // Block time counter + float m_fBlockMove; // Block move counter + A3DVECTOR3 m_vBlockMove; + bool m_bLocalMove; // true, Moving info isn't sent to server public CECHostMove(CECHostPlayer pHost) { @@ -42,8 +50,8 @@ public class CECHostMove { var m = m_DelayedStop; - // a_GetTime() -> Environment.TickCount (ms) - ulong dwCurrent = (ulong)Mathf.RoundToInt( Time.time * 1000); + // a_GetTime() . Environment.TickCount (ms) + ulong dwCurrent = (ulong)Mathf.RoundToInt(Time.time * 1000); // iTime: th峄漣 gian t铆ch l农y (ms) + delta t峄 timestamp 膽岷縩 hi峄噉 t岷 int iTime = (int)((m.fTime * 1000f) @@ -57,9 +65,9 @@ public class CECHostMove // make a potential check with tuojigua iMoveMode |= (int)GPMoveMode.GP_MOVE_DEAD; - UnityGameSession.Instance.c2s_SendCmdStopMove( - m.vPos, fSpeed, iMoveMode, m.byDir, m_wMoveStamp++, iTime - ); + UnityGameSession.Instance.c2s_SendCmdStopMove( + m.vPos, fSpeed, iMoveMode, m.byDir, m_wMoveStamp++, iTime + ); // Record this position m_vLastSevPos = m.vPos; @@ -73,6 +81,33 @@ public class CECHostMove m_vLastPos = m_pHost.transform.position; m_dwLastTime = dwDeltaTime; } + + public void SendStopMoveCmd() + { + int iMoveMode = (int)GPMoveMode.GP_MOVE_RUN; + float fSpeed = 0f; + switch (m_pHost.GetMoveEnv()) + { + case EC_Player.Move_environment.MOVEENV_AIR: + + iMoveMode |= (int)GPMoveMode.GP_MOVE_AIR; + fSpeed = m_pHost.GetFlySpeed(); + break; + + //case EC_Player.Move_environment.MOVEENV_WATER: + + // iMoveMode |= (int)GPMoveMode.GP_MOVE_WATER; + // fSpeed = m_pHost.GetSwimSpeedSev(); + // break; + + default: + + fSpeed = m_pHost.GetGroundSpeed(); + break; + } + SendStopMoveCmd(EC_Utility.ToVector3(m_pHost.GetPos()), fSpeed, iMoveMode); + } + public void SendStopMoveCmd(in Vector3 vPos, float fSpeed, int iMoveMode) { Debug.LogWarning("HoangDev : SendStopMoveCmd"); @@ -87,7 +122,7 @@ public class CECHostMove UnityGameSession.Instance.c2s_SendCmdStopMove(vPos, fSpeed, iMoveMode, byDir, m_wMoveStamp++, iTime); - m_vLastSevPos = vPos; + m_vLastSevPos = vPos; Reset(); } else @@ -115,14 +150,31 @@ public class CECHostMove float fSpeed = vMoveDir.magnitude; SendMoveCmd(vCurPos, fSpeed, iMoveMode, bForceSend); } + + public void SendMoveCmd(A3DVECTOR3 vCurPos, int iDestType, A3DVECTOR3 vDest, A3DVECTOR3 vVel, int iMoveMode, bool bForceSend = false) + { + + A3DVECTOR3 vMoveDir = vVel; + float fSpeed = vMoveDir.Normalize(); + SendMoveCmd(vCurPos, iDestType, vDest, vMoveDir, fSpeed, iMoveMode, bForceSend); + } + + void SendMoveCmd(A3DVECTOR3 vCurPos, int iDestType, A3DVECTOR3 vDest, + A3DVECTOR3 vMoveDir, float fSpeed, int iMoveMode, bool bForceSend) + + { + Vector3 pos = new Vector3(vCurPos.x, vCurPos.y, vCurPos.z); + SendMoveCmd(pos, fSpeed, iMoveMode, bForceSend); + } + void SendMoveCmd(in Vector3 vCurPos, - float fSpeed, int iMoveMode, bool bForceSend) + float fSpeed, int iMoveMode, bool bForceSend) { if (m_bStop) { // m_CmdTimeCnt.Reset(); - cmdmovedelayCounter = (ulong)( m_fMoveTime * 1000); + cmdmovedelayCounter = (ulong)(m_fMoveTime * 1000); m_bStop = false; } if (!bForceSend && cmdmovedelayCounter < 500) @@ -151,7 +203,7 @@ public class CECHostMove m_vLastSevPos = vCurPos; } - + float l_CalcAverageSpeed(in Vector3 p1, in Vector3 p2, float fTime, float fDefSpeed) { if (Mathf.Approximately(fTime, 0f)) @@ -183,14 +235,107 @@ public class CECHostMove struct STOPMOVE { - public bool bValid; // Valid flag - public Vector3 vPos; - public float fSpeed; - public int iMoveMode; - public byte byDir; - public ulong dwTimeStamp; - public float fTime; + public bool bValid; // Valid flag + public Vector3 vPos; + public float fSpeed; + public int iMoveMode; + public byte byDir; + public ulong dwTimeStamp; + public float fTime; }; + + // Check whether host meet a slope + // vMoveDirH: normalized horizontal moving direction + // fMaxSpeed (out): maximum vertical speed + public bool MeetSlope(A3DVECTOR3 vMoveDirH, float fMaxSpeedV) + { + A3DVECTOR3 vTangent = m_pHost.m_GndInfo.vGndNormal; + + float d = vTangent.MagnitudeH(); + float tan = d / (float)Math.Abs(vTangent.y); + float max = m_pHost.GetGroundSpeed() * tan * 0.96f; + // Prevent max is too small, tan60 = 1.732 + EC_Utility.a_ClampFloor(max, m_pHost.GetGroundSpeed() * 1.732f); + fMaxSpeedV = EC_Utility.a_Min(max, 19.5f); + + // fMaxSpeedV = 100.0f; + + vTangent.y = 0.0f; + vTangent.Normalize(); + + if (A3DVECTOR3.DotProduct(vMoveDirH, vTangent) <= -0.85f) + return true; + + return false; + } + + public A3DVECTOR3 GroundMove(A3DVECTOR3 vDirH, float fSpeedH, float fTime, float fSpeedV = 0f, float fGravity = 9.8f) + { + A3DVECTOR3 vRealDirH = vDirH; + + if (Math.Abs(vRealDirH.y) > 0.0001) + { + vRealDirH.y = 0.0f; + vRealDirH.Normalize(); + } + + // OnGroundMove only accept positive speed value + if (fSpeedH < 0.0f) + { + vRealDirH = -vDirH; + fSpeedH = -fSpeedH; + } + + //int idInst = g_pGame.GetGameRun().GetWorld().GetInstanceID(); + //CECInstance pInstance = g_pGame.GetGameRun().GetInstance(idInst); + //if (pInstance.GetLimitJump()) + fGravity *= 4.0f; + + CDR_INFO cdr = m_pHost.m_CDRInfo; + var pos = m_pHost.m_aabbServer.Center; + cdr.vCenter = new Vector3(pos.x, pos.y, pos.z); + cdr.vXOZVelDir = new Vector3(vRealDirH.x, vRealDirH.y, vRealDirH.z); + cdr.fSpeed = fSpeedH; + cdr.t = fTime; + cdr.fGravityAccel = fGravity; + cdr.fYVel += fSpeedV; + + EC_CDR.OnGroundMove(ref cdr); + + //if (g_pGame.GetGameRun().GetWorld().GetAssureMove()) + // g_pGame.GetGameRun().GetWorld().GetAssureMove().AssureMove(m_pHost.m_aabbServer.Center, cdr.vCenter); + + if (cdr.vTPNormal != Vector3.zero) + m_pHost.SetGroundNormal(new A3DVECTOR3(cdr.vTPNormal.x, cdr.vTPNormal.y, cdr.vTPNormal.z)); + else + m_pHost.SetGroundNormal(GPDataTypeHelper.g_vAxisY); + + A3DVECTOR3 vNewPos = new A3DVECTOR3(cdr.vCenter.x, cdr.vCenter.y, cdr.vCenter.z) - GPDataTypeHelper.g_vAxisY * m_pHost.m_aabbServer.Extents.y; + + m_iBlockedCnt = 0; + m_fBlockMove += (vNewPos - m_pHost.GetPos()).Magnitude(); + m_vBlockMove += vNewPos - m_pHost.GetPos(); + if ((m_fBlockTime += fTime) >= 1.0f) + { + if (m_fBlockMove < GPDataTypeHelper.MIN_MOVELEN_ON_GROUND || m_vBlockMove.Magnitude() < GPDataTypeHelper.MIN_MOVELEN_FOR_DETECT_VIBRATION) + { + m_iBlockedCnt = 5; + } + + m_fBlockTime = 0.0f; + m_fBlockMove = 0.0f; + m_vBlockMove.Clear(); + } + + m_fMoveTime += fTime; + + return vNewPos; + } + + public int MoveBlocked() { return m_iBlockedCnt; } + public void SetSlideLock(bool bLock) { m_bSlideLock = bLock; } + // Is stoping ? + public bool IsStop() { return m_bStop; } } public struct CDR_INFO { diff --git a/Assets/Scripts/Move/EC_Player.cs b/Assets/Scripts/Move/EC_Player.cs index 830d7710fc..16b479fba9 100644 --- a/Assets/Scripts/Move/EC_Player.cs +++ b/Assets/Scripts/Move/EC_Player.cs @@ -1,18 +1,30 @@ 锘縰sing BrewMonster; +using CSNetwork.GPDataType; using ModelRenderer.Scripts.GameData; +using PerfectWorld.Scripts.Player; using System; using System.Collections.Generic; using UnityEngine; -public abstract class EC_Player : MonoBehaviour +public abstract class EC_Player : CECObject { private static PLAYER_ACTION[] _default_actions; private static PLAYER_ACTION[] _turning_actions; PLAYER_ACTION[] m_PlayerActions; - [SerializeField] protected INFO m_PlayerInfo; + [SerializeField] internal INFO m_PlayerInfo; protected GameObject m_pPlayerModel; protected float rotationSpeed = 5; - + internal int m_iMoveMode; // Player's move mode + internal int m_idSelTarget; // 脩隆脰脨脛驴卤锚碌脛ID + uint m_dwStates; // Player's basic states + protected ROLEEXTPROP m_ExtProps; // Extend properties + protected float m_fTouchRad = 0.3f; // Touch radius + protected int m_iBattleCamp = Player_camp_in_battle.GP_BATTLE_CAMP_NONE; // Battle this player belongs to + byte m_factionPVPMask; // pvp mask + protected ROLEBASICPROP m_BasicProps; + public int m_iMoveEnv = Move_environment.MOVEENV_GROUND; // Move environment + public bool m_bWalkRun; + public A3DAABB m_aabbServer; // 脫毛路镁脦帽脝梅卤拢鲁脰脪禄脰脗碌脛aabb拢卢 虏禄脢脺脣玫路脜脫掳脧矛 protected void Awake() { m_PlayerActions = _default_actions; @@ -30,7 +42,10 @@ public abstract class EC_Player : MonoBehaviour { BuildActionList(); } - public bool IsValidAction(int iIndex) { return (iIndex >= 0 && iIndex < (int)PLAYER_ACTION_TYPE.ACT_MAX) ? true : false; } + + public bool IsDead(){ return (m_dwStates & PlayerNPCState.GP_STATE_CORPSE) != 0; } + + public bool IsValidAction(int iIndex) { return (iIndex >= 0 && iIndex < (int)PLAYER_ACTION_TYPE.ACT_MAX) ? true : false; } private static void BuildActionList() { if (_default_actions == null) @@ -270,6 +285,102 @@ public abstract class EC_Player : MonoBehaviour ACT_CASTSKILL // Ch峄 l脿 placeholder cho skill actions } + public float GetTouchRadius(){ return m_fTouchRad; } + // Is player in battle + public bool IsInBattle() { return m_iBattleCamp != Player_camp_in_battle.GP_BATTLE_CAMP_NONE; } + + // Check whether specified npc in a same battle camp + public bool InSameBattleCamp(CECNPC pNPC) + { + if (!pNPC || m_iBattleCamp == Player_camp_in_battle.GP_BATTLE_CAMP_NONE || + (m_iBattleCamp == Player_camp_in_battle.GP_BATTLE_CAMP_INVADER && !pNPC.IsInBattleInvaderCamp()) || + (m_iBattleCamp == Player_camp_in_battle.GP_BATTLE_CAMP_DEFENDER && !pNPC.IsInBattleDefenderCamp())) + return false; + + return true; + } + public bool IsInFactionPVP() => (m_factionPVPMask & 0x01) != 0; + public bool CanAttackFactionPVPMineCar() => (m_factionPVPMask & 0x02) != 0; + public bool CanAttackFactionPVPMineBase() => (m_factionPVPMask & 0x04) != 0; + + // Get basic properties + public ROLEBASICPROP GetBasicProps() { return m_BasicProps; } + + public int GetMoveStandAction(bool bMove, bool bFight = false) + { + int iMoveEnv = m_iMoveEnv; + //if (m_AttachMode != enumAttachNone) + //{ + // bFight = false; + // if (m_bHangerOn) + // iMoveEnv = MOVEENV_GROUND; + //} + + int iAction = (int)PLAYER_ACTION_TYPE.ACT_STAND; + + if (bMove) + { + // Play appropriate actions + if (iMoveEnv == (int)MoveEnvironment.MOVEENV_GROUND) + { + if (m_bWalkRun) + iAction = (int)PLAYER_ACTION_TYPE.ACT_RUN; + else + iAction = (int)PLAYER_ACTION_TYPE.ACT_WALK; + } + //else if (iMoveEnv == MOVEENV_AIR) + //{ + // //if (/*UsingWing()*/ m_wingType == WINGTYPE_WING) + // // iAction = ACT_FLY; + // //else + // // iAction = ACT_FLY_SWORD; + //} + //else if (iMoveEnv == MOVEENV_WATER) + //{ + // //if (CanCombineWithMoveForSkill()) + // //{ + // // iAction = ACT_SWIM_FOR_MOVESKILL; + // //} + // //else + // //{ + // // iAction = ACT_SWIM; + // //} + //} + } + else + { + // Play appropriate actions + if (iMoveEnv == (int)MoveEnvironment.MOVEENV_GROUND) + { + if (bFight) + iAction = (int)PLAYER_ACTION_TYPE.ACT_FIGHTSTAND; + else + iAction = (int)PLAYER_ACTION_TYPE.ACT_STAND; + } + //else if (iMoveEnv == MOVEENV_AIR) + //{ + // if (/*UsingWing()*/ m_wingType == WINGTYPE_WING) + // iAction = ACT_HANGINAIR; + // else + // iAction = ACT_HANGINAIR_SWORD; + //} + //else if (iMoveEnv == MOVEENV_WATER) + // iAction = ACT_HANGINWATER; + } + + return iAction; + } + + public float GetGroundSpeed() + { + // return m_bWalkRun ? g_pGame->GetConfigs()->GetHostRunSpeed() : m_ExtProps.mv.walk_speed; + return m_bWalkRun ? m_ExtProps.mv.run_speed : m_ExtProps.mv.walk_speed; + } + + // Get move environment + public int GetMoveEnv(){ return m_iMoveEnv; } + // Get character ID + public int GetCharacterID(){ return m_PlayerInfo.cid; } } public struct PlayActionEvent { @@ -291,4 +402,22 @@ public struct INFO this.crc_c = crc_c; this.crc_e = crc_; } -}; \ No newline at end of file +} + +public static class Duel_state // Duel state +{ + public const int DUEL_ST_NONE = 0, + DUEL_ST_PREPARE = 1, + DUEL_ST_INDUEL = 2, + DUEL_ST_STOPPING = 3; +} + +//// Move mode +//public static class Move_Mode +//{ +// public const int MOVE_STAND = 0, +// MOVE_MOVE = 1, // Normal move, walk, run, swim or fly +// MOVE_JUMP = 2, +// MOVE_FREEFALL = 3, +// MOVE_SLIDE = 4; +//} \ No newline at end of file diff --git a/Assets/Scripts/PlayerStateMachine.cs b/Assets/Scripts/PlayerStateMachine.cs index 787af10b2d..da9131e4e7 100644 --- a/Assets/Scripts/PlayerStateMachine.cs +++ b/Assets/Scripts/PlayerStateMachine.cs @@ -5,6 +5,8 @@ public class PlayerStateMachine PlayerState _state; CECHostPlayer _characterCtrl; + public PlayerState State { get => _state; } + public void InitState(PlayerState state) { if (_state != null)