WIP:show equipment for else player

This commit is contained in:
Le Duc Anh
2026-03-13 00:21:52 +07:00
parent dc0092eab0
commit 5b31865962
7 changed files with 290 additions and 52 deletions
@@ -58,25 +58,26 @@ namespace PerfectWorld.Scripts.Managers
OnMsgPlayerStopMove(Msg);
break;
}
case int value when value == EC_MsgDef.MSG_PM_PLAYERBASEINFO:
case int value2 when value2 == EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY:
case int value3 when value3 == EC_MsgDef.MSG_PM_PLAYERATKRESULT:
case int value4 when value4 == EC_MsgDef.MSG_PM_CASTSKILL:
case int value5 when value5 == EC_MsgDef.MSG_PM_ENCHANTRESULT:
case int value6 when value6 == EC_MsgDef.MSG_PM_PLAYERDOEMOTE:
case int value7 when value7 == EC_MsgDef.MSG_PM_PLAYERGATHER:
case int value8 when value8 == EC_MsgDef.MSG_PM_PLAYERFLY:
case int value9 when value9 == EC_MsgDef.MSG_PM_PLAYERMOUNT:
case int value10 when value10 == EC_MsgDef.MSG_PM_PLAYERCHGSHAPE:
case EC_MsgDef.MSG_PM_PLAYEREQUIPDATA:
case EC_MsgDef.MSG_PM_PLAYERBASEINFO:
case EC_MsgDef.MSG_PM_FACTION_PVP_MASK_MODIFY:
case EC_MsgDef.MSG_PM_PLAYERATKRESULT:
case EC_MsgDef.MSG_PM_CASTSKILL:
case EC_MsgDef.MSG_PM_ENCHANTRESULT:
case EC_MsgDef.MSG_PM_PLAYERDOEMOTE:
case EC_MsgDef.MSG_PM_PLAYERGATHER:
case EC_MsgDef.MSG_PM_PLAYERFLY:
case EC_MsgDef.MSG_PM_PLAYERMOUNT:
case EC_MsgDef.MSG_PM_PLAYERCHGSHAPE:
TransmitMessage(Msg);
break;
case int value when value == EC_MsgDef.MSG_PM_PLAYERDIED:
case EC_MsgDef.MSG_PM_PLAYERDIED:
OnMsgPlayerDied(Msg);
break;
case int value when value == EC_MsgDef.MSG_PM_PLAYERREVIVE:
case EC_MsgDef.MSG_PM_PLAYERREVIVE:
OnMsgPlayerRevive(Msg);
break;
case int value when value == EC_MsgDef.MSG_PM_PLAYERRUNOUT:
case EC_MsgDef.MSG_PM_PLAYERRUNOUT:
OnMsgPlayerRunOut(Msg);
break;
case EC_MsgDef.MSG_PM_PICKUPMATTER:
@@ -622,14 +623,26 @@ namespace PerfectWorld.Scripts.Managers
switch (Msg.dwMsg)
{
case long value when value == EC_MsgDef.MSG_PM_PLAYEREQUIPDATA:
if ((int)Msg.dwParam2 == CommandID.EQUIP_DATA)
cid = GPDataTypeHelper.FromBytes<cmd_equip_data>((byte[])Msg.dwParam1).idPlayer;
case EC_MsgDef.MSG_PM_PLAYEREQUIPDATA:
var param2 = Convert.ToInt32(Msg.dwParam2);
if (param2 == CommandID.EQUIP_DATA)
{
// cid = GPDataTypeHelper.FromBytes<cmd_equip_data>((byte[])Msg.dwParam1).idPlayer;
var buffer = new byte[4];
Array.Copy((byte[])Msg.dwParam1, 2, buffer, 0, 4);
cid = BitConverter.ToInt32(buffer, 0);
}
else // EQUIP_DATA_CHANGED
cid = GPDataTypeHelper.FromBytes<cmd_equip_data_changed>((byte[])Msg.dwParam1).idPlayer;
{
// cid = GPDataTypeHelper.FromBytes<cmd_equip_data_changed>((byte[])Msg.dwParam1).idPlayer;
var buffer = new byte[4];
Array.Copy((byte[])Msg.dwParam1, 2, buffer, 0, 4);
cid = BitConverter.ToInt32(buffer, 0);
}
break;
case long value when value == EC_MsgDef.MSG_PM_PLAYERBASEINFO:
case EC_MsgDef.MSG_PM_PLAYERBASEINFO:
cid = (int)((playerbaseinfo_re)Msg.dwParam1).Player.id;
// Xoá khỏi cache
UnityGameSession.Instance.GetC2SCmdCache().RemovePlayerBaseInfo(cid);
@@ -645,22 +658,22 @@ namespace PerfectWorld.Scripts.Managers
else
cid = ((cmd_object_landing)msg.dwParam1).object_id;
break;*/
case long value when value == EC_MsgDef.MSG_PM_PLAYERATKRESULT:
case EC_MsgDef.MSG_PM_PLAYERATKRESULT:
cmd_object_atk_result pCmdAtk = GPDataTypeHelper.FromBytes<cmd_object_atk_result>((byte[])Msg.dwParam1);
cid = pCmdAtk.attacker_id;
break;
case long value when value == EC_MsgDef.MSG_PM_CASTSKILL:
case EC_MsgDef.MSG_PM_CASTSKILL:
switch (Convert.ToInt32(Msg.dwParam2))
{
case int value2 when value2 == CommandID.OBJECT_CAST_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_object_cast_skill>((byte[])Msg.dwParam1)).caster; break;
case int value2 when value2 == CommandID.OBJECT_CAST_INSTANT_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_object_cast_instant_skill>((byte[])Msg.dwParam1)).caster; break;
case int value2 when value2 == CommandID.OBJECT_CAST_POS_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_object_cast_pos_skill>((byte[])Msg.dwParam1)).caster; break;
case int value2 when value2 == CommandID.SKILL_INTERRUPTED: cid = (GPDataTypeHelper.FromBytes<cmd_skill_interrupted>((byte[])Msg.dwParam1)).caster; break;
case int value2 when value2 == CommandID.PLAYER_CAST_RUNE_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_player_cast_rune_skill>((byte[])Msg.dwParam1)).caster; break;
case int value2 when value2 == CommandID.PLAYER_CAST_RUNE_INSTANT_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_player_cast_rune_instant_skill>((byte[])Msg.dwParam1)).caster; break;
case CommandID.OBJECT_CAST_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_object_cast_skill>((byte[])Msg.dwParam1)).caster; break;
case CommandID.OBJECT_CAST_INSTANT_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_object_cast_instant_skill>((byte[])Msg.dwParam1)).caster; break;
case CommandID.OBJECT_CAST_POS_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_object_cast_pos_skill>((byte[])Msg.dwParam1)).caster; break;
case CommandID.SKILL_INTERRUPTED: cid = (GPDataTypeHelper.FromBytes<cmd_skill_interrupted>((byte[])Msg.dwParam1)).caster; break;
case CommandID.PLAYER_CAST_RUNE_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_player_cast_rune_skill>((byte[])Msg.dwParam1)).caster; break;
case CommandID.PLAYER_CAST_RUNE_INSTANT_SKILL: cid = (GPDataTypeHelper.FromBytes<cmd_player_cast_rune_instant_skill>((byte[])Msg.dwParam1)).caster; break;
}
break;
case long value when value == EC_MsgDef.MSG_PM_PLAYERDOEMOTE:
case EC_MsgDef.MSG_PM_PLAYERDOEMOTE:
if (Convert.ToInt32(Msg.dwParam2) == CommandID.OBJECT_DO_EMOTE)
{
@@ -673,11 +686,11 @@ namespace PerfectWorld.Scripts.Managers
}
break;
case long value when value == EC_MsgDef.MSG_PM_ENCHANTRESULT:
case EC_MsgDef.MSG_PM_ENCHANTRESULT:
cid = GPDataTypeHelper.FromBytes<cmd_enchant_result>((byte[])Msg.dwParam1).caster;
break;
case long value when value == EC_MsgDef.MSG_PM_PLAYERGATHER:
case EC_MsgDef.MSG_PM_PLAYERGATHER:
if (Convert.ToInt32(Msg.dwParam2) == CommandID.PLAYER_GATHER_START)
{
@@ -696,7 +709,7 @@ namespace PerfectWorld.Scripts.Managers
}
break;
case long value when value == EC_MsgDef.MSG_PM_PLAYERFLY:
case EC_MsgDef.MSG_PM_PLAYERFLY:
if (Convert.ToInt32(Msg.dwParam2) == CommandID.OBJECT_TAKEOFF)
cid = (GPDataTypeHelper.FromBytes<cmd_object_takeoff>((byte[])Msg.dwParam1)).object_id;
@@ -704,12 +717,12 @@ namespace PerfectWorld.Scripts.Managers
cid = (GPDataTypeHelper.FromBytes<cmd_object_landing>((byte[])Msg.dwParam1)).object_id;
break;
case long value when value == EC_MsgDef.MSG_PM_PLAYERMOUNT:
case EC_MsgDef.MSG_PM_PLAYERMOUNT:
cid = (GPDataTypeHelper.FromBytes<cmd_player_mounting>((byte[])Msg.dwParam1)).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.
case long value when value == EC_MsgDef.MSG_PM_PLAYERCHGSHAPE:
case EC_MsgDef.MSG_PM_PLAYERCHGSHAPE:
cid = (GPDataTypeHelper.FromBytes<cmd_player_chgshape>((byte[])Msg.dwParam1)).idPlayer;
break;
default:
@@ -719,7 +732,7 @@ namespace PerfectWorld.Scripts.Managers
if (cid == 0)
{
System.Diagnostics.Debug.Assert(false, "cid = 0");
BMLogger.LogError("cid = 0, Msg.dwMsg = " + Msg.dwMsg);
return false;
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d0c06c588e2a6442488a3542551fb243
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -702,7 +702,6 @@ namespace CSNetwork.GPDataType
public ushort crc;
public int idPlayer;
public long mask;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public int[] data; //0 ~ 29
// bool CheckValid(size_t buf_size, size_t& sz) const
@@ -720,6 +719,72 @@ namespace CSNetwork.GPDataType
// return buf_size >= sz;
// }
public static cmd_equip_data FromBytes(byte[] buffer)
{
cmd_equip_data cmd = new cmd_equip_data();
if (buffer.Length > 0)
{
byte[] tempBuf = new byte[2];
Array.Copy(buffer, 0, tempBuf, 0, 2);
cmd.crc = BitConverter.ToUInt16(tempBuf, 0);
tempBuf = new byte[4];
Array.Copy(buffer, 2, tempBuf, 0, 4);
cmd.idPlayer = BitConverter.ToInt32(tempBuf, 0);
tempBuf = new byte[8];
Array.Copy(buffer, 6, tempBuf, 0, 8);
cmd.mask = BitConverter.ToInt64(tempBuf, 0);
byte sz = 0;
for (int i = 0; i < 32; i++)
{
if ((cmd.mask & (1L << i)) != 0)
sz += 4; // sizeof(int)
}
if (buffer.Length < sz)
return cmd;
tempBuf = new byte[4];
cmd.data = new int[sz / 4];
for (int i = 0; i < cmd.data.Length; i++)
{
Array.Copy(buffer, 14 + i * 4, tempBuf, 0, 4);
cmd.data[i] = BitConverter.ToInt32(tempBuf, 0);
}
return cmd;
}
return cmd;
}
}
public struct cmd_equip_data_changed
{
public ushort crc;
public int idPlayer;
public long mask_add;
public long mask_del;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public int[] data_add; //0 ~ 29
public bool CheckValid(uint buf_size, uint sz)
{
// sz = sizeof(*this) - sizeof(data_add);
// if (buf_size < sz)
// return false;
// for (int i = 0; i < 32; i++)
// {
// if (mask_add & (1 << i))
// sz += sizeof(int);
// }
// return buf_size >= sz;
return true;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
@@ -817,7 +817,9 @@ namespace CSNetwork
break;
case CommandID.EQUIP_DATA:
case CommandID.EQUIP_DATA_CHANGED:
BMLogger.Log($"### EQUIP_DATA: CMDID {pCmdHeader}");
// BMLogger.Log($"### EQUIP_DATA: CMDID {pCmdHeader}");
// MSG_PM_PLAYEREQUIPDATA, MAN_PLAYER, -1, (DWORD)pDataBuf, pCmdHeader->cmd, dwDataSize);
EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYEREQUIPDATA, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader);
break;
case CommandID.PLAYER_EQUIP_DETAIL:
// View other player profile/equip detail — parse and log with real game data (item names, slot names)
@@ -16,6 +16,7 @@ using Cysharp.Threading.Tasks;
using PerfectWorld.Scripts;
using PerfectWorld.Scripts.Managers;
using UnityEngine;
using System.Collections.Generic;
namespace BrewMonster
{
@@ -47,6 +48,9 @@ namespace BrewMonster
CECEPWorkMan m_pEPWorkMan;
private CECEPWork _workStand;
CECHostPlayer pHost => EC_ManMessageMono.Instance?.GetECManPlayer?.GetHostPlayer();
public int[] m_aNewEquips = new int[InventoryConst.SIZE_ALL_EQUIPIVTR]; // New equipment item ID array
public long m_i64NewEqpMask; // New equipment mask
public void Init(info_player_1 Info, int iAppearFlag)
{
@@ -428,21 +432,12 @@ namespace BrewMonster
{
switch (Msg.dwMsg)
{
case long value when value == EC_MsgDef.MSG_PM_PLAYERBASEINFO:
OnMsgPlayerBaseInfo(Msg);
break;
case long value when value == EC_MsgDef.MSG_PM_PLAYERATKRESULT:
OnMsgPlayerAtkResult(Msg);
break;
case long value when value == EC_MsgDef.MSG_PM_PLAYERDOEMOTE:
OnMsgPlayerDoEmote(Msg);
break;
case long value when value == EC_MsgDef.MSG_PM_PLAYERGATHER:
OnMsgPlayerGather(Msg);
break;
case long value when value == EC_MsgDef.MSG_PM_PLAYERMOUNT:
OnMsgPlayerMount(Msg);
break;
case EC_MsgDef.MSG_PM_PLAYERBASEINFO: OnMsgPlayerBaseInfo(Msg); break;
case EC_MsgDef.MSG_PM_PLAYEREQUIPDATA: OnMsgPlayerEquipData(Msg); break;
case EC_MsgDef.MSG_PM_PLAYERATKRESULT: OnMsgPlayerAtkResult(Msg); break;
case EC_MsgDef.MSG_PM_PLAYERDOEMOTE: OnMsgPlayerDoEmote(Msg); break;
case EC_MsgDef.MSG_PM_PLAYERGATHER: OnMsgPlayerGather(Msg); break;
case EC_MsgDef.MSG_PM_PLAYERMOUNT: OnMsgPlayerMount(Msg); break;
}
return true;
}
@@ -482,6 +477,44 @@ namespace BrewMonster
}
}
public void OnMsgPlayerEquipData(ECMSG Msg)
{
// using namespace S2C;
// int crc, *aAdded=NULL;
int crc = -1;
int[] aAdded = null;
bool bReset = false;
long iAddMask = 0;
long iDelMask = 0;
int dwParam2 = Convert.ToInt32(Msg.dwParam2);
if (dwParam2 == CommandID.EQUIP_DATA)
{
cmd_equip_data pCmd = cmd_equip_data.FromBytes((byte[])Msg.dwParam1);
bReset = true;
crc = pCmd.crc;
iAddMask = pCmd.mask;
iDelMask = 0;
aAdded = pCmd.data;
}
// else // Msg.dwParam2 == EQUIP_DATA_CHANGED
// {
// cmd_equip_data_changed* pCmd = (cmd_equip_data_changed*)Msg.dwParam1;
// ASSERT(pCmd);
// bReset = false;
// crc = pCmd->crc;
// iAddMask = pCmd->mask_add;
// iDelMask = pCmd->mask_del;
// aAdded = iAddMask ? pCmd->data_add : NULL;
// }
// // Change equipment
ChangeEquipments(bReset, crc, iAddMask, iDelMask, aAdded);
}
void OnMsgPlayerAtkResult(ECMSG Msg)
{
@@ -636,6 +669,124 @@ namespace BrewMonster
// return new A3DVECTOR3(transform.position.x, transform.position.y, transform.position.z);
//}
// Change equipment
bool ChangeEquipments(bool bReset, int crc, long iAddMask, long iDelMask, int[] aAddedEquip)
{
m_PlayerInfo.crc_e = crc;
if (bReset)
{
// m_i64NewEqpMask = EQUIP_MASK64_ALL;
m_bEquipReady = true;
// memset(m_aEquips, 0xff, sizeof (m_aEquips));
// memset(m_aNewEquips, 0, sizeof (m_aNewEquips));
}
// Remove equipment at first
if (iDelMask != 0)
{
for (int i=0; i < InventoryConst.SIZE_ALL_EQUIPIVTR; i++)
{
if ((iDelMask & (1L << i)) != 0)
{
m_aNewEquips[i] = 0;
m_i64NewEqpMask |= (1L << i);
}
}
}
if (iAddMask != 0 && aAddedEquip != null)
{
int iCount = 0;
for (int i=0; i < InventoryConst.SIZE_ALL_EQUIPIVTR; i++)
{
if ((iAddMask & (1L << i)) != 0)
{
m_aNewEquips[i] = aAddedEquip[iCount++];
m_i64NewEqpMask |= (1L << i);
}
}
}
// this is some sort of hack to get the equipment to load immediately
// TODO: Check again if this should be done here
ShowEquipments(m_aNewEquips, true, true);
// TODO: Implement the rest of the equipment logic
/*/
if (!ShouldUseModel())
return true;
if (IsSkeletonReady())
LoadPlayerEquipments();
// Deal with goblin£¨¼òµ¥Ä£ÐͲ»¼ÓÔØÐ¡¾«Á飩
if(m_aNewEquips[EQUIPIVTR_GOBLIN] != 0 && ShouldUseClothedModel())
{
int tid = m_aNewEquips[EQUIPIVTR_GOBLIN] & 0x0000ffff;
int idModel = (m_aNewEquips[EQUIPIVTR_GOBLIN] >>16) & 0x000000ff;
int iRefineLvl = (m_aNewEquips[EQUIPIVTR_GOBLIN] >>24) & 0x000000ff;
ASSERT(idModel >= 1 && idModel <= 4);
ASSERT(iRefineLvl >=0 && iRefineLvl <= 36);
if( !m_pGoblin )
{
m_pGoblin = new CECGoblin();
if(!m_pGoblin->Init(tid, idModel,iRefineLvl,this))
{
ASSERT(0);
m_pGoblin->Release();
delete m_pGoblin;
m_pGoblin = NULL;
}
}
else
{
if(tid != m_pGoblin->GetTemplateID() ||
idModel != (int)m_pGoblin->GetModelID() ||
iRefineLvl != m_pGoblin->GetRefineLevel())
{
m_pGoblin->Release();
delete m_pGoblin;
m_pGoblin = NULL;
m_pGoblin = new CECGoblin();
if(!m_pGoblin->Init(tid, idModel,iRefineLvl,this))
{
ASSERT(0);
m_pGoblin->Release();
delete m_pGoblin;
m_pGoblin = NULL;
}
}
}
}
else // m_aNewEquips[EQUIPIVTR_GOBLIN] == 0
{
if(m_pGoblin)
{
m_pGoblin->Release();
delete m_pGoblin;
m_pGoblin = NULL;
}
}
// Deal with armet
if(InFashionMode())
{
UpdateHairModel(true, m_aNewEquips[EQUIPIVTR_FASHION_HEAD]);
}
else
{
UpdateHairModel(true, m_aNewEquips[EQUIPIVTR_HEAD]);
}
//*/
return true;
}
private void SetPlayerBriefInfo(int iProf, int iGender, string szName)
{
m_iProfession = iProf;
@@ -18,7 +18,7 @@ MonoBehaviour:
m_Value: 0
threshold:
m_OverrideState: 1
m_Value: 0.5
m_Value: 0.8
intensity:
m_OverrideState: 1
m_Value: 1
@@ -85,7 +85,7 @@ MonoBehaviour:
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d7fd9488000d3734a9e00ee676215985, type: 3}
m_Name: SampleSceneProfile
m_Name: PC_SceneProfile
m_EditorClassIdentifier:
components:
- {fileID: 849379129802519247}