fix: update namespace.

feat: add new logic EC_World.
This commit is contained in:
Tungdv
2025-10-14 18:34:16 +07:00
parent 955ba80dff
commit 001a16cf32
56 changed files with 7574 additions and 7075 deletions
@@ -0,0 +1,6 @@
using UnityEngine;
public class A3DTerrain2
{
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 828eeca29c5904541bdb0f5162832508
+240 -236
View File
@@ -1,4 +1,5 @@
using BrewMonster;
using BrewMonster.Managers;
using CSNetwork;
using CSNetwork.GPDataType;
using DG.Tweening;
@@ -8,267 +9,270 @@ using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
public class CECNPCMan : CECObject, IMsgHandler
namespace BrewMonster.Scripts.Player
{
private Dictionary<int, CECNPC> m_NPCTab = new Dictionary<int, CECNPC>(512);
private Dictionary<int, int> m_UkNPCTab = new Dictionary<int, int>(32);
Vector3 m_vServerPos;
public int HandlerId => (int)MANAGER_INDEX.MAN_NPC;
public class CECNPCMan : CECObject, IMsgHandler
{
private Dictionary<int, CECNPC> m_NPCTab = new Dictionary<int, CECNPC>(512);
private Dictionary<int, int> m_UkNPCTab = new Dictionary<int, int>(32);
Vector3 m_vServerPos;
public int HandlerId => (int)MANAGER_INDEX.MAN_NPC;
public CECNPCMan()
{
m_vServerPos = Vector3.zero;
m_iCID = (int)Class_ID.OCID_MONSTER;
}
public bool ProcessMessage(ECMSG Msg)
{
if (Msg.iSubID == 0)
public CECNPCMan()
{
switch (Msg.dwMsg)
{
case long value when value == EC_MsgDef.MSG_NM_NPCINFO: OnMsgNPCInfo(Msg); break;
case long value when value == EC_MsgDef.MSG_NM_NPCMOVE: OnMsgNPCMove(Msg); break;
case long value when value == EC_MsgDef.MSG_NM_NPCSTOPMOVE: OnMsgNPCStopMove(Msg); break;
}
m_vServerPos = Vector3.zero;
m_iCID = (int)Class_ID.OCID_MONSTER;
}
return true;
}
private bool OnMsgNPCStopMove(ECMSG msg)
{
cmd_object_stop_move pCmd = EC_Utility.ByteArrayToStructure<cmd_object_stop_move>((byte[])msg.dwParam1);
CECNPC pNPC = SeekOutNPC(pCmd.id);
if (pNPC)
pNPC.StopMoveTo(pCmd);
return true;
}
private bool OnMsgNPCMove(ECMSG msg)
{
var buffer = (byte[])msg.dwParam1;
cmd_object_move pCmd = MemoryMarshal.Read<cmd_object_move>(buffer);
if (pCmd.use_time == 0)
public bool ProcessMessage(ECMSG Msg)
{
if (Msg.iSubID == 0)
{
switch (Msg.dwMsg)
{
case long value when value == EC_MsgDef.MSG_NM_NPCINFO: OnMsgNPCInfo(Msg); break;
case long value when value == EC_MsgDef.MSG_NM_NPCMOVE: OnMsgNPCMove(Msg); break;
case long value when value == EC_MsgDef.MSG_NM_NPCSTOPMOVE: OnMsgNPCStopMove(Msg); break;
}
}
return true;
CECNPC pNPC = SeekOutNPC(pCmd.id);
if (pNPC)
pNPC.MoveTo(pCmd);
return true;
}
public CECNPC SeekOutNPC(int nid)
{
if (!m_NPCTab.TryGetValue(nid, out var npc))
{
// Couldn't find this NPC, put it into unknown NPC table
m_UkNPCTab[nid] = nid;
return null;
}
return npc;
}
private bool OnMsgNPCInfo(ECMSG msg)
{
switch (Convert.ToInt32(msg.dwParam2))
private bool OnMsgNPCStopMove(ECMSG msg)
{
case CommandID.NPC_INFO_LIST:
{
cmd_object_stop_move pCmd = EC_Utility.ByteArrayToStructure<cmd_object_stop_move>((byte[])msg.dwParam1);
// msg.dwParam1 chính là buffer chứa placeholder data (không có header cmd_npc_info_list)
cmd_npc_info_list pCmd = MemoryMarshal.Read<cmd_npc_info_list>(
((byte[])msg.dwParam1).AsSpan());
CECNPC pNPC = SeekOutNPC(pCmd.id);
if (pNPC)
pNPC.StopMoveTo(pCmd);
int offset = Marshal.OffsetOf<cmd_npc_info_list>("placeholder").ToInt32();
byte[] buffer = (byte[])msg.dwParam1;
Span<byte> pDataBuf = buffer.AsSpan(offset);
for (int i = 0; i < pCmd.count; i++)
{
// giống const info_npc& Info = *(const info_npc*)pDataBuf;
info_npc info = MemoryMarshal.Read<info_npc>(pDataBuf);
int iSize = info_npc.HEADER_SIZE;
if ((info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0)
iSize += sizeof(uint) * NumberDWORDsPlayerNPC.OBJECT_EXT_STATE_COUNT;
if ((info.state & PlayerNPCState.GP_STATE_NPC_PET) != 0)
iSize += sizeof(int);
if ((info.state & PlayerNPCState.GP_STATE_NPC_NAME) != 0)
{
byte len = pDataBuf[iSize];
iSize += 1 + len;
}
if ((info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0)
{
int countEff = BinaryPrimitives.ReadInt32LittleEndian(
pDataBuf.Slice(iSize, sizeof(int)));
iSize += sizeof(int) + countEff * (sizeof(int) + 1);
}
if ((info.state & PlayerNPCState.GP_STATE_NPC_MAFIA) != 0)
iSize += sizeof(int);
NPCEnter(info, false, buffer, offset);
// dịch pDataBuf về sau (giống pDataBuf += iSize)
pDataBuf = pDataBuf.Slice(iSize);
offset += iSize;
}
break;
}
case CommandID.NPC_ENTER_SLICE:
{
var buffer = (byte[])msg.dwParam1;
info_npc info = MemoryMarshal.Read<info_npc>(buffer.AsSpan(0, info_npc.HEADER_SIZE));
NPCEnter(info, false, buffer, info_npc.HEADER_SIZE);
break;
}
case CommandID.NPC_ENTER_WORLD:
{
var buffer = (byte[])msg.dwParam1;
info_npc info = MemoryMarshal.Read<info_npc>(buffer.AsSpan(0, info_npc.HEADER_SIZE));
NPCEnter(info, true, buffer, info_npc.HEADER_SIZE);
break;
}
case CommandID.NPC_INFO_00:
{
var buffer = (byte[])msg.dwParam1;
cmd_npc_info_00 pCmd = GPDataTypeHelper.FromBytes<cmd_npc_info_00>(buffer);
//cmd_npc_info_00 pCmd = MemoryMarshal.Read<cmd_npc_info_00>(buffer.AsSpan(0, cmd_npc_info_00.));
CECNPC pNPC = SeekOutNPC(pCmd.idNPC);
if (pNPC)
{
ROLEBASICPROP bp = pNPC.GetBasicProps();
ROLEEXTPROP ep = pNPC.GetExtendProps();
bp.iCurHP = pCmd.iHP;
ep.bs.max_hp = pCmd.iMaxHP;
pNPC.SetSelectedTarget(pCmd.iTargetID);
}
break;
}
case CommandID.NPC_VISIBLE_TID_NOTIFY:
{
cmd_npc_visible_tid_notify pCmd = (cmd_npc_visible_tid_notify)msg.dwParam1;
CECNPC pNPC = SeekOutNPC(pCmd.nid);
if (pNPC)
pNPC.TransformShape(pCmd.vis_tid);
break;
}
}
return true;
}
public bool NPCEnter(in info_npc Info, bool bBornInSight, ReadOnlySpan<byte> packet, int infoOffset)
{
var npc = GetNPC(Info.nid);
if (npc != null)
{
m_NPCTab.Remove(Info.nid);
return true;
}
// Nếu id này có trong bảng unknown thì xóa nó
if (m_UkNPCTab.ContainsKey(Info.nid))
private bool OnMsgNPCMove(ECMSG msg)
{
m_UkNPCTab.Remove(Info.nid);
var buffer = (byte[])msg.dwParam1;
cmd_object_move pCmd = MemoryMarshal.Read<cmd_object_move>(buffer);
if (pCmd.use_time == 0)
return true;
CECNPC pNPC = SeekOutNPC(pCmd.id);
if (pNPC)
pNPC.MoveTo(pCmd);
return true;
}
// Tạo NPC mới
npc = CreateNPC(Info, bBornInSight, packet, infoOffset);
if(npc != null)
public CECNPC SeekOutNPC(int nid)
{
npc.SetUpCECNPC(this);
}
if (object.ReferenceEquals(npc, null))
{
BrewMonster.BMLogger.LogError($"Failed to create NPC ({Info.tid})");
return false;
}
// Thêm NPC vào bảng
m_NPCTab[Info.nid] = npc;
return true;
}
// Get NPC by id and optional bornStamp
public CECNPC GetNPC(int nid, uint bornStamp = 0)
{
if (!m_NPCTab.TryGetValue(nid, out var npc))
return null;
return npc;
}
public CECNPC CreateNPC(info_npc Info, bool bBornInSight, ReadOnlySpan<byte> packet, int infoOffset)
{
CECNPC pNPC = null;
int tid = Info.tid;
bool bPet = (Info.state & PlayerNPCState.GP_STATE_NPC_PET) != 0;
// Get data type from database
var edm = ElementDataManProvider.GetElementDataMan(); // tương đương g_pGame->GetElementDataMan()
DATA_TYPE dataType = edm.get_data_type((uint)tid, ID_SPACE.ID_SPACE_ESSENCE);
if (dataType != DATA_TYPE.DT_NPC_ESSENCE &&
dataType != DATA_TYPE.DT_MONSTER_ESSENCE &&
dataType != DATA_TYPE.DT_PET_ESSENCE)
{
// Try default npc
tid = 4249;
dataType = edm.get_data_type((uint)tid, ID_SPACE.ID_SPACE_ESSENCE);
}
if (bPet)
{
//pNPC = new CECPet(this);
}
else
{
switch (dataType)
if (!m_NPCTab.TryGetValue(nid, out var npc))
{
case DATA_TYPE.DT_NPC_ESSENCE: /*pNPC = new CECNPCServer(this);*/ break;
case DATA_TYPE.DT_MONSTER_ESSENCE:
pNPC = GameController.Instance.GetMonster();
break;
case DATA_TYPE.DT_PET_ESSENCE:/* pNPC = new CECPet(this);*/ break;
default:
UnityEngine.Debug.Assert(false, "Invalid DATA_TYPE in CreateNPC");
return null;
// Couldn't find this NPC, put it into unknown NPC table
m_UkNPCTab[nid] = nid;
return null;
}
return npc;
}
// Set born stamp & born-in-sight (giữ nguyên semantics)
uint bornStamp = CECWorld.Instance.GetBornStamp();
if (!object.ReferenceEquals(pNPC, null))
private bool OnMsgNPCInfo(ECMSG msg)
{
pNPC.SetBornStamp(bornStamp);
pNPC.SetBornInSight(bBornInSight);
switch (Convert.ToInt32(msg.dwParam2))
{
case CommandID.NPC_INFO_LIST:
{
// msg.dwParam1 chính là buffer chứa placeholder data (không có header cmd_npc_info_list)
cmd_npc_info_list pCmd = MemoryMarshal.Read<cmd_npc_info_list>(
((byte[])msg.dwParam1).AsSpan());
int offset = Marshal.OffsetOf<cmd_npc_info_list>("placeholder").ToInt32();
byte[] buffer = (byte[])msg.dwParam1;
Span<byte> pDataBuf = buffer.AsSpan(offset);
for (int i = 0; i < pCmd.count; i++)
{
// giống const info_npc& Info = *(const info_npc*)pDataBuf;
info_npc info = MemoryMarshal.Read<info_npc>(pDataBuf);
int iSize = info_npc.HEADER_SIZE;
if ((info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0)
iSize += sizeof(uint) * NumberDWORDsPlayerNPC.OBJECT_EXT_STATE_COUNT;
if ((info.state & PlayerNPCState.GP_STATE_NPC_PET) != 0)
iSize += sizeof(int);
if ((info.state & PlayerNPCState.GP_STATE_NPC_NAME) != 0)
{
byte len = pDataBuf[iSize];
iSize += 1 + len;
}
if ((info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0)
{
int countEff = BinaryPrimitives.ReadInt32LittleEndian(
pDataBuf.Slice(iSize, sizeof(int)));
iSize += sizeof(int) + countEff * (sizeof(int) + 1);
}
if ((info.state & PlayerNPCState.GP_STATE_NPC_MAFIA) != 0)
iSize += sizeof(int);
NPCEnter(info, false, buffer, offset);
// dịch pDataBuf về sau (giống pDataBuf += iSize)
pDataBuf = pDataBuf.Slice(iSize);
offset += iSize;
}
break;
}
case CommandID.NPC_ENTER_SLICE:
{
var buffer = (byte[])msg.dwParam1;
info_npc info = MemoryMarshal.Read<info_npc>(buffer.AsSpan(0, info_npc.HEADER_SIZE));
NPCEnter(info, false, buffer, info_npc.HEADER_SIZE);
break;
}
case CommandID.NPC_ENTER_WORLD:
{
var buffer = (byte[])msg.dwParam1;
info_npc info = MemoryMarshal.Read<info_npc>(buffer.AsSpan(0, info_npc.HEADER_SIZE));
NPCEnter(info, true, buffer, info_npc.HEADER_SIZE);
break;
}
case CommandID.NPC_INFO_00:
{
var buffer = (byte[])msg.dwParam1;
cmd_npc_info_00 pCmd = GPDataTypeHelper.FromBytes<cmd_npc_info_00>(buffer);
//cmd_npc_info_00 pCmd = MemoryMarshal.Read<cmd_npc_info_00>(buffer.AsSpan(0, cmd_npc_info_00.));
CECNPC pNPC = SeekOutNPC(pCmd.idNPC);
if (pNPC)
{
ROLEBASICPROP bp = pNPC.GetBasicProps();
ROLEEXTPROP ep = pNPC.GetExtendProps();
bp.iCurHP = pCmd.iHP;
ep.bs.max_hp = pCmd.iMaxHP;
pNPC.SetSelectedTarget(pCmd.iTargetID);
}
break;
}
case CommandID.NPC_VISIBLE_TID_NOTIFY:
{
cmd_npc_visible_tid_notify pCmd = (cmd_npc_visible_tid_notify)msg.dwParam1;
CECNPC pNPC = SeekOutNPC(pCmd.nid);
if (pNPC)
pNPC.TransformShape(pCmd.vis_tid);
break;
}
}
return true;
}
else
public bool NPCEnter(in info_npc Info, bool bBornInSight, ReadOnlySpan<byte> packet, int infoOffset)
{
return null;
}
var npc = GetNPC(Info.nid);
if (npc != null)
{
m_NPCTab.Remove(Info.nid);
}
// Init với tid + Info như C++
if (!pNPC.Init(tid, Info, packet, infoOffset))
// Nếu id này có trong bảng unknown thì xóa nó
if (m_UkNPCTab.ContainsKey(Info.nid))
{
m_UkNPCTab.Remove(Info.nid);
}
// Tạo NPC mới
npc = CreateNPC(Info, bBornInSight, packet, infoOffset);
if (npc != null)
{
npc.SetUpCECNPC(this);
}
if (object.ReferenceEquals(npc, null))
{
BrewMonster.BMLogger.LogError($"Failed to create NPC ({Info.tid})");
return false;
}
// Thêm NPC vào bảng
m_NPCTab[Info.nid] = npc;
return true;
}
// Get NPC by id and optional bornStamp
public CECNPC GetNPC(int nid, uint bornStamp = 0)
{
if (!m_NPCTab.TryGetValue(nid, out var npc))
return null;
// đảm bảo giải phóng nếu bạn có tài nguyên kèm theo
//pNPC?.Release();
pNPC = null;
// log lỗi tương tự glb_ErrorOutput
UnityEngine.Debug.LogError($"CECNPCMan::CreateNPC failed, tid={tid}");
return null;
return npc;
}
public CECNPC CreateNPC(info_npc Info, bool bBornInSight, ReadOnlySpan<byte> packet, int infoOffset)
{
CECNPC pNPC = null;
return pNPC;
int tid = Info.tid;
bool bPet = (Info.state & PlayerNPCState.GP_STATE_NPC_PET) != 0;
// Get data type from database
var edm = ElementDataManProvider.GetElementDataMan(); // tương đương g_pGame->GetElementDataMan()
DATA_TYPE dataType = edm.get_data_type((uint)tid, ID_SPACE.ID_SPACE_ESSENCE);
if (dataType != DATA_TYPE.DT_NPC_ESSENCE &&
dataType != DATA_TYPE.DT_MONSTER_ESSENCE &&
dataType != DATA_TYPE.DT_PET_ESSENCE)
{
// Try default npc
tid = 4249;
dataType = edm.get_data_type((uint)tid, ID_SPACE.ID_SPACE_ESSENCE);
}
if (bPet)
{
//pNPC = new CECPet(this);
}
else
{
switch (dataType)
{
case DATA_TYPE.DT_NPC_ESSENCE: /*pNPC = new CECNPCServer(this);*/ break;
case DATA_TYPE.DT_MONSTER_ESSENCE:
pNPC = GameController.Instance.GetMonster();
break;
case DATA_TYPE.DT_PET_ESSENCE:/* pNPC = new CECPet(this);*/ break;
default:
UnityEngine.Debug.Assert(false, "Invalid DATA_TYPE in CreateNPC");
return null;
}
}
// Set born stamp & born-in-sight (giữ nguyên semantics)
uint bornStamp = CECWorld.Instance.GetBornStamp();
if (!object.ReferenceEquals(pNPC, null))
{
pNPC.SetBornStamp(bornStamp);
pNPC.SetBornInSight(bBornInSight);
}
else
{
return null;
}
// Init với tid + Info như C++
if (!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();
pNPC = null;
// log lỗi tương tự glb_ErrorOutput
UnityEngine.Debug.LogError($"CECNPCMan::CreateNPC failed, tid={tid}");
return null;
}
return pNPC;
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,155 +1,157 @@
using BrewMonster;
using BrewMonster.Managers;
using BrewMonster.Network;
using BrewMonster.Scripts.Player;
using CSNetwork.GPDataType;
using PerfectWorld.Scripts.Managers;
using PerfectWorld.Scripts.Player;
using UnityEngine;
class CECHPWorkPostTickCommand1 : CECHPWorkPostTickRunWorkCommand
namespace BrewMonster.Scripts
{
public CECHPWorkPostTickCommand1(CECHPWork pWork) : base(pWork, true)
class CECHPWorkPostTickCommand1 : CECHPWorkPostTickRunWorkCommand
{
}
public virtual bool Run(CECHPWorkMan pWorkMan)
{
if (!base.Run(pWorkMan))
public CECHPWorkPostTickCommand1(CECHPWork pWork) : base(pWork, true)
{
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)
public virtual bool Run(CECHPWorkMan pWorkMan)
{
m_bFinished = true;
if (!base.Run(pWorkMan))
{
return false;
}
//AP_ActionEvent(AP_EVENT_MELEEOUTOFRANGE);
return true;
}
};
// If target turn to be un-attackable, cancel action
if (m_pHost.AttackableJudge(m_idTarget, true) == 0)
///////////////////////////////////////////////////////////////////////////
//
// 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)
{
UnityGameSession.c2s_CmdCancelAction();
//g_pGame.GetGameSession().c2s_CmdCancelAction();
m_bFinished = true;
return true;
m_dwMask = Work_mask.MASK_HACKOBJECT;
m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_TRACEOBJECT;
Reset();
}
if (m_iIdleTimeCnt < m_iIdleTime)
// Tick routine
public virtual bool Tick(float dwDeltaTime)
{
m_iIdleTimeCnt += (int)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;
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();
// 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;
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;
CECHPWorkMelee pSrc = (CECHPWorkMelee)pWork;
m_idTarget = pSrc.m_idTarget;
m_iIdleTime = pSrc.m_iIdleTime;
m_iIdleTimeCnt = pSrc.m_iIdleTimeCnt;
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);
}
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; }
// 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);
// 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;
}
};
m_idTarget = m_pHost.m_idSelTarget;
}
};
}
@@ -1,367 +1,370 @@
using CSNetwork.GPDataType;
using UnityEngine;
public class CECHPWorkMove : CECHPWork
namespace BrewMonster.Scripts
{
public static class Types
public class CECHPWorkMove : CECHPWork
{
public const int DEST_2D = 0,
DEST_3D = 1,
DEST_DIR = 2,
DEST_PUSH = 3,
DEST_STANDJUMP = 4,
DEST_AUTOPF = 5; // Movement type
}
protected A3DVECTOR3 m_vMoveDest; // Move destination position or direction
protected int m_iDestType; // Destination type
protected bool m_bHaveDest; // true, have destination
protected bool m_bMeetSlide; // true, meet slide
protected A3DVECTOR3 m_vCurDir; // Current move direction
protected bool m_bReadyCancel; // true, ready to cancel
protected bool m_bGliding; // glide
protected float m_fGlideTime;
protected float m_fGlideSpan;
protected float m_fGlideAng;
protected float m_fGlideVel; // glide angular vel
protected float m_fGlidePitch; // glide pitch angle
protected float m_fCurPitch;
protected float m_fPushPitch;
protected float m_fPushLean;
protected bool m_bUseAutoMoveDialog; // Auto move
protected float m_fAutoHeight; // Height of auto moving destination
protected bool m_bAutoLand; // Auto land when arrive at destination
protected bool m_bAutoFly; // Auto fly
protected bool m_bReachedHeight;// Player reached specified height
protected bool m_bAutoFlyPending; // Mark whether a fly command had been executed
protected int m_iNPCTempleId;
protected int m_iTaskId;
protected bool m_bSwitchTo2D;
protected bool m_bResetAutoPF;
public CECHPWorkMove(CECHPWorkMan pWorkMan) : base (Host_work_ID.WORK_MOVETOPOS, pWorkMan)
{
m_dwMask = Work_mask.MASK_MOVETOPOS;
m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_TRACEOBJECT | Work_mask.MASK_FOLLOW;
Reset();
}
public CECHPWorkMove(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan)
{
}
// Set destination position or direction
public void SetDestination(int iDestType, A3DVECTOR3 vMoveDest)
{
m_iDestType = iDestType;
m_vMoveDest = vMoveDest;
m_bHaveDest = true;
m_bGliding = false;
//m_pHost->SetAdjustOrient(false); // 2014-9-10 徐文彬:在 CECHPWorkMove 创建的时候都会调用此函数,会导致其它时机通过 SetDestDirAndUp 调用对人物的朝向调整失效。
// 重现方法为:月仙“望月咏”技能释放后、马上按住'A'或'D'等移动键并摁住不放,将导致人物施法方向偏离目标而朝向移动方向(需多次尝试)
//清空任务信息
m_iTaskId = 0;
m_iNPCTempleId = 0;
ResetUseAutoPF();
if (iDestType == Types.DEST_DIR)
public static class Types
{
m_vCurDir = vMoveDest;
if (m_bUseAutoMoveDialog)
public const int DEST_2D = 0,
DEST_3D = 1,
DEST_DIR = 2,
DEST_PUSH = 3,
DEST_STANDJUMP = 4,
DEST_AUTOPF = 5; // Movement type
}
protected A3DVECTOR3 m_vMoveDest; // Move destination position or direction
protected int m_iDestType; // Destination type
protected bool m_bHaveDest; // true, have destination
protected bool m_bMeetSlide; // true, meet slide
protected A3DVECTOR3 m_vCurDir; // Current move direction
protected bool m_bReadyCancel; // true, ready to cancel
protected bool m_bGliding; // glide
protected float m_fGlideTime;
protected float m_fGlideSpan;
protected float m_fGlideAng;
protected float m_fGlideVel; // glide angular vel
protected float m_fGlidePitch; // glide pitch angle
protected float m_fCurPitch;
protected float m_fPushPitch;
protected float m_fPushLean;
protected bool m_bUseAutoMoveDialog; // Auto move
protected float m_fAutoHeight; // Height of auto moving destination
protected bool m_bAutoLand; // Auto land when arrive at destination
protected bool m_bAutoFly; // Auto fly
protected bool m_bReachedHeight;// Player reached specified height
protected bool m_bAutoFlyPending; // Mark whether a fly command had been executed
protected int m_iNPCTempleId;
protected int m_iTaskId;
protected bool m_bSwitchTo2D;
protected bool m_bResetAutoPF;
public CECHPWorkMove(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_MOVETOPOS, pWorkMan)
{
m_dwMask = Work_mask.MASK_MOVETOPOS;
m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_TRACEOBJECT | Work_mask.MASK_FOLLOW;
Reset();
}
public CECHPWorkMove(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan)
{
}
// Set destination position or direction
public void SetDestination(int iDestType, A3DVECTOR3 vMoveDest)
{
m_iDestType = iDestType;
m_vMoveDest = vMoveDest;
m_bHaveDest = true;
m_bGliding = false;
//m_pHost->SetAdjustOrient(false); // 2014-9-10 徐文彬:在 CECHPWorkMove 创建的时候都会调用此函数,会导致其它时机通过 SetDestDirAndUp 调用对人物的朝向调整失效。
// 重现方法为:月仙“望月咏”技能释放后、马上按住'A'或'D'等移动键并摁住不放,将导致人物施法方向偏离目标而朝向移动方向(需多次尝试)
//清空任务信息
m_iTaskId = 0;
m_iNPCTempleId = 0;
ResetUseAutoPF();
if (iDestType == Types.DEST_DIR)
{
m_bUseAutoMoveDialog = false;
m_bAutoLand = false;
m_fAutoHeight = -1.0f;
m_bAutoFly = false;
m_bReachedHeight = true;
m_bAutoFlyPending = false;
m_vCurDir = vMoveDest;
if (m_bUseAutoMoveDialog)
{
m_bUseAutoMoveDialog = false;
m_bAutoLand = false;
m_fAutoHeight = -1.0f;
m_bAutoFly = false;
m_bReachedHeight = true;
m_bAutoFlyPending = false;
}
}
}
else if (iDestType == Types.DEST_2D || iDestType == Types.DEST_3D)
{
m_vCurDir = vMoveDest - new A3DVECTOR3(m_pHost.transform.position.x, m_pHost.transform.position.y, m_pHost.transform.position.z);
m_vCurDir.y = 0.0f;
m_vCurDir.Normalize();
}
else if (IsAutoPF())
{
else if (iDestType == Types.DEST_2D || iDestType == Types.DEST_3D)
{
m_vCurDir = vMoveDest - new A3DVECTOR3(m_pHost.transform.position.x, m_pHost.transform.position.y, m_pHost.transform.position.z);
m_vCurDir.y = 0.0f;
m_vCurDir.Normalize();
}
else if (IsAutoPF())
{
// TO DO: fix later
//m_vCurDir = CECIntelligentRoute::Instance().GetCurDest() - m_pHost->GetPos();
//m_vCurDir.y = 0.0f;
//m_vCurDir.Normalize();
//if (m_bUseAutoMoveDialog)
//{
// // 此处禁用 m_bUseAutoMoveDialog,见 SetUseAutoMoveDialog 中说明
// m_bUseAutoMoveDialog = false;
// m_bAutoLand = false;
// m_fAutoHeight = -1.0f;
// m_bAutoFly = false;
// m_bReachedHeight = true;
// m_bAutoFlyPending = false;
//}
}
// TO DO: fix later
//m_vCurDir = CECIntelligentRoute::Instance().GetCurDest() - m_pHost->GetPos();
//m_vCurDir.y = 0.0f;
//m_vCurDir.Normalize();
//if (m_bUseAutoMoveDialog)
//if (m_pHost.m_pMoveTargetGFX)
//{
// // 此处禁用 m_bUseAutoMoveDialog,见 SetUseAutoMoveDialog 中说明
// m_bUseAutoMoveDialog = false;
// m_bAutoLand = false;
// m_fAutoHeight = -1.0f;
// m_bAutoFly = false;
// m_bReachedHeight = true;
// m_bAutoFlyPending = false;
// if (iDestType != DEST_PUSH)
// m_pHost.m_pMoveTargetGFX.Stop();
//}
}
// TO DO: fix later
//if (m_pHost.m_pMoveTargetGFX)
//{
// if (iDestType != DEST_PUSH)
// m_pHost.m_pMoveTargetGFX.Stop();
//}
}
void ResetUseAutoPF()
{
m_bResetAutoPF = true;
}
void ResetUseAutoPF()
{
m_bResetAutoPF = true;
}
// Tick routine
public virtual bool Tick(float dwDeltaTime)
{
//UpdateResetUseAutoPF();
//if (m_bSwitchTo2D)
//{
// SwitchToDest2D();
// m_bSwitchTo2D = false;
// return true;
//}
//if (IsAutoPF())
//{
// if (CECIntelligentRoute::Instance().IsIdle())
// {
// // 智能寻路模式未成功时,等待下个 Tick 切换到 DEST_2D 模式
// return true;
// }
// if (m_pHost.IsFlying())
// {
// // 中途切换到飞行模式时,切换到 DEST_2D 模式
// CECIntelligentRoute::Instance().ResetSearch();
// m_bSwitchTo2D = true;
// return true;
// }
//}
// Tick routine
public virtual bool Tick(float dwDeltaTime)
{
//UpdateResetUseAutoPF();
//if (m_bSwitchTo2D)
//{
// SwitchToDest2D();
// m_bSwitchTo2D = false;
// return true;
//}
//if (IsAutoPF())
//{
// if (CECIntelligentRoute::Instance().IsIdle())
// {
// // 智能寻路模式未成功时,等待下个 Tick 切换到 DEST_2D 模式
// return true;
// }
// if (m_pHost.IsFlying())
// {
// // 中途切换到飞行模式时,切换到 DEST_2D 模式
// CECIntelligentRoute::Instance().ResetSearch();
// m_bSwitchTo2D = true;
// return true;
// }
//}
//base.Tick(dwDeltaTime);
//base.Tick(dwDeltaTime);
//if (m_pHost.IsRooting())
// return true;
//if (m_pHost.IsRooting())
// return true;
//if (m_bUseAutoMoveDialog)
//{
// if (m_pHost.IsFlying())
// {
// m_bAutoFly = false;
// m_bAutoFlyPending = false;
// }
//if (m_bUseAutoMoveDialog)
//{
// if (m_pHost.IsFlying())
// {
// m_bAutoFly = false;
// m_bAutoFlyPending = false;
// }
// if (m_bAutoFly && !m_bAutoFlyPending && !m_pHost.IsFlying())
// {
// if (m_pHost.CmdFly())
// {
// m_bAutoFly = false;
// m_bAutoFlyPending = true;
// }
// }
//}
//else
//{
// // Make sure 'Win_AutoPlay' dialog doesn't show up
// CECGameUIMan pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan();
// pGameUI.AutoMoveShowDialog(false);
//}
// if (m_bAutoFly && !m_bAutoFlyPending && !m_pHost.IsFlying())
// {
// if (m_pHost.CmdFly())
// {
// m_bAutoFly = false;
// m_bAutoFlyPending = true;
// }
// }
//}
//else
//{
// // Make sure 'Win_AutoPlay' dialog doesn't show up
// CECGameUIMan pGameUI = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan();
// pGameUI.AutoMoveShowDialog(false);
//}
////寻路过程中找到NPC对象转为WorkTrace状态
//if ((m_vMoveDest - m_pHost.GetPos()).MagnitudeH() <= 5.0f)
//{
// if (m_iNPCTempleId)
// {
// CECNPC pNPC = g_pGame.GetGameRun().GetWorld().GetNPCMan().FindNPCByTempleID(m_iNPCTempleId);
// if (pNPC && m_pHost.SelectTarget(pNPC->GetNPCID()))
// {
// CECHPWorkTrace pWork = m_pWorkMan.CreateNPCTraceWork(pNPC, m_iTaskId);
// if (pWork)
// {
// m_bAutoLand = false; //防止飞行状态寻路结束,转到worktrace之前自动着陆,进入workfall。
// Finish();
// m_pWorkMan.SetPostTickCommand(new CECHPWorkPostTickRunWorkCommand(pWork, true));
// return true;
// }
// }
// }
//}
////寻路过程中找到NPC对象转为WorkTrace状态
//if ((m_vMoveDest - m_pHost.GetPos()).MagnitudeH() <= 5.0f)
//{
// if (m_iNPCTempleId)
// {
// CECNPC pNPC = g_pGame.GetGameRun().GetWorld().GetNPCMan().FindNPCByTempleID(m_iNPCTempleId);
// if (pNPC && m_pHost.SelectTarget(pNPC->GetNPCID()))
// {
// CECHPWorkTrace pWork = m_pWorkMan.CreateNPCTraceWork(pNPC, m_iTaskId);
// if (pWork)
// {
// m_bAutoLand = false; //防止飞行状态寻路结束,转到worktrace之前自动着陆,进入workfall。
// Finish();
// m_pWorkMan.SetPostTickCommand(new CECHPWorkPostTickRunWorkCommand(pWork, true));
// return true;
// }
// }
// }
//}
//float fDeltaTime = dwDeltaTime;
//if (m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_GROUND ||
// m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_WATER && m_pHost.IsJumping() && (m_pHost.m_CDRInfo.vAbsVelocity.y > 0 || m_pHost.m_CDRInfo.fYVel > 0))
//{
// // Play appropriate actions
// if (!m_pHost.IsJumping() && !m_pHost.IsPlayingAction(CECPlayer::ACT_TRICK_RUN) &&
// m_pHost.m_iMoveMode != CECPlayer::MOVE_SLIDE && !m_bMeetSlide)
// {
// int iAction = m_pHost->GetMoveStandAction(true);
// m_pHost.PlayAction(iAction, false);
// }
//float fDeltaTime = dwDeltaTime;
//if (m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_GROUND ||
// m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_WATER && m_pHost.IsJumping() && (m_pHost.m_CDRInfo.vAbsVelocity.y > 0 || m_pHost.m_CDRInfo.fYVel > 0))
//{
// // Play appropriate actions
// if (!m_pHost.IsJumping() && !m_pHost.IsPlayingAction(CECPlayer::ACT_TRICK_RUN) &&
// m_pHost.m_iMoveMode != CECPlayer::MOVE_SLIDE && !m_bMeetSlide)
// {
// int iAction = m_pHost->GetMoveStandAction(true);
// m_pHost.PlayAction(iAction, false);
// }
// Tick_Walk(fDeltaTime);
//}
//else // (m_pHost->m_iMoveEnv == CECPlayer::MOVEENV_AIR || m_pHost->m_iMoveEnv == CECPlayer::MOVEENV_WATER)
//{
// m_pHost->ResetJump();
// Tick_Walk(fDeltaTime);
//}
//else // (m_pHost->m_iMoveEnv == CECPlayer::MOVEENV_AIR || m_pHost->m_iMoveEnv == CECPlayer::MOVEENV_WATER)
//{
// m_pHost->ResetJump();
// // Play appropriate actions
// if (!m_bGliding)
// {
// int iAction = m_pHost.GetMoveStandAction(true);
// m_pHost.PlayAction(iAction, false);
// }
// // Play appropriate actions
// if (!m_bGliding)
// {
// int iAction = m_pHost.GetMoveStandAction(true);
// m_pHost.PlayAction(iAction, false);
// }
// Tick_FlySwim(fDeltaTime);
//}
// Tick_FlySwim(fDeltaTime);
//}
return true;
}
// Reset work
public virtual void Reset()
{
return true;
}
// Reset work
public virtual void Reset()
{
}
// Work is cancel
public virtual void Cancel()
{
}
// This work is do player moving ?
public virtual bool IsMoving() { return true; }
// Copy work data
public virtual bool CopyData(CECHPWork pWork)
{
return true;
}
// Play move target effect
public void PlayMoveTargetGFX(A3DVECTOR3 vPos, A3DVECTOR3 vNormal)
{
}
// User press cancel button
public void PressCancel() { m_bReadyCancel = true; }
public void SetUseAutoMoveDialog(bool bUseAutoMoveDialog)
{
}
public bool GetUseAutoMoveDialog() { return m_bUseAutoMoveDialog; }
public bool GetAutoMove()
{
return true;
}
void SetAutoLand(bool bAutoLand) { m_bAutoLand = bAutoLand; }
bool GetAutoLand() { return m_bAutoLand; }
void SetAutoHeight(float fHeight) { m_fAutoHeight = fHeight; m_bAutoFly = true; m_bReachedHeight = false; }
float GetAutoHeight() { return m_fAutoHeight; }
bool IsAutoFly() { return m_bAutoFly; }
bool IsAutoPF() { return m_iDestType == Types.DEST_AUTOPF; }
// Finish work
void Finish()
{
}
void SetTaskNPCInfo(int tid, int taskid)
{
}
void SwitchToDest2D()
{
//int tid, taskid;
//tid = m_iNPCTempleId;
//taskid = m_iTaskId;
//CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan();
//pGameUI->SetAutoMoveShowDialogTarget((int)m_vMoveDest.x, (int)m_vMoveDest.z);
//SetDestination(CECHPWorkMove::DEST_2D, m_vMoveDest);
//SetTaskNPCInfo(tid, taskid);
//SetUseAutoMoveDialog(true);
}
// On first tick
protected virtual void OnFirstTick()
{
}
// Tick routine of walking on ground
protected bool Tick_Walk(float fDeltaTime)
{
return true;
}
// Tick routine of flying or swimming
protected bool Tick_FlySwim(float fDeltaTime)
{
return true;
}
// Start gliding
protected void Glide(float fMoveTime, A3DVECTOR3 vMoveDirH, float fDeltaTime, bool bFly)
{
}
// Calculate vertical speed when fly or swim
protected float CalcFlySwimVertSpeed(float fSpeed1, float fPushDir, float fPushAccel, float fDeltaTime)
{
return 0;
}
protected void ClearResetUseAutoPF()
{
}
protected void UpdateResetUseAutoPF()
{
// if (!m_bResetAutoPF)
// {
// return;
// }
// CECIntelligentRoute::Instance().SetUsage(CECIntelligentRoute::enumUsageWorkMove);
// CECIntelligentRoute::Instance().ResetSearch();
// if (m_iDestType == DEST_2D || m_iDestType == DEST_3D)
// {
//# ifdef SHOW_AUTOMOVE_FOOTPRINTS
// g_AutoPFFollowPoints.clear();
// g_AutoPFPathPoints.clear();
//#endif
// }
// else if (IsAutoPF())
// {
// bool bSwitchTo2D(true);
// while (true)
// {
// if (m_pHost->IsFlying())
// {
// break;
// }
// CECHostBrushTest brushTester(m_pHost->GetPos(), m_pHost->m_CDRInfo.vExtent, m_pHost->m_CDRInfo.fStepHeight);
// if (CECIntelligentRoute::Instance().Search(m_pHost->GetPos(), m_vMoveDest, &brushTester) != CECIntelligentRoute::enumSearchSuccess)
// {
// break;
// }
// bSwitchTo2D = false;
// break;
// }
// if (bSwitchTo2D)
// {
// m_bSwitchTo2D = true;
// }
// }
// ClearResetUseAutoPF();
}
}
// Work is cancel
public virtual void Cancel()
{
}
// This work is do player moving ?
public virtual bool IsMoving() { return true; }
// Copy work data
public virtual bool CopyData(CECHPWork pWork)
{
return true;
}
// Play move target effect
public void PlayMoveTargetGFX(A3DVECTOR3 vPos, A3DVECTOR3 vNormal)
{
}
// User press cancel button
public void PressCancel() { m_bReadyCancel = true; }
public void SetUseAutoMoveDialog(bool bUseAutoMoveDialog)
{
}
public bool GetUseAutoMoveDialog() { return m_bUseAutoMoveDialog; }
public bool GetAutoMove()
{
return true;
}
void SetAutoLand(bool bAutoLand) { m_bAutoLand = bAutoLand; }
bool GetAutoLand() { return m_bAutoLand; }
void SetAutoHeight(float fHeight) { m_fAutoHeight = fHeight; m_bAutoFly = true; m_bReachedHeight = false; }
float GetAutoHeight() { return m_fAutoHeight; }
bool IsAutoFly() { return m_bAutoFly;}
bool IsAutoPF(){ return m_iDestType == Types.DEST_AUTOPF; }
// Finish work
void Finish()
{
}
void SetTaskNPCInfo(int tid, int taskid)
{
}
void SwitchToDest2D()
{
//int tid, taskid;
//tid = m_iNPCTempleId;
//taskid = m_iTaskId;
//CECGameUIMan* pGameUI = g_pGame->GetGameRun()->GetUIManager()->GetInGameUIMan();
//pGameUI->SetAutoMoveShowDialogTarget((int)m_vMoveDest.x, (int)m_vMoveDest.z);
//SetDestination(CECHPWorkMove::DEST_2D, m_vMoveDest);
//SetTaskNPCInfo(tid, taskid);
//SetUseAutoMoveDialog(true);
}
// On first tick
protected virtual void OnFirstTick()
{
}
// Tick routine of walking on ground
protected bool Tick_Walk(float fDeltaTime)
{
return true;
}
// Tick routine of flying or swimming
protected bool Tick_FlySwim(float fDeltaTime)
{
return true;
}
// Start gliding
protected void Glide(float fMoveTime, A3DVECTOR3 vMoveDirH, float fDeltaTime, bool bFly)
{
}
// Calculate vertical speed when fly or swim
protected float CalcFlySwimVertSpeed(float fSpeed1, float fPushDir, float fPushAccel, float fDeltaTime)
{
return 0;
}
protected void ClearResetUseAutoPF()
{
}
protected void UpdateResetUseAutoPF()
{
// if (!m_bResetAutoPF)
// {
// return;
// }
// CECIntelligentRoute::Instance().SetUsage(CECIntelligentRoute::enumUsageWorkMove);
// CECIntelligentRoute::Instance().ResetSearch();
// if (m_iDestType == DEST_2D || m_iDestType == DEST_3D)
// {
//# ifdef SHOW_AUTOMOVE_FOOTPRINTS
// g_AutoPFFollowPoints.clear();
// g_AutoPFPathPoints.clear();
//#endif
// }
// else if (IsAutoPF())
// {
// bool bSwitchTo2D(true);
// while (true)
// {
// if (m_pHost->IsFlying())
// {
// break;
// }
// CECHostBrushTest brushTester(m_pHost->GetPos(), m_pHost->m_CDRInfo.vExtent, m_pHost->m_CDRInfo.fStepHeight);
// if (CECIntelligentRoute::Instance().Search(m_pHost->GetPos(), m_vMoveDest, &brushTester) != CECIntelligentRoute::enumSearchSuccess)
// {
// break;
// }
// bSwitchTo2D = false;
// break;
// }
// if (bSwitchTo2D)
// {
// m_bSwitchTo2D = true;
// }
// }
// ClearResetUseAutoPF();
}
}
@@ -1,75 +1,78 @@
using UnityEngine;
///////////////////////////////////////////////////////////////////////////
//
// Class CECHPWorkSpell
//
///////////////////////////////////////////////////////////////////////////
public class CECHPWorkSpell : CECHPWork
namespace BrewMonster.Scripts
{
public static class Spell_magic_state
///////////////////////////////////////////////////////////////////////////
//
// Class CECHPWorkSpell
//
///////////////////////////////////////////////////////////////////////////
public class CECHPWorkSpell : CECHPWork
{
public const int ST_INCANT = 0,
ST_SPELL = 1;
}
public static class Spell_magic_state
{
public const int ST_INCANT = 0,
ST_SPELL = 1;
}
public CECHPWorkSpell(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_SPELLOBJECT, pWorkMan)
{
m_dwMask = Work_mask.MASK_SPELLOBJECT;
m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_TRACEOBJECT;
Reset();
}
public CECHPWorkSpell(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_SPELLOBJECT, pWorkMan)
{
m_dwMask = Work_mask.MASK_SPELLOBJECT;
m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_TRACEOBJECT;
Reset();
}
public CECHPWorkSpell(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan)
{
}
public CECHPWorkSpell(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan)
{
}
protected CECSkill m_pSkill; // Skill object
protected CECCounter m_OverTimeCnt; // Over time counter
protected int m_iState;
protected int m_idTarget; // Target id
protected CECSkill m_pSkill; // Skill object
protected CECCounter m_OverTimeCnt; // Over time counter
protected int m_iState;
protected int m_idTarget; // Target id
// On first tick
protected virtual void OnFirstTick()
{
//m_pHost.m_iMoveMode = CECHostPlayer::MOVE_STAND;
}
// Prepare cast
public void PrepareCast(int idTarget, CECSkill pSkill, int iIncantTime)
{
// On first tick
protected virtual void OnFirstTick()
{
//m_pHost.m_iMoveMode = CECHostPlayer::MOVE_STAND;
}
// Prepare cast
public void PrepareCast(int idTarget, CECSkill pSkill, int iIncantTime)
{
}
// Change state
public void ChangeState(int iState)
{
}
// Change state
public void ChangeState(int iState)
{
}
// Get state
public int GetState()
{
return m_iState;
}
public CECSkill GetSkill()
{
return m_pSkill;
}
}
// Get state
public int GetState()
{
return m_iState;
}
public CECSkill GetSkill()
{
return m_pSkill;
}
// Tick routine
public virtual bool Tick(uint dwDeltaTime)
{
return false;
}
// Reset work
public virtual void Reset()
{
// Tick routine
public virtual bool Tick(uint dwDeltaTime)
{
return false;
}
// Reset work
public virtual void Reset()
{
}
// Copy work data
public virtual bool CopyData(CECHPWork pWork)
{
return false;
}
// Cancel work
public virtual void Cancel()
{
}
// Copy work data
public virtual bool CopyData(CECHPWork pWork)
{
return false;
}
// Cancel work
public virtual void Cancel()
{
}
}
}
File diff suppressed because it is too large Load Diff
@@ -5,7 +5,7 @@ using System;
using System.Runtime.InteropServices;
using UnityEngine;
namespace PerfectWorld.Scripts.Managers
namespace BrewMonster.Scripts.Managers
{
namespace BrewMonster.Managers
{
@@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using UnityEngine;
namespace PerfectWorld.Scripts.Managers
namespace BrewMonster.Scripts.Managers
{
public static class EC_Inventory
@@ -7,7 +7,7 @@ using BrewMonster.Network;
using BrewMonster;
using ModelRenderer.Scripts.GameData;
namespace PerfectWorld.Scripts.Managers
namespace BrewMonster.Scripts.Managers
{
public class EC_InventoryUI : MonoBehaviour
{
@@ -8,7 +8,7 @@ using ModelRenderer.Scripts.Common;
using ModelRenderer.Scripts.GameData;
using UnityEngine;
namespace PerfectWorld.Scripts.Managers
namespace BrewMonster.Scripts.Managers
{
public class InventoryItemData
{
@@ -3,7 +3,7 @@ using UnityEngine;
using ModelRenderer.Scripts.GameData;
using BrewMonster;
namespace PerfectWorld.Scripts.Managers
namespace BrewMonster.Scripts.Managers
{
public static class EC_IvtrType
{
@@ -1,10 +1,6 @@
using BrewMonster;
using BrewMonster.Network;
using BrewMonster.Scripts;
using CSNetwork;
using CSNetwork.GPDataType;
using CSNetwork.Protocols;
using CSNetwork.Protocols.RPCData;
using PerfectWorld.Scripts.Player;
using System;
using System.Collections;
using System.Collections.Generic;
@@ -12,250 +8,246 @@ using System.Linq;
using System.Runtime.InteropServices;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace PerfectWorld.Scripts.Managers
namespace BrewMonster.Managers
{
namespace BrewMonster.Managers
/// <summary>
/// Matter Manager - Handles matter data storage and provides access to other classes
///
/// Usage Examples:
/// // Get matter manager instance
/// var matterManager = EC_ManMessageMono.Instance.GetECManMatter;
///
/// // Get specific matter data
/// var matterData = matterManager.GetMatterData(12345);
///
/// // Get individual fields
/// int? mid = matterManager.GetMatterId(12345);
/// int? tid = matterManager.GetMatterTid(12345);
/// A3DVECTOR3? pos = matterManager.GetMatterPosition(12345);
/// byte? state = matterManager.GetMatterState(12345);
///
/// // Find matters by criteria
/// int[] mattersByTid = matterManager.FindMattersByTid(100);
/// int[] mattersByState = matterManager.FindMattersByState(1);
/// int[] nearbyMatters = matterManager.FindMattersNearPosition(new A3DVECTOR3(0,0,0), 10.0f);
/// </summary>
[Serializable]
public class EC_ManMatter : IMsgHandler
{
/// <summary>
/// Matter Manager - Handles matter data storage and provides access to other classes
///
/// Usage Examples:
/// // Get matter manager instance
/// var matterManager = EC_ManMessageMono.Instance.GetECManMatter;
///
/// // Get specific matter data
/// var matterData = matterManager.GetMatterData(12345);
///
/// // Get individual fields
/// int? mid = matterManager.GetMatterId(12345);
/// int? tid = matterManager.GetMatterTid(12345);
/// A3DVECTOR3? pos = matterManager.GetMatterPosition(12345);
/// byte? state = matterManager.GetMatterState(12345);
///
/// // Find matters by criteria
/// int[] mattersByTid = matterManager.FindMattersByTid(100);
/// int[] mattersByState = matterManager.FindMattersByState(1);
/// int[] nearbyMatters = matterManager.FindMattersNearPosition(new A3DVECTOR3(0,0,0), 10.0f);
/// </summary>
[Serializable]
public class EC_ManMatter : IMsgHandler
public int HandlerId => (int)MANAGER_INDEX.MAN_MATTER;
// Storage for matter data that players can access later
private Dictionary<int, info_matter> matterDataStorage = new Dictionary<int, info_matter>();
public bool ProcessMessage(ECMSG Msg)
{
public int HandlerId => (int)MANAGER_INDEX.MAN_MATTER;
// Storage for matter data that players can access later
private Dictionary<int, info_matter> matterDataStorage = new Dictionary<int, info_matter>();
public bool ProcessMessage(ECMSG Msg)
if (Msg.iSubID == 0)
{
if (Msg.iSubID == 0)
switch ((int)Msg.dwMsg)
{
switch ((int)Msg.dwMsg)
{
case int value when value == EC_MsgDef.MSG_MM_MATTERINFO:
{
Debug.Log("MATTERINFO");
//ENABLE LATER: It fetch all matters in the game world, causing performance issues
//OnMsgMatterInfo(Msg);
break;
}
case int value when value == EC_MsgDef.MSG_MM_MATTERENTWORLD:
{
Debug.Log("MATTERENTWORLD");
OnMsgMatterEnterWorld(Msg);
break;
}
}
}
else
{
}
return true;
}
public void OnMsgMatterInfo(ECMSG Msg)
{
byte[] data = (byte[])Msg.dwParam1;
try
{
// Parse the data structure: count + info_matter array
int offset = 0;
// Read count (int)
int count = BitConverter.ToInt32(data, offset);
offset += sizeof(int);
Debug.Log($"MATTERINFO: Received {count} matter entries");
// Parse each info_matter entry
for (int i = 0; i < count; i++)
{
// Parse info_matter structure
info_matter matterInfo = CSNetwork.GPDataType.GPDataTypeHelper.FromBytes<info_matter>(data, offset);
offset += Marshal.SizeOf(typeof(info_matter));
// Store the matter data for later player access
matterDataStorage[matterInfo.mid] = matterInfo;
Debug.Log($"Matter info - ID: {matterInfo.mid}, TID: {matterInfo.tid}, Position: {matterInfo.pos}, State: {matterInfo.state}");
// Spawn cube for this matter since it has entered the world
SpawnMatterCube(matterInfo.mid);
}
}
catch (Exception ex)
{
Debug.LogError($"Failed to parse matter info data: {ex.Message}");
case int value when value == EC_MsgDef.MSG_MM_MATTERINFO:
{
Debug.Log("MATTERINFO");
//ENABLE LATER: It fetch all matters in the game world, causing performance issues
//OnMsgMatterInfo(Msg);
break;
}
case int value when value == EC_MsgDef.MSG_MM_MATTERENTWORLD:
{
Debug.Log("MATTERENTWORLD");
OnMsgMatterEnterWorld(Msg);
break;
}
}
}
public void OnMsgMatterEnterWorld(ECMSG Msg)
else
{
byte[] data = (byte[])Msg.dwParam1;
try
}
return true;
}
public void OnMsgMatterInfo(ECMSG Msg)
{
byte[] data = (byte[])Msg.dwParam1;
try
{
// Parse the data structure: count + info_matter array
int offset = 0;
// Read count (int)
int count = BitConverter.ToInt32(data, offset);
offset += sizeof(int);
Debug.Log($"MATTERINFO: Received {count} matter entries");
// Parse each info_matter entry
for (int i = 0; i < count; i++)
{
// Parse the byte array into info_matter structure
info_matter matterInfo = CSNetwork.GPDataType.GPDataTypeHelper.FromBytes<info_matter>(data);
// Parse info_matter structure
info_matter matterInfo = CSNetwork.GPDataType.GPDataTypeHelper.FromBytes<info_matter>(data, offset);
offset += Marshal.SizeOf(typeof(info_matter));
// Store the matter data for later player access
matterDataStorage[matterInfo.mid] = matterInfo;
Debug.Log($"Matter entered world - ID: {matterInfo.mid}, TID: {matterInfo.tid}, Position: {matterInfo.pos}, State: {matterInfo.state}");
// Notify pickupItem to create cube for this matter
NotifyPickupItem(matterInfo.mid);
}
catch (Exception ex)
{
Debug.LogError($"Failed to parse matter data: {ex.Message}");
Debug.Log($"Matter info - ID: {matterInfo.mid}, TID: {matterInfo.tid}, Position: {matterInfo.pos}, State: {matterInfo.state}");
// Spawn cube for this matter since it has entered the world
SpawnMatterCube(matterInfo.mid);
}
}
private void SpawnMatterCube(int matterId)
catch (Exception ex)
{
// Find the pickupItem component in the scene and create cube for this specific matter
pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType<pickupItem>();
if (pickupScript != null)
{
pickupScript.CreateMatterCube(matterId);
}
else
{
Debug.LogWarning("pickupItem component not found in scene - cannot spawn matter cube");
}
Debug.LogError($"Failed to parse matter info data: {ex.Message}");
}
private void NotifyPickupItem(int matterId)
}
public void OnMsgMatterEnterWorld(ECMSG Msg)
{
byte[] data = (byte[])Msg.dwParam1;
try
{
// Find the pickupItem component in the scene and update cubes
pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType<pickupItem>();
if (pickupScript != null)
{
pickupScript.UpdateMatterCubes();
}
// Parse the byte array into info_matter structure
info_matter matterInfo = CSNetwork.GPDataType.GPDataTypeHelper.FromBytes<info_matter>(data);
// Store the matter data for later player access
matterDataStorage[matterInfo.mid] = matterInfo;
Debug.Log($"Matter entered world - ID: {matterInfo.mid}, TID: {matterInfo.tid}, Position: {matterInfo.pos}, State: {matterInfo.state}");
// Notify pickupItem to create cube for this matter
NotifyPickupItem(matterInfo.mid);
}
// Public methods for players to access matter data
public info_matter? GetMatterData(int matterId)
catch (Exception ex)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data : null;
Debug.LogError($"Failed to parse matter data: {ex.Message}");
}
public Dictionary<int, info_matter> GetAllMatterData()
}
private void SpawnMatterCube(int matterId)
{
// Find the pickupItem component in the scene and create cube for this specific matter
pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType<pickupItem>();
if (pickupScript != null)
{
return new Dictionary<int, info_matter>(matterDataStorage);
pickupScript.CreateMatterCube(matterId);
}
public bool HasMatterData(int matterId)
else
{
return matterDataStorage.ContainsKey(matterId);
Debug.LogWarning("pickupItem component not found in scene - cannot spawn matter cube");
}
public void RemoveMatterData(int matterId)
}
private void NotifyPickupItem(int matterId)
{
// Find the pickupItem component in the scene and update cubes
pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType<pickupItem>();
if (pickupScript != null)
{
if (matterDataStorage.ContainsKey(matterId))
{
matterDataStorage.Remove(matterId);
Debug.Log($"Removed matter data for ID: {matterId}");
}
pickupScript.UpdateMatterCubes();
}
public int GetMatterCount()
}
// Public methods for players to access matter data
public info_matter? GetMatterData(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data : null;
}
public Dictionary<int, info_matter> GetAllMatterData()
{
return new Dictionary<int, info_matter>(matterDataStorage);
}
public bool HasMatterData(int matterId)
{
return matterDataStorage.ContainsKey(matterId);
}
public void RemoveMatterData(int matterId)
{
if (matterDataStorage.ContainsKey(matterId))
{
return matterDataStorage.Count;
matterDataStorage.Remove(matterId);
Debug.Log($"Removed matter data for ID: {matterId}");
}
// Convenience methods to get specific fields from matter data
public int? GetMatterId(int matterId)
}
public int GetMatterCount()
{
return matterDataStorage.Count;
}
// Convenience methods to get specific fields from matter data
public int? GetMatterId(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.mid : null;
}
public int? GetMatterTid(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.tid : null;
}
public A3DVECTOR3? GetMatterPosition(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.pos : null;
}
public byte? GetMatterDir0(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.dir0 : null;
}
public byte? GetMatterDir1(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.dir1 : null;
}
public byte? GetMatterRadius(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.rad : null;
}
public byte? GetMatterState(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.state : null;
}
public byte? GetMatterValue(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.value : null;
}
// Get all matter IDs
public int[] GetAllMatterIds()
{
return matterDataStorage.Keys.ToArray();
}
// Find matters by template ID (tid)
public int[] FindMattersByTid(int tid)
{
return matterDataStorage.Where(kvp => kvp.Value.tid == tid).Select(kvp => kvp.Key).ToArray();
}
// Find matters by state
public int[] FindMattersByState(byte state)
{
return matterDataStorage.Where(kvp => kvp.Value.state == state).Select(kvp => kvp.Key).ToArray();
}
// Get matters within a certain distance from a position
public int[] FindMattersNearPosition(A3DVECTOR3 position, float maxDistance)
{
return matterDataStorage.Where(kvp =>
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.mid : null;
}
public int? GetMatterTid(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.tid : null;
}
public A3DVECTOR3? GetMatterPosition(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.pos : null;
}
public byte? GetMatterDir0(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.dir0 : null;
}
public byte? GetMatterDir1(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.dir1 : null;
}
public byte? GetMatterRadius(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.rad : null;
}
public byte? GetMatterState(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.state : null;
}
public byte? GetMatterValue(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.value : null;
}
// Get all matter IDs
public int[] GetAllMatterIds()
{
return matterDataStorage.Keys.ToArray();
}
// Find matters by template ID (tid)
public int[] FindMattersByTid(int tid)
{
return matterDataStorage.Where(kvp => kvp.Value.tid == tid).Select(kvp => kvp.Key).ToArray();
}
// Find matters by state
public int[] FindMattersByState(byte state)
{
return matterDataStorage.Where(kvp => kvp.Value.state == state).Select(kvp => kvp.Key).ToArray();
}
// Get matters within a certain distance from a position
public int[] FindMattersNearPosition(A3DVECTOR3 position, float maxDistance)
{
return matterDataStorage.Where(kvp =>
{
float distance = (kvp.Value.pos - position).Magnitude();
return distance <= maxDistance;
}).Select(kvp => kvp.Key).ToArray();
}
float distance = (kvp.Value.pos - position).Magnitude();
return distance <= maxDistance;
}).Select(kvp => kvp.Key).ToArray();
}
}
}
@@ -1,10 +1,8 @@
using BrewMonster;
using BrewMonster.Network;
using BrewMonster.Scripts.Player;
using CSNetwork;
using CSNetwork.GPDataType;
using CSNetwork.Protocols;
using CSNetwork.Protocols.RPCData;
using PerfectWorld.Scripts.Player;
using System;
using System.Collections;
using System.Collections.Generic;
@@ -13,476 +11,473 @@ using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace PerfectWorld.Scripts.Managers
namespace BrewMonster.Managers
{
namespace BrewMonster.Managers
[Serializable]
public class EC_ManPlayer : IMsgHandler
{
[Serializable]
public class EC_ManPlayer : IMsgHandler
Dictionary<int, int> m_UkPlayerTab = new Dictionary<int, int>();
Dictionary<int, EC_ElsePlayer> m_PlayerTab = new Dictionary<int, EC_ElsePlayer>();
private readonly object m_csPlayerTab = new object();
CECHostPlayer m_pHostPlayer;
public int HandlerId => (int)MANAGER_INDEX.MAN_PLAYER;
public bool ProcessMessage(ECMSG Msg)
{
Dictionary<int, int> m_UkPlayerTab = new Dictionary<int, int>();
Dictionary<int, EC_ElsePlayer> m_PlayerTab = new Dictionary<int, EC_ElsePlayer>();
private readonly object m_csPlayerTab = new object();
CECHostPlayer m_pHostPlayer;
public int HandlerId => (int)MANAGER_INDEX.MAN_PLAYER;
public bool ProcessMessage(ECMSG Msg)
Debug.Log("HoangDev: ProcessMessageManPlayer :");
if (Msg.iSubID == 0)
{
Debug.Log("HoangDev: ProcessMessageManPlayer :");
if (Msg.iSubID == 0)
{
if (GameController.Instance == null) return true;
GameController.Instance.GetHostPlayer().ProcessMessage(Msg);
}
else if (Msg.iSubID < 0)
{
switch ((int)Msg.dwMsg)
{
case int value when value == EC_MsgDef.MSG_PM_PLAYERINFO:
{
OnMsgPlayerInfo(Msg);
break;
}
case int value when value == EC_MsgDef.MSG_PM_PLAYERMOVE:
{
OnMsgPlayerMove(Msg);
break;
}
case int value when value == EC_MsgDef.MSG_PM_PLAYERSTOPMOVE:
{
OnMsgPlayerStopMove(Msg);
break;
}
case int value when value == EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY:
Debug.Log("EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY");
TransmitMessage(Msg);
break;
}
}
else
{
}
return true;
if (GameController.Instance == null) return true;
GameController.Instance.GetHostPlayer().ProcessMessage(Msg);
}
public void OnMsgPlayerInfo(ECMSG Msg)
else if (Msg.iSubID < 0)
{
int iHostID = Convert.ToInt32(Msg.dwParam3);
int lenghtByte = Marshal.SizeOf<int>();
byte[] byteArray = new byte[lenghtByte];
byte[] data = (byte[])Msg.dwParam1;
for (int i = 0; i < lenghtByte; i++)
switch ((int)Msg.dwMsg)
{
byteArray[i] = data[i];
}
int cid = BitConverter.ToInt32(byteArray);
int commandID = Convert.ToInt32(Msg.dwParam2);
switch (commandID)
{
case CommandID.PLAYER_INFO_1:
case CommandID.PLAYER_ENTER_WORLD:
case CommandID.PLAYER_ENTER_SLICE:
case int value when value == EC_MsgDef.MSG_PM_PLAYERINFO:
{
if (cid != iHostID)
{
info_player_1 info_Player_1 = GPDataTypeHelper.FromBytes<info_player_1>((byte[])Msg.dwParam1);
RoleInfo roleInfo = (RoleInfo)Msg.dwParam4;
ElsePlayerEnter(info_Player_1, commandID, roleInfo);
GameController.Instance.Log("ElsePlayer has join");
}
OnMsgPlayerInfo(Msg);
break;
}
case CommandID.SELF_INFO_1:
Debug.Log("SELF_INFO_1");
cmd_self_info_1 info = GPDataTypeHelper.FromBytes<cmd_self_info_1>((byte[])Msg.dwParam1);
HostPlayerInfo1(info);
case int value when value == EC_MsgDef.MSG_PM_PLAYERMOVE:
{
OnMsgPlayerMove(Msg);
break;
}
case int value when value == EC_MsgDef.MSG_PM_PLAYERSTOPMOVE:
{
OnMsgPlayerStopMove(Msg);
break;
}
case int value when value == EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY:
Debug.Log("EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY");
TransmitMessage(Msg);
break;
case CommandID.PLAYER_INFO_2: break;
case CommandID.PLAYER_INFO_3: break;
case CommandID.PLAYER_INFO_4: break;
}
}
else
{
case CommandID.PLAYER_INFO_1_LIST:
}
return true;
}
public void OnMsgPlayerInfo(ECMSG Msg)
{
int iHostID = Convert.ToInt32(Msg.dwParam3);
int lenghtByte = Marshal.SizeOf<int>();
byte[] byteArray = new byte[lenghtByte];
byte[] data = (byte[])Msg.dwParam1;
for (int i = 0; i < lenghtByte; i++)
{
byteArray[i] = data[i];
}
int cid = BitConverter.ToInt32(byteArray);
int commandID = Convert.ToInt32(Msg.dwParam2);
switch (commandID)
{
case CommandID.PLAYER_INFO_1:
case CommandID.PLAYER_ENTER_WORLD:
case CommandID.PLAYER_ENTER_SLICE:
{
if (cid != iHostID)
{
byte[] bytes = (byte[])Msg.dwParam1;
cmd_player_info_1_list pCmd = GPDataTypeHelper.FromBytes<cmd_player_info_1_list>(bytes);
if (pCmd.count == 0)
{
break;
}
int lenght = Marshal.SizeOf<info_player_1>();
int preSize = 0;
byte[] pDataBuf = null;
preSize += Marshal.SizeOf<ushort>();
info_player_1 info_Player_1 = GPDataTypeHelper.FromBytes<info_player_1>((byte[])Msg.dwParam1);
RoleInfo roleInfo = (RoleInfo)Msg.dwParam4;
for (int i = 0; i < pCmd.count; i++)
{
pDataBuf = new byte[lenght];
for (int j = 0; j < pDataBuf.Length; j++)
{
pDataBuf[j] = bytes[preSize + j];
}
info_player_1 Info = GPDataTypeHelper.FromBytes<info_player_1>(pDataBuf);
if (Info.cid != iHostID)
{
EC_ElsePlayer pPlayer = ElsePlayerEnter(Info, commandID, roleInfo);
}
ElsePlayerEnter(info_Player_1, commandID, roleInfo);
GameController.Instance.Log("ElsePlayer has join");
}
break;
}
case CommandID.SELF_INFO_1:
Debug.Log("SELF_INFO_1");
cmd_self_info_1 info = GPDataTypeHelper.FromBytes<cmd_self_info_1>((byte[])Msg.dwParam1);
HostPlayerInfo1(info);
break;
case CommandID.PLAYER_INFO_2: break;
case CommandID.PLAYER_INFO_3: break;
case CommandID.PLAYER_INFO_4: break;
// Calculate player info data size and skip it
int iSize = Marshal.SizeOf<info_player_1>();
if ((Info.state & PlayerNPCState.GP_STATE_ADV_MODE) != 0)
iSize += Marshal.SizeOf<int>() * 2;
if ((Info.state & PlayerNPCState.GP_STATE_SHAPE) != 0)
iSize += Marshal.SizeOf<byte>();
if ((Info.state & PlayerNPCState.GP_STATE_EMOTE) != 0)
iSize += Marshal.SizeOf<byte>();
if ((Info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0)
iSize += Marshal.SizeOf<int>() * NumberDWORDsPlayerNPC.OBJECT_EXT_STATE_COUNT;
if ((Info.state & PlayerNPCState.GP_STATE_FACTION) != 0)
iSize += (Marshal.SizeOf<int>() + Marshal.SizeOf<byte>());
if ((Info.state & PlayerNPCState.GP_STATE_BOOTH) != 0)
iSize += Marshal.SizeOf<byte>();
//// Parse effect data
if ((Info.state & PlayerNPCState.GP_STATE_EFFECT) != 0)
{
iSize += Marshal.SizeOf<byte>();
byte byNum = bytes[preSize + iSize];
if (byNum > 0)
iSize += byNum * Marshal.SizeOf<short>();
}
if ((Info.state & PlayerNPCState.GP_STATE_PARIAH) != 0)
iSize += Marshal.SizeOf<byte>();
if ((Info.state & PlayerNPCState.GP_STATE_IN_MOUNT) != 0)
iSize += Marshal.SizeOf<ushort>() + Marshal.SizeOf<int>();
// Parse bind data
if ((Info.state & PlayerNPCState.GP_STATE_IN_BIND) != 0)
iSize += Marshal.SizeOf<char>() + Marshal.SizeOf<int>();
// Parse spouse data
if ((Info.state & PlayerNPCState.GP_STATE_SPOUSE) != 0)
iSize += Marshal.SizeOf<int>();
if ((Info.state & PlayerNPCState.GP_STATE_EQUIPDISABLED) != 0)
iSize += Marshal.SizeOf<long>();
if ((Info.state & PlayerNPCState.GP_STATE_PLAYERFORCE) != 0)
iSize += Marshal.SizeOf<int>();
if ((Info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0)
{
int effectNum = Marshal.ReadInt32(bytes, iSize);//*(int*)(pDataBuf + iSize);
iSize += Marshal.SizeOf<int>();
if (effectNum > 0)
iSize += effectNum * (Marshal.SizeOf<int>() + Marshal.SizeOf<char>());
}
if ((Info.state & PlayerNPCState.GP_STATE_COUNTRY) != 0)
iSize += Marshal.SizeOf<int>();
if ((Info.state2 & PlayerNPCState2.GP_STATE2_TITLE) != 0)
iSize += Marshal.SizeOf<ushort>();
if ((Info.state2 & PlayerNPCState2.GP_STATE2_REINCARNATION) != 0)
iSize += Marshal.SizeOf<byte>();
if ((Info.state2 & PlayerNPCState2.GP_STATE2_REALM) != 0)
iSize += Marshal.SizeOf<byte>();
if ((Info.state2 & PlayerNPCState2.GP_STATE2_FACTION_PVP_MASK) != 0)
iSize += Marshal.SizeOf<byte>();
// Goblin refine data
if ((Info.state & PlayerNPCState.GP_STATE_GOBLINREFINE) != 0)
iSize += Marshal.SizeOf<int>();
//pDataBuf += iSize;
preSize += iSize;
}
Debug.LogError("PLAYER_INFO_1_LIST");
case CommandID.PLAYER_INFO_1_LIST:
{
byte[] bytes = (byte[])Msg.dwParam1;
cmd_player_info_1_list pCmd = GPDataTypeHelper.FromBytes<cmd_player_info_1_list>(bytes);
if (pCmd.count == 0)
{
break;
}
}
}
int lenght = Marshal.SizeOf<info_player_1>();
int preSize = 0;
byte[] pDataBuf = null;
preSize += Marshal.SizeOf<ushort>();
RoleInfo roleInfo = (RoleInfo)Msg.dwParam4;
for (int i = 0; i < pCmd.count; i++)
{
pDataBuf = new byte[lenght];
for (int j = 0; j < pDataBuf.Length; j++)
{
pDataBuf[j] = bytes[preSize + j];
}
info_player_1 Info = GPDataTypeHelper.FromBytes<info_player_1>(pDataBuf);
if (Info.cid != iHostID)
{
EC_ElsePlayer pPlayer = ElsePlayerEnter(Info, commandID, roleInfo);
}
public void OnMsgPlayerMove(ECMSG Msg)
{
int iHostID = Convert.ToInt32(Msg.dwParam3);
cmd_object_move pCmd = GPDataTypeHelper.FromBytes<cmd_object_move>((byte[])Msg.dwParam1);
if (pCmd.use_time == 0)
return;
if (pCmd.id != iHostID)
{
EC_ElsePlayer pPlayer = SeekOutElsePlayer(pCmd.id);
if (pPlayer)
{
pPlayer.MoveTo(pCmd);
// Calculate player info data size and skip it
int iSize = Marshal.SizeOf<info_player_1>();
if ((Info.state & PlayerNPCState.GP_STATE_ADV_MODE) != 0)
iSize += Marshal.SizeOf<int>() * 2;
if ((Info.state & PlayerNPCState.GP_STATE_SHAPE) != 0)
iSize += Marshal.SizeOf<byte>();
if ((Info.state & PlayerNPCState.GP_STATE_EMOTE) != 0)
iSize += Marshal.SizeOf<byte>();
if ((Info.state & PlayerNPCState.GP_STATE_EXTEND_PROPERTY) != 0)
iSize += Marshal.SizeOf<int>() * NumberDWORDsPlayerNPC.OBJECT_EXT_STATE_COUNT;
if ((Info.state & PlayerNPCState.GP_STATE_FACTION) != 0)
iSize += (Marshal.SizeOf<int>() + Marshal.SizeOf<byte>());
if ((Info.state & PlayerNPCState.GP_STATE_BOOTH) != 0)
iSize += Marshal.SizeOf<byte>();
//// Parse effect data
if ((Info.state & PlayerNPCState.GP_STATE_EFFECT) != 0)
{
iSize += Marshal.SizeOf<byte>();
byte byNum = bytes[preSize + iSize];
if (byNum > 0)
iSize += byNum * Marshal.SizeOf<short>();
}
if ((Info.state & PlayerNPCState.GP_STATE_PARIAH) != 0)
iSize += Marshal.SizeOf<byte>();
if ((Info.state & PlayerNPCState.GP_STATE_IN_MOUNT) != 0)
iSize += Marshal.SizeOf<ushort>() + Marshal.SizeOf<int>();
// Parse bind data
if ((Info.state & PlayerNPCState.GP_STATE_IN_BIND) != 0)
iSize += Marshal.SizeOf<char>() + Marshal.SizeOf<int>();
// Parse spouse data
if ((Info.state & PlayerNPCState.GP_STATE_SPOUSE) != 0)
iSize += Marshal.SizeOf<int>();
if ((Info.state & PlayerNPCState.GP_STATE_EQUIPDISABLED) != 0)
iSize += Marshal.SizeOf<long>();
if ((Info.state & PlayerNPCState.GP_STATE_PLAYERFORCE) != 0)
iSize += Marshal.SizeOf<int>();
if ((Info.state & PlayerNPCState.GP_STATE_MULTIOBJ_EFFECT) != 0)
{
int effectNum = Marshal.ReadInt32(bytes, iSize);//*(int*)(pDataBuf + iSize);
iSize += Marshal.SizeOf<int>();
if (effectNum > 0)
iSize += effectNum * (Marshal.SizeOf<int>() + Marshal.SizeOf<char>());
}
if ((Info.state & PlayerNPCState.GP_STATE_COUNTRY) != 0)
iSize += Marshal.SizeOf<int>();
if ((Info.state2 & PlayerNPCState2.GP_STATE2_TITLE) != 0)
iSize += Marshal.SizeOf<ushort>();
if ((Info.state2 & PlayerNPCState2.GP_STATE2_REINCARNATION) != 0)
iSize += Marshal.SizeOf<byte>();
if ((Info.state2 & PlayerNPCState2.GP_STATE2_REALM) != 0)
iSize += Marshal.SizeOf<byte>();
if ((Info.state2 & PlayerNPCState2.GP_STATE2_FACTION_PVP_MASK) != 0)
iSize += Marshal.SizeOf<byte>();
// Goblin refine data
if ((Info.state & PlayerNPCState.GP_STATE_GOBLINREFINE) != 0)
iSize += Marshal.SizeOf<int>();
//pDataBuf += iSize;
preSize += iSize;
}
Debug.LogError("PLAYER_INFO_1_LIST");
break;
}
}
}
}
public bool HostPlayerInfo1(cmd_self_info_1 info)
public void OnMsgPlayerMove(ECMSG Msg)
{
int iHostID = Convert.ToInt32(Msg.dwParam3);
cmd_object_move pCmd = GPDataTypeHelper.FromBytes<cmd_object_move>((byte[])Msg.dwParam1);
if (pCmd.use_time == 0)
return;
if (pCmd.id != iHostID)
{
//bool isDoneWorldRender = false;
//bool isDoneNPCRender = false;
//Action actLoadChar = () =>
//{
// if (!isDoneNPCRender || !isDoneWorldRender)
// {
// return;
// }
// GameController.Instance.InitCharacter(info);
//};
//string nameScene = "NPCRender";
//UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Single, (value) =>
//{
// isDoneNPCRender = value;
// actLoadChar?.Invoke();
//});
//nameScene = "WorldRender";
//UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Additive, (value) =>
//{
// isDoneWorldRender = value;
// actLoadChar?.Invoke();
//});
//UnityGameSession.Instance.LoadScene("HoangTest", LoadSceneMode.Single, (value) =>
//{
// isDoneWorldRender = value;
// actLoadChar?.Invoke();
//});
GameController.Instance.InitCharacter(info);
return true;
}
public EC_ElsePlayer ElsePlayerEnter(info_player_1 info, int iCmd, RoleInfo roleInfo)
{
// If this player's id is in unknown table, remove it because this player
// won't be unknown anymore
if (m_UkPlayerTab.TryGetValue(info.cid, out int value))
{
if (value != 0) // Pair.second != 0
{
m_UkPlayerTab.Remove(info.cid);
}
}
int iAppearFlag = (iCmd == (int)CommandID.PLAYER_ENTER_WORLD) ?
(int)PlayerAppearFlag.APPEAR_ENTERWORLD : (int)PlayerAppearFlag.APPEAR_RUNINTOVIEW;
// Has player been in active player table ?
EC_ElsePlayer pPlayer = GetElsePlayer(info.cid);
EC_ElsePlayer pPlayer = SeekOutElsePlayer(pCmd.id);
if (pPlayer)
{
// This player has existed in player table, call special initial function
// TODO: fix after pPlayer init
pPlayer.Init(roleInfo, info);
return pPlayer;
pPlayer.MoveTo(pCmd);
}
}
}
// Create a new player
if (!(pPlayer = CreateElsePlayer(roleInfo, info, iAppearFlag)))
public bool HostPlayerInfo1(cmd_self_info_1 info)
{
//bool isDoneWorldRender = false;
//bool isDoneNPCRender = false;
//Action actLoadChar = () =>
//{
// if (!isDoneNPCRender || !isDoneWorldRender)
// {
// return;
// }
// GameController.Instance.InitCharacter(info);
//};
//string nameScene = "NPCRender";
//UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Single, (value) =>
//{
// isDoneNPCRender = value;
// actLoadChar?.Invoke();
//});
//nameScene = "WorldRender";
//UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Additive, (value) =>
//{
// isDoneWorldRender = value;
// actLoadChar?.Invoke();
//});
//UnityGameSession.Instance.LoadScene("HoangTest", LoadSceneMode.Single, (value) =>
//{
// isDoneWorldRender = value;
// actLoadChar?.Invoke();
//});
GameController.Instance.InitCharacter(info);
return true;
}
public EC_ElsePlayer ElsePlayerEnter(info_player_1 info, int iCmd, RoleInfo roleInfo)
{
// If this player's id is in unknown table, remove it because this player
// won't be unknown anymore
if (m_UkPlayerTab.TryGetValue(info.cid, out int value))
{
if (value != 0) // Pair.second != 0
{
return null;
}
lock (m_csPlayerTab)
{
if (m_PlayerTab.ContainsKey(info.cid))
{
m_PlayerTab[info.cid] = pPlayer;
}
else
{
m_PlayerTab.Add(info.cid, pPlayer);
}
m_UkPlayerTab.Remove(info.cid);
}
}
int iAppearFlag = (iCmd == (int)CommandID.PLAYER_ENTER_WORLD) ?
(int)PlayerAppearFlag.APPEAR_ENTERWORLD : (int)PlayerAppearFlag.APPEAR_RUNINTOVIEW;
// Has player been in active player table ?
EC_ElsePlayer pPlayer = GetElsePlayer(info.cid);
if (pPlayer)
{
// This player has existed in player table, call special initial function
// TODO: fix after pPlayer init
pPlayer.Init(roleInfo, info);
return pPlayer;
}
private EC_ElsePlayer CreateElsePlayer(RoleInfo roleInfo, info_player_1 info, int iAppearFlag)
// Create a new player
if (!(pPlayer = CreateElsePlayer(roleInfo, info, iAppearFlag)))
{
GameObject ob = GameController.Instance.InitCharacter(info);
EC_ElsePlayer elsePlayer = ob.AddComponent<EC_ElsePlayer>();
elsePlayer.GetComponent<CECHostPlayer>().enabled = false;
//init
elsePlayer.Init(roleInfo, info);
return elsePlayer;
return null;
}
public EC_ElsePlayer GetElsePlayer(int cid, long dwBornStamp = 0)
lock (m_csPlayerTab)
{
lock (m_csPlayerTab)
if (m_PlayerTab.ContainsKey(info.cid))
{
if (!m_PlayerTab.TryGetValue(cid, out var player))
return null;
if (dwBornStamp != 0)
{
//TO DO: fix after GetBornStamp() is create in code
//if (player.GetBornStamp() != dwBornStamp)
return null;
}
return player;
m_PlayerTab[info.cid] = pPlayer;
}
else
{
m_PlayerTab.Add(info.cid, pPlayer);
}
}
return pPlayer;
}
private EC_ElsePlayer SeekOutElsePlayer(int cid)
private EC_ElsePlayer CreateElsePlayer(RoleInfo roleInfo, info_player_1 info, int iAppearFlag)
{
GameObject ob = GameController.Instance.InitCharacter(info);
EC_ElsePlayer elsePlayer = ob.AddComponent<EC_ElsePlayer>();
elsePlayer.GetComponent<CECHostPlayer>().enabled = false;
//init
elsePlayer.Init(roleInfo, info);
return elsePlayer;
}
public EC_ElsePlayer GetElsePlayer(int cid, long dwBornStamp = 0)
{
lock (m_csPlayerTab)
{
if (!m_PlayerTab.TryGetValue(cid, out var player))
return null;
if (dwBornStamp != 0)
{
// Couldn't find this else player, put it into unknown player table
m_UkPlayerTab[cid] = cid;
//TO DO: fix after GetBornStamp() is create in code
//if (player.GetBornStamp() != dwBornStamp)
return null;
}
return player;
}
}
public bool OnMsgPlayerStopMove(ECMSG Msg)
private EC_ElsePlayer SeekOutElsePlayer(int cid)
{
if (!m_PlayerTab.TryGetValue(cid, out var player))
{
cmd_object_stop_move pCmd = GPDataTypeHelper.FromBytes<cmd_object_stop_move>((byte[])Msg.dwParam1);
EC_ElsePlayer pPlayer = SeekOutElsePlayer(pCmd.id);
if (pPlayer)
pPlayer.StopMoveTo(pCmd);
return true;
// Couldn't find this else player, put it into unknown player table
m_UkPlayerTab[cid] = cid;
return null;
}
//private cmd_object_move ConvertToStruct(byte[] bytes)
//{
// if (bytes.Length < Marshal.SizeOf<cmd_object_move>())
// {
// return default;
// }
return player;
}
// cmd_object_move result = new cmd_object_move();
// int preLenghtData = 0;
// int lenghtDataType = Marshal.SizeOf<int>();
// byte[] arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
// result.id = BitConverter.ToInt32(arrByteData);
// preLenghtData += lenghtDataType;
// lenghtDataType = Marshal.SizeOf<float>();
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
// result.dest_X = BitConverter.ToSingle(arrByteData);
public bool OnMsgPlayerStopMove(ECMSG Msg)
{
cmd_object_stop_move pCmd = GPDataTypeHelper.FromBytes<cmd_object_stop_move>((byte[])Msg.dwParam1);
EC_ElsePlayer pPlayer = SeekOutElsePlayer(pCmd.id);
if (pPlayer)
pPlayer.StopMoveTo(pCmd);
return true;
}
// preLenghtData += lenghtDataType;
// lenghtDataType = Marshal.SizeOf<float>();
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
// result.dest_Y = BitConverter.ToSingle(arrByteData);
//private cmd_object_move ConvertToStruct(byte[] bytes)
//{
// if (bytes.Length < Marshal.SizeOf<cmd_object_move>())
// {
// return default;
// }
// preLenghtData += lenghtDataType;
// lenghtDataType = Marshal.SizeOf<float>();
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
// result.dest_Z = BitConverter.ToSingle(arrByteData);
// cmd_object_move result = new cmd_object_move();
// int preLenghtData = 0;
// int lenghtDataType = Marshal.SizeOf<int>();
// byte[] arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
// result.id = BitConverter.ToInt32(arrByteData);
// preLenghtData += lenghtDataType;
// lenghtDataType = Marshal.SizeOf<ushort>();
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
// result.use_time = BitConverter.ToUInt16(arrByteData);
// preLenghtData += lenghtDataType;
// lenghtDataType = Marshal.SizeOf<float>();
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
// result.dest_X = BitConverter.ToSingle(arrByteData);
// preLenghtData += lenghtDataType;
// lenghtDataType = Marshal.SizeOf<short>();
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
// result.sSpeed = BitConverter.ToInt16(arrByteData);
// preLenghtData += lenghtDataType;
// lenghtDataType = Marshal.SizeOf<float>();
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
// result.dest_Y = BitConverter.ToSingle(arrByteData);
// preLenghtData += lenghtDataType;
// result.move_mode = bytes[preLenghtData + 1];
// return result;
//}
// preLenghtData += lenghtDataType;
// lenghtDataType = Marshal.SizeOf<float>();
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
// result.dest_Z = BitConverter.ToSingle(arrByteData);
private byte[] GetBytes(byte[] bytes, int length, int index)
// preLenghtData += lenghtDataType;
// lenghtDataType = Marshal.SizeOf<ushort>();
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
// result.use_time = BitConverter.ToUInt16(arrByteData);
// preLenghtData += lenghtDataType;
// lenghtDataType = Marshal.SizeOf<short>();
// arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData);
// result.sSpeed = BitConverter.ToInt16(arrByteData);
// preLenghtData += lenghtDataType;
// result.move_mode = bytes[preLenghtData + 1];
// return result;
//}
private byte[] GetBytes(byte[] bytes, int length, int index)
{
byte[] arrByteData = new byte[length];
for (int i = 0; i < length; i++)
{
byte[] arrByteData = new byte[length];
for (int i = 0; i < length; i++)
{
arrByteData[i] = bytes[i + index];
}
return arrByteData;
arrByteData[i] = bytes[i + index];
}
return arrByteData;
}
public void Initialize()
public void Initialize()
{
}
public bool TransmitMessage(ECMSG msg)
{
int cid = 0;
var host = GameController.Instance.GetHostPlayer();
switch (msg.dwMsg)
{
/*case long value when value == EC_MsgDef.MSG_PM_PLAYEREQUIPDATA:
if (msg.dwParam2 == S2C.EQUIP_DATA)
cid = ((cmd_equip_data)msg.dwParam1).idPlayer;
else // EQUIP_DATA_CHANGED
cid = ((cmd_equip_data_changed)msg.dwParam1).idPlayer;
break;*/
}
public bool TransmitMessage(ECMSG msg)
{
int cid = 0;
var host = GameController.Instance.GetHostPlayer();
case long value when value == EC_MsgDef.MSG_PM_PLAYERBASEINFO:
cid = (int)((playerbaseinfo_re)msg.dwParam1).Player.id;
// Xoá khỏi cache
//g_pGame.GetGameSession().GetC2SCmdCache().RemovePlayerBaseInfo(cid);
break;
switch (msg.dwMsg)
{
/*case long value when value == EC_MsgDef.MSG_PM_PLAYEREQUIPDATA:
if (msg.dwParam2 == S2C.EQUIP_DATA)
cid = ((cmd_equip_data)msg.dwParam1).idPlayer;
else // EQUIP_DATA_CHANGED
cid = ((cmd_equip_data_changed)msg.dwParam1).idPlayer;
break;*/
/*case long value when value == EC_MsgDef.MSG_PM_PLAYERCUSTOM:
cid = ((GetCustomData_Re)msg.dwParam1).cus_roleid;
break;
case long value when value == EC_MsgDef.MSG_PM_PLAYERBASEINFO:
cid = (int)((playerbaseinfo_re)msg.dwParam1).Player.id;
// Xoá khỏi cache
//g_pGame.GetGameSession().GetC2SCmdCache().RemovePlayerBaseInfo(cid);
break;
case long value when value == EC_MsgDef.MSG_PM_PLAYERFLY:
if (msg.dwParam2 == S2C.OBJECT_TAKEOFF)
cid = ((cmd_object_takeoff)msg.dwParam1).object_id;
else
cid = ((cmd_object_landing)msg.dwParam1).object_id;
break;*/
/*case long value when value == EC_MsgDef.MSG_PM_PLAYERCUSTOM:
cid = ((GetCustomData_Re)msg.dwParam1).cus_roleid;
break;
// ⚠️ Các case khác cũng tương tự, chỉ việc lấy ra đúng trường id / caster / user ...
// Do quá dài nên bạn có thể copy dần từng case từ C++ sang.
case long value when value == EC_MsgDef.MSG_PM_PLAYERFLY:
if (msg.dwParam2 == S2C.OBJECT_TAKEOFF)
cid = ((cmd_object_takeoff)msg.dwParam1).object_id;
else
cid = ((cmd_object_landing)msg.dwParam1).object_id;
break;*/
// ⚠️ Các case khác cũng tương tự, chỉ việc lấy ra đúng trường id / caster / user ...
// Do quá dài nên bạn có thể copy dần từng case từ C++ sang.
default:
System.Diagnostics.Debug.Assert(false, "Unknown message");
return false;
}
/* if (cid == 0)
{
System.Diagnostics.Debug.Assert(false, "cid = 0");
default:
System.Diagnostics.Debug.Assert(false, "Unknown message");
return false;
}
if (host != null && cid == host.GetCharacterID())
{
host.ProcessMessage(msg);
}
else
{
var elsePlayer = SeekOutElsePlayer(cid);
if (elsePlayer != null)
elsePlayer.ProcessMessage(msg);
}*/
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);
}
/* if (cid == 0)
{
System.Diagnostics.Debug.Assert(false, "cid = 0");
return false;
}
public CECHostPlayer GetHostPlayer()
{
return GameController.Instance.GetHostPlayer();
}
if (host != null && cid == host.GetCharacterID())
{
host.ProcessMessage(msg);
}
else
{
var elsePlayer = SeekOutElsePlayer(cid);
if (elsePlayer != null)
elsePlayer.ProcessMessage(msg);
}*/
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();
}
}
}
+208 -206
View File
@@ -1,245 +1,247 @@
using CSNetwork.GPDataType;
using CSNetwork.Protocols;
using UnityEngine;
///////////////////////////////////////////////////////////////////////////
//
// Class CECObject
//
///////////////////////////////////////////////////////////////////////////
public class CECObject : MonoBehaviour
namespace BrewMonster.Scripts.Player
{
// Class ID
public static class Class_ID
///////////////////////////////////////////////////////////////////////////
//
// Class CECObject
//
///////////////////////////////////////////////////////////////////////////
public class CECObject : MonoBehaviour
{
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 复制的角色模型
}
// 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;
}
// 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;
}
// 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;
// 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_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;
}
m_bSelectable = true;
}
public virtual void SetUpCECObject()
{
m_dwBornStamp = 0;
m_bBornInSight = false;
//m_bSelectable = false;
m_iCID = (int)Class_ID.OCID_OBJECT;
}
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; }
public void SetSelectable(bool bSelectable) { m_bSelectable = bSelectable; }
// Tick routine
public bool Tick(float dwDeltaTime)
{
if (m_bAdjustOrient)
AdjustOrientation(dwDeltaTime);
// 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;
}
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);
// 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;
// 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 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);
//}
//// 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);
}
//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();
}
// 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 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);
}
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)
{
// 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;
}
// 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 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;
// 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;
}
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 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_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_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
protected bool m_bSelectable; // whether the object can be selected
public A3DVECTOR3 GetGroundNormal(){ return m_vecGroundNormal; }
public bool GetUseGroundNormal(){ return m_bUseGroundNormal; }
public A3DVECTOR3 GetGroundNormal() { return m_vecGroundNormal; }
public bool GetUseGroundNormal() { return m_bUseGroundNormal; }
public void SetUseGroundNormal(bool bFlag)
{
//if (m_bUseGroundNormal == bFlag)
// return;
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;
}
//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)
{
protected void AdjustOrientation(float dwDeltaTime)
{
}
}
}
@@ -1,64 +1,67 @@
using UnityEngine;
public class CECObjectWork
namespace BrewMonster.Scripts
{
// Attributes
protected int m_iWorkID; // Work ID
protected bool m_bFinished; // true, Work is finished
protected uint m_dwMask; // Mask of this work
protected uint m_dwTransMask; // Work transfer masks
protected bool m_bFirstTick;
// Constructor
public CECObjectWork(int iWorkID)
public class CECObjectWork
{
m_iWorkID = iWorkID;
m_bFinished = false;
m_dwMask = 0;
m_dwTransMask = 0;
m_bFinished = true;
}
public virtual bool Tick(float dwDeltaTime)
{
if (m_bFirstTick)
// Attributes
protected int m_iWorkID; // Work ID
protected bool m_bFinished; // true, Work is finished
protected uint m_dwMask; // Mask of this work
protected uint m_dwTransMask; // Work transfer masks
protected bool m_bFirstTick;
// Constructor
public CECObjectWork(int iWorkID)
{
m_bFirstTick = false;
OnFirstTick();
m_iWorkID = iWorkID;
m_bFinished = false;
m_dwMask = 0;
m_dwTransMask = 0;
m_bFinished = true;
}
return true;
public virtual bool Tick(float dwDeltaTime)
{
if (m_bFirstTick)
{
m_bFirstTick = false;
OnFirstTick();
}
return true;
}
// Reset work
public virtual void Reset()
{
m_bFinished = false;
m_bFirstTick = true;
}
// Work is cancel
public virtual void Cancel() { }
// Can work transfer to another work with specified mask
public virtual bool CanTransferTo(uint dwMask)
{
return (m_dwTransMask & dwMask) != 0;
}
// On work shift to
public virtual void OnWorkShift() { }
// Get work ID
public int GetWorkID() => m_iWorkID;
// Is work finished?
public bool IsFinished() => m_bFinished;
// Get work mask
public uint GetWorkMask() => m_dwMask;
// Get work transfer works
public uint GetTransferMask() => m_dwTransMask;
// On first tick
protected virtual void OnFirstTick() { }
}
// Reset work
public virtual void Reset()
{
m_bFinished = false;
m_bFirstTick = true;
}
// Work is cancel
public virtual void Cancel() { }
// Can work transfer to another work with specified mask
public virtual bool CanTransferTo(uint dwMask)
{
return (m_dwTransMask & dwMask) != 0;
}
// On work shift to
public virtual void OnWorkShift() { }
// Get work ID
public int GetWorkID() => m_iWorkID;
// Is work finished?
public bool IsFinished() => m_bFinished;
// Get work mask
public uint GetWorkMask() => m_dwMask;
// Get work transfer works
public uint GetTransferMask() => m_dwTransMask;
// On first tick
protected virtual void OnFirstTick() { }
}
@@ -0,0 +1,6 @@
using UnityEngine;
//public class CECWorld
//{
//}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4f8b18d59a72e044fbcf236fe5b2991c
@@ -0,0 +1,166 @@
using CSNetwork.GPDataType;
using System;
using UnityEngine;
using UnityEngine.UIElements;
namespace BrewMonster.Scripts
{
public class CHalfSpace
{
public static float DistThresh; //空间一顶点到halfspace平面的距离阈值,作为判断是在半空间内部、外部,or 边界上
//该阈值属于整个类而不是某一个对象,因此定义为静态成员
//根据三个顶点构造平面及半空间区域
//Attributes
public const float HS_DEFAULT_DISTTHRESH = 0.000001f; //距离差的阈值,作为判断是在半空间内部or边界上
protected A3DVECTOR3 m_vNormal;
protected float m_d;
public void Set(A3DVECTOR3 v1, A3DVECTOR3 v2)
{
m_vNormal = A3DVECTOR3.CrossProduct(v2 - v1, new A3DVECTOR3(0.0f, 0.0f, 1.0f));
m_vNormal.Normalize();
m_d = A3DVECTOR3.DotProduct(v1, m_vNormal);
}
public void Set(A3DVECTOR3 v1, A3DVECTOR3 v2, A3DVECTOR3 v3)
{
m_vNormal = A3DVECTOR3.CrossProduct(v2 - v1, v3 - v1);
m_vNormal.Normalize();
m_d = A3DVECTOR3.DotProduct(v1, m_vNormal);
}
//直接设置法向
public void SetNormal(A3DVECTOR3 n) { m_vNormal = n; m_vNormal.Normalize(); }
public float GetDist() { return m_d; }
//直接设置距离d
public void SetD(float d) { m_d = d; }
public CHalfSpace(A3DVECTOR3 v1, A3DVECTOR3 v2, A3DVECTOR3 v3)
{
Set(v1, v2, v3);
}
//根据两个顶点构造平行于Z轴的平面及半空间区域
public CHalfSpace(A3DVECTOR3 v1, A3DVECTOR3 v2)
{
Set(v1, v2);
}
public CHalfSpace()
{
}
public CHalfSpace(CHalfSpace hs)
{
m_vNormal = hs.m_vNormal;
m_d = hs.m_d;
}
// 对决定Halfspace的平面进行变换!变换矩阵为mtxTrans
public virtual void Transform(A3DMATRIX4 mtxTrans)
{
//从mtxTrans分解出Scale,Rotate,Translate分量
A3DVECTOR3 vTranslate = mtxTrans.GetRow(3);
float fScale = mtxTrans.GetCol(0).Magnitude();
// 与mtxTrans一样,仍定义为右乘矩阵
A3DMATRIX3 mtx3Rotate = new A3DMATRIX3();
mtx3Rotate.m = new float[3 * 3];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
mtx3Rotate.m[(i * 3) + j] = mtxTrans.m[(i * 4) + j] / fScale;
//对于平面方程N.X=D的变换(s,R,t)如下:
// N'=NR
SetNormal(m_vNormal * mtx3Rotate);
//D'=s*D+N'.t
SetD(fScale * m_d + A3DVECTOR3.DotProduct(m_vNormal, vTranslate));
}
public void Translate(float Delta) { m_d += Delta; } //沿法线方向作一个平移
public void Inverse() { m_d = -m_d; m_vNormal = -m_vNormal; } //翻转半空间的正反方向
//点v到半空间定义平面的距离,此距离带符号!
public float DistV2Plane(A3DVECTOR3 v)
{
float d = A3DVECTOR3.DotProduct(v, m_vNormal);
return (d - m_d);
}
//与线段求交
public int IntersectLineSeg(A3DVECTOR3 v1, A3DVECTOR3 v2, A3DVECTOR3 vIntersection)
{
vIntersection = new A3DVECTOR3(0.0f, 0.0f, 0.0f);
//先处理在平面上的情况
bool v1InPlane = OnPlane(v1);
bool v2InPlane = OnPlane(v2);
if (v1InPlane && v2InPlane) return 3;
if (v1InPlane) return 1;
if (v2InPlane) return 2;
if (Outside(v1) ^ Outside(v2))
{
//两顶点分别在两侧,计算交点
A3DVECTOR3 vd = v2 - v1;
float t = m_d - A3DVECTOR3.DotProduct(m_vNormal, v1);
t /= A3DVECTOR3.DotProduct(m_vNormal, vd);
//assert(t < 1.0f && t > 0.0f);
vIntersection = v1 + t * vd;
return 4;
}
else
return 0;
}
////////////////////////////////////////////////////////////
// 判断一个三维点是否处于半空间内部,或者说处于平面的一侧
// 注意halfspace的OutSide,Inside定义方式
// /\
// /||\
// ||
// || normal (Outside)
//------------------------------------------Plane
// (Inside)
//
public bool Inside(A3DVECTOR3 v)
{
float d = A3DVECTOR3.DotProduct(v, m_vNormal);
bool bInside = (m_d - d > DistThresh);
return (bInside);
}
public bool Outside(A3DVECTOR3 v)
{
float d = A3DVECTOR3.DotProduct(v, m_vNormal);
bool bOutside = (d - m_d > DistThresh);
return (bOutside);
}
public bool OnPlane(A3DVECTOR3 v)
{
float d = A3DVECTOR3.DotProduct(v, m_vNormal);
bool bOnPlane = (Math.Abs(m_d - d) <= DistThresh);
return bOnPlane;
}
//set && get operations
public static void SetDistThresh(float DThresh = HS_DEFAULT_DISTTHRESH) //并设定一个缺省值
{
DistThresh = DThresh;
}
public A3DVECTOR3 GetNormal() { return m_vNormal; }
//点法式
public void SetNV(A3DVECTOR3 n, A3DVECTOR3 v)
{
m_vNormal = n;
m_vNormal.Normalize();
m_d = A3DVECTOR3.DotProduct(m_vNormal, v);
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 495f51cd9612ff441a012f1aea98974d
@@ -1,6 +1,6 @@
using UnityEngine;
namespace PerfectWorld.Scripts.Managers
namespace BrewMonster.Scripts.Managers
{
public class NPCManager : MonoBehaviour
{
@@ -0,0 +1,66 @@
using CSNetwork.GPDataType;
using BrewMonster.Scripts.Player;
namespace BrewMonster.Scripts
{
//////////////////////////////////////////////////////////////////////////
// define a new compact Convex Hull data type which is used in ElementClient!
//////////////////////////////////////////////////////////////////////////
public class BrushTraceInfo
{
//////////////////////////////////////////////////////////////////////////
// In
//////////////////////////////////////////////////////////////////////////
// aabb's info
public A3DVECTOR3 vStart; // Start point
public A3DVECTOR3 vDelta; // Move delta
public A3DVECTOR3 vExtents;
public A3DAABB BoundAABB;
// Dist Epsilon
public float fDistEpsilon; // Dist Epsilon
public bool bIsPoint; //raytrace
//////////////////////////////////////////////////////////////////////////
// Out
//////////////////////////////////////////////////////////////////////////
public bool bStartSolid; // Collide something at start point
public bool bAllSolid; // All in something
public CHalfSpace ClipPlane; // Clip plane
public int iClipPlane; // Clip plane's index
public float fFraction; // Fraction
public uint dwUser1; // User defined data 1
public uint dwUser2; // User defined data 2
public void Init(A3DVECTOR3 start, A3DVECTOR3 delta, A3DVECTOR3 ext, bool bRay = false, float epsilon = 0.03125f)
{
vStart = start;
vDelta = delta;
vExtents = ext;
fDistEpsilon = epsilon;
fFraction = 100.0f;
bIsPoint = bRay;
bStartSolid = false;
bAllSolid = false;
dwUser1 = 0;
dwUser2 = 0;
if (!bIsPoint)
{
BoundAABB.Clear();
BoundAABB.AddVertex(vStart);
BoundAABB.AddVertex(vStart + vExtents);
BoundAABB.AddVertex(vStart - vExtents);
BoundAABB.AddVertex(vStart + vDelta);
BoundAABB.AddVertex(vStart + vDelta + vExtents);
BoundAABB.AddVertex(vStart + vDelta - vExtents);
BoundAABB.CompleteCenterExts();
}
else
{
//@note : it cheats the caller. By Kuiwu[25/8/2005]
//@todo : refine me. By Kuiwu[25/8/2005]
fDistEpsilon = 1E-5f;
}
}
};
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2ac2c48a14ff7e1478eb76c24ead3cc3
+37 -39
View File
@@ -1,51 +1,49 @@
using BrewMonster;
using CSNetwork.GPDataType;
using ModelRenderer.Scripts.GameData;
using CSNetwork.GPDataType;
using System;
using Unity.VisualScripting;
using UnityEngine;
using static CECNPC;
public class CECMonster : CECNPC
namespace BrewMonster.Scripts.Player
{
MONSTER_ESSENCE m_pDBEssence;
public override void SetUpCECNPC(CECNPCMan pNPCMan)
public class CECMonster : CECNPC
{
base.SetUpCECNPC(pNPCMan);
m_iCID = (int)Class_ID.OCID_MONSTER;
m_pDBEssence = default;
}
public override bool Init(int tid, in info_npc info, ReadOnlySpan<byte> packet, int infoOffset)
{
base.Init(tid, info, packet, infoOffset);
BrewMonster.BMLogger.Log("HoangDev: MonsterInit");
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);
m_fTouchRad = m_pDBEssence.size;
m_BasicProps.iLevel = m_pDBEssence.level;
MONSTER_ESSENCE m_pDBEssence;
QueueLoadNPCModel();
/* float fExt = m_fTouchRad * 1.5f;
m_cdr.vExts.Set(fExt, fExt, fExt);
m_pNPCModelPolicy.SetDefaultPickAABBExt(m_cdr.vExts);*/
// If NPC doesn't have specific name, use the name in database
if ((info.state & (int)PlayerNPCState.GP_STATE_NPC_NAME) == 0)
public override void SetUpCECNPC(CECNPCMan pNPCMan)
{
m_strName = m_pDBEssence.name.ToString();
/* if (m_pPateName)
m_pPateName->SetText(m_strName, false);*/
base.SetUpCECNPC(pNPCMan);
m_iCID = (int)Class_ID.OCID_MONSTER;
m_pDBEssence = default;
}
public override bool Init(int tid, in info_npc info, ReadOnlySpan<byte> packet, int infoOffset)
{
base.Init(tid, info, packet, infoOffset);
BrewMonster.BMLogger.Log("HoangDev: MonsterInit");
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);
m_fTouchRad = m_pDBEssence.size;
m_BasicProps.iLevel = m_pDBEssence.level;
if ((m_pDBEssence.combined_switch & (uint)MONSTER_COMBINED_SWITCH. MCS_FORBID_SELECTION) != 0)
SetSelectable(false);
QueueLoadNPCModel();
transform.position = EC_Utility.ToVector3(info.pos);
/* float fExt = m_fTouchRad * 1.5f;
m_cdr.vExts.Set(fExt, fExt, fExt);
m_pNPCModelPolicy.SetDefaultPickAABBExt(m_cdr.vExts);*/
StartWork((int)WorkType.WT_NOTHING, (int)WorkID.WORK_STAND);
return true;
// If NPC doesn't have specific name, use the name in database
if ((info.state & (int)PlayerNPCState.GP_STATE_NPC_NAME) == 0)
{
m_strName = m_pDBEssence.name.ToString();
/* if (m_pPateName)
m_pPateName->SetText(m_strName, false);*/
}
if ((m_pDBEssence.combined_switch & (uint)MONSTER_COMBINED_SWITCH.MCS_FORBID_SELECTION) != 0)
SetSelectable(false);
transform.position = EC_Utility.ToVector3(info.pos);
StartWork((int)WorkType.WT_NOTHING, (int)WorkID.WORK_STAND);
return true;
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,120 +1,124 @@
using CSNetwork.Protocols;
using BrewMonster.Scripts.Player;
using CSNetwork.Protocols;
using UnityEngine;
public class CECNPCModelDefaultPolicy
: CECNPCModelPolicy
namespace BrewMonster.Scripts
{
CECModel m_pNPCModel;
public CECNPCModelDefaultPolicy(CECNPC pNPC)
public class CECNPCModelDefaultPolicy
: CECNPCModelPolicy
{
CECModel m_pNPCModel;
}
public string GetActionName(int iAct, bool bAttackStart = false)
{
// Tạo builder thay cho static char[128]
var sb = new System.Text.StringBuilder();
// Thêm tên base action
sb.Append(CECNPC.GetBaseActionName(iAct));
// Nếu là attack action thì thêm hậu tố
if (CECNPC.IsAttackAction(iAct))
public CECNPCModelDefaultPolicy(CECNPC pNPC)
{
sb.Append(bAttackStart ? "Æð" : "Âä");
}
// Xử lý loại bỏ dấu nháy kép (nếu có)
string result = sb.ToString().Replace("\"", "");
// Trả về kết quả đã clean
return result;
}
public override bool PlayModelAction(int iAction, bool bRestart)
{
/* if (m_pNPCModel == null)
public string GetActionName(int iAct, bool bAttackStart = false)
{
return false;
}
*/
bool result = false;
// Tạo builder thay cho static char[128]
var sb = new System.Text.StringBuilder();
if (iAction == (int)NPCActionIndex.ACT_WOUNDED)
{
string szAct = GetActionName(iAction);
if (!_npcVisual.IsAnimationExist(szAct))
// Thêm tên base action
sb.Append(CECNPC.GetBaseActionName(iAct));
// Nếu là attack action thì thêm hậu tố
if (CECNPC.IsAttackAction(iAct))
{
szAct = GetActionName((int)NPCActionIndex.ACT_WOUNDED2);
sb.Append(bAttackStart ? "Æð" : "Âä");
}
result = _npcVisual.TryPlayAction(szAct);
// Xử lý loại bỏ dấu nháy kép (nếu có)
string result = sb.ToString().Replace("\"", "");
// Trả về kết quả đã clean
return result;
}
else if (iAction == (int)NPCActionIndex.ACT_ATTACK1 || iAction == (int)NPCActionIndex.ACT_ATTACK2)
public override bool PlayModelAction(int iAction, bool bRestart)
{
//bool bHideFX = !CECOptimize::Instance().GetGFX().CanShowAttack(m_pNPC->GetNPCID(), m_pNPC->GetClassID());
result = _npcVisual.TryPlayAction(GetActionName(iAction, true));
if (result)
/* if (m_pNPCModel == null)
{
return false;
}
*/
bool result = false;
if (iAction == (int)NPCActionIndex.ACT_WOUNDED)
{
/* m_pNPCModel->QueueAction(GetActionName(iAction, false), 0, 0, false, false, bHideFX);
m_pNPCModel->QueueAction(GetActionName(CECNPC::ACT_GUARD), 300);*/
string szAct = GetActionName(iAction);
if (!_npcVisual.IsAnimationExist(szAct))
{
szAct = GetActionName((int)NPCActionIndex.ACT_WOUNDED2);
}
result = _npcVisual.TryPlayAction(szAct);
}
}
else if (iAction == (int)NPCActionIndex.ACT_IDLE)
{
result = _npcVisual.TryPlayAction(GetActionName(iAction));
if (result)
else if (iAction == (int)NPCActionIndex.ACT_ATTACK1 || iAction == (int)NPCActionIndex.ACT_ATTACK2)
{
//m_pNPCModel->QueueAction(GetActionName((int)NPCActionIndex.ACT_STAND));
//bool bHideFX = !CECOptimize::Instance().GetGFX().CanShowAttack(m_pNPC->GetNPCID(), m_pNPC->GetClassID());
result = _npcVisual.TryPlayAction(GetActionName(iAction, true));
if (result)
{
/* m_pNPCModel->QueueAction(GetActionName(iAction, false), 0, 0, false, false, bHideFX);
m_pNPCModel->QueueAction(GetActionName(CECNPC::ACT_GUARD), 300);*/
}
}
}
else if (iAction == (int)NPCActionIndex.ACT_NPC_IDLE1 || iAction == (int)NPCActionIndex.ACT_NPC_IDLE2)
{
result = _npcVisual.TryPlayAction(GetActionName(iAction));
if (result)
else if (iAction == (int)NPCActionIndex.ACT_IDLE)
{
//m_pNPCModel->QueueAction(GetActionName((int)NPCActionIndex.ACT_NPC_STAND));
result = _npcVisual.TryPlayAction(GetActionName(iAction));
if (result)
{
//m_pNPCModel->QueueAction(GetActionName((int)NPCActionIndex.ACT_STAND));
}
}
}
else if (iAction == (int)NPCActionIndex.ACT_NPC_ATTACK)
{
//bool bHideFX = !CECOptimize::Instance().GetGFX().CanShowAttack(m_pNPC->GetNPCID(), m_pNPC->GetClassID());
result = _npcVisual.TryPlayAction(GetActionName(iAction)); ;
if (result)
else if (iAction == (int)NPCActionIndex.ACT_NPC_IDLE1 || iAction == (int)NPCActionIndex.ACT_NPC_IDLE2)
{
/*m_pNPCModel->QueueAction(GetActionName(iAction, false), 0, 0, false, false, bHideFX);
m_pNPCModel->QueueAction(GetActionName(CECNPC::ACT_NPC_STAND), 300);*/
result = _npcVisual.TryPlayAction(GetActionName(iAction));
if (result)
{
//m_pNPCModel->QueueAction(GetActionName((int)NPCActionIndex.ACT_NPC_STAND));
}
}
}
else if (iAction == (int)NPCActionIndex.ACT_COMMON_BORN)
{
result = _npcVisual.TryPlayAction(GetActionName(iAction));
if (result)
else if (iAction == (int)NPCActionIndex.ACT_NPC_ATTACK)
{
//m_pNPCModel->QueueAction(GetActionName((int)NPCActionIndex.ACT_STAND));
//bool bHideFX = !CECOptimize::Instance().GetGFX().CanShowAttack(m_pNPC->GetNPCID(), m_pNPC->GetClassID());
result = _npcVisual.TryPlayAction(GetActionName(iAction)); ;
if (result)
{
/*m_pNPCModel->QueueAction(GetActionName(iAction, false), 0, 0, false, false, bHideFX);
m_pNPCModel->QueueAction(GetActionName(CECNPC::ACT_NPC_STAND), 300);*/
}
}
else if (iAction == (int)NPCActionIndex.ACT_COMMON_BORN)
{
result = _npcVisual.TryPlayAction(GetActionName(iAction));
if (result)
{
//m_pNPCModel->QueueAction(GetActionName((int)NPCActionIndex.ACT_STAND));
}
}
else
{
result = _npcVisual.TryPlayAction(GetActionName(iAction));
}
return result;
}
else
public override bool IsPlayingAction()
{
result = _npcVisual.TryPlayAction(GetActionName(iAction));
return _npcVisual.IsPlayAnimation();
}
public override bool IsPlayingAction(int iAction)
{
return _npcVisual.IsPlayAnimation(GetActionName(iAction));
}
public override bool HasAction(int iAction)
{
return _npcVisual.IsAnimationExist(GetActionName(iAction));
}
public override void SetNpcVisual(NPCVisual npcVisual)
{
_npcVisual = npcVisual;
}
return result;
}
public override bool IsPlayingAction()
{
return _npcVisual.IsPlayAnimation();
}
public override bool IsPlayingAction(int iAction)
{
return _npcVisual.IsPlayAnimation(GetActionName(iAction));
}
public override bool HasAction(int iAction)
{
return _npcVisual.IsAnimationExist(GetActionName(iAction));
}
public override void SetNpcVisual(NPCVisual npcVisual)
{
_npcVisual = npcVisual;
}
}
@@ -15,6 +15,8 @@ using System.Numerics;
using CSNetwork.C2SCommand;
using CSNetwork.GPDataType;
using BrewMonster;
using BrewMonster.Managers;
using BrewMonster.Scripts.Player;
namespace CSNetwork
{
@@ -1,12 +1,10 @@
using System;
using UnityEngine;
using CSNetwork;
using PerfectWorld.Scripts.Managers.BrewMonster.Managers;
using BrewMonster.Network;
using UnityEngine.SceneManagement;
using CSNetwork.GPDataType;
using BrewMonster.Scripts.Player;
namespace BrewMonster
namespace BrewMonster.Managers
{
[Serializable]
public class EC_ManMessageMono : MonoBehaviour
@@ -1,4 +1,6 @@
using BrewMonster;
using BrewMonster.Scripts;
using BrewMonster.Scripts.Player;
using CSNetwork;
using CSNetwork.Protocols;
using CSNetwork.Protocols.RPCData;
@@ -1,11 +1,10 @@
using BrewMonster;
using CSNetwork;
using BrewMonster.Managers;
using CSNetwork.GPDataType;
using CSNetwork.Protocols.RPCData;
using System;
using UnityEngine;
namespace PerfectWorld.Scripts.Player
namespace BrewMonster.Scripts.Player
{
public class EC_ElsePlayer : EC_Player
{
+385 -384
View File
@@ -1,442 +1,443 @@
using UnityEngine;
using UnityEngine.UI;
using BrewMonster.Network;
using PerfectWorld.Scripts.Managers.BrewMonster.Managers;
using PerfectWorld.Scripts.Managers;
using CSNetwork.GPDataType;
using BrewMonster.Scripts.Managers;
using System.Collections.Generic;
using BrewMonster;
using TMPro;
using BrewMonster.Managers;
public class pickupItem : MonoBehaviour
namespace BrewMonster.Scripts
{
public InputField mid;
public InputField tid;
public Button send;
// Dictionary to store created cubes with their matter IDs
private Dictionary<int, GameObject> matterCubes = new Dictionary<int, GameObject>();
// Dictionary to track pending pickups by TID
private Dictionary<int, int> pendingPickups = new Dictionary<int, int>(); // TID -> MatterID
// Set to track items that have been picked up by the player (to prevent respawn)
private HashSet<int> pickedUpItems = new HashSet<int>(); // MID of picked up items
// Reference to the matter manager
private EC_ManMatter matterManager;
public class pickupItem : MonoBehaviour
{
public InputField mid;
public InputField tid;
public Button send;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
// Add button click listener
if (send != null)
{
send.onClick.AddListener(OnPickupButtonClicked);
}
// Get reference to matter manager
if (EC_ManMessageMono.Instance != null)
{
matterManager = EC_ManMessageMono.Instance.GetECManMatter;
}
else
{
Debug.LogError("EC_ManMessageMono.Instance is null - matter manager not available");
}
// Subscribe to matter enter world events
SubscribeToMatterEvents();
}
// Dictionary to store created cubes with their matter IDs
private Dictionary<int, GameObject> matterCubes = new Dictionary<int, GameObject>();
// Update is called once per frame
void Update()
{
// Check for mouse clicks on cubes
if (Input.GetMouseButtonDown(0))
// Dictionary to track pending pickups by TID
private Dictionary<int, int> pendingPickups = new Dictionary<int, int>(); // TID -> MatterID
// Set to track items that have been picked up by the player (to prevent respawn)
private HashSet<int> pickedUpItems = new HashSet<int>(); // MID of picked up items
// Reference to the matter manager
private EC_ManMatter matterManager;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
HandleCubeClick();
}
}
private void SubscribeToMatterEvents()
{
// We'll need to hook into the matter manager's events
// For now, we'll check for new matters in Update
}
private void HandleCubeClick()
{
// Find the main camera
Camera mainCamera = Camera.main;
if (mainCamera == null)
{
mainCamera = FindFirstObjectByType<Camera>();
}
if (mainCamera == null)
{
Debug.LogWarning("No camera found for raycast");
return;
}
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
GameObject clickedObject = hit.collider.gameObject;
// Check if the clicked object is one of our matter cubes
foreach (var kvp in matterCubes)
// Add button click listener
if (send != null)
{
if (kvp.Value == clickedObject)
{
int matterId = kvp.Key;
SendPickupCommand(matterId);
break;
}
send.onClick.AddListener(OnPickupButtonClicked);
}
}
}
public void SendPickupCommand(int matterId)
{
if (matterManager != null)
{
var matterData = matterManager.GetMatterData(matterId);
if (matterData.HasValue)
// Get reference to matter manager
if (EC_ManMessageMono.Instance != null)
{
// Track this pickup request
pendingPickups[matterData.Value.tid] = matterId;
UnityGameSession.RequestPickupItem(matterData.Value.mid, matterData.Value.tid);
Debug.Log($"Pickup request sent for matter - MID: {matterData.Value.mid}, TID: {matterData.Value.tid}");
matterManager = EC_ManMessageMono.Instance.GetECManMatter;
}
else
{
Debug.LogWarning($"No matter data found for matter ID: {matterId}");
Debug.LogError("EC_ManMessageMono.Instance is null - matter manager not available");
}
// Subscribe to matter enter world events
SubscribeToMatterEvents();
}
// Update is called once per frame
void Update()
{
// Check for mouse clicks on cubes
if (Input.GetMouseButtonDown(0))
{
HandleCubeClick();
}
}
else
private void SubscribeToMatterEvents()
{
Debug.LogError("Matter manager is null - cannot send pickup command");
// We'll need to hook into the matter manager's events
// For now, we'll check for new matters in Update
}
}
public void CreateMatterCube(int matterId)
{
if (matterManager == null) return;
var matterData = matterManager.GetMatterData(matterId);
if (!matterData.HasValue) return;
// Check if this item was previously picked up by the player
if (pickedUpItems.Contains(matterId))
private void HandleCubeClick()
{
Debug.Log($"Skipping cube creation for matter {matterId} - item was previously picked up by player");
return;
// Find the main camera
Camera mainCamera = Camera.main;
if (mainCamera == null)
{
mainCamera = FindFirstObjectByType<Camera>();
}
if (mainCamera == null)
{
Debug.LogWarning("No camera found for raycast");
return;
}
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
GameObject clickedObject = hit.collider.gameObject;
// Check if the clicked object is one of our matter cubes
foreach (var kvp in matterCubes)
{
if (kvp.Value == clickedObject)
{
int matterId = kvp.Key;
SendPickupCommand(matterId);
break;
}
}
}
}
// Check if cube already exists
if (matterCubes.ContainsKey(matterId))
public void SendPickupCommand(int matterId)
{
Debug.Log($"Cube for matter {matterId} already exists");
return;
if (matterManager != null)
{
var matterData = matterManager.GetMatterData(matterId);
if (matterData.HasValue)
{
// Track this pickup request
pendingPickups[matterData.Value.tid] = matterId;
UnityGameSession.RequestPickupItem(matterData.Value.mid, matterData.Value.tid);
Debug.Log($"Pickup request sent for matter - MID: {matterData.Value.mid}, TID: {matterData.Value.tid}");
}
else
{
Debug.LogWarning($"No matter data found for matter ID: {matterId}");
}
}
else
{
Debug.LogError("Matter manager is null - cannot send pickup command");
}
}
// Create cube GameObject
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.name = $"Matter_{matterData.Value.mid}_TID_{matterData.Value.tid}";
cube.transform.localScale = new Vector3(0.3f, 0.3f, 0.3f);
// Position the cube based on matter position
Vector3 position = new Vector3(
matterData.Value.pos.x,
matterData.Value.pos.y,
matterData.Value.pos.z
);
cube.transform.position = position;
// Add a collider if it doesn't have one
if (cube.GetComponent<Collider>() == null)
public void CreateMatterCube(int matterId)
{
cube.AddComponent<BoxCollider>();
if (matterManager == null) return;
var matterData = matterManager.GetMatterData(matterId);
if (!matterData.HasValue) return;
// Check if this item was previously picked up by the player
if (pickedUpItems.Contains(matterId))
{
Debug.Log($"Skipping cube creation for matter {matterId} - item was previously picked up by player");
return;
}
// Check if cube already exists
if (matterCubes.ContainsKey(matterId))
{
Debug.Log($"Cube for matter {matterId} already exists");
return;
}
// Create cube GameObject
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.name = $"Matter_{matterData.Value.mid}_TID_{matterData.Value.tid}";
cube.transform.localScale = new Vector3(0.3f, 0.3f, 0.3f);
// Position the cube based on matter position
Vector3 position = new Vector3(
matterData.Value.pos.x,
matterData.Value.pos.y,
matterData.Value.pos.z
);
cube.transform.position = position;
// Add a collider if it doesn't have one
if (cube.GetComponent<Collider>() == null)
{
cube.AddComponent<BoxCollider>();
}
// Create text object to display item name above the cube
CreateItemNameText(cube, matterData.Value.tid);
// Add a script to handle click events
MatterCubeClickHandler clickHandler = cube.AddComponent<MatterCubeClickHandler>();
clickHandler.Initialize(matterId, this);
// Store reference to the cube
matterCubes[matterId] = cube;
Debug.Log($"Created cube for matter {matterId} at position {position}");
}
// Create text object to display item name above the cube
CreateItemNameText(cube, matterData.Value.tid);
// Add a script to handle click events
MatterCubeClickHandler clickHandler = cube.AddComponent<MatterCubeClickHandler>();
clickHandler.Initialize(matterId, this);
// Store reference to the cube
matterCubes[matterId] = cube;
Debug.Log($"Created cube for matter {matterId} at position {position}");
}
private void CreateItemNameText(GameObject cube, int tid)
{
// Create a child GameObject for the text
GameObject textObject = new GameObject("ItemNameText");
textObject.transform.SetParent(cube.transform);
// Position the text above the cube
textObject.transform.localPosition = new Vector3(0, 1.2f, 0); // Above the cube
// Add TextMeshPro component
TextMeshPro textMesh = textObject.AddComponent<TextMeshPro>();
// Get the item name
string itemName = EC_IvtrItem.ResolveItemName(tid);
if (string.IsNullOrEmpty(itemName))
{
itemName = $"Item {tid}";
}
// Configure the text
textMesh.text = itemName;
textMesh.fontSize = 10f;
textMesh.color = Color.white;
textMesh.alignment = TextAlignmentOptions.Center;
// Make the text face the camera
textObject.AddComponent<Billboard>();
// Add a background for better visibility
GameObject background = new GameObject("TextBackground");
background.transform.SetParent(textObject.transform);
background.transform.localPosition = Vector3.zero;
background.transform.localScale = new Vector3(2f, 0.8f, 0.1f);
// Add a simple quad renderer for background
MeshRenderer bgRenderer = background.AddComponent<MeshRenderer>();
MeshFilter bgFilter = background.AddComponent<MeshFilter>();
// Create a simple quad mesh for the background
Mesh quadMesh = new Mesh();
quadMesh.vertices = new Vector3[]
private void CreateItemNameText(GameObject cube, int tid)
{
// Create a child GameObject for the text
GameObject textObject = new GameObject("ItemNameText");
textObject.transform.SetParent(cube.transform);
// Position the text above the cube
textObject.transform.localPosition = new Vector3(0, 1.2f, 0); // Above the cube
// Add TextMeshPro component
TextMeshPro textMesh = textObject.AddComponent<TextMeshPro>();
// Get the item name
string itemName = EC_IvtrItem.ResolveItemName(tid);
if (string.IsNullOrEmpty(itemName))
{
itemName = $"Item {tid}";
}
// Configure the text
textMesh.text = itemName;
textMesh.fontSize = 10f;
textMesh.color = Color.white;
textMesh.alignment = TextAlignmentOptions.Center;
// Make the text face the camera
textObject.AddComponent<Billboard>();
// Add a background for better visibility
GameObject background = new GameObject("TextBackground");
background.transform.SetParent(textObject.transform);
background.transform.localPosition = Vector3.zero;
background.transform.localScale = new Vector3(2f, 0.8f, 0.1f);
// Add a simple quad renderer for background
MeshRenderer bgRenderer = background.AddComponent<MeshRenderer>();
MeshFilter bgFilter = background.AddComponent<MeshFilter>();
// Create a simple quad mesh for the background
Mesh quadMesh = new Mesh();
quadMesh.vertices = new Vector3[]
{
new Vector3(-0.5f, -0.5f, 0),
new Vector3(0.5f, -0.5f, 0),
new Vector3(0.5f, 0.5f, 0),
new Vector3(-0.5f, 0.5f, 0)
};
quadMesh.triangles = new int[] { 0, 1, 2, 0, 2, 3 };
quadMesh.uv = new Vector2[]
{
};
quadMesh.triangles = new int[] { 0, 1, 2, 0, 2, 3 };
quadMesh.uv = new Vector2[]
{
new Vector2(0, 0),
new Vector2(1, 0),
new Vector2(1, 1),
new Vector2(0, 1)
};
quadMesh.RecalculateNormals();
bgFilter.mesh = quadMesh;
// Create a simple material for the background
Material bgMaterial = new Material(Shader.Find("Standard"));
bgMaterial.color = new Color(0, 0, 0, 0.7f); // Semi-transparent black
bgRenderer.material = bgMaterial;
Debug.Log($"Created item name text for TID {tid}: {itemName}");
}
public void RemoveMatterCube(int matterId)
{
if (matterCubes.ContainsKey(matterId))
{
GameObject cube = matterCubes[matterId];
if (cube != null)
{
Destroy(cube);
}
matterCubes.Remove(matterId);
Debug.Log($"Removed cube for matter {matterId}");
}
}
public void UpdateMatterCubes()
{
if (matterManager == null) return;
// Get all current matter IDs
int[] allMatterIds = matterManager.GetAllMatterIds();
// Create cubes for new matters (but skip items previously picked up by player)
foreach (int matterId in allMatterIds)
{
if (!matterCubes.ContainsKey(matterId) && !pickedUpItems.Contains(matterId))
{
CreateMatterCube(matterId);
}
}
// Remove cubes for matters that no longer exist
List<int> cubesToRemove = new List<int>();
foreach (var kvp in matterCubes)
{
if (!matterManager.HasMatterData(kvp.Key))
{
cubesToRemove.Add(kvp.Key);
}
}
foreach (int matterId in cubesToRemove)
{
RemoveMatterCube(matterId);
}
}
/// <summary>
/// Called when a pickup is successful. Removes the cube for the picked up item.
/// </summary>
/// <param name="tid">Template ID of the picked up item</param>
public void OnPickupSuccess(int tid)
{
if (pendingPickups.ContainsKey(tid))
{
int matterId = pendingPickups[tid];
// Track this item as picked up by the player
pickedUpItems.Add(matterId);
// Remove the cube
RemoveMatterCube(matterId);
// Remove from pending pickups
pendingPickups.Remove(tid);
Debug.Log($"Successfully picked up item with TID: {tid}, removed cube for matter ID: {matterId}");
}
else
{
Debug.LogWarning($"Received pickup success for TID {tid} but no pending pickup found");
}
}
/// <summary>
/// Called when a pickup fails. Removes the pending pickup tracking.
/// </summary>
/// <param name="tid">Template ID of the failed pickup</param>
public void OnPickupFailed(int tid)
{
if (pendingPickups.ContainsKey(tid))
{
pendingPickups.Remove(tid);
Debug.Log($"Pickup failed for TID: {tid}, removed from pending pickups");
}
}
/// <summary>
/// Clears the tracking of picked up items. Call this when player changes areas or logs out.
/// </summary>
public void ClearPickedUpItemsTracking()
{
pickedUpItems.Clear();
Debug.Log("Cleared picked up items tracking");
}
/// <summary>
/// Gets the count of items that have been picked up by the player.
/// </summary>
/// <returns>Number of items picked up</returns>
public int GetPickedUpItemsCount()
{
return pickedUpItems.Count;
}
};
quadMesh.RecalculateNormals();
private void OnPickupButtonClicked()
{
// Validate input fields
if (mid == null || tid == null)
{
Debug.LogError("PickupItem: Mid or Tid InputField is not assigned!");
return;
bgFilter.mesh = quadMesh;
// Create a simple material for the background
Material bgMaterial = new Material(Shader.Find("Standard"));
bgMaterial.color = new Color(0, 0, 0, 0.7f); // Semi-transparent black
bgRenderer.material = bgMaterial;
Debug.Log($"Created item name text for TID {tid}: {itemName}");
}
// Parse the input values
if (int.TryParse(mid.text, out int midValue) && int.TryParse(tid.text, out int tidValue))
public void RemoveMatterCube(int matterId)
{
// Call the pickup item request
UnityGameSession.RequestPickupItem(midValue, tidValue);
Debug.Log($"Pickup request sent - MID: {midValue}, TID: {tidValue}");
if (matterCubes.ContainsKey(matterId))
{
GameObject cube = matterCubes[matterId];
if (cube != null)
{
Destroy(cube);
}
matterCubes.Remove(matterId);
Debug.Log($"Removed cube for matter {matterId}");
}
}
else
public void UpdateMatterCubes()
{
Debug.LogError("PickupItem: Invalid input values. Please enter valid integers for MID and TID.");
if (matterManager == null) return;
// Get all current matter IDs
int[] allMatterIds = matterManager.GetAllMatterIds();
// Create cubes for new matters (but skip items previously picked up by player)
foreach (int matterId in allMatterIds)
{
if (!matterCubes.ContainsKey(matterId) && !pickedUpItems.Contains(matterId))
{
CreateMatterCube(matterId);
}
}
// Remove cubes for matters that no longer exist
List<int> cubesToRemove = new List<int>();
foreach (var kvp in matterCubes)
{
if (!matterManager.HasMatterData(kvp.Key))
{
cubesToRemove.Add(kvp.Key);
}
}
foreach (int matterId in cubesToRemove)
{
RemoveMatterCube(matterId);
}
}
/// <summary>
/// Called when a pickup is successful. Removes the cube for the picked up item.
/// </summary>
/// <param name="tid">Template ID of the picked up item</param>
public void OnPickupSuccess(int tid)
{
if (pendingPickups.ContainsKey(tid))
{
int matterId = pendingPickups[tid];
// Track this item as picked up by the player
pickedUpItems.Add(matterId);
// Remove the cube
RemoveMatterCube(matterId);
// Remove from pending pickups
pendingPickups.Remove(tid);
Debug.Log($"Successfully picked up item with TID: {tid}, removed cube for matter ID: {matterId}");
}
else
{
Debug.LogWarning($"Received pickup success for TID {tid} but no pending pickup found");
}
}
/// <summary>
/// Called when a pickup fails. Removes the pending pickup tracking.
/// </summary>
/// <param name="tid">Template ID of the failed pickup</param>
public void OnPickupFailed(int tid)
{
if (pendingPickups.ContainsKey(tid))
{
pendingPickups.Remove(tid);
Debug.Log($"Pickup failed for TID: {tid}, removed from pending pickups");
}
}
/// <summary>
/// Clears the tracking of picked up items. Call this when player changes areas or logs out.
/// </summary>
public void ClearPickedUpItemsTracking()
{
pickedUpItems.Clear();
Debug.Log("Cleared picked up items tracking");
}
/// <summary>
/// Gets the count of items that have been picked up by the player.
/// </summary>
/// <returns>Number of items picked up</returns>
public int GetPickedUpItemsCount()
{
return pickedUpItems.Count;
}
private void OnPickupButtonClicked()
{
// Validate input fields
if (mid == null || tid == null)
{
Debug.LogError("PickupItem: Mid or Tid InputField is not assigned!");
return;
}
// Parse the input values
if (int.TryParse(mid.text, out int midValue) && int.TryParse(tid.text, out int tidValue))
{
// Call the pickup item request
UnityGameSession.RequestPickupItem(midValue, tidValue);
Debug.Log($"Pickup request sent - MID: {midValue}, TID: {tidValue}");
}
else
{
Debug.LogError("PickupItem: Invalid input values. Please enter valid integers for MID and TID.");
}
}
private void OnDestroy()
{
// Clean up button listener
if (send != null)
{
send.onClick.RemoveListener(OnPickupButtonClicked);
}
// Clean up all matter cubes
foreach (var kvp in matterCubes)
{
if (kvp.Value != null)
{
Destroy(kvp.Value);
}
}
matterCubes.Clear();
// Clean up pending pickups
pendingPickups.Clear();
// Clean up picked up items tracking
pickedUpItems.Clear();
}
}
private void OnDestroy()
// Helper class to handle click events on matter cubes
public class MatterCubeClickHandler : MonoBehaviour
{
// Clean up button listener
if (send != null)
private int matterId;
private pickupItem pickupItemScript;
public void Initialize(int id, pickupItem script)
{
send.onClick.RemoveListener(OnPickupButtonClicked);
matterId = id;
pickupItemScript = script;
}
// Clean up all matter cubes
foreach (var kvp in matterCubes)
private void OnMouseDown()
{
if (kvp.Value != null)
if (pickupItemScript != null)
{
Destroy(kvp.Value);
pickupItemScript.SendPickupCommand(matterId);
}
}
matterCubes.Clear();
// Clean up pending pickups
pendingPickups.Clear();
// Clean up picked up items tracking
pickedUpItems.Clear();
}
}
// Helper class to handle click events on matter cubes
public class MatterCubeClickHandler : MonoBehaviour
{
private int matterId;
private pickupItem pickupItemScript;
public void Initialize(int id, pickupItem script)
// Simple Billboard component to make text always face the camera
public class Billboard : MonoBehaviour
{
matterId = id;
pickupItemScript = script;
}
private void OnMouseDown()
{
if (pickupItemScript != null)
private Camera mainCamera;
void Start()
{
pickupItemScript.SendPickupCommand(matterId);
}
}
}
// Simple Billboard component to make text always face the camera
public class Billboard : MonoBehaviour
{
private Camera mainCamera;
void Start()
{
mainCamera = Camera.main;
if (mainCamera == null)
{
mainCamera = FindFirstObjectByType<Camera>();
}
}
void Update()
{
if (mainCamera != null)
{
// Make the text face the camera
transform.LookAt(mainCamera.transform);
transform.Rotate(0, 180, 0); // Flip to face the camera properly
mainCamera = Camera.main;
if (mainCamera == null)
{
mainCamera = FindFirstObjectByType<Camera>();
}
}
void Update()
{
if (mainCamera != null)
{
// Make the text face the camera
transform.LookAt(mainCamera.transform);
transform.Rotate(0, 180, 0); // Flip to face the camera properly
}
}
}
}
+16 -4
View File
@@ -1,9 +1,21 @@
using BrewMonster;
using UnityEngine;
public class CECWorld : MonoSingleton<CECWorld>
{
uint m_dwBornStamp = 0;
public uint GetBornStamp() { return m_dwBornStamp++; }
namespace BrewMonster.Scripts.World
{
public class CECWorld : MonoSingleton<CECWorld>
{
protected A3DTerrain2 m_pA3DTerrain; // Terrain object
uint m_dwBornStamp = 0;
public uint GetBornStamp() { return m_dwBornStamp++; }
// Get terrain object
public A3DTerrain2 GetTerrain()
{
return m_pA3DTerrain;
}
}
}
File diff suppressed because it is too large Load Diff
+36 -33
View File
@@ -1,47 +1,50 @@
using BrewMonster.UI;
using CSNetwork.Protocols.RPCData;
using PerfectWorld.Scripts.Managers;
using BrewMonster.Scripts.Managers;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
public class CanvasController : MonoBehaviour
namespace BrewMonster.Managers
{
[SerializeField] private ScreenLogin screenLogin;
[SerializeField] private SelecScreenCharacter screenCharacter;
[SerializeField] private GameObject bgr;
[SerializeField] private GameController gameController;
GameObject screenLoginOb;
GameObject screenCharacterOb;
private SynchronizationContext context;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
public class CanvasController : MonoBehaviour
{
bgr.gameObject.SetActive(true);
screenLogin.gameObject.SetActive(true);
screenCharacter.gameObject.SetActive(false);
context = SynchronizationContext.Current;
}
[SerializeField] private ScreenLogin screenLogin;
[SerializeField] private SelecScreenCharacter screenCharacter;
[SerializeField] private GameObject bgr;
[SerializeField] private GameController gameController;
public void ShowScreenSelectCharacter(List<RoleInfo> roleInfos)
{
context.Post(_ =>
GameObject screenLoginOb;
GameObject screenCharacterOb;
private SynchronizationContext context;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
screenLogin.gameObject.SetActive(false);
screenCharacter.gameObject.SetActive(true);
screenCharacter.InitScreen(roleInfos, OnClickSelectChacter);
}, null);
}
bgr.gameObject.SetActive(true);
screenLogin.gameObject.SetActive(true);
screenCharacter.gameObject.SetActive(false);
context = SynchronizationContext.Current;
}
private void OnClickSelectChacter(RoleInfo roleInfo)
{
}
public void ShowScreenSelectCharacter(List<RoleInfo> roleInfos)
{
context.Post(_ =>
{
screenLogin.gameObject.SetActive(false);
screenCharacter.gameObject.SetActive(true);
screenCharacter.InitScreen(roleInfos, OnClickSelectChacter);
}, null);
}
private void OnDestroy()
{
private void OnClickSelectChacter(RoleInfo roleInfo)
{
}
private void OnDestroy()
{
}
}
}
+103 -102
View File
@@ -1,130 +1,131 @@
using BrewMonster;
using CSNetwork.GPDataType;
using CSNetwork.GPDataType;
using System;
using System.Collections;
using System.Runtime.InteropServices;
using UnityEngine;
using static EC_Player;
using static BrewMonster.Scripts.Player.EC_Player;
public static class EC_Utility
namespace BrewMonster.Scripts
{
public static byte glb_CompressDirH(float x, float z)
public static class EC_Utility
{
const float fInvInter = 256.0f / 360.0f;
if (Math.Abs(x) < 0.00001f)
public static byte glb_CompressDirH(float x, float z)
{
if (z > 0.0f)
return 64;
const float fInvInter = 256.0f / 360.0f;
if (Math.Abs(x) < 0.00001f)
{
if (z > 0.0f)
return 64;
else
return 192;
}
else
return 192;
{
// atan2 trong C# trả về radian, cần đổi sang độ
float fDeg = (float)(Math.Atan2(z, x) * (180.0 / Math.PI));
// đảm bảo góc nằm trong [0, 360)
if (fDeg < 0)
fDeg += 360.0f;
return (byte)(fDeg * fInvInter);
}
}
else
public static float FIX8TOFLOAT(int x) => x / 256.0f;
public static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
// atan2 trong C# trả về radian, cần đổi sang độ
float fDeg = (float)(Math.Atan2(z, x) * (180.0 / Math.PI));
// đảm bảo góc nằm trong [0, 360)
if (fDeg < 0)
fDeg += 360.0f;
return (byte)(fDeg * fInvInter);
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
{
return Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject());
}
finally
{
handle.Free();
}
}
}
public static float FIX8TOFLOAT(int x) => x / 256.0f;
public static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
public static Vector3 glb_DecompressDirH(byte byDir)
{
return Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject());
const float fInter = 360.0f / 256.0f;
float fRad = Mathf.Deg2Rad * (byDir * fInter);
Vector3 v;
v.x = Mathf.Cos(fRad);
v.z = Mathf.Sin(fRad);
v.y = 0.0f;
return v;
}
finally
public static System.Numerics.Vector3 ToNumerics(this UnityEngine.Vector3 v)
{
handle.Free();
return new System.Numerics.Vector3(v.x, v.y, v.z);
}
}
public static Vector3 glb_DecompressDirH(byte byDir)
{
const float fInter = 360.0f / 256.0f;
float fRad = Mathf.Deg2Rad * (byDir * fInter);
Vector3 v;
v.x = Mathf.Cos(fRad);
v.z = Mathf.Sin(fRad);
v.y = 0.0f;
return v;
}
public static System.Numerics.Vector3 ToNumerics(this UnityEngine.Vector3 v)
{
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);
}
public static float MagnitudeH(this Vector3 v)
{
return Mathf.Sqrt(v.x * v.x + v.z * v.z);
}
public static string BuildActionName(PLAYER_ACTION action, int weaponType)
{
string prefix = action.data.ActionPrefix ?? string.Empty;
string suffix = string.Empty;
if (action.data.action_weapon_suffix != null
&& weaponType >= 0
&& weaponType < action.data.action_weapon_suffix.Length)
public static A3DVECTOR3 ToA3DVECTOR3(this UnityEngine.Vector3 v)
{
suffix = action.data.action_weapon_suffix[weaponType].Suffix ?? string.Empty;
return new A3DVECTOR3(v.x, v.y, v.z);
}
public static Vector3 ToVector3(A3DVECTOR3 a3DVECTOR3)
{
return new Vector3(a3DVECTOR3.x, a3DVECTOR3.y, a3DVECTOR3.z);
}
public static float MagnitudeH(this Vector3 v)
{
return Mathf.Sqrt(v.x * v.x + v.z * v.z);
}
public static string BuildActionName(PLAYER_ACTION action, int weaponType)
{
string prefix = action.data.ActionPrefix ?? string.Empty;
string suffix = string.Empty;
if (action.data.action_weapon_suffix != null
&& weaponType >= 0
&& weaponType < action.data.action_weapon_suffix.Length)
{
suffix = action.data.action_weapon_suffix[weaponType].Suffix ?? string.Empty;
}
return $"{prefix}_{suffix}";
}
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();
// 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_Player)
// {
// byMask |= GP_PVPMASK_FORCE;
// if (pConfigs->GetGameSettings().bAtk_NoMafia)
// byMask |= GP_PVPMASK_NOMAFIA;
// if (pConfigs->GetGameSettings().bAtk_NoMafia)
// byMask |= GP_PVPMASK_NOMAFIA;
// if (pConfigs->GetGameSettings().bAtk_NoWhite)
// byMask |= GP_PVPMASK_NOWHITE;
// if (pConfigs->GetGameSettings().bAtk_NoWhite)
// byMask |= GP_PVPMASK_NOWHITE;
// if (pConfigs->GetGameSettings().bAtk_NoAlliance)
// byMask |= GP_PVPMASK_NOALLIANCE;
// if (pConfigs->GetGameSettings().bAtk_NoAlliance)
// byMask |= GP_PVPMASK_NOALLIANCE;
// if (pConfigs->GetGameSettings().bAtk_NoForce)
// byMask |= GP_PVPMASK_NOFORCE;
// }
//}
// if (pConfigs->GetGameSettings().bAtk_NoForce)
// byMask |= GP_PVPMASK_NOFORCE;
// }
//}
return byMask;
}
return byMask;
}
public static T a_ClampFloor<T>(T x, T min) where T : IComparable<T>
{
return (x.CompareTo(min) < 0) ? min : x;
}
public static T a_ClampFloor<T>(T x, T min) where T : IComparable<T>
{
return (x.CompareTo(min) < 0) ? min : x;
}
public static T a_Min<T>(T x, T y) where T : IComparable<T>
{
return (y.CompareTo(x) < 0) ? y : x;
public static T a_Min<T>(T x, T y) where T : IComparable<T>
{
return (y.CompareTo(x) < 0) ? y : x;
}
}
}
+69 -69
View File
@@ -1,89 +1,89 @@
using BrewMonster.Scripts.Player;
using CSNetwork.GPDataType;
using CSNetwork.Protocols.RPCData;
using System.Data;
using Unity.Cinemachine;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UIElements;
public class GameController : MonoBehaviour
namespace BrewMonster.Managers
{
private static GameController instance;
[SerializeField] private CECHostPlayer characterPrefab;
[SerializeField] private CECMonster monsterPrefab;
[SerializeField] private CinemachineCamera cinemachineCamera;
//[SerializeField] private Transform ground;
CECHostPlayer hostPlayer;
public static GameController Instance
public class GameController : MonoBehaviour
{
get
private static GameController instance;
[SerializeField] private CECHostPlayer characterPrefab;
[SerializeField] private CECMonster monsterPrefab;
[SerializeField] private CinemachineCamera cinemachineCamera;
//[SerializeField] private Transform ground;
CECHostPlayer hostPlayer;
public static GameController Instance
{
get
{
if (instance == null)
{
instance = FindAnyObjectByType<GameController>();
}
return instance;
}
}
private void Awake()
{
if (instance == null)
{
instance = FindAnyObjectByType<GameController>();
instance = this;
}
return instance;
}
}
private void Awake()
{
if (instance == null)
{
instance = this;
}
}
public void Log(string s)
{
Debug.LogError(s);
}
public CECHostPlayer GetHostPlayer()
{
if (hostPlayer == null)
public void Log(string s)
{
hostPlayer = FindAnyObjectByType<CECHostPlayer>();
Debug.LogError(s);
}
return hostPlayer;
}
public void InitCharacter(cmd_self_info_1 info)
{
if (characterPrefab == null)
public CECHostPlayer GetHostPlayer()
{
Debug.LogError("null prefab");
return;
if (hostPlayer == null)
{
hostPlayer = FindAnyObjectByType<CECHostPlayer>();
}
return hostPlayer;
}
EC_Player.InitStaticRes();
hostPlayer = Instantiate(characterPrefab, transform);
hostPlayer.InitCharacter(info);
cinemachineCamera.Follow = hostPlayer.transform;
cinemachineCamera.ForceCameraPosition(hostPlayer.transform.position, Quaternion.identity);
//Vector3 pos = new Vector3(info.pos.x, info.pos.y, info.pos.z);
//Vector3 posCam = pos;
//posCam.z -= 10f;
//camera.transform.position = posCam;
//Vector3 posGround = pos;
//posGround.y -= 2f;
//ground.transform.position = posGround;
}
public CECMonster GetMonster()
{
return Instantiate(monsterPrefab, transform);
}
public GameObject InitCharacter(info_player_1 info)
{
if (characterPrefab == null)
public void InitCharacter(cmd_self_info_1 info)
{
Debug.LogError("null prefab");
return null;
if (characterPrefab == null)
{
Debug.LogError("null prefab");
return;
}
EC_Player.InitStaticRes();
hostPlayer = Instantiate(characterPrefab, transform);
hostPlayer.InitCharacter(info);
cinemachineCamera.Follow = hostPlayer.transform;
cinemachineCamera.ForceCameraPosition(hostPlayer.transform.position, Quaternion.identity);
//Vector3 pos = new Vector3(info.pos.x, info.pos.y, info.pos.z);
//Vector3 posCam = pos;
//posCam.z -= 10f;
//camera.transform.position = posCam;
//Vector3 posGround = pos;
//posGround.y -= 2f;
//ground.transform.position = posGround;
}
public CECMonster GetMonster()
{
return Instantiate(monsterPrefab, transform);
}
public GameObject InitCharacter(info_player_1 info)
{
if (characterPrefab == null)
{
Debug.LogError("null prefab");
return null;
}
CECHostPlayer character = Instantiate(characterPrefab, transform);
character.InitCharacter(info);
return character.gameObject;
}
private void OnDestroy()
{
instance = null;
}
CECHostPlayer character = Instantiate(characterPrefab, transform);
character.InitCharacter(info);
return character.gameObject;
}
private void OnDestroy()
{
instance = null;
}
}
+10 -7
View File
@@ -1,15 +1,18 @@
using BrewMonster;
using UnityEngine;
public class InitializePlayer /*: IAutoInitialize*/
namespace BrewMonster.Scripts.Player
{
public void Dispose()
public class InitializePlayer /*: IAutoInitialize*/
{
EC_Player.Dispose();
}
public void Dispose()
{
EC_Player.Dispose();
}
public void Initialize()
{
EC_Player.InitStaticRes();
public void Initialize()
{
EC_Player.InitStaticRes();
}
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
using ModelRenderer.Scripts.GameData;
using PerfectWorld.Scripts.Task;
using BrewMonster.Scripts.Task;
using UnityEngine;
namespace BrewMonster.Network
{
+340 -336
View File
@@ -1,4 +1,5 @@
using BrewMonster.Network;
using BrewMonster.Scripts.Player;
using CSNetwork;
using CSNetwork.C2SCommand;
using CSNetwork.GPDataType;
@@ -10,360 +11,363 @@ using System.Security.Cryptography;
using System.Text;
using UnityEngine;
public class CECHostMove
namespace BrewMonster.Scripts
{
ushort m_wMoveStamp;
float m_fMoveTime;
CECHostPlayer m_pHost;
bool m_bStop;
const float MOVECMD_INTERVAL = .5f;
Vector3 m_vLastSevPos;
STOPMOVE m_DelayedStop;
ulong cmdstopdelayCounter = 500;
ulong cmdmovedelayCounter = 500;
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)
public class CECHostMove
{
m_wMoveStamp = 0;
m_fMoveTime = 0.0f;
m_pHost = pHost;
m_bStop = false;
}
ushort m_wMoveStamp;
float m_fMoveTime;
CECHostPlayer m_pHost;
bool m_bStop;
const float MOVECMD_INTERVAL = .5f;
Vector3 m_vLastSevPos;
STOPMOVE m_DelayedStop;
ulong cmdstopdelayCounter = 500;
ulong cmdmovedelayCounter = 500;
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 void Tick(ulong dwDeltaTime)
{
cmdstopdelayCounter += dwDeltaTime;
cmdmovedelayCounter += dwDeltaTime;
if (cmdstopdelayCounter >= 500 && m_DelayedStop.bValid)
public CECHostMove(CECHostPlayer pHost)
{
var m = m_DelayedStop;
// a_GetTime() . Environment.TickCount (ms)
ulong dwCurrent = (ulong)Mathf.RoundToInt(Time.time * 1000);
// iTime: thời gian tích lũy (ms) + delta từ timestamp đến hiện tại
int iTime = (int)((m.fTime * 1000f)
+ ((dwCurrent > m.dwTimeStamp) ? (dwCurrent - m.dwTimeStamp) : 0));
// tính tốc độ trung bình (giây = iTime * 0.001f)
float fSpeed = l_CalcAverageSpeed(m_vLastSevPos, m.vPos, iTime * 0.001f, m.fSpeed);
int iMoveMode = m.iMoveMode;
// 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
);
// Record this position
m_vLastSevPos = m.vPos;
Reset();
}
m_dwLastTime = Math.Max(m_dwLastTime, 1);
Vector3 vOffset = m_pHost.transform.position - m_vLastPos;
m_fAverSpeedH = EC_Utility.MagnitudeH(vOffset) * 1000.0f / m_dwLastTime;
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");
iMoveMode |= (int)GPMoveMode.GP_MOVE_DEAD;
if (cmdstopdelayCounter == 500)
{
Vector3 vDir = m_pHost.transform.forward;
byte byDir = EC_Utility.glb_CompressDirH(vDir.x, vDir.z);
fSpeed = l_CalcAverageSpeed(m_vLastSevPos, vPos, m_fMoveTime, fSpeed);
int iTime = (int)(m_fMoveTime * 1000);
UnityGameSession.Instance.c2s_SendCmdStopMove(vPos, fSpeed, iMoveMode, byDir, m_wMoveStamp++, iTime);
m_vLastSevPos = vPos;
Reset();
}
else
{
Vector3 vDir = m_pHost.transform.forward;
byte byDir = EC_Utility.glb_CompressDirH(vDir.x, vDir.z);
if (!m_DelayedStop.bValid)
{
m_DelayedStop.dwTimeStamp = (ulong)Mathf.RoundToInt(Time.time * 1000);
m_DelayedStop.fTime = m_fMoveTime;
}
m_DelayedStop.bValid = true;
m_DelayedStop.byDir = byDir;
m_DelayedStop.vPos = vPos;
m_DelayedStop.iMoveMode = iMoveMode;
m_DelayedStop.fSpeed = fSpeed;
}
m_fMoveTime = 0.0f;
}
public void SendMoveCmd(in Vector3 vCurPos, in Vector3 vVel, int iMoveMode, bool bForceSend = false)
{
Vector3 vMoveDir = vVel;
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)
{
if (m_bStop)
{
// m_CmdTimeCnt.Reset();
cmdmovedelayCounter = (ulong)(m_fMoveTime * 1000);
m_wMoveStamp = 0;
m_fMoveTime = 0.0f;
m_pHost = pHost;
m_bStop = false;
}
if (!bForceSend && cmdmovedelayCounter < 500)
return;
int iTime = (int)(m_fMoveTime * 1000);
if (iTime < 200)
public void Tick(ulong dwDeltaTime)
{
if (iTime == 0 || !bForceSend)
cmdstopdelayCounter += dwDeltaTime;
cmdmovedelayCounter += dwDeltaTime;
if (cmdstopdelayCounter >= 500 && m_DelayedStop.bValid)
{
// if time is too little, wait again
cmdmovedelayCounter = (ulong)(iTime);
var m = m_DelayedStop;
// a_GetTime() . Environment.TickCount (ms)
ulong dwCurrent = (ulong)Mathf.RoundToInt(Time.time * 1000);
// iTime: thời gian tích lũy (ms) + delta từ timestamp đến hiện tại
int iTime = (int)((m.fTime * 1000f)
+ ((dwCurrent > m.dwTimeStamp) ? (dwCurrent - m.dwTimeStamp) : 0));
// tính tốc độ trung bình (giây = iTime * 0.001f)
float fSpeed = l_CalcAverageSpeed(m_vLastSevPos, m.vPos, iTime * 0.001f, m.fSpeed);
int iMoveMode = m.iMoveMode;
// 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
);
// Record this position
m_vLastSevPos = m.vPos;
Reset();
}
m_dwLastTime = Math.Max(m_dwLastTime, 1);
Vector3 vOffset = m_pHost.transform.position - m_vLastPos;
m_fAverSpeedH = EC_Utility.MagnitudeH(vOffset) * 1000.0f / m_dwLastTime;
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");
iMoveMode |= (int)GPMoveMode.GP_MOVE_DEAD;
if (cmdstopdelayCounter == 500)
{
Vector3 vDir = m_pHost.transform.forward;
byte byDir = EC_Utility.glb_CompressDirH(vDir.x, vDir.z);
fSpeed = l_CalcAverageSpeed(m_vLastSevPos, vPos, m_fMoveTime, fSpeed);
int iTime = (int)(m_fMoveTime * 1000);
UnityGameSession.Instance.c2s_SendCmdStopMove(vPos, fSpeed, iMoveMode, byDir, m_wMoveStamp++, iTime);
m_vLastSevPos = vPos;
Reset();
}
else
{
Vector3 vDir = m_pHost.transform.forward;
byte byDir = EC_Utility.glb_CompressDirH(vDir.x, vDir.z);
if (!m_DelayedStop.bValid)
{
m_DelayedStop.dwTimeStamp = (ulong)Mathf.RoundToInt(Time.time * 1000);
m_DelayedStop.fTime = m_fMoveTime;
}
m_DelayedStop.bValid = true;
m_DelayedStop.byDir = byDir;
m_DelayedStop.vPos = vPos;
m_DelayedStop.iMoveMode = iMoveMode;
m_DelayedStop.fSpeed = fSpeed;
}
m_fMoveTime = 0.0f;
}
public void SendMoveCmd(in Vector3 vCurPos, in Vector3 vVel, int iMoveMode, bool bForceSend = false)
{
Vector3 vMoveDir = vVel;
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)
{
if (m_bStop)
{
// m_CmdTimeCnt.Reset();
cmdmovedelayCounter = (ulong)(m_fMoveTime * 1000);
m_bStop = false;
}
if (!bForceSend && cmdmovedelayCounter < 500)
return;
}
}
cmdmovedelayCounter = 0;
m_DelayedStop.bValid = false;
int iTime = (int)(m_fMoveTime * 1000);
fSpeed = l_CalcAverageSpeed(m_vLastSevPos, vCurPos, m_fMoveTime, fSpeed);
m_fMoveTime = 0.0f;
iMoveMode |= (int)GPMoveMode.GP_MOVE_DEAD;
UnityGameSession.Instance.c2s_CmdPlayerMove(vCurPos, vCurPos, iTime/* MOVECMD_INTERVAL */, fSpeed, iMoveMode, m_wMoveStamp++);
m_vLastSevPos = vCurPos;
}
float l_CalcAverageSpeed(in Vector3 p1, in Vector3 p2, float fTime, float fDefSpeed)
{
if (Mathf.Approximately(fTime, 0f))
return fDefSpeed;
Vector3 d = p2 - p1;
float fSpeed = d.magnitude / fTime;
if (fTime < 0.05f || fSpeed > 50.0f)
{
// tương đương ASSERT(0) trong C++, ở đây có thể Debug.LogWarning
Debug.LogWarning("CalcAverageSpeed: invalid input, fallback to default speed.");
return fDefSpeed;
}
return fSpeed;
}
private void Reset()
{
cmdstopdelayCounter = 0;
m_bStop = true;
m_DelayedStop.bValid = false;
}
public void GroundMove(float ftime)
{
m_fMoveTime += ftime;
}
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;
};
// 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)
if (iTime < 200)
{
m_iBlockedCnt = 5;
if (iTime == 0 || !bForceSend)
{
// if time is too little, wait again
cmdmovedelayCounter = (ulong)(iTime);
return;
}
}
m_fBlockTime = 0.0f;
m_fBlockMove = 0.0f;
m_vBlockMove.Clear();
cmdmovedelayCounter = 0;
m_DelayedStop.bValid = false;
fSpeed = l_CalcAverageSpeed(m_vLastSevPos, vCurPos, m_fMoveTime, fSpeed);
m_fMoveTime = 0.0f;
iMoveMode |= (int)GPMoveMode.GP_MOVE_DEAD;
UnityGameSession.Instance.c2s_CmdPlayerMove(vCurPos, vCurPos, iTime/* MOVECMD_INTERVAL */, fSpeed, iMoveMode, m_wMoveStamp++);
m_vLastSevPos = vCurPos;
}
m_fMoveTime += fTime;
float l_CalcAverageSpeed(in Vector3 p1, in Vector3 p2, float fTime, float fDefSpeed)
{
if (Mathf.Approximately(fTime, 0f))
return fDefSpeed;
return vNewPos;
Vector3 d = p2 - p1;
float fSpeed = d.magnitude / fTime;
if (fTime < 0.05f || fSpeed > 50.0f)
{
// tương đương ASSERT(0) trong C++, ở đây có thể Debug.LogWarning
Debug.LogWarning("CalcAverageSpeed: invalid input, fallback to default speed.");
return fDefSpeed;
}
return fSpeed;
}
private void Reset()
{
cmdstopdelayCounter = 0;
m_bStop = true;
m_DelayedStop.bValid = false;
}
public void GroundMove(float ftime)
{
m_fMoveTime += ftime;
}
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;
};
// 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
{
//the aabb
public Vector3 vCenter;
//@note : the caller should make sure ext(.x, .y, .z) > 0. By Kuiwu[22/9/2005]
public Vector3 vExtent;
public int MoveBlocked() { return m_iBlockedCnt; }
public void SetSlideLock(bool bLock) { m_bSlideLock = bLock; }
// Is stoping ?
public bool IsStop() { return m_bStop; }
public float fStepHeight;
// Velocity Info
public Vector3 vXOZVelDir;
public float fYVel;
public float fSpeed;
// time span ( sec )
public float t;
// Gravity acceleration
public float fGravityAccel;
// the Climb Slope Thresh
public float fSlopeThresh;
// Tangent plane Info
public Vector3 vTPNormal;
// Absolute Velocity: output for forcast!
public Vector3 vAbsVelocity;
//the moving dist
public float fMoveDist;
};
}
public struct CDR_INFO
{
//the aabb
public Vector3 vCenter;
//@note : the caller should make sure ext(.x, .y, .z) > 0. By Kuiwu[22/9/2005]
public Vector3 vExtent;
public float fStepHeight;
// Velocity Info
public Vector3 vXOZVelDir;
public float fYVel;
public float fSpeed;
// time span ( sec )
public float t;
// Gravity acceleration
public float fGravityAccel;
// the Climb Slope Thresh
public float fSlopeThresh;
// Tangent plane Info
public Vector3 vTPNormal;
// Absolute Velocity: output for forcast!
public Vector3 vAbsVelocity;
//the moving dist
public float fMoveDist;
};
+398 -209
View File
@@ -1,251 +1,440 @@
using CSNetwork.GPDataType;
using System;
using TMPro;
using Unity.VisualScripting;
using UnityEditor.PackageManager;
using UnityEngine;
public static class EC_CDR
namespace BrewMonster.Scripts
{
// Cho phép CECHostMove gán mask theo scene (giữ linh hoạt nhưng không phá cấu trúc)
public static LayerMask BrushMask { get; set; } = ~0;
public static LayerMask TerrainMask { get; set; } = ~0;
static LayerMask UsedMask_Ground() => BrushMask | TerrainMask;
// == Thay CollideWithEnv (C++) bằng BoxCast ==
static bool CollideWithEnv_BoxCast(Vector3 vStart, Vector3 vDelta, Vector3 vExt,
LayerMask mask,
out RaycastHit hit, out float fFraction, out Vector3 vHitNormal, out bool bStartSolid,
float skin = 0.01f)
public static class EC_CDR
{
hit = default;
vHitNormal = Vector3.up;
bStartSolid = false;
fFraction = 1.0f;
// Cho phép CECHostMove gán mask theo scene (giữ linh hoạt nhưng không phá cấu trúc)
public static LayerMask BrushMask { get; set; } = ~0;
public static LayerMask TerrainMask { get; set; } = ~0;
float dist = vDelta.magnitude;
if (dist <= 1e-6f) return false;
// start-in-solid
var overlapped = Physics.OverlapBox(vStart, vExt - Vector3.one * skin, Quaternion.identity, mask, QueryTriggerInteraction.Ignore);
if (overlapped != null && overlapped.Length > 0)
//[Flags]
public class CDR_EVN
{
bStartSolid = true;
return true;
public const int CDR_BRUSH = 0x1,
CDR_TERRAIN = 0x2,
CDR_WATER = 0x4;
}
// sweep AABB
Vector3 dir = vDelta / Mathf.Max(dist, 1e-6f);
if (Physics.BoxCast(vStart, vExt - Vector3.one * skin, dir, out hit, Quaternion.identity, dist, mask, QueryTriggerInteraction.Ignore))
static LayerMask UsedMask_Ground() => BrushMask | TerrainMask;
static bool CollideWithEnv(env_trace_t pEnvTrc)
{
fFraction = Mathf.Clamp01(hit.distance / Mathf.Max(dist, 1e-6f));
vHitNormal = hit.normal;
return true;
}
return false;
}
// == Thay RetrieveSupportPlane (C++) bằng Raycast xuống ==
static bool DoGroundProbe(Vector3 vStart, Vector3 vExt, float fDeltaY, LayerMask mask,
out Vector3 vEnd, out Vector3 vHitNormal, out bool bSupport,
float skin = 0.01f)
{
vEnd = vStart;
vHitNormal = Vector3.up;
bSupport = false;
float dist = Mathf.Max(fDeltaY, 0f) + vExt.y + skin + 0.05f;
Vector3 origin = vStart + Vector3.up * 0.05f;
if (Physics.Raycast(origin, Vector3.down, out RaycastHit hit, dist, mask, QueryTriggerInteraction.Ignore))
{
vHitNormal = hit.normal;
vEnd = new Vector3(vStart.x, hit.point.y + vExt.y + skin, vStart.z);
bSupport = (vHitNormal.y >= 0f);
return true;
}
return true; // không thấy ground → bSupport=false
}
// ======= STATIC OnGroundMove GIỮ NGUYÊN VAI TRÒ TOÀN CỤC (C API) =======
public static void OnGroundMove(ref CDR_INFO CDRInfo)
{
const float VEL_EPSILON = 1e-4f;
const float DIST_EPSILON = 1e-4f;
const float NORMAL_EPSILON = 1e-2f;
const float VEL_MAX_SPEED = 200f;
const float VEL_REFLECT = 0.3f;
CDRInfo.fMoveDist = 0.0f;
bool bFreeFall = (CDRInfo.vTPNormal.y < CDRInfo.fSlopeThresh);
if (Mathf.Abs(CDRInfo.fYVel) < VEL_EPSILON && Mathf.Abs(CDRInfo.fSpeed) < VEL_EPSILON && !bFreeFall)
return;
float fYVel = CDRInfo.fYVel;
bool bJump = (fYVel > 0.5f);
Vector3 vVelocity = CDRInfo.fSpeed * new Vector3(CDRInfo.vXOZVelDir.x, 0f, CDRInfo.vXOZVelDir.z) + fYVel * Vector3.up;
if (bFreeFall)
{
vVelocity += -CDRInfo.fGravityAccel * CDRInfo.t * Vector3.up;
fYVel += -CDRInfo.fGravityAccel * CDRInfo.t;
}
Vector3 vVelDir = vVelocity;
float fVelSpeed = vVelDir.magnitude;
if (fVelSpeed > 1e-6f) vVelDir /= fVelSpeed; else vVelDir = Vector3.zero;
if (!bFreeFall) fVelSpeed = Mathf.Min(fVelSpeed, VEL_MAX_SPEED);
vVelocity = vVelDir * fVelSpeed;
float dtp = Vector3.Dot(vVelDir, CDRInfo.vTPNormal);
if (dtp < 0f || !bJump)
{
vVelocity = (vVelDir - CDRInfo.vTPNormal * dtp - CDRInfo.vTPNormal * dtp * 0.01f) * fVelSpeed;
}
CDRInfo.vAbsVelocity = vVelocity;
Vector3 vStart = CDRInfo.vCenter;
Vector3 vExt = CDRInfo.vExtent;
float fTime = CDRInfo.t;
Vector3 vDelta, vNormal = Vector3.up, vFinalPos = vStart;
bool bPull = false;
bool bTryPull = false;
int nTry = 0;
LayerMask mask = UsedMask_Ground();
while (nTry < 4)
{
vDelta = vVelocity * fTime;
float fDeltaDist = vDelta.magnitude;
if (fDeltaDist < DIST_EPSILON) break;
bool hasHit = CollideWithEnv_BoxCast(vStart, vDelta, vExt, mask,
out RaycastHit hit, out float fFraction, out Vector3 hitNormal, out bool bStartSolid);
nTry++;
if (bStartSolid)
pEnvTrc.fFraction = 100.0f;
pEnvTrc.bStartSolid = false;
pEnvTrc.dwClsFlag = 0;
if ((pEnvTrc.dwCheckFlag & CDR_EVN.CDR_BRUSH) == CDR_EVN.CDR_BRUSH)
{
CDRInfo.fMoveDist = 0f;
if (CDRInfo.vTPNormal.y < CDRInfo.fSlopeThresh) CDRInfo.vTPNormal = Vector3.up;
BrushTraceInfo bruInfo = new BrushTraceInfo();
bruInfo.Init(pEnvTrc.vStart, pEnvTrc.vDelta, pEnvTrc.vExt);
if (AABBCollideWithBrush(ref bruInfo))
{
pEnvTrc.fFraction = bruInfo.fFraction;
pEnvTrc.vHitNormal = bruInfo.ClipPlane.GetNormal();
pEnvTrc.bStartSolid = bruInfo.bStartSolid;
pEnvTrc.dwClsFlag = CDR_EVN.CDR_BRUSH;
}
}
if ((pEnvTrc.dwCheckFlag & CDR_EVN.CDR_TERRAIN) == CDR_EVN.CDR_TERRAIN)
{
float fFraction = 0f;
A3DVECTOR3 vTerNormal = new A3DVECTOR3();
bool bStart = false;
if (CollideWithTerrain(pEnvTrc.vTerStart, pEnvTrc.vDelta, ref fFraction, ref vTerNormal, ref bStart)
&& (fFraction < pEnvTrc.fFraction))
{
//assert(fFraction >= 0.0f);
//pEnvTrc.fFraction = a_Max(0.0f, fFraction - 1E-4f);
pEnvTrc.fFraction = fFraction;
pEnvTrc.vHitNormal = vTerNormal;
pEnvTrc.bStartSolid = bStart;
pEnvTrc.dwClsFlag = CDR_EVN.CDR_TERRAIN;
}
}
if ((pEnvTrc.dwCheckFlag & CDR_EVN.CDR_WATER) == CDR_EVN.CDR_WATER)
{
float fFraction = 0f;
A3DVECTOR3 vWatNormal = new A3DVECTOR3();
bool bStart = false;
//@todo : TBD: use center or foot? By Kuiwu[10/10/2005]
if (CollideWithWater(pEnvTrc.vWatStart, pEnvTrc.vDelta, pEnvTrc.bWaterSolid, ref fFraction, ref vWatNormal, ref bStart)
&& fFraction < pEnvTrc.fFraction)
{
pEnvTrc.fFraction = fFraction;
pEnvTrc.vHitNormal = vWatNormal;
pEnvTrc.bStartSolid = bStart;
pEnvTrc.dwClsFlag = CDR_EVN.CDR_WATER;
//# ifdef CDR_DEBUG
// A3DVECTOR3 vHitPos(pEnvTrc.vWatStart +pEnvTrc.vDelta * fFraction);
// sprintf(msg, "collide water, fraction %f pos %f %f %f \n", fFraction, vHitPos.x, vHitPos.y, vHitPos.z);
// OUTPUT_DEBUG_INFO(msg);
//#endif
}
}
return (pEnvTrc.fFraction < 1.0f + 1E-4f);
}
// == Thay CollideWithEnv (C++) bằng BoxCast ==
static bool CollideWithEnv_BoxCast(Vector3 vStart, Vector3 vDelta, Vector3 vExt,
LayerMask mask,
out RaycastHit hit, out float fFraction, out Vector3 vHitNormal, out bool bStartSolid,
float skin = 0.01f)
{
hit = default;
vHitNormal = Vector3.up;
bStartSolid = false;
fFraction = 1.0f;
float dist = vDelta.magnitude;
if (dist <= 1e-6f) return false;
// start-in-solid
var overlapped = Physics.OverlapBox(vStart, vExt - Vector3.one * skin, Quaternion.identity, mask, QueryTriggerInteraction.Ignore);
if (overlapped != null && overlapped.Length > 0)
{
bStartSolid = true;
return true;
}
// sweep AABB
Vector3 dir = vDelta / Mathf.Max(dist, 1e-6f);
if (Physics.BoxCast(vStart, vExt - Vector3.one * skin, dir, out hit, Quaternion.identity, dist, mask, QueryTriggerInteraction.Ignore))
{
fFraction = Mathf.Clamp01(hit.distance / Mathf.Max(dist, 1e-6f));
vHitNormal = hit.normal;
return true;
}
return false;
}
// == Thay RetrieveSupportPlane (C++) bằng Raycast xuống ==
static bool DoGroundProbe(Vector3 vStart, Vector3 vExt, float fDeltaY, LayerMask mask,
out Vector3 vEnd, out Vector3 vHitNormal, out bool bSupport,
float skin = 0.01f)
{
vEnd = vStart;
vHitNormal = Vector3.up;
bSupport = false;
float dist = Mathf.Max(fDeltaY, 0f) + vExt.y + skin + 0.05f;
Vector3 origin = vStart + Vector3.up * 0.05f;
if (Physics.Raycast(origin, Vector3.down, out RaycastHit hit, dist, mask, QueryTriggerInteraction.Ignore))
{
vHitNormal = hit.normal;
vEnd = new Vector3(vStart.x, hit.point.y + vExt.y + skin, vStart.z);
bSupport = (vHitNormal.y >= 0f);
return true;
}
return true; // không thấy ground → bSupport=false
}
// ======= STATIC OnGroundMove GIỮ NGUYÊN VAI TRÒ TOÀN CỤC (C API) =======
public static void OnGroundMove(ref CDR_INFO CDRInfo)
{
const float VEL_EPSILON = 1e-4f;
const float DIST_EPSILON = 1e-4f;
const float NORMAL_EPSILON = 1e-2f;
const float VEL_MAX_SPEED = 200f;
const float VEL_REFLECT = 0.3f;
CDRInfo.fMoveDist = 0.0f;
bool bFreeFall = (CDRInfo.vTPNormal.y < CDRInfo.fSlopeThresh);
if (Mathf.Abs(CDRInfo.fYVel) < VEL_EPSILON && Mathf.Abs(CDRInfo.fSpeed) < VEL_EPSILON && !bFreeFall)
return;
float fYVel = CDRInfo.fYVel;
bool bJump = (fYVel > 0.5f);
Vector3 vVelocity = CDRInfo.fSpeed * new Vector3(CDRInfo.vXOZVelDir.x, 0f, CDRInfo.vXOZVelDir.z) + fYVel * Vector3.up;
if (bFreeFall)
{
vVelocity += -CDRInfo.fGravityAccel * CDRInfo.t * Vector3.up;
fYVel += -CDRInfo.fGravityAccel * CDRInfo.t;
}
if (!hasHit)
Vector3 vVelDir = vVelocity;
float fVelSpeed = vVelDir.magnitude;
if (fVelSpeed > 1e-6f) vVelDir /= fVelSpeed; else vVelDir = Vector3.zero;
if (!bFreeFall) fVelSpeed = Mathf.Min(fVelSpeed, VEL_MAX_SPEED);
vVelocity = vVelDir * fVelSpeed;
float dtp = Vector3.Dot(vVelDir, CDRInfo.vTPNormal);
if (dtp < 0f || !bJump)
{
vFinalPos = vStart + vDelta;
CDRInfo.fMoveDist += fDeltaDist;
break;
vVelocity = (vVelDir - CDRInfo.vTPNormal * dtp - CDRInfo.vTPNormal * dtp * 0.01f) * fVelSpeed;
}
vStart += vDelta * fFraction;
CDRInfo.fMoveDist += (fDeltaDist * fFraction);
fTime -= fTime * fFraction;
vNormal = hitNormal;
CDRInfo.vAbsVelocity = vVelocity;
// Step-up (giữ tinh thần bản gốc)
if (!bFreeFall && !bTryPull && !bJump)
Vector3 vStart = CDRInfo.vCenter;
Vector3 vExt = CDRInfo.vExtent;
float fTime = CDRInfo.t;
Vector3 vDelta, vNormal = Vector3.up, vFinalPos = vStart;
bool bPull = false;
bool bTryPull = false;
int nTry = 0;
LayerMask mask = UsedMask_Ground();
while (nTry < 4)
{
float skin = 0.01f;
Vector3 vStartUp = vStart + new Vector3(0f, CDRInfo.fStepHeight, 0f);
bool upBlocked = Physics.CheckBox(vStartUp, vExt - Vector3.one * skin, Quaternion.identity, mask, QueryTriggerInteraction.Ignore);
if (!upBlocked)
vDelta = vVelocity * fTime;
float fDeltaDist = vDelta.magnitude;
if (fDeltaDist < DIST_EPSILON) break;
// TO DO: fix later beacuse logic in CollideWithEnv_BoxCast is wrong
//bool hasHit = CollideWithEnv_BoxCast(vStart, vDelta, vExt, mask,
// out RaycastHit hit, out float fFraction, out Vector3 hitNormal, out bool bStartSolid);
bool hasHit = false, bStartSolid = false;
float fFraction = 0f;
Vector3 hitNormal = Vector3.zero;
nTry++;
if (bStartSolid)
{
Vector3 vDelta2 = vVelocity;
bool hasHit2 = CollideWithEnv_BoxCast(vStartUp, vDelta2, vExt, mask,
out RaycastHit hit2, out float frac2, out Vector3 hitNormal2, out bool bStartSolid2);
if (hasHit2) vDelta2 *= frac2;
CDRInfo.fMoveDist = 0f;
if (CDRInfo.vTPNormal.y < CDRInfo.fSlopeThresh) CDRInfo.vTPNormal = Vector3.up;
return;
}
if (vDelta2.sqrMagnitude >= (vExt.x * vExt.x * 4f))
if (!hasHit)
{
vFinalPos = vStart + vDelta;
CDRInfo.fMoveDist += fDeltaDist;
break;
}
vStart += vDelta * fFraction;
CDRInfo.fMoveDist += (fDeltaDist * fFraction);
fTime -= fTime * fFraction;
vNormal = hitNormal;
// Step-up (giữ tinh thần bản gốc)
if (!bFreeFall && !bTryPull && !bJump)
{
float skin = 0.01f;
Vector3 vStartUp = vStart + new Vector3(0f, CDRInfo.fStepHeight, 0f);
bool upBlocked = Physics.CheckBox(vStartUp, vExt - Vector3.one * skin, Quaternion.identity, mask, QueryTriggerInteraction.Ignore);
if (!upBlocked)
{
vStart = vStartUp;
vDelta = vDelta2;
Vector3 vDelta2 = vVelocity;
bool hasHit2 = CollideWithEnv_BoxCast(vStartUp, vDelta2, vExt, mask,
out RaycastHit hit2, out float frac2, out Vector3 hitNormal2, out bool bStartSolid2);
if (hasHit2) vDelta2 *= frac2;
float distAll = vVelocity.magnitude;
float distMoved = vDelta.magnitude;
if (distAll > 1e-6f) fTime *= Mathf.Clamp01(distMoved / Mathf.Max(distAll, 1e-6f));
if (vDelta2.sqrMagnitude >= (vExt.x * vExt.x * 4f))
{
vStart = vStartUp;
vDelta = vDelta2;
bPull = true;
float distAll = vVelocity.magnitude;
float distMoved = vDelta.magnitude;
if (distAll > 1e-6f) fTime *= Mathf.Clamp01(distMoved / Mathf.Max(distAll, 1e-6f));
bPull = true;
}
}
bTryPull = true;
}
if (!bPull)
{
if (vVelocity.sqrMagnitude > 1e-12f)
{
vVelDir = vVelocity.normalized;
fVelSpeed = vVelocity.magnitude * (1f - nTry * 0.1f);
dtp = Vector3.Dot(vNormal, vVelDir);
float fRelSpeed = Mathf.Min(fVelSpeed, 5.0f);
if (dtp >= 0f && dtp < 1e-4f)
{
vVelocity += vNormal * VEL_REFLECT * fRelSpeed;
}
else
{
vVelocity = (vVelDir - vNormal * dtp) * fVelSpeed - vNormal * dtp * VEL_REFLECT * fRelSpeed;
}
}
if (fYVel > VEL_EPSILON)
{
if (vNormal.y >= CDRInfo.fSlopeThresh || vNormal.y < -NORMAL_EPSILON) fYVel = 0f;
}
else if (fYVel < -VEL_EPSILON)
{
if (vNormal.y >= CDRInfo.fSlopeThresh) fYVel = 0f;
}
}
bTryPull = true;
}
if (!bPull)
// “vertical ground trace” thay RetrieveSupportPlane
Vector3 vTPNormal = Vector3.zero;
Vector3 vFinal = vFinalPos;
float downDist = 0.3f;
if (bPull) downDist = CDRInfo.fStepHeight + 0.1f;
if (bJump) downDist = 0.0f;
if (downDist > 0f)
{
if (vVelocity.sqrMagnitude > 1e-12f)
if (!DoGroundProbe(vFinalPos, vExt, downDist, mask, out Vector3 vEnd, out Vector3 groundNormal, out bool bSupport))
{
vVelDir = vVelocity.normalized;
fVelSpeed = vVelocity.magnitude * (1f - nTry * 0.1f);
dtp = Vector3.Dot(vNormal, vVelDir);
float fRelSpeed = Mathf.Min(fVelSpeed, 5.0f);
if (dtp >= 0f && dtp < 1e-4f)
{
vVelocity += vNormal * VEL_REFLECT * fRelSpeed;
}
else
{
vVelocity = (vVelDir - vNormal * dtp) * fVelSpeed - vNormal * dtp * VEL_REFLECT * fRelSpeed;
}
CDRInfo.fMoveDist = 0f;
CDRInfo.vTPNormal = Vector3.up;
return;
}
if (fYVel > VEL_EPSILON)
if (bSupport)
{
if (vNormal.y >= CDRInfo.fSlopeThresh || vNormal.y < -NORMAL_EPSILON) fYVel = 0f;
}
else if (fYVel < -VEL_EPSILON)
{
if (vNormal.y >= CDRInfo.fSlopeThresh) fYVel = 0f;
vFinal = vEnd;
if (!bJump) vTPNormal = groundNormal;
}
}
if ((vTPNormal.y >= CDRInfo.fSlopeThresh && fYVel < 0.0f) || (!bJump && fYVel > 0.0f))
fYVel = 0.0f;
CDRInfo.vCenter = vFinal;
CDRInfo.fYVel = fYVel;
if (vTPNormal != Vector3.zero) CDRInfo.vTPNormal = vTPNormal;
}
// “vertical ground trace” thay RetrieveSupportPlane
Vector3 vTPNormal = Vector3.zero;
Vector3 vFinal = vFinalPos;
bool CollideWithTerrain(A3DVECTOR3 vStart, A3DVECTOR3 vDelta, ref float fFraction, ref A3DVECTOR3 vHitNormal, ref bool bStart)
{
float downDist = 0.3f;
if (bPull) downDist = CDRInfo.fStepHeight + 0.1f;
if (bJump) downDist = 0.0f;
CECWorld pWorld = g_pGame.GetGameRun().GetWorld();
A3DTerrain2 pTerrain = pWorld.GetTerrain();
bStart = false;
float h1 = pTerrain.GetPosHeight(vStart, &vHitNormal);
if (h1 > vStart.y + 1E-4f )
{//start under terrain
bStart = true;
fFraction = 0.0f;
return true;
}
if (downDist > 0f)
{
if (!DoGroundProbe(vFinalPos, vExt, downDist, mask, out Vector3 vEnd, out Vector3 groundNormal, out bool bSupport))
{
CDRInfo.fMoveDist = 0f;
CDRInfo.vTPNormal = Vector3.up;
return;
}
if (bSupport)
{
vFinal = vEnd;
if (!bJump) vTPNormal = groundNormal;
}
}
int nWid, nHei; // in grid, 2 meters
float fMag = vDelta.Magnitude();
if ((vTPNormal.y >= CDRInfo.fSlopeThresh && fYVel < 0.0f) || (!bJump && fYVel > 0.0f))
fYVel = 0.0f;
nWid = (int) ceil(fMag / 2.0f);
nWid = a_Max(3, nWid);
nHei = nWid;
int nTriangles = nWid * nHei * 2;
A3DVECTOR3* pVerts = (A3DVECTOR3*)a_malloctemp(sizeof(A3DVECTOR3) * ((nWid + 1) * (nHei + 1)));
assert(pVerts != NULL);
memset(pVerts, 0, sizeof(A3DVECTOR3)* (nWid + 1) * (nHei + 1));
WORD* pIndices = (WORD*)a_malloctemp(sizeof(WORD) * (nTriangles * 3));
assert(pIndices != NULL);
memset(pIndices, 0, sizeof(WORD)* nTriangles * 3);
if (!pTerrain.GetFacesOfArea(vStart, nWid, nHei, pVerts, pIndices))
{
a_freetemp(pVerts);
a_freetemp(pIndices);
return false;
}
int i;
A3DVECTOR3* vert[3];
//@note : Here init the fraction. By Kuiwu[9/10/2005]
fFraction = 100.0f;
float tmpFraction = fFraction;
CDRInfo.vCenter = vFinal;
CDRInfo.fYVel = fYVel;
if (vTPNormal != Vector3.zero) CDRInfo.vTPNormal = vTPNormal;
}
for (i = 0; i < nTriangles; i++)
{
vert[0] = pVerts + pIndices[i * 3];
vert[1] = pVerts + pIndices[i * 3 + 1];
vert[2] = pVerts + pIndices[i * 3 + 2];
A3DVECTOR3 vPt;
//@note: Tomas Moller's JGT code : By Kuiwu[9/10/2005]
//@note: discard the engine version because it put back the hit point too much. By Kuiwu[13/10/2005]
// if(CLS_RayToTriangle(vStart, vDelta, *vert[0], *vert[1], *vert[2], vPt, true, &tmpFraction)
// && (tmpFraction <= 1.0f) && (tmpFraction < fFraction))
if (SegmentTriangleIntersect(vStart, vDelta, vert, tmpFraction, true) && (tmpFraction < fFraction))
{
//get the triangle normal
A3DVECTOR3 vEdge1((* vert[1]) -(*vert[0]) );
A3DVECTOR3 vEdge2((* vert[2]) -(*vert[0]) );
vHitNormal = CrossProduct(vEdge1, vEdge2);
vHitNormal.Normalize();
//@note : may be redundant, but to assure. By Kuiwu[17/10/2005]
A3DVECTOR3 vDir;
Normalize(vDelta, vDir);
if (DotProduct(vHitNormal, vDir) > 0.01f)
{//leave the hit plane
assert(0 && "hit a plane with same direction!");
continue;
}
fFraction = a_Max(0.0f, tmpFraction);
}
}
a_freetemp(pVerts);
a_freetemp(pIndices);
# ifdef CDR_DEBUG
// if (fFraction <= 1.0f)
// {
// A3DVECTOR3 vHitPos(vStart + vDelta * fFraction);
// A3DVECTOR3 vTerNormal;
// float fH2 = pTerrain.GetPosHeight(vHitPos, &vTerNormal);
// sprintf(msg, "terrain hit %f %f %f normal %f %f %f trcNormal %f %f %f fFraction %f\n", vHitPos.x, vHitPos.y, vHitPos.z,
// vHitNormal.x, vHitNormal.y, vHitNormal.z, vTerNormal.x, vTerNormal.y, vTerNormal.z, fFraction);
// OUTPUT_DEBUG_INFO(msg);
//
// //vHitNormal = vTerNormal;
// }
// else
// {
// A3DVECTOR3 vEnd(vStart + vDelta);
// float fH2 = pTerrain.GetPosHeight(vEnd);
// sprintf(msg, "terrain test clear %f %f %f height %f\n", vEnd.x, vEnd.y, vEnd.z,fH2);
// OUTPUT_DEBUG_INFO(msg);
// }
#endif
return (fFraction <= 1.0f);
}
}
public struct OtherPlayer_Move_Info
{
// Bounding sphere of avator
public A3DVECTOR3 vCenter;
public A3DVECTOR3 vExts;
public float fStepHeight;
public A3DVECTOR3 vVelocity;
public float t;
public bool bTraceGround; // Whether trace the ground
public bool bTestTrnOnly; // Trace terrain only
public A3DVECTOR3 vecGroundNormal; // if bTraceGround is true, this will contain the ground normal when returned
};
//@desc :used to trace the environment, brush&terrain&water By Kuiwu[8/10/2005]
public struct env_trace_t
{
public A3DVECTOR3 vStart; // brush start
public A3DVECTOR3 vExt;
public A3DVECTOR3 vDelta;
public A3DVECTOR3 vTerStart;
public A3DVECTOR3 vWatStart;
public uint dwCheckFlag;
public bool bWaterSolid;
public float fFraction;
public A3DVECTOR3 vHitNormal;
public bool bStartSolid; //start in solid
public uint dwClsFlag; //collision flag
};
}
public struct OtherPlayer_Move_Info
{
// Bounding sphere of avator
public A3DVECTOR3 vCenter;
public A3DVECTOR3 vExts;
public float fStepHeight;
public A3DVECTOR3 vVelocity;
public float t;
public bool bTraceGround; // Whether trace the ground
public bool bTestTrnOnly; // Trace terrain only
public A3DVECTOR3 vecGroundNormal; // if bTraceGround is true, this will contain the ground normal when returned
};
+386 -386
View File
@@ -1,38 +1,38 @@
using BrewMonster;
using CSNetwork.GPDataType;
using CSNetwork.GPDataType;
using ModelRenderer.Scripts.GameData;
using PerfectWorld.Scripts.Player;
using System;
using System.Collections.Generic;
using UnityEngine;
public abstract class EC_Player : CECObject
namespace BrewMonster.Scripts.Player
{
private static PLAYER_ACTION[] _default_actions;
private static PLAYER_ACTION[] _turning_actions;
PLAYER_ACTION[] m_PlayerActions;
[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 = new A3DAABB(); // Óë·þÎñÆ÷±£³ÖÒ»ÖµÄaabb£¬ ²»ÊÜËõ·ÅÓ°Ïì
public A3DAABB m_aabb = new A3DAABB(); // Player's aabb£¬ÓÃÓÚÏÔʾµÄaabb£¬ÊÜËõ·ÅÓ°Ïì
public int m_iProfession; // Profession
public float m_fScaleBySkill;
public int m_iGender; // Gender
public MOVECONST m_MoveConst; // Const used when moving control
public abstract class EC_Player : CECObject
{
private static PLAYER_ACTION[] _default_actions;
private static PLAYER_ACTION[] _turning_actions;
PLAYER_ACTION[] m_PlayerActions;
[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 = new A3DAABB(); // Óë·þÎñÆ÷±£³ÖÒ»ÖµÄaabb£¬ ²»ÊÜËõ·ÅÓ°Ïì
public A3DAABB m_aabb = new A3DAABB(); // Player's aabb£¬ÓÃÓÚÏÔʾµÄaabb£¬ÊÜËõ·ÅÓ°Ïì
public int m_iProfession; // Profession
public float m_fScaleBySkill;
public int m_iGender; // Gender
public MOVECONST m_MoveConst; // Const used when moving control
public MOVECONST[] aMoveConsts = new MOVECONST[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER]
{
public MOVECONST[] aMoveConsts = new MOVECONST[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER]
{
// ÎäÏÀ
// fStepHei fMinAirHei fMinWaterHei fShoreDepth fWaterSurf
new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f),
@@ -70,10 +70,10 @@ public abstract class EC_Player : CECObject
// ÔÂÏÉ
new MOVECONST(0.8f, 1.6f, 0.3f, 1.6f, 0.6f),
new MOVECONST(0.8f, 1.6f, 0.3f, 1.5f, 0.55f),
};
};
public A3DVECTOR3[] aExts = new A3DVECTOR3[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER]
{
public A3DVECTOR3[] aExts = new A3DVECTOR3[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER]
{
new A3DVECTOR3(0.4f, 0.9f, 0.4f), // ÎäÏÀ
new A3DVECTOR3(0.3f, 0.85f, 0.3f),
new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ·¨Ê¦
@@ -98,404 +98,404 @@ public abstract class EC_Player : CECObject
new A3DVECTOR3(0.3f, 0.85f, 0.3f),
new A3DVECTOR3(0.3f, 0.9f, 0.3f), // ÔÂÏÉ
new A3DVECTOR3(0.3f, 0.85f, 0.3f),
};
};
protected void Awake()
{
m_PlayerActions = _default_actions;
}
public void SetPlayerInfor(INFO playinfo)
{
m_PlayerInfo = playinfo;
}
public INFO GetPlayInfo()
{
return m_PlayerInfo;
}
public void CalcPlayerAABB()
{
int iIndex = m_iProfession * GENDER.NUM_GENDER + m_iGender;
m_aabb.Extents = aExts[iIndex] * m_fScaleBySkill;
m_aabbServer.Extents = aExts[iIndex];
m_MoveConst = aMoveConsts[iIndex];
}
public static void InitStaticRes()
{
BuildActionList();
}
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)
protected void Awake()
{
// thay cho hashtab trong C++
Dictionary<string, PLAYER_ACTION_INFO_CONFIG> actionMap =
new Dictionary<string, PLAYER_ACTION_INFO_CONFIG>(100);
m_PlayerActions = _default_actions;
}
public void SetPlayerInfor(INFO playinfo)
{
m_PlayerInfo = playinfo;
}
public INFO GetPlayInfo()
{
return m_PlayerInfo;
}
Dictionary<string, PLAYER_ACTION_INFO_CONFIG> skillActionMap =
new Dictionary<string, PLAYER_ACTION_INFO_CONFIG>(100);
public void CalcPlayerAABB()
{
int iIndex = m_iProfession * GENDER.NUM_GENDER + m_iGender;
elementdataman dataman = ElementDataManProvider.GetElementDataMan();
PLAYER_ACTION_INFO_CONFIG data;
m_aabb.Extents = aExts[iIndex] * m_fScaleBySkill;
m_aabbServer.Extents = aExts[iIndex];
m_MoveConst = aMoveConsts[iIndex];
}
int count = dataman.get_data_num(ID_SPACE.ID_SPACE_CONFIG);
public static void InitStaticRes()
{
BuildActionList();
}
DATA_TYPE dt = default;
uint id = 0;
public bool IsDead() { return (m_dwStates & PlayerNPCState.GP_STATE_CORPSE) != 0; }
for (int i = 0; i < count; ++i)
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)
{
id = dataman.get_data_id(ID_SPACE.ID_SPACE_CONFIG, i, ref dt);
if (dt != DATA_TYPE.DT_PLAYER_ACTION_INFO_CONFIG)
continue;
// thay cho hashtab trong C++
Dictionary<string, PLAYER_ACTION_INFO_CONFIG> actionMap =
new Dictionary<string, PLAYER_ACTION_INFO_CONFIG>(100);
data = (PLAYER_ACTION_INFO_CONFIG)dataman.get_data_ptr(id, ID_SPACE.ID_SPACE_CONFIG, ref dt);
if (!string.IsNullOrEmpty(data.ActionName) && data.ActionName[0] != '0')
Dictionary<string, PLAYER_ACTION_INFO_CONFIG> skillActionMap =
new Dictionary<string, PLAYER_ACTION_INFO_CONFIG>(100);
elementdataman dataman = ElementDataManProvider.GetElementDataMan();
PLAYER_ACTION_INFO_CONFIG data;
int count = dataman.get_data_num(ID_SPACE.ID_SPACE_CONFIG);
DATA_TYPE dt = default;
uint id = 0;
for (int i = 0; i < count; ++i)
{
if (!actionMap.TryAdd(data.ActionName, data))
{
id = dataman.get_data_id(ID_SPACE.ID_SPACE_CONFIG, i, ref dt);
if (dt != DATA_TYPE.DT_PLAYER_ACTION_INFO_CONFIG)
continue;
data = (PLAYER_ACTION_INFO_CONFIG)dataman.get_data_ptr(id, ID_SPACE.ID_SPACE_CONFIG, ref dt);
if (!string.IsNullOrEmpty(data.ActionName) && data.ActionName[0] != '0')
{
if (!actionMap.TryAdd(data.ActionName, data))
{
}
}
}
}
CECStringTab actionNames = new CECStringTab();
actionNames.Init("actions_player", false);
CECStringTab actionNames = new CECStringTab();
actionNames.Init("actions_player", false);
_default_actions = new PLAYER_ACTION[(int)PLAYER_ACTION_TYPE.ACT_MAX];
_default_actions = new PLAYER_ACTION[(int)PLAYER_ACTION_TYPE.ACT_MAX];
for (int i = 0; i < _default_actions.Length; i++)
{
_default_actions[i].type = (PLAYER_ACTION_TYPE)i;
string szName = actionNames.GetANSIString(i);
if (!string.IsNullOrEmpty(szName))
for (int i = 0; i < _default_actions.Length; i++)
{
if (actionMap.TryGetValue(szName, out var it))
_default_actions[i].type = (PLAYER_ACTION_TYPE)i;
string szName = actionNames.GetANSIString(i);
if (!string.IsNullOrEmpty(szName))
{
_default_actions[i].data = it;
if (actionMap.TryGetValue(szName, out var it))
{
_default_actions[i].data = it;
}
}
}
}
}
}
public bool PlayAction(int iAction, bool bRestart/* true */, int iTransTime/* 200 */, bool bQueue/* false */)
{
return PlayActionWithConfig(iAction, 0, bRestart, iTransTime, bQueue);
}
public bool PlayActionWithConfig(int iAction, int actionConfigID, bool bRestart/* =true */, int iTransTime/* =200 */, bool bQueue/* =false */)
{
if (iAction < 0 || iAction >= (int)PLAYER_ACTION_TYPE.ACT_MAX)
public bool PlayAction(int iAction, bool bRestart/* true */, int iTransTime/* 200 */, bool bQueue/* false */)
{
return false;
return PlayActionWithConfig(iAction, 0, bRestart, iTransTime, bQueue);
}
if (actionConfigID > 0)
public bool PlayActionWithConfig(int iAction, int actionConfigID, bool bRestart/* =true */, int iTransTime/* =200 */, bool bQueue/* =false */)
{
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
var p = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)actionConfigID, ID_SPACE.ID_SPACE_CONFIG, ref dt);
if (dt == DATA_TYPE.DT_PLAYER_ACTION_INFO_CONFIG)
if (iAction < 0 || iAction >= (int)PLAYER_ACTION_TYPE.ACT_MAX)
{
PLAYER_ACTION actionConfig;
actionConfig.type = (PLAYER_ACTION_TYPE)iAction;
actionConfig.data = (PLAYER_ACTION_INFO_CONFIG)p;
return PlayActionWithConfig(iAction, actionConfig, bRestart, iTransTime, bQueue);
return false;
}
if (actionConfigID > 0)
{
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
var p = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)actionConfigID, ID_SPACE.ID_SPACE_CONFIG, ref dt);
if (dt == DATA_TYPE.DT_PLAYER_ACTION_INFO_CONFIG)
{
PLAYER_ACTION actionConfig;
actionConfig.type = (PLAYER_ACTION_TYPE)iAction;
actionConfig.data = (PLAYER_ACTION_INFO_CONFIG)p;
return PlayActionWithConfig(iAction, actionConfig, bRestart, iTransTime, bQueue);
}
else
{
}
}
return PlayActionWithConfig(iAction, m_PlayerActions[iAction], bRestart, iTransTime, bQueue);
}
public bool PlayActionWithConfig(int iAction, in PLAYER_ACTION actionConfig,
bool bRestart = true, int iTransTime = 200, bool bQueue = false)
{
PLAYER_ACTION action = actionConfig;
var szAct = EC_Utility.BuildActionName(action, 0);
EventBus.PublishChannel(m_PlayerInfo.cid, new PlayActionEvent(szAct));
return true;
}
public static void Dispose()
{
_default_actions = null;
_turning_actions = null;
}
public struct PLAYER_ACTION
{
public PLAYER_ACTION_TYPE type;
public PLAYER_ACTION_INFO_CONFIG data;
};
public enum PLAYER_ACTION_TYPE
{
// 0
ACT_STAND = 0, // Đứng
ACT_FIGHTSTAND, // Đứng chiến đấu
ACT_WALK, // Đi bộ
ACT_RUN, // Chạy
ACT_JUMP_START, // Bắt đầu nhảy
// 5
ACT_JUMP_LOOP, // Nhảy trên không lặp lại
ACT_JUMP_LAND, // Nhảy tiếp đất
ACT_SWIM, // Bơi
ACT_HANGINWATER, // Lơ lửng trong nước
ACT_TAKEOFF, // Cất cánh (should be ACT_TAKEOFF_WING)
// 10
ACT_HANGINAIR, // Treo trên không (should be ACT_HANGINAIR_WING)
ACT_FLY, // Bay (should be ACT_FLY_WING)
ACT_FLYDOWN, // Bay xuống cao (should be ACT_FLYDOWN_WING_HIGH)
ACT_FLYDOWN_WING_LOW, // Bay xuống thấp (should be ACT_FLYDOWN_WING_LOW)
ACT_LANDON, // Hạ cánh (should be ACT_LAND_WING)
// 15
ACT_TAKEOFF_SWORD, // Kiếm bay - cất cánh
ACT_HANGINAIR_SWORD, // Kiếm bay - treo không trung
ACT_FLY_SWORD, // Kiếm bay - tiến tới
ACT_FLYDOWN_SWORD_HIGH, // Kiếm bay - rơi cao
ACT_FLYDOWN_SWORD_LOW, // Kiếm bay - rơi thấp
// 20
ACT_LANDON_SWORD, // Kiếm bay - hạ cánh
ACT_SITDOWN, // Ngồi
ACT_SITDOWN_LOOP, // Ngồi lặp lại
ACT_STANDUP, // Đứng dậy
ACT_WOUNDED, // Bị thương
// 25
ACT_GROUNDDIE, // Chết trên mặt đất
ACT_GROUNDDIE_LOOP, // Chết trên đất (loop)
ACT_WATERDIE, // Chết trong nước
ACT_WATERDIE_LOOP, // Chết trong nước (loop)
ACT_AIRDIE_ST, // Chết trên không (bắt đầu)
// 30
ACT_AIRDIE, // Chết trên không (loop rơi)
ACT_AIRDIE_ED, // Chết trên không (chạm đất)
ACT_AIRDIE_LAND_LOOP, // Chết rơi đất (loop)
ACT_REVIVE, // Hồi sinh
ACT_CUSTOMIZE, // Động tác tùy chỉnh
// 35
ACT_STRIKEBACK, // Bị đánh lùi
ACT_STRIKEDOWN, // Bị đánh ngã
ACT_STRIKEDOWN_LOOP, // Bị đánh ngã (loop)
ACT_STRIKEDOWN_STANDUP, // Bị đánh ngã rồi đứng dậy
ACT_PICKUP, // Nhặt đồ
// 40
ACT_PICKUP_LOOP, // Nhặt đồ (loop)
ACT_PICKUP_STANDUP, // Nhặt đồ đứng dậy
ACT_PICKUP_MATTER, // Nhặt vật thể
ACT_GAPE, // Há miệng
ACT_LOOKAROUND, // Nhìn quanh
// 45
ACT_PLAYWEAPON, // Vung vũ khí
ACT_EXP_WAVE, // Vẫy tay
ACT_EXP_NOD, // Gật đầu
ACT_EXP_SHAKEHEAD, // Lắc đầu
ACT_EXP_SHRUG, // Nhún vai
// 50
ACT_EXP_LAUGH, // Cười lớn
ACT_EXP_ANGRY, // Tức giận
ACT_EXP_STUN, // Choáng
ACT_EXP_DEPRESSED, // Buồn bã
ACT_EXP_KISSHAND, // Hôn tay
// 55
ACT_EXP_SHY, // Ngại ngùng
ACT_EXP_SALUTE, // Chào
ACT_EXP_SITDOWN, // Ngồi xuống
ACT_EXP_SITDOWN_LOOP, // Ngồi xuống (loop)
ACT_EXP_SITDOWN_STANDUP, // Ngồi xuống rồi đứng dậy
// 60
ACT_EXP_ASSAULT, // Tấn công
ACT_EXP_THINK, // Suy nghĩ
ACT_EXP_DEFIANCE, // Thách thức
ACT_EXP_VICTORY, // Chiến thắng
ACT_EXP_KISS, // Hôn
// 65
ACT_EXP_KISS_LOOP, // Hôn (loop)
ACT_EXP_KISS_END, // Kết thúc hôn
ACT_ATTACK_1, // Tấn công 1
ACT_ATTACK_2, // Tấn công 2
ACT_ATTACK_3, // Tấn công 3
// 70
ACT_ATTACK_4, // Tấn công 4
ACT_ATTACK_TOSS, // Ném vũ khí
ACT_TRICK_RUN, // Chiêu khi chạy
ACT_TRICK_JUMP, // Chiêu khi nhảy
ACT_FLY_GLIDE, // Lượn
// 75
ACT_FLY_GLIDE_SWORD, // Kiếm bay - lượn
ACT_EXP_FIGHT, // Tư thế chiến đấu
ACT_EXP_ATTACK1, // Tấn công diễn xuất 1
ACT_EXP_ATTACK2, // Tấn công diễn xuất 2
ACT_EXP_ATTACK3, // Tấn công diễn xuất 3
// 80
ACT_EXP_ATTACK4, // Tấn công diễn xuất 4
ACT_EXP_DEFENCE, // Phòng thủ
ACT_EXP_FALL, // Té ngã
ACT_EXP_FALLONGROUND, // Ngã xuống đất
ACT_EXP_LOOKAROUND, // Nhìn quanh
// 85
ACT_EXP_DANCE, // Nhảy múa
ACT_EXP_FASHIONWEAPON, // Động tác vũ khí thời trang
ACT_USEITEM, // Dùng item
ACT_USEITMELOOP, // Dùng item (loop)
ACT_TWO_KISS, // Hôn đôi
// 90
ACT_USING_TARGET_ITEM, // Dùng đạo cụ
ACT_SWIM_FOR_MOVESKILL, // Bơi trong lúc dùng skill di chuyển
ACT_MAX,
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;
}
return PlayActionWithConfig(iAction, m_PlayerActions[iAction], bRestart, iTransTime, bQueue);
}
public bool PlayActionWithConfig(int iAction, in PLAYER_ACTION actionConfig,
bool bRestart = true, int iTransTime = 200, bool bQueue = false)
{
PLAYER_ACTION action = actionConfig;
var szAct = EC_Utility.BuildActionName(action, 0);
EventBus.PublishChannel(m_PlayerInfo.cid, new PlayActionEvent(szAct));
return true;
}
public static void Dispose()
{
_default_actions = null;
_turning_actions = null;
}
public struct PLAYER_ACTION
{
public PLAYER_ACTION_TYPE type;
public PLAYER_ACTION_INFO_CONFIG data;
};
public enum PLAYER_ACTION_TYPE
{
// 0
ACT_STAND = 0, // Đứng
ACT_FIGHTSTAND, // Đứng chiến đấu
ACT_WALK, // Đi bộ
ACT_RUN, // Chạy
ACT_JUMP_START, // Bắt đầu nhảy
// 5
ACT_JUMP_LOOP, // Nhảy trên không lặp lại
ACT_JUMP_LAND, // Nhảy tiếp đất
ACT_SWIM, // Bơi
ACT_HANGINWATER, // Lơ lửng trong nước
ACT_TAKEOFF, // Cất cánh (should be ACT_TAKEOFF_WING)
// 10
ACT_HANGINAIR, // Treo trên không (should be ACT_HANGINAIR_WING)
ACT_FLY, // Bay (should be ACT_FLY_WING)
ACT_FLYDOWN, // Bay xuống cao (should be ACT_FLYDOWN_WING_HIGH)
ACT_FLYDOWN_WING_LOW, // Bay xuống thấp (should be ACT_FLYDOWN_WING_LOW)
ACT_LANDON, // Hạ cánh (should be ACT_LAND_WING)
// 15
ACT_TAKEOFF_SWORD, // Kiếm bay - cất cánh
ACT_HANGINAIR_SWORD, // Kiếm bay - treo không trung
ACT_FLY_SWORD, // Kiếm bay - tiến tới
ACT_FLYDOWN_SWORD_HIGH, // Kiếm bay - rơi cao
ACT_FLYDOWN_SWORD_LOW, // Kiếm bay - rơi thấp
// 20
ACT_LANDON_SWORD, // Kiếm bay - hạ cánh
ACT_SITDOWN, // Ngồi
ACT_SITDOWN_LOOP, // Ngồi lặp lại
ACT_STANDUP, // Đứng dậy
ACT_WOUNDED, // Bị thương
// 25
ACT_GROUNDDIE, // Chết trên mặt đất
ACT_GROUNDDIE_LOOP, // Chết trên đất (loop)
ACT_WATERDIE, // Chết trong nước
ACT_WATERDIE_LOOP, // Chết trong nước (loop)
ACT_AIRDIE_ST, // Chết trên không (bắt đầu)
// 30
ACT_AIRDIE, // Chết trên không (loop rơi)
ACT_AIRDIE_ED, // Chết trên không (chạm đất)
ACT_AIRDIE_LAND_LOOP, // Chết rơi đất (loop)
ACT_REVIVE, // Hồi sinh
ACT_CUSTOMIZE, // Động tác tùy chỉnh
// 35
ACT_STRIKEBACK, // Bị đánh lùi
ACT_STRIKEDOWN, // Bị đánh ngã
ACT_STRIKEDOWN_LOOP, // Bị đánh ngã (loop)
ACT_STRIKEDOWN_STANDUP, // Bị đánh ngã rồi đứng dậy
ACT_PICKUP, // Nhặt đồ
// 40
ACT_PICKUP_LOOP, // Nhặt đồ (loop)
ACT_PICKUP_STANDUP, // Nhặt đồ đứng dậy
ACT_PICKUP_MATTER, // Nhặt vật thể
ACT_GAPE, // Há miệng
ACT_LOOKAROUND, // Nhìn quanh
// 45
ACT_PLAYWEAPON, // Vung vũ khí
ACT_EXP_WAVE, // Vẫy tay
ACT_EXP_NOD, // Gật đầu
ACT_EXP_SHAKEHEAD, // Lắc đầu
ACT_EXP_SHRUG, // Nhún vai
// 50
ACT_EXP_LAUGH, // Cười lớn
ACT_EXP_ANGRY, // Tức giận
ACT_EXP_STUN, // Choáng
ACT_EXP_DEPRESSED, // Buồn bã
ACT_EXP_KISSHAND, // Hôn tay
// 55
ACT_EXP_SHY, // Ngại ngùng
ACT_EXP_SALUTE, // Chào
ACT_EXP_SITDOWN, // Ngồi xuống
ACT_EXP_SITDOWN_LOOP, // Ngồi xuống (loop)
ACT_EXP_SITDOWN_STANDUP, // Ngồi xuống rồi đứng dậy
// 60
ACT_EXP_ASSAULT, // Tấn công
ACT_EXP_THINK, // Suy nghĩ
ACT_EXP_DEFIANCE, // Thách thức
ACT_EXP_VICTORY, // Chiến thắng
ACT_EXP_KISS, // Hôn
// 65
ACT_EXP_KISS_LOOP, // Hôn (loop)
ACT_EXP_KISS_END, // Kết thúc hôn
ACT_ATTACK_1, // Tấn công 1
ACT_ATTACK_2, // Tấn công 2
ACT_ATTACK_3, // Tấn công 3
// 70
ACT_ATTACK_4, // Tấn công 4
ACT_ATTACK_TOSS, // Ném vũ khí
ACT_TRICK_RUN, // Chiêu khi chạy
ACT_TRICK_JUMP, // Chiêu khi nhảy
ACT_FLY_GLIDE, // Lượn
// 75
ACT_FLY_GLIDE_SWORD, // Kiếm bay - lượn
ACT_EXP_FIGHT, // Tư thế chiến đấu
ACT_EXP_ATTACK1, // Tấn công diễn xuất 1
ACT_EXP_ATTACK2, // Tấn công diễn xuất 2
ACT_EXP_ATTACK3, // Tấn công diễn xuất 3
// 80
ACT_EXP_ATTACK4, // Tấn công diễn xuất 4
ACT_EXP_DEFENCE, // Phòng thủ
ACT_EXP_FALL, // Té ngã
ACT_EXP_FALLONGROUND, // Ngã xuống đất
ACT_EXP_LOOKAROUND, // Nhìn quanh
// 85
ACT_EXP_DANCE, // Nhảy múa
ACT_EXP_FASHIONWEAPON, // Động tác vũ khí thời trang
ACT_USEITEM, // Dùng item
ACT_USEITMELOOP, // Dùng item (loop)
ACT_TWO_KISS, // Hôn đôi
// 90
ACT_USING_TARGET_ITEM, // Dùng đạo cụ
ACT_SWIM_FOR_MOVESKILL, // Bơi trong lúc dùng skill di chuyển
ACT_MAX,
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)
public float GetGroundSpeed()
{
// 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;
// //}
//}
// 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;
}
else
// Get move environment
public int GetMoveEnv() { return m_iMoveEnv; }
// Get character ID
public int GetCharacterID() { return m_PlayerInfo.cid; }
}
public struct PlayActionEvent
{
public string AnimationName;
public PlayActionEvent(string animationName)
{
// 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;
this.AnimationName = animationName;
}
return iAction;
}
public float GetGroundSpeed()
[Serializable]
public struct INFO
{
// 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;
public int cid; // Character ID
public int crc_c; // customized data crc
public int crc_e; // Equipment data crc
public INFO(int cid, int crc_c, int crc_)
{
this.cid = cid;
this.crc_c = crc_c;
this.crc_e = crc_;
}
}
// Get move environment
public int GetMoveEnv(){ return m_iMoveEnv; }
// Get character ID
public int GetCharacterID(){ return m_PlayerInfo.cid; }
}
public struct PlayActionEvent
{
public string AnimationName;
public PlayActionEvent(string animationName)
public static class Duel_state // Duel state
{
this.AnimationName = animationName;
public const int DUEL_ST_NONE = 0,
DUEL_ST_PREPARE = 1,
DUEL_ST_INDUEL = 2,
DUEL_ST_STOPPING = 3;
}
}
[Serializable]
public struct INFO
{
public int cid; // Character ID
public int crc_c; // customized data crc
public int crc_e; // Equipment data crc
public INFO(int cid, int crc_c, int crc_)
{
this.cid = cid;
this.crc_c = crc_c;
this.crc_e = crc_;
}
}
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
//{
+16 -13
View File
@@ -1,24 +1,27 @@
using UnityEngine;
using static EC_Player;
using static BrewMonster.Scripts.Player.EC_Player;
public class PlayerIdleState : PlayerState
namespace BrewMonster.Scripts.Player
{
public PlayerIdleState(CECHostPlayer characterCtrl) : base(characterCtrl)
public class PlayerIdleState : PlayerState
{
}
public PlayerIdleState(CECHostPlayer characterCtrl) : base(characterCtrl)
{
}
public override void Enter()
{
_characterCtrl.PlayAction((int)PLAYER_ACTION_TYPE.ACT_STAND, true, 1, false);
}
public override void Enter()
{
_characterCtrl.PlayAction((int)PLAYER_ACTION_TYPE.ACT_STAND, true, 1, false);
}
public override void Exit()
{
public override void Exit()
{
}
}
public override void Update()
{
public override void Update()
{
}
}
}
+19 -16
View File
@@ -1,25 +1,28 @@
using UnityEngine;
using static EC_Player;
using static BrewMonster.Scripts.Player.EC_Player;
public class PlayerMoveState : PlayerState
namespace BrewMonster.Scripts.Player
{
public PlayerMoveState(CECHostPlayer characterCtrl) : base(characterCtrl)
public class PlayerMoveState : PlayerState
{
}
public PlayerMoveState(CECHostPlayer characterCtrl) : base(characterCtrl)
{
}
public override void Enter()
{
_characterCtrl.PlayAction((int)PLAYER_ACTION_TYPE.ACT_WALK,true,1,false);
}
public override void Enter()
{
_characterCtrl.PlayAction((int)PLAYER_ACTION_TYPE.ACT_WALK, true, 1, false);
}
public override void Exit()
{
_characterCtrl.StopMovement();
}
public override void Exit()
{
_characterCtrl.StopMovement();
}
public override void Update()
{
_characterCtrl.HandleMovement();
}
public override void Update()
{
_characterCtrl.HandleMovement();
}
}
}
+10 -7
View File
@@ -1,13 +1,16 @@
using UnityEngine;
public abstract class PlayerState
namespace BrewMonster.Scripts.Player
{
protected readonly CECHostPlayer _characterCtrl;
public PlayerState(CECHostPlayer characterCtrl)
public abstract class PlayerState
{
_characterCtrl = characterCtrl;
protected readonly CECHostPlayer _characterCtrl;
public PlayerState(CECHostPlayer characterCtrl)
{
_characterCtrl = characterCtrl;
}
public abstract void Enter();
public abstract void Exit();
public abstract void Update();
}
public abstract void Enter();
public abstract void Exit();
public abstract void Update();
}
+37 -34
View File
@@ -1,41 +1,44 @@
using UnityEngine;
public class PlayerStateMachine
namespace BrewMonster.Scripts.Player
{
PlayerState _state;
CECHostPlayer _characterCtrl;
public PlayerState State { get => _state; }
public void InitState(PlayerState state)
public class PlayerStateMachine
{
if (_state != null)
{
Debug.LogWarning("_state is already inited");
return;
}
_state = state;
_state.Enter();
}
PlayerState _state;
CECHostPlayer _characterCtrl;
public void ChangeState(PlayerState state)
{
if (_state == null )
{
Debug.LogError("you need to init state first ");
return;
}
if (_state == state)
{
Debug.LogWarning("Unchanged state");
}
_state.Exit();
_state = state;
_state.Enter();
}
public void UpdateState()
{
_state.Update();
}
public PlayerState State { get => _state; }
public void InitState(PlayerState state)
{
if (_state != null)
{
Debug.LogWarning("_state is already inited");
return;
}
_state = state;
_state.Enter();
}
public void ChangeState(PlayerState state)
{
if (_state == null)
{
Debug.LogError("you need to init state first ");
return;
}
if (_state == state)
{
Debug.LogWarning("Unchanged state");
}
_state.Exit();
_state = state;
_state.Enter();
}
public void UpdateState()
{
_state.Update();
}
}
}
+33 -30
View File
@@ -2,42 +2,45 @@ using Animancer;
using System;
using UnityEngine;
public class PlayerVisual : MonoBehaviour
namespace BrewMonster.Scripts.Player
{
[SerializeField] NamedAnimancerComponent namedAnimancer;
[SerializeField] private INFO _playerInfo;
private void PlayActionEventHandler(PlayActionEvent @event)
public class PlayerVisual : MonoBehaviour
{
BrewMonster.BMLogger.Log("PlayActionEventHandler : "+@event.AnimationName);
namedAnimancer.TryPlay(@event.AnimationName);
}
[SerializeField] NamedAnimancerComponent namedAnimancer;
public void InitHostPlayerEventDoneHandler()
{
namedAnimancer = GetComponentInChildren<NamedAnimancerComponent>();
if(namedAnimancer == null)
[SerializeField] private INFO _playerInfo;
private void PlayActionEventHandler(PlayActionEvent @event)
{
BrewMonster.BMLogger.LogError("animancer == null");
return;
BrewMonster.BMLogger.Log("PlayActionEventHandler : " + @event.AnimationName);
namedAnimancer.TryPlay(@event.AnimationName);
}
var player = GetComponentInParent<EC_Player>();
if(player == null)
public void InitHostPlayerEventDoneHandler()
{
BrewMonster.BMLogger.LogError("player == null");
return;
namedAnimancer = GetComponentInChildren<NamedAnimancerComponent>();
if (namedAnimancer == null)
{
BrewMonster.BMLogger.LogError("animancer == null");
return;
}
var player = GetComponentInParent<EC_Player>();
if (player == null)
{
BrewMonster.BMLogger.LogError("player == null");
return;
}
_playerInfo = player.GetPlayInfo();
EventBus.SubscribeChannel<PlayActionEvent>(_playerInfo.cid, PlayActionEventHandler);
}
private void OnDestroy()
{
EventBus.UnsubscribeAllInChannel(_playerInfo.cid);
}
public bool IsAnimationExist(string animationName)
{
return namedAnimancer.States.TryGet("ActionName", out var existingState) ? true : false;
}
_playerInfo = player.GetPlayInfo();
EventBus.SubscribeChannel<PlayActionEvent>(_playerInfo.cid, PlayActionEventHandler);
}
private void OnDestroy()
{
EventBus.UnsubscribeAllInChannel(_playerInfo.cid);
}
public bool IsAnimationExist(string animationName)
{
return namedAnimancer.States.TryGet("ActionName", out var existingState) ? true : false;
}
}
+28 -25
View File
@@ -4,35 +4,38 @@ using UnityEngine.UI;
using System.Collections.Generic;
using CSNetwork.Protocols.RPCData;
public class ScreenLogin : MonoBehaviour
namespace BrewMonster.Managers
{
[SerializeField] private TMP_InputField ifUsername;
[SerializeField] private TMP_InputField ifPassword;
[SerializeField] private TMP_Dropdown ip;
[SerializeField] private Button btnLogin;
[SerializeField] private CanvasController canvasController;
private void Start()
public class ScreenLogin : MonoBehaviour
{
btnLogin.onClick.AddListener(OnClickBtnLogin);
}
[SerializeField] private TMP_InputField ifUsername;
[SerializeField] private TMP_InputField ifPassword;
[SerializeField] private TMP_Dropdown ip;
[SerializeField] private Button btnLogin;
[SerializeField] private CanvasController canvasController;
private void OnClickBtnLogin()
{
string _username = ifUsername.text;
string _password = ifPassword.text;
string _ip = ip.options[ip.value].text;
Debug.LogError("Login...");
}
private void Start()
{
btnLogin.onClick.AddListener(OnClickBtnLogin);
}
private void HandleLoginComplete(List<RoleInfo> roleInfos)
{
Debug.LogError("Success");
canvasController.ShowScreenSelectCharacter(roleInfos);
}
private void OnClickBtnLogin()
{
string _username = ifUsername.text;
string _password = ifPassword.text;
string _ip = ip.options[ip.value].text;
Debug.LogError("Login...");
}
private void HandleLoginFaile(string reslut)
{
Debug.LogError(reslut);
private void HandleLoginComplete(List<RoleInfo> roleInfos)
{
Debug.LogError("Success");
canvasController.ShowScreenSelectCharacter(roleInfos);
}
private void HandleLoginFaile(string reslut)
{
Debug.LogError(reslut);
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace PerfectWorld.Scripts.Task
namespace BrewMonster.Scripts.Task
{
public class ATaskTemplMan
{
+2 -1
View File
@@ -1,8 +1,9 @@
using BrewMonster.Network;
using BrewMonster.Scripts.Player;
using System.Collections.Generic;
using UnityEngine;
namespace PerfectWorld.Scripts.Task
namespace BrewMonster.Scripts.Task
{
public class CECTaskInterface : TaskInterface
{
+1 -1
View File
@@ -1,4 +1,4 @@
namespace PerfectWorld.Scripts.Task
namespace BrewMonster.Scripts.Task
{
public struct TASK_EXPRESSION
{
+1 -1
View File
@@ -1,4 +1,4 @@
namespace PerfectWorld.Scripts.Task
namespace BrewMonster.Scripts.Task
{
public interface TaskInterface
{
+1 -1
View File
@@ -1,6 +1,6 @@
using System;
using System.Runtime.InteropServices;
using PerfectWorld.Scripts.Task;
using BrewMonster.Scripts.Task;
using UnityEngine;
public class TaskProcess
+1 -1
View File
@@ -3,7 +3,7 @@ using System.IO;
using System.Runtime.InteropServices;
namespace PerfectWorld.Scripts.Task
namespace BrewMonster.Scripts.Task
{
public sealed class TaskConstant
{
+1 -1
View File
@@ -2,7 +2,7 @@ using System.IO;
using UnityEngine;
namespace PerfectWorld.Scripts.Task
namespace BrewMonster.Scripts.Task
{
public class TaskTest : MonoBehaviour
{
@@ -1,4 +1,5 @@
using UnityEngine;
using BrewMonster.Scripts.Player;
using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif