diff --git a/Assets/PerfectWorld/Scripts/Managers/A3DFuncs.cs b/Assets/PerfectWorld/Scripts/Managers/A3DFuncs.cs new file mode 100644 index 0000000000..d06611f62a --- /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 + 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..d7b8b18944 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/A3DMatrix.cs @@ -0,0 +1,684 @@ +using CSNetwork.GPDataType; +using System; +using UnityEngine; +using static A3DMATRIX3; + +/////////////////////////////////////////////////////////////////////////// +// +// class A3DMATRIX3 +// +/////////////////////////////////////////////////////////////////////////// + +public class A3DMATRIX3 +{ + // Construct flag + public enum CONSTRUCT + { + IDENTITY = 0, // Construct a identity matrix + CLEARED, // Construct a cleared matrix + } + + public float _11, _12, _13; + public float _21, _22, _23; + public float _31, _32, _33; + + public float[,] m + { + get + { + return new float[3, 3] { + { _11, _12, _13 }, + { _21, _22, _23 }, + { _31, _32, _33 } + }; + } + set + { + if (value.GetLength(0) != 3 || value.GetLength(1) != 3) + throw new ArgumentException("Matrix must be 3x3"); + _11 = value[0, 0]; _12 = value[0, 1]; _13 = value[0, 2]; + _21 = value[1, 0]; _22 = value[1, 1]; _23 = value[1, 2]; + _31 = value[2, 0]; _32 = value[2, 1]; _33 = value[2, 2]; + } + } + + public A3DMATRIX3() { } + + public A3DMATRIX3(CONSTRUCT c) + { + if (c == CONSTRUCT.IDENTITY) + { + _12 = _13 = 0.0f; + _21 = _23 = 0.0f; + _31 = _32 = 0.0f; + _11 = _22 = _33 = 1.0f; + } + else if (c == CONSTRUCT.CLEARED) + { + _11 = _12 = _13 = 0.0f; + _21 = _22 = _23 = 0.0f; + _31 = _32 = _33 = 0.0f; + } + } + + public A3DMATRIX3(float[,] arr) + { + _11 = arr[0, 0]; _12 = arr[0, 1]; _13 = arr[0, 2]; + _21 = arr[1, 0]; _22 = arr[1, 1]; _23 = arr[1, 2]; + _31 = arr[2, 0]; _32 = arr[2, 1]; _33 = arr[2, 2]; + } + + public A3DMATRIX3(A3DMATRIX3 rkMatrix) + { + _11 = rkMatrix._11; _12 = rkMatrix._12; _13 = rkMatrix._13; + _21 = rkMatrix._21; _22 = rkMatrix._22; _23 = rkMatrix._23; + _31 = rkMatrix._31; _32 = rkMatrix._32; _33 = rkMatrix._33; + } + + public A3DMATRIX3(float fEntry00, float fEntry01, float fEntry02, + float fEntry10, float fEntry11, float fEntry12, + float fEntry20, float fEntry21, float fEntry22) + + { + m[0, 0] = fEntry00; + m[0, 1] = fEntry01; + m[0, 2] = fEntry02; + m[1, 0] = fEntry10; + m[1, 1] = fEntry11; + m[1, 2] = fEntry12; + m[2, 0] = fEntry20; + m[2, 1] = fEntry21; + m[2, 2] = fEntry22; + } + // Operations + + public A3DVECTOR3 GetRow(int i) { return new A3DVECTOR3(m[i, 0], m[i, 1], m[i, 2]); } + public A3DVECTOR3 GetCol(int i) { return new A3DVECTOR3(m[0, i], m[1, i], m[2, i]); } + + // * operator + public static A3DVECTOR3 operator *(A3DVECTOR3 v, A3DMATRIX3 mat) + { + return new A3DVECTOR3(v.x * mat._11 + v.y * mat._21 + v.z * mat._31, + v.x * mat._12 + v.y * mat._22 + v.z * mat._32, + v.x * mat._13 + v.y * mat._23 + v.z * mat._33); + } + public static A3DVECTOR3 operator *(A3DMATRIX3 mat, A3DVECTOR3 v) + { + return new A3DVECTOR3(v.x * mat._11 + v.y * mat._21 + v.z * mat._31, + v.x * mat._12 + v.y * mat._22 + v.z * mat._32, + v.x * mat._13 + v.y * mat._23 + v.z * mat._33); + } + public static A3DMATRIX3 operator *(A3DMATRIX3 mat1, A3DMATRIX3 mat2) + { + A3DMATRIX3 matRet = new A3DMATRIX3(); + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + for (int k = 0; k < 3; k++) + matRet.m[i, j] += mat1.m[i, k] * mat2.m[k, 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[0, 1]; m[0, 1] = m[1, 0]; m[1, 0] = t; + t = m[0, 2]; m[0, 2] = m[2, 0]; m[2, 0] = t; + t = m[1, 2]; m[1, 2] = m[2, 1]; m[2, 1] = t; + } + + // Clear all elements to zero + void Clear() + { + _11 = _12 = _13 = 0.0f; + _21 = _22 = _23 = 0.0f; + _31 = _32 = _33 = 0.0f; + } + // Set matrix to identity matrix + void Identity() + { + _12 = _13 = 0.0f; + _21 = _23 = 0.0f; + _31 = _32 = 0.0f; + _11 = _22 = _33 = 1.0f; + } + + // Build matrix to be translation and rotation matrix + void Translate(float x, float y) + { + Identity(); + _31 = x; + _32 = y; + } + void Rotate(float fRad) + { + Identity(); + m[1, 1] = m[0, 0] = (float)Math.Cos(fRad); + m[0, 1] = (float)Math.Cos(fRad); + m[1, 0] = -m[0, 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 class A3DMATRIX4 +{ + // Construct flag + public enum CONSTRUCT + { + IDENTITY = 0, // Construct a identity matrix + } + + public float _11, _12, _13, _14; + public float _21, _22, _23, _24; + public float _31, _32, _33, _34; + public float _41, _42, _43, _44; + + // Constructions and Destructions + + public A3DMATRIX4() {} + + public A3DMATRIX4(float[] v) + { + for (int i=0; i < 4; i++) + { + for (int j=0; j < 4; j++) + m[i,j] = v[i * 4 + j]; + } + } + + public A3DMATRIX4(A3DMATRIX4 mat) + { + for (int i=0; i < 4; i++) + { + for (int j=0; j < 4; j++) + m[i,j] = mat.m[i,j]; + } + } + + A3DMATRIX4(CONSTRUCT c) + { + _12 = _13 = _14 = 0.0f; + _21 = _23 = _24 = 0.0f; + _31 = _32 = _34 = 0.0f; + _41 = _42 = _43 = 0.0f; + _11 = _22 = _33 = _44 = 1.0f; + } + + 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[0,0] = fEntry00; + m[0,1] = fEntry01; + m[0,2] = fEntry02; + m[0,3] = fEntry03; + + m[1,0] = fEntry10; + m[1,1] = fEntry11; + m[1,2] = fEntry12; + m[1,3] = fEntry13; + + m[2,0] = fEntry20; + m[2,1] = fEntry21; + m[2,2] = fEntry22; + m[2,3] = fEntry23; + + m[3,0] = fEntry30; + m[3,1] = fEntry31; + m[3,2] = fEntry32; + m[3,3] = fEntry33; + } + public float[,] m + { + get + { + return new float[4, 4] { + { _11, _12, _13, _14 }, + { _21, _22, _23, _24 }, + { _31, _32, _33, _34 }, + {_41, _42, _43, _44 } + }; + } + set + { + if (value.GetLength(0) != 3 || value.GetLength(1) != 3) + throw new ArgumentException("Matrix must be 3x3"); + _11 = value[0, 0]; _12 = value[0, 1]; _13 = value[0, 2]; _14 = value[0, 3]; + _21 = value[1, 0]; _22 = value[1, 1]; _23 = value[1, 2]; _14 = value[1, 3]; + _31 = value[2, 0]; _32 = value[2, 1]; _33 = value[2, 2]; _14 = value[2, 3]; + _41 = value[3, 0]; _32 = value[3, 1]; _33 = value[3, 2]; _14 = value[3, 3]; + } + } + // Operaitons + + // Get row and column + public A3DVECTOR3 GetRow(int i) { return new A3DVECTOR3(m[i,0], m[i,1], m[i,2]); } + public A3DVECTOR3 GetCol(int i) { return new A3DVECTOR3(m[0,i], m[1,i], m[2,i]); } + // Set row and column + public void SetRow(int i, A3DVECTOR3 v) { m[i,0]=v.x; m[i,1]=v.y; m[i,2]=v.z; } + public void SetCol(int i, A3DVECTOR3 v) { m[0,i]=v.x; m[1,i]=v.y; m[2,i]=v.z; } + + // * operator + public static A3DVECTOR3 operator * (A3DVECTOR3 v, A3DMATRIX4 mat) + { + A3DVECTOR3 vRet; + D3DXVec3TransformCoord((D3DXVECTOR3)vRet, (D3DXVECTOR3)v, (D3DXMATRIX)mat); + return vRet; + } + public static A3DVECTOR3 operator * (A3DMATRIX4 mat, A3DVECTOR3 v); + public static A3DVECTOR4 operator * (A3DVECTOR4 v, A3DMATRIX4 mat); + public static A3DVECTOR4 operator * (A3DMATRIX4 mat, A3DVECTOR4 v); + public static A3DMATRIX4 operator * (A3DMATRIX4 mat1, A3DMATRIX4 mat2); + + // Scale matrix + public static A3DMATRIX4 operator * (const A3DMATRIX4& mat, float s); + public static A3DMATRIX4 operator * (float s, const A3DMATRIX4& mat) { return mat * s; } + public static A3DMATRIX4 operator / (const A3DMATRIX4& mat, float s) { return mat * (1.0f / s); } + + // *= operator + public static A3DMATRIX4 & operator *= (const A3DMATRIX4& mat) + { + *this = *this * mat; + return *this; + } + public static A3DMATRIX4 & operator *= (float s); + // /= operator + public static A3DMATRIX4 & operator /= (float s) { return *this *= (1.0f / s); } + + // == operator + public static bool operator == (A3DMATRIX4 mat1, A3DMATRIX4 mat2) + { + for (int i=0; i < 4; i++) + { + for (int j=0; j < 4; j++) + { + if (mat1.m[i][j] != mat2.m[i][j]) + return false; + } + } + return true; + } + +// != operator + public static bool operator != (A3DMATRIX4 mat1, A3DMATRIX4 mat2) + { + for (int i=0; i < 4; i++) + { + for (int j=0; j < 4; j++) + { + if (mat1.m[i][j] != mat2.m[i][j]) + return true; + } + } + return false; + } + + // + operator + public static A3DMATRIX4 operator + (A3DMATRIX4 mat1, A3DMATRIX4 mat2); + // - operator + public static A3DMATRIX4 operator - (A3DMATRIX4 mat1, A3DMATRIX4 mat2); + // += operator + public static A3DMATRIX4 & operator += (A3DMATRIX4 mat); + // -= operator + public staticA3DMATRIX4 & operator -= (A3DMATRIX4 mat); + + // Clear all elements to zero + void Clear(); + // Set matrix to identity matrix + void Identity(); + // Transpose matrix + void Transpose(); + // Get transpose matrix of this matrix + A3DMATRIX4 GetTranspose() const; + // Inverse matrix +// void Inverse() { *this = GetInverse(); } + // Get inverse matrix of this matrix +// A3DMATRIX4 GetInverse() const; + // Inverse matrix (used only by transform matrix) + void InverseTM() { *this = GetInverseTM(); } + // Get inverse matrix (used only by transform matrix) + A3DMATRIX4 GetInverseTM() const; + // Get determinant of this matrix + float Determinant() const; + + // Build matrix to be translation and rotation matrix + void Translate(float x, float y, float z); + void RotateX(float fRad); + void RotateY(float fRad); + void RotateZ(float fRad); + void RotateAxis(const A3DVECTOR3& v, float fRad); + void RotateAxis(const A3DVECTOR3& vPos, const A3DVECTOR3& vAxis, float fRad); + void Scale(float sx, float sy, float sz); + +protected: // Attributes + + // Calcualte determinant of a 3x3 matrix + float Det3x3(float a11, float a12, float a13, float a21, float a22, float a23, + float a31, float a32, float a33) const + { + return a11 * a22 * a33 + a21 * a32 * a13 + a31 * a12 * a23 - + a13 * a22 * a31 - a23 * a32 * a11 - a33 * a12 * a21; + } + +protected: // Operations + +};/////////////////////////////////////////////////////////////////////////// +// +// class A3DMATRIX4 +// +/////////////////////////////////////////////////////////////////////////// + +class A3DMATRIX4 +{ +public: // Types + + // Construct flag + enum CONSTRUCT + { + IDENTITY = 0, // Construct a identity matrix + }; + +public: // Constructions and Destructions + + A3DMATRIX4() {} + + A3DMATRIX4(float* v) + { + for (int i=0; i < 4; i++) + { + for (int j=0; j < 4; j++) + m[i][j] = v[i * 4 + j]; + } + } + + A3DMATRIX4(const A3DMATRIX4& mat) + { + for (int i=0; i < 4; i++) + { + for (int j=0; j < 4; j++) + m[i][j] = mat.m[i][j]; + } + } + + A3DMATRIX4(CONSTRUCT c) + { + _12 = _13 = _14 = 0.0f; + _21 = _23 = _24 = 0.0f; + _31 = _32 = _34 = 0.0f; + _41 = _42 = _43 = 0.0f; + _11 = _22 = _33 = _44 = 1.0f; + } + + 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[0][0] = fEntry00; + m[0][1] = fEntry01; + m[0][2] = fEntry02; + m[0][3] = fEntry03; + + m[1][0] = fEntry10; + m[1][1] = fEntry11; + m[1][2] = fEntry12; + m[1][3] = fEntry13; + + m[2][0] = fEntry20; + m[2][1] = fEntry21; + m[2][2] = fEntry22; + m[2][3] = fEntry23; + + m[3][0] = fEntry30; + m[3][1] = fEntry31; + m[3][2] = fEntry32; + m[3][3] = fEntry33; + } + +public: // Attributes + + union + { + struct + { + float _11, _12, _13, _14; + float _21, _22, _23, _24; + float _31, _32, _33, _34; + float _41, _42, _43, _44; + }; + + float m[4][4]; + }; + +public: // Operaitons + + // Get row and column + A3DVECTOR3 GetRow(int i) const { return A3DVECTOR3(m[i][0], m[i][1], m[i][2]); } + A3DVECTOR3 GetCol(int i) const { return A3DVECTOR3(m[0][i], m[1][i], m[2][i]); } + // Set row and column + void SetRow(int i, const A3DVECTOR3& v) { m[i][0]=v.x; m[i][1]=v.y; m[i][2]=v.z; } + void SetCol(int i, const A3DVECTOR3& v) { m[0][i]=v.x; m[1][i]=v.y; m[2][i]=v.z; } + + // * operator + friend A3DVECTOR3 operator * (const A3DVECTOR3& v, const A3DMATRIX4& mat); + friend A3DVECTOR3 operator * (const A3DMATRIX4& mat, const A3DVECTOR3& v); + friend A3DVECTOR4 operator * (const A3DVECTOR4& v, const A3DMATRIX4& mat); + friend A3DVECTOR4 operator * (const A3DMATRIX4& mat, const A3DVECTOR4& v); + friend A3DMATRIX4 operator * (const A3DMATRIX4& mat1, const A3DMATRIX4& mat2); + + // Scale matrix + friend A3DMATRIX4 operator * (const A3DMATRIX4& mat, float s); + friend A3DMATRIX4 operator * (float s, const A3DMATRIX4& mat) { return mat * s; } + friend A3DMATRIX4 operator / (const A3DMATRIX4& mat, float s) { return mat * (1.0f / s); } + + // *= operator + A3DMATRIX4& operator *= (const A3DMATRIX4& mat) + { + *this = *this * mat; + return *this; + } + A3DMATRIX4& operator *= (float s); + // /= operator + A3DMATRIX4& operator /= (float s) { return *this *= (1.0f / s); } + + // == operator + friend bool operator == (const A3DMATRIX4& mat1, const A3DMATRIX4& mat2) + { + for (int i=0; i < 4; i++) + { + for (int j=0; j < 4; j++) + { + if (mat1.m[i][j] != mat2.m[i][j]) + return false; + } + } + return true; + } + + // != operator + friend bool operator != (const A3DMATRIX4& mat1, const A3DMATRIX4& mat2) + { + for (int i=0; i < 4; i++) + { + for (int j=0; j < 4; j++) + { + if (mat1.m[i][j] != mat2.m[i][j]) + return true; + } + } + return false; + } + + // + operator + friend A3DMATRIX4 operator + (const A3DMATRIX4& mat1, const A3DMATRIX4& mat2); + // - operator + friend A3DMATRIX4 operator - (const A3DMATRIX4& mat1, const A3DMATRIX4& mat2); + // += operator + A3DMATRIX4& operator += (const A3DMATRIX4& mat); + // -= operator + A3DMATRIX4& operator -= (const A3DMATRIX4& mat); + + // Clear all elements to zero + void Clear(); + // Set matrix to identity matrix + void Identity(); + // Transpose matrix + void Transpose(); + // Get transpose matrix of this matrix + A3DMATRIX4 GetTranspose() const; + // Inverse matrix +// void Inverse() { *this = GetInverse(); } + // Get inverse matrix of this matrix +// A3DMATRIX4 GetInverse() const; + // Inverse matrix (used only by transform matrix) + void InverseTM() { *this = GetInverseTM(); } + // Get inverse matrix (used only by transform matrix) + A3DMATRIX4 GetInverseTM() const; + // Get determinant of this matrix + float Determinant() const; + + // Build matrix to be translation and rotation matrix + void Translate(float x, float y, float z); + void RotateX(float fRad); + void RotateY(float fRad); + void RotateZ(float fRad); + void RotateAxis(const A3DVECTOR3& v, float fRad); + void RotateAxis(const A3DVECTOR3& vPos, const A3DVECTOR3& vAxis, float fRad); + void Scale(float sx, float sy, float sz); + +protected: // Attributes + + // Calcualte determinant of a 3x3 matrix + float Det3x3(float a11, float a12, float a13, float a21, float a22, float a23, + float a31, float a32, float a33) const + { + return a11 * a22 * a33 + a21 * a32 * a13 + a31 * a12 * a23 - + a13 * a22 * a31 - a23 * a32 * a11 - a33 * a12 * a21; + } + +protected: // Operations + +}; + + 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/EC_HPWork.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs index 08246cd78d..df1793511a 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWork.cs @@ -203,6 +203,50 @@ public class CECHPWorkMan 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) { @@ -415,3 +459,30 @@ 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; + } +} diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs new file mode 100644 index 0000000000..f6da35bf78 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkMelee.cs @@ -0,0 +1,150 @@ +using CSNetwork.GPDataType; +using UnityEditor.Experimental.GraphView; +using UnityEngine; + +/////////////////////////////////////////////////////////////////////////// +// +// 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)) + { + 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 (ISPLAYERID(m_idTarget)) + { + CECElsePlayer* pPlayer = m_pHost.m_pPlayerMan.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 (ISNPCID(m_idTarget)) + { + CECNPC* pNPC = g_pGame.GetGameRun().GetWorld().GetNPCMan().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 && !m_pHost.IsRooting()) + { + CECHPWorkTrace* pWork = (CECHPWorkTrace*)m_pWorkMan.CreateWork(WORK_TRACEOBJECT); + pWork.SetTraceTarget(pWork.CreatTraceTarget(idTraceTarget, CECHPWorkTrace::TRACE_ATTACK)); + class CECHPWorkPostTickCommand1 : CECHPWorkPostTickRunWorkCommand + { + public CECHPWorkPostTickCommand1(CECHPWork pWork) : CECHPWorkPostTickRunWorkCommand(pWork, true) + { + } + public virtual bool Run(CECHPWorkMan pWorkMan) + { + if (!CECHPWorkPostTickRunWorkCommand::Run(pWorkMan)) + { + return false; + } + AP_ActionEvent(AP_EVENT_MELEEOUTOFRANGE); + return true; + } + }; + 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_HPWorkTrace.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs index 3581d786d9..6b40748995 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkTrace.cs @@ -1,5 +1,4 @@ using CSNetwork.GPDataType; -using UnityEditor.Rendering; /////////////////////////////////////////////////////////////////////////// // diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs new file mode 100644 index 0000000000..1f356d9546 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Managers/EC_Object.cs @@ -0,0 +1,211 @@ +using CSNetwork.GPDataType; +using CSNetwork.Protocols; +using UnityEngine; + +/////////////////////////////////////////////////////////////////////////// +// +// Class CECObject +// +/////////////////////////////////////////////////////////////////////////// + +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; + } + + // 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; + } + + private 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) + { + + } + + 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 inline const A3DVECTOR3& GetGroundNormal()const { return m_vecGroundNormal; } + public inline bool GetUseGroundNormal()const { return m_bUseGroundNormal; } + + public void SetUseGroundNormal(bool bFlag) + { + + } + public void SetGroundNormal(A3DVECTOR3 vecNormal) + { + + } + public void SetSelectable(bool bSelectable) { m_bSelectable = bSelectable; } + + 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/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index ac6c1ec344..83485d60c7 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -10,7 +10,6 @@ using System.IO; using System.Runtime.InteropServices; using System.Text; using TMPro; -using Unity.VisualScripting; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; @@ -32,6 +31,9 @@ public class CECHostPlayer : EC_Player PlayerIdleState _idleState; CECHostMove m_MoveCtrl; + CECHPWorkMan m_pWorkMan; // Host work manager + uint m_dwLIES; // Logic-influence extend states + float playerSpeed = 5.0f; float jumpHeight = 1.5f; float gravityValue = -9.81f; @@ -361,6 +363,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) @@ -397,7 +406,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; @@ -437,16 +446,16 @@ public class CECHostPlayer : EC_Player //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()) @@ -457,7 +466,7 @@ 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); } @@ -471,22 +480,22 @@ public class CECHostPlayer : EC_Player // We should have check target isn't dead return false; } - //if (!g_pGame->GetGameRun()->GetWorld()->GetObject(idTarget, 1)) + //if (!g_pGame.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) + //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)) + 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)) + 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 @@ -500,7 +509,7 @@ public class CECHostPlayer : EC_Player bStartNewWork = true; } - if (pWorkTrace) + if (pWorkTrace != null) { pWorkTrace.SetTraceTarget(pWorkTrace.CreatTraceTarget(idTarget, CECHPWorkTrace.Trace_reason.TRACE_ATTACK, bForceAttack), bUseAutoPF); pWorkTrace.SetMoveCloseFlag(bMoreClose); @@ -511,6 +520,172 @@ public class CECHostPlayer : EC_Player } 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 = g_pGame.GetGameRun().GetWorld().GetObject(idTarget, 1); + if (!pObject) + return -1; + + // If target is pet, it's attacked possibility depends on it's monster + if (ISNPCID(idTarget)) + { + CECNPC* pNPC = (CECNPC*)pObject; + int idMaster = pNPC.GetMasterID(); + if (idMaster) + { + // 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 = g_pGame.GetGameRun().GetWorld().GetObject(idTarget, 1); + if (!pObject) + return -1; + } + } + + int iRet = 0; + + if (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; + } + } + } + else if (ISPLAYERID(idTarget)) + { + // Check duel at first + if (m_pvp.iDuelState == DUEL_ST_INDUEL && m_pvp.idDuelOpp == idTarget) + return 1; + else if (m_pvp.iDuelState == 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); + CECElsePlayer* pPlayer = (CECElsePlayer*)pObject; + const ROLEBASICPROP&bp = pPlayer.GetBasicProps(); + const 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; + } + + public bool CannotAttack() { return (m_dwLIES & (uint)Logic_Influence_Extned_states.LIES_DISABLEFIGHT) != 0; } } public enum StateAnim @@ -520,3 +695,16 @@ 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, +} diff --git a/Assets/Scripts/Move/EC_Player.cs b/Assets/Scripts/Move/EC_Player.cs index abf4fef640..c02961f229 100644 --- a/Assets/Scripts/Move/EC_Player.cs +++ b/Assets/Scripts/Move/EC_Player.cs @@ -9,10 +9,11 @@ public abstract class EC_Player : MonoBehaviour 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; - protected int m_iMoveMode; // Player's move mode + internal int m_iMoveMode; // Player's move mode + internal int m_idSelTarget; // 脩隆脰脨脛驴卤锚碌脛ID protected void Awake() {