fix: update namespace.
feat: add new logic EC_World.
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class A3DTerrain2
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 828eeca29c5904541bdb0f5162832508
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1242
-1243
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,5 +1,5 @@
|
||||
using ModelRenderer.Scripts.GameData;
|
||||
using PerfectWorld.Scripts.Task;
|
||||
using BrewMonster.Scripts.Task;
|
||||
using UnityEngine;
|
||||
namespace BrewMonster.Network
|
||||
{
|
||||
|
||||
+340
-336
@@ -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
@@ -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
@@ -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
|
||||
//{
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
public abstract class PlayerState
|
||||
namespace BrewMonster.Scripts.Player
|
||||
{
|
||||
protected readonly CECHostPlayer _characterCtrl;
|
||||
public PlayerState(CECHostPlayer characterCtrl)
|
||||
public abstract class PlayerState
|
||||
{
|
||||
_characterCtrl = characterCtrl;
|
||||
protected readonly CECHostPlayer _characterCtrl;
|
||||
public PlayerState(CECHostPlayer characterCtrl)
|
||||
{
|
||||
_characterCtrl = characterCtrl;
|
||||
}
|
||||
public abstract void Enter();
|
||||
public abstract void Exit();
|
||||
public abstract void Update();
|
||||
}
|
||||
public abstract void Enter();
|
||||
public abstract void Exit();
|
||||
public abstract void Update();
|
||||
}
|
||||
|
||||
@@ -1,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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PerfectWorld.Scripts.Task
|
||||
namespace BrewMonster.Scripts.Task
|
||||
{
|
||||
public class ATaskTemplMan
|
||||
{
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts.Player;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PerfectWorld.Scripts.Task
|
||||
namespace BrewMonster.Scripts.Task
|
||||
{
|
||||
public class CECTaskInterface : TaskInterface
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PerfectWorld.Scripts.Task
|
||||
namespace BrewMonster.Scripts.Task
|
||||
{
|
||||
public struct TASK_EXPRESSION
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PerfectWorld.Scripts.Task
|
||||
namespace BrewMonster.Scripts.Task
|
||||
{
|
||||
public interface TaskInterface
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using PerfectWorld.Scripts.Task;
|
||||
using BrewMonster.Scripts.Task;
|
||||
using UnityEngine;
|
||||
|
||||
public class TaskProcess
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace PerfectWorld.Scripts.Task
|
||||
namespace BrewMonster.Scripts.Task
|
||||
{
|
||||
public sealed class TaskConstant
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@ using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace PerfectWorld.Scripts.Task
|
||||
namespace BrewMonster.Scripts.Task
|
||||
{
|
||||
public class TaskTest : MonoBehaviour
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using BrewMonster.Scripts.Player;
|
||||
using UnityEngine;
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user