npc Process
This commit is contained in:
Binary file not shown.
@@ -4,9 +4,11 @@ public class CECObject : MonoBehaviour
|
||||
{
|
||||
private uint m_dwBornStamp;
|
||||
private bool m_bBornInSight;
|
||||
private bool m_bSelectable;
|
||||
|
||||
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,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using UnityEngine;
|
||||
|
||||
public struct ROLEBASICPROP
|
||||
{
|
||||
public int iLevel; // Level
|
||||
public int iLevel2; // 2th. level
|
||||
public int iCurHP; // Current HP
|
||||
public int iCurMP; // Current MP
|
||||
public int iExp; // Experience
|
||||
public int iSP; // Skill point
|
||||
public int iStatusPt; // Status point
|
||||
public int iCurAP; // Current AP
|
||||
public int iAtkDegree; // Attack degree
|
||||
public int iDefDegree; // Defence degree
|
||||
public int iCritRate; // Critical rate
|
||||
public int iCritDamageBonus;// Critical damage bonus
|
||||
public int iInvisibleDegree;// Invisible degree
|
||||
public int iAntiInvisibleDegree; // Anti-invisible degree
|
||||
public int iPenetration; // ´©Í¸Á¦
|
||||
public int iResilience; // µÖ¿¹Á¦
|
||||
public int iVigour; // ÆøÆÇ
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f315b4c1df822c84f90cddb595d11482
|
||||
@@ -53,20 +53,20 @@ public class CECNPCMan : IMsgHandler
|
||||
|
||||
int iSize = info_npc.HEADER_SIZE;
|
||||
|
||||
if ((info.state & info_npc.GP_STATE_EXTEND_PROPERTY) != 0)
|
||||
if ((info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0)
|
||||
iSize += sizeof(uint) * NumberDWORDsPlayerNPC.OBJECT_EXT_STATE_COUNT;
|
||||
|
||||
if ((info.state & info_npc.GP_STATE_NPC_PET) != 0)
|
||||
if ((info.state & PlayerNPCState.GP_STATE_NPC_PET) != 0)
|
||||
iSize += sizeof(int);
|
||||
|
||||
if ((info.state & info_npc.GP_STATE_NPC_NAME) != 0)
|
||||
if ((info.state & PlayerNPCState.GP_STATE_NPC_NAME) != 0)
|
||||
{
|
||||
if (buffer.Length < offset + iSize + 1) return false;
|
||||
byte len = buffer[offset + iSize];
|
||||
iSize += 1 + len;
|
||||
}
|
||||
|
||||
if ((info.state & info_npc.GP_STATE_MULTIOBJ_EFFECT) != 0)
|
||||
if ((info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0)
|
||||
{
|
||||
if (buffer.Length < offset + iSize + sizeof(int)) return false;
|
||||
int countEff = BinaryPrimitives.ReadInt32LittleEndian(
|
||||
@@ -75,13 +75,13 @@ public class CECNPCMan : IMsgHandler
|
||||
iSize += countEff * (sizeof(int) + 1);
|
||||
}
|
||||
|
||||
if ((info.state & info_npc.GP_STATE_NPC_MAFIA) != 0)
|
||||
if ((info.state & PlayerNPCState.GP_STATE_NPC_MAFIA) != 0)
|
||||
iSize += sizeof(int);
|
||||
|
||||
Console.WriteLine(
|
||||
$"HoangDev: NPC_INFO_LIST, nid: {info.nid}, tid: {info.tid}, vis_tid: {info.vis_tid}, pos: {info.pos.x} {info.pos.y} {info.pos.z}");
|
||||
|
||||
NPCEnter(info, false);
|
||||
NPCEnter(info, false,buffer,offset);
|
||||
|
||||
offset += iSize;
|
||||
}
|
||||
@@ -90,7 +90,7 @@ public class CECNPCMan : IMsgHandler
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public bool NPCEnter(in info_npc Info, bool bBornInSight)
|
||||
public bool NPCEnter(in info_npc Info, bool bBornInSight, ReadOnlySpan<byte> packet, int infoOffset)
|
||||
{
|
||||
var npc = GetNPC(Info.nid);
|
||||
if (npc != null)
|
||||
@@ -105,7 +105,7 @@ public class CECNPCMan : IMsgHandler
|
||||
}
|
||||
|
||||
// Tạo NPC mới
|
||||
npc = CreateNPC(Info, bBornInSight);
|
||||
npc = CreateNPC(Info, bBornInSight, packet, infoOffset);
|
||||
if (npc == null)
|
||||
{
|
||||
BrewMonster.Logger.LogError($"Failed to create NPC ({Info.tid})");
|
||||
@@ -125,7 +125,7 @@ public class CECNPCMan : IMsgHandler
|
||||
|
||||
return npc;
|
||||
}
|
||||
public CECNPC CreateNPC(info_npc Info, bool bBornInSight)
|
||||
public CECNPC CreateNPC(info_npc Info, bool bBornInSight, ReadOnlySpan<byte> packet, int infoOffset)
|
||||
{
|
||||
CECNPC pNPC = null;
|
||||
|
||||
@@ -169,7 +169,7 @@ public class CECNPCMan : IMsgHandler
|
||||
|
||||
|
||||
// Init với tid + Info như C++
|
||||
if (pNPC == null || !pNPC.Init(tid, Info))
|
||||
if (pNPC == null || !pNPC.Init(tid, Info, packet, infoOffset))
|
||||
{
|
||||
// đảm bảo giải phóng nếu bạn có tài nguyên kèm theo
|
||||
//pNPC?.Release();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using BrewMonster;
|
||||
using CSNetwork.GPDataType;
|
||||
using ModelRenderer.Scripts.GameData;
|
||||
using System;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -16,13 +17,17 @@ public class CECMonster : CECNPC
|
||||
m_iCID = (int)ClassID.OCID_MONSTER;
|
||||
m_pDBEssence = default;
|
||||
|
||||
|
||||
m_fTouchRad = m_pDBEssence.size;
|
||||
m_BasicProps.iLevel = m_pDBEssence.level;
|
||||
QueueLoadNPCModel();
|
||||
}
|
||||
public override bool Init(int tid, info_npc Info)
|
||||
public override bool Init(int tid, in info_npc info, ReadOnlySpan<byte> packet, int infoOffset)
|
||||
{
|
||||
base.Init(tid, Info);
|
||||
base.Init(tid, info, packet,infoOffset);
|
||||
|
||||
var pDB = ElementDataManProvider.GetElementDataMan();
|
||||
DATA_TYPE DataType = default ;
|
||||
m_pDBEssence = (MONSTER_ESSENCE)pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE,ref DataType);
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
@@ -3,78 +3,199 @@ using System.Text;
|
||||
using System;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEngine;
|
||||
using BrewMonster;
|
||||
using CSNetwork;
|
||||
using ModelRenderer.Scripts.Common;
|
||||
|
||||
public class CECNPC : CECObject
|
||||
{
|
||||
INFO m_NPCInfo;
|
||||
private uint m_dwStates;
|
||||
private uint m_dwStates2;
|
||||
private A3DVECTOR3 m_vServerPos;
|
||||
private int m_iRandomProp;
|
||||
private int m_iMoveEnv;
|
||||
int m_idMaster;
|
||||
string m_strName;
|
||||
int m_idOwnerFaction;
|
||||
protected INFO m_NPCInfo;
|
||||
protected private uint m_dwStates;
|
||||
protected private uint m_dwStates2;
|
||||
protected private A3DVECTOR3 m_vServerPos;
|
||||
protected private int m_iRandomProp;
|
||||
protected private int m_iMoveEnv;
|
||||
protected int m_idMaster;
|
||||
protected string m_strName;
|
||||
protected int m_idOwnerFaction;
|
||||
protected float m_fDistToHost;
|
||||
protected float m_fDistToHostH;
|
||||
protected OtherPlayer_Move_Info m_cdr;
|
||||
protected float m_fTouchRad;
|
||||
protected ROLEBASICPROP m_BasicProps;
|
||||
|
||||
public CECNPC(CECNPCMan pNPCMan)
|
||||
{
|
||||
|
||||
}
|
||||
public virtual bool Init(int tid, info_npc Info)
|
||||
public virtual bool Init(int tid, in info_npc info, ReadOnlySpan<byte> packet, int infoOffset)
|
||||
{
|
||||
m_NPCInfo.nid = Info.nid;
|
||||
m_NPCInfo.nid = info.nid;
|
||||
m_NPCInfo.tid = tid;
|
||||
m_NPCInfo.vis_tid = Info.vis_tid;
|
||||
m_dwStates = (uint)Info.state;
|
||||
m_dwStates2 = (uint)Info.state2;
|
||||
m_vServerPos = Info.pos;
|
||||
m_iRandomProp = (Info.state & 0x0f00) >> 8;
|
||||
m_NPCInfo.vis_tid = info.vis_tid;
|
||||
m_dwStates = (uint)info.state;
|
||||
m_dwStates2 = (uint)info.state2;
|
||||
m_vServerPos = info.pos;
|
||||
m_iRandomProp = (info.state & 0x0f00) >> 8;
|
||||
|
||||
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 ? EnviromentMoveType.MOVEENV_AIR
|
||||
: (info.state & PlayerNPCState.GP_STATE_NPC_SWIM) != 0 ? EnviromentMoveType.MOVEENV_WATER
|
||||
: EnviromentMoveType.MOVEENV_GROUND);
|
||||
|
||||
// đọc phần đuôi bằng reader, KHÔNG cần đổi Info_npc
|
||||
var r = new ByteReader(new ReadOnlySpan<byte>() );
|
||||
var oj_ext_state_count = (int)OBJECT_EXT_STATE.OBJECT_EXT_STATE_COUNT;
|
||||
uint[] ext = new uint[oj_ext_state_count];
|
||||
if ((Info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0)
|
||||
// 2) Cắt “đuôi” ngay sau phần cố định info_npc
|
||||
int fixedSize = System.Runtime.InteropServices.Marshal.SizeOf<info_npc>();
|
||||
var tail = packet.Slice(infoOffset + fixedSize);
|
||||
|
||||
var r = new ByteReader(tail);
|
||||
|
||||
// 3) Đọc theo cờ state, giống C++ (pData tăng dần)
|
||||
// EXTEND_PROPERTY
|
||||
var ojexitStateCount = (uint)OBJECT_EXT_STATE.OBJECT_EXT_STATE_COUNT;
|
||||
|
||||
var ext = new uint[ojexitStateCount];
|
||||
if ((info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0)
|
||||
r.ReadInto(ext);
|
||||
//SetNewExtendStates(0, ext, oj_ext_state_count);
|
||||
//SetNewExtendStates(0, ext, ojexitStateCount );
|
||||
|
||||
// PET
|
||||
m_idMaster = 0;
|
||||
if ((Info.state & PlayerNPCState.GP_STATE_NPC_PET) != 0)
|
||||
if ((info.state & PlayerNPCState.GP_STATE_NPC_PET) != 0)
|
||||
m_idMaster = r.ReadInt32();
|
||||
|
||||
if ((Info.state & PlayerNPCState.GP_STATE_NPC_NAME) != 0)
|
||||
// NAME
|
||||
if ((info.state & PlayerNPCState.GP_STATE_NPC_NAME) != 0)
|
||||
{
|
||||
byte len = r.ReadByte();
|
||||
if (len > 0)
|
||||
m_strName = Encoding.Unicode.GetString(r.ReadBytes(len));
|
||||
{
|
||||
// ACHAR thường là UTF-16LE → len là số byte
|
||||
var nameBytes = r.ReadBytes(len);
|
||||
m_strName = System.Text.Encoding.Unicode.GetString(nameBytes);
|
||||
}
|
||||
}
|
||||
|
||||
/*SetSelectable((Info.state & PlayerNPCState.GP_STATE_FORBIDBESELECTED) == 0);
|
||||
SetSelectable((info.state & PlayerNPCState.GP_STATE_FORBIDBESELECTED) == 0);
|
||||
|
||||
if ((Info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0)
|
||||
// MULTIOBJ_EFFECT
|
||||
if ((info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0)
|
||||
{
|
||||
int n = r.ReadInt32();
|
||||
for (int i = 0; i < n; i++) { int idT = r.ReadInt32(); char t = (char)r.ReadByte(); AddMultiObjectEffect(idT, t); }
|
||||
}*/
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
int idTarget = r.ReadInt32();
|
||||
char cType = (char)r.ReadByte();
|
||||
//AddMultiObjectEffect(idTarget, cType);
|
||||
}
|
||||
}
|
||||
|
||||
// MAFIA
|
||||
m_idOwnerFaction = 0;
|
||||
if ((Info.state & PlayerNPCState.GP_STATE_NPC_MAFIA) != 0)
|
||||
if ((info.state & PlayerNPCState.GP_STATE_NPC_MAFIA) != 0)
|
||||
m_idOwnerFaction = r.ReadInt32();
|
||||
|
||||
// … phần seed collider, khoảng cách tới host, v.v. y hệt như bản trước
|
||||
m_cdr.fStepHeight = 0.4f;
|
||||
m_cdr.vVelocity.Clear();
|
||||
|
||||
var pHost = GameController.Instance.GetHostPlayer();
|
||||
if (pHost != null)
|
||||
{
|
||||
m_fDistToHost = Vector3.Distance(EC_Utility.ToVector3(m_vServerPos), pHost.transform.position);
|
||||
m_fDistToHostH = Vector2.Distance(
|
||||
new Vector2(m_vServerPos.x, m_vServerPos.z),
|
||||
new Vector2(pHost.transform.position.x, pHost.transform.position.z));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
struct INFO
|
||||
public void QueueLoadNPCModel()
|
||||
{
|
||||
/* if (ShouldUseMasterModel())
|
||||
{
|
||||
if (GetMaster())
|
||||
{
|
||||
return; // ÄÜ»ñÈ¡½ÇɫģÐÍʱ£¬µ½Ï¸ö Tick ¼ÓÔØÄ£ÐÍ
|
||||
} // ÎÞ·¨»ñÈ¡½Çɫʱ¡¢ÔÝʱʹÓà NPC Ä£ÐÍ
|
||||
}*/
|
||||
int tid = 0;
|
||||
string szModelFile = "";
|
||||
if (!GetVisibleModel( out tid, out szModelFile))
|
||||
{
|
||||
return;
|
||||
}
|
||||
//QueueECModelForLoad(MTL_ECM_NPC, GetNPCInfo().nid, GetBornStamp(), GetServerPos(), szModelFile, tid);
|
||||
}
|
||||
public bool GetVisibleModel(out int tid, out string szModelFile)
|
||||
{
|
||||
tid = 0;
|
||||
szModelFile = string.Empty;
|
||||
|
||||
// nếu vis_tid có model file
|
||||
if (GetModelFile(GetNPCInfo().vis_tid, out szModelFile))
|
||||
{
|
||||
tid = GetNPCInfo().vis_tid;
|
||||
}
|
||||
// nếu không có thì thử lấy từ tid thường
|
||||
else if (GetModelFile(GetNPCInfo().tid, out szModelFile))
|
||||
{
|
||||
tid = GetNPCInfo().tid;
|
||||
}
|
||||
|
||||
return tid > 0;
|
||||
}
|
||||
public bool GetModelFile(int tid, out string szModelFile)
|
||||
{
|
||||
szModelFile = string.Empty;
|
||||
|
||||
// Lấy database
|
||||
var pDB = ElementDataManProvider.GetElementDataMan(); // g_pGame->GetElementDataMan()
|
||||
DATA_TYPE dataType = default;
|
||||
|
||||
// Giả định get_data_ptr trả về object (Essence) và out DataType
|
||||
var pDBEssence = pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref dataType);
|
||||
if (pDBEssence == null)
|
||||
return false;
|
||||
|
||||
bool ret = true;
|
||||
Debug.Log($"HoangDev : DataType : {dataType}");
|
||||
|
||||
switch (dataType)
|
||||
{
|
||||
case DATA_TYPE.DT_MONSTER_ESSENCE:
|
||||
{
|
||||
var ess = (MONSTER_ESSENCE)pDBEssence;
|
||||
szModelFile = ByteToStringUtils.ByteArrayToCP936String( ess.file_model);
|
||||
Debug.Log($"HoangDev : MONSTER_ESSENCE path : {szModelFile}");
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE.DT_PET_ESSENCE:
|
||||
{
|
||||
var ess = (PET_ESSENCE)pDBEssence;
|
||||
szModelFile = ByteToStringUtils.ByteArrayToCP936String(ess.file_model);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE.DT_NPC_ESSENCE:
|
||||
{
|
||||
var ess = (NPC_ESSENCE)pDBEssence;
|
||||
szModelFile = ByteToStringUtils.ByteArrayToCP936String(ess.file_model);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
Debug.Log($"HoangDev : path 99 : {szModelFile}");
|
||||
return ret;
|
||||
}
|
||||
|
||||
public INFO GetNPCInfo() { return m_NPCInfo; }
|
||||
|
||||
public struct INFO
|
||||
{
|
||||
public int nid; // NPC id
|
||||
public int tid; // Template id
|
||||
public int vis_tid;// template id for shape
|
||||
};
|
||||
|
||||
}
|
||||
public ref struct ByteReader
|
||||
{
|
||||
|
||||
@@ -34,6 +34,10 @@ public static class EC_Utility
|
||||
{
|
||||
return new System.Numerics.Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
public static A3DVECTOR3 ToA3DVECTOR3(this UnityEngine.Vector3 v)
|
||||
{
|
||||
return new A3DVECTOR3(v.x, v.y, v.z);
|
||||
}
|
||||
public static Vector3 ToVector3(A3DVECTOR3 a3DVECTOR3)
|
||||
{
|
||||
return new Vector3(a3DVECTOR3.x, a3DVECTOR3.y, a3DVECTOR3.z);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using CSNetwork.GPDataType;
|
||||
using System;
|
||||
using TMPro;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
@@ -236,3 +237,15 @@ public static class EC_CDR
|
||||
if (vTPNormal != Vector3.zero) CDRInfo.vTPNormal = vTPNormal;
|
||||
}
|
||||
}
|
||||
public struct OtherPlayer_Move_Info
|
||||
{
|
||||
// Bounding sphere of avator
|
||||
public A3DVECTOR3 vCenter;
|
||||
public A3DVECTOR3 vExts;
|
||||
public float fStepHeight;
|
||||
public A3DVECTOR3 vVelocity;
|
||||
public float t;
|
||||
public bool bTraceGround; // Whether trace the ground
|
||||
public bool bTestTrnOnly; // Trace terrain only
|
||||
public A3DVECTOR3 vecGroundNormal; // if bTraceGround is true, this will contain the ground normal when returned
|
||||
};
|
||||
Reference in New Issue
Block a user