This commit is contained in:
Le Duc Anh
2026-01-20 11:22:27 +07:00
1272 changed files with 65917 additions and 7385 deletions
+35 -20
View File
@@ -86,11 +86,25 @@ public partial class CECGameRun
AddressableManager.Instance.ReleaseAsset(AddressResourceConfig.NpcServerPrefab);
}
private async void LoadPrefabs()
private void LoadPrefabs()
{
_playerPrefab = await AddressableManager.Instance.LoadPrefabAsync(AddressResourceConfig.PlayerPrefab);
_monsterPrefab = await AddressableManager.Instance.LoadPrefabAsync(AddressResourceConfig.MonsterPrefab);
_npcServerPrefab = await AddressableManager.Instance.LoadPrefabAsync(AddressResourceConfig.NpcServerPrefab);
_playerPrefab = Resources.Load<GameObject>(AddressResourceConfig.PlayerPrefab);
_monsterPrefab = Resources.Load<GameObject>(AddressResourceConfig.MonsterPrefab);
_npcServerPrefab = Resources.Load<GameObject>(AddressResourceConfig.NpcServerPrefab);
#if UNITY_EDITOR
if (_playerPrefab == null)
{
BMLogger.LogError("CECGameRun::LoadPrefabs, Failed to load player prefab.");
}
if (_monsterPrefab == null)
{
BMLogger.LogError("CECGameRun::LoadPrefabs, Failed to load _monsterPrefab prefab.");
}
if (_npcServerPrefab == null)
{
BMLogger.LogError("CECGameRun::LoadPrefabs, Failed to load _npcServerPrefab prefab.");
}
#endif
}
private bool init;
@@ -258,6 +272,7 @@ public partial class CECGameRun
/// <returns>True if loaded successfully / 加载成功返回true</returns>
public bool LoadConfigsFromServer(byte[] pDataBuf, int iDataSize)
{
BMLogger.LogError("LoadConfigsFromServer ");
const uint USERCFG_VERSION = 3;
if (pDataBuf == null || iDataSize == 0)
@@ -344,16 +359,16 @@ public partial class CECGameRun
// Load UI configs / 加载UI配置
CECGameUIMan pGameUI = m_pUIManager.GetInGameUIMan();
/* if (pGameUI != null)
{
int iSize = dr.ReadInt();
byte[] uiConfigData = dr.ReadData(iSize);
if (!pGameUI.SetUserLayout(uiConfigData, iSize))
{
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to set user layout");
return false;
}
}*/
/* if (pGameUI != null)
{
int iSize = dr.ReadInt();
byte[] uiConfigData = dr.ReadData(iSize);
if (!pGameUI.SetUserLayout(uiConfigData, iSize))
{
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to set user layout");
return false;
}
}*/
// Load user settings / 加载用户设置
if (dwVer >= 2)
@@ -361,11 +376,11 @@ public partial class CECGameRun
// TODO: Uncomment when game configs are available
int iSize = dr.ReadInt();
byte[] settingsData = dr.ReadData(iSize);
if (!EC_Game.GetConfigs().LoadUserConfigData(settingsData, iSize))
{
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to load user config data");
return false;
}
/* if (!EC_Game.GetConfigs().LoadUserConfigData(settingsData, iSize))
{
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to load user config data");
return false;
}*/
}
}
catch (System.Exception e)
@@ -486,7 +501,7 @@ public partial class CECGameRun
string szRet = null;
if (i >= 0 && i < (int)Profession.NUM_PROFESSION)
{
int[] s_ProfDesc = {
int[] s_ProfDesc = {
(int)FixedMsg.FIXMSG_PROF_WARRIOR,
(int)FixedMsg.FIXMSG_PROF_MAGE,
(int)FixedMsg.FIXMSG_PROF_MONK,
+529 -112
View File
@@ -18,10 +18,12 @@ using PerfectWorld.Scripts.Managers;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using static BrewMonster.Scripts.Managers.EC_Inventory;
using Host_work_ID = BrewMonster.Scripts.CECHPWork.Host_work_ID;
using Trace_reason = BrewMonster.CECHPWorkTrace.Trace_reason;
@@ -87,6 +89,8 @@ namespace BrewMonster
private CECSkill m_pTargetItemSkill; // Target item skill
public CECComboSkill m_pComboSkill; // Combo skill
public A3DVECTOR3 m_vAccel; // Accelerate\
public byte m_RealmLevel;
REINCARNATION_TOME m_ReincarnationTome; // תÉú
public bool m_bRushFly = false; // true, in rush fly mode
private CECCounter m_IncantCnt;
@@ -155,6 +159,8 @@ namespace BrewMonster
private UnityEngine.InputSystem.Mouse m_cachedMouse;
private UnityEngine.InputSystem.Keyboard m_cachedKeyboard;
int[] targetsCastSkill;
public bool IsChangingFace()
{
return m_bChangingFace;
@@ -162,13 +168,16 @@ namespace BrewMonster
// ===== Inventory packs (instance-based) =====
// 0 = normal pack, 1 = equip pack, 2 = task pack (see InventoryConst.IVTRTYPE_*)
private readonly EC_Inventory m_packInventory = new EC_Inventory();
private readonly EC_Inventory m_equipInventory = new EC_Inventory();
private readonly EC_Inventory m_taskInventory = new EC_Inventory();
private readonly EC_Inventory m_pPack = new EC_Inventory();
/// <summary>
/// m_pEquipPack is changed to m_equipInventory
/// </summary>
private readonly EC_Inventory m_pEquipPack = new EC_Inventory();
private readonly EC_Inventory m_pTaskPack = new EC_Inventory();
public EC_Inventory PackInventory => m_packInventory;
public EC_Inventory EquipInventory => m_equipInventory;
public EC_Inventory TaskInventory => m_taskInventory;
public EC_Inventory IvtrPack => m_pPack;
public EC_Inventory IvtrEquipPack => m_pEquipPack;
public EC_Inventory IvtrTaskPack => m_pTaskPack;
public Transform PointCam { get => pointCam; }
@@ -187,10 +196,18 @@ namespace BrewMonster
{
return m_pAutoTeam;
}
public EC_Inventory GetPack()
{
return m_pPack;
}
public EC_Inventory GetTaskPack()
{
return m_taskInventory;
return m_pTaskPack;
}
public EC_Inventory GetEquipment()
{
return m_pEquipPack;
}
// Get work manager // 获取工作管理器
@@ -244,11 +261,11 @@ namespace BrewMonster
switch (byPackage)
{
case InventoryConst.IVTRTYPE_PACK:
return m_packInventory;
return m_pPack;
case InventoryConst.IVTRTYPE_EQUIPPACK:
return m_equipInventory;
return m_pEquipPack;
case InventoryConst.IVTRTYPE_TASKPACK:
return m_taskInventory;
return m_pTaskPack;
default:
return null;
}
@@ -289,6 +306,7 @@ namespace BrewMonster
public bool LoadResources()
{
//BMLogger.LogError("HoangDev: CECHostPlayer::LoadResources");
RoleInfo RoleInfo = UnityGameSession.Instance.GetRoleInfo();
m_iProfession = RoleInfo.occupation;
m_iGender = RoleInfo.gender;
@@ -536,6 +554,9 @@ namespace BrewMonster
case int value when value == EC_MsgDef.MSG_HST_PICKUPITEM:
OnMsgHstPickupItem(Msg);
break;
case int value when value == EC_MsgDef.MSG_HST_PRODUCEITEM:
OnMsgHstProduceItem(Msg);
break;
case int value when value == EC_MsgDef.MSG_HST_SELTARGET:
OnMsgHstSelTarget(Msg); break;
case int value when value == EC_MsgDef.MSG_HST_ATKRESULT: OnMsgHstAttackResult(Msg); break;
@@ -560,6 +581,8 @@ namespace BrewMonster
case int value when value == EC_MsgDef.MSG_HST_COOLTIMEDATA: OnMsgHstCoolTimeData(Msg); break;
case int value when value == EC_MsgDef.MSG_HST_SETCOOLTIME: OnMsgHstSetCoolTime(Msg); break;
case int value when value == EC_MsgDef.MSG_HST_PRESSCANCEL: OnMsgHstPressCancel(Msg); break;
case int value when value == EC_MsgDef.MSG_HST_LEARNSKILL: OnMsgHstLearnSkill(Msg); break;
case int value when value == EC_MsgDef.MSG_PM_PLAYERFLY: OnMsgPlayerFly(Msg); break;
}
@@ -584,6 +607,53 @@ namespace BrewMonster
}*/
}
private void OnMsgHstLearnSkill(ECMSG Msg)
{
BMLogger.LogError("OnMsgHstLearnSkill");
cmd_learn_skill pCmd = GPDataTypeHelper.FromBytes<cmd_learn_skill>((byte[])Msg.dwParam1);
CECSkill pSkill = GetNormalSkill(pCmd.skill_id);
if (pSkill != null)
{
if (pCmd.skill_level > 0)
{
pSkill.LevelUp();
ElementSkill.SetLevel((uint)pCmd.skill_id, pCmd.skill_level);
}
else
{
RemoveNormalSkill(pCmd.skill_id);
}
}
else if (pCmd.skill_level > 0)
{
pSkill = new CECSkill(pCmd.skill_id, pCmd.skill_level);
if (pSkill == null)
{
Debug.Assert(pSkill != null);
return;
}
if (!pSkill.GetJunior().Empty())
{
ReplaceJuniorSkill(pSkill);
}
else
{
if (pSkill.GetType() != (int)CECSkill.SkillType.TYPE_PASSIVE &&
pSkill.GetType() != (int)CECSkill.SkillType.TYPE_PRODUCE &&
pSkill.GetType() != (int)CECSkill.SkillType.TYPE_LIVE)
m_aPtSkills.Add(pSkill);
else
m_aPsSkills.Add(pSkill);
}
ElementSkill.SetLevel((uint)pCmd.skill_id, pCmd.skill_level);
}
CECHostSkillModel.Instance.OnLearnSkill(pCmd.skill_id, pCmd.skill_level);
}
private void OnMsgHstSetCoolTime(ECMSG Msg)
{
BMLogger.LogError("HoangDev : OnMsgHstSetCoolTime ");
@@ -609,15 +679,15 @@ namespace BrewMonster
// other goblin skills should be set public cool down, 1 second
/* for (i = 0; i < m_aGoblinSkills.GetSize(); i++)
{
if (m_aGoblinSkills[i] && m_aGoblinSkills[i].GetCoolingCnt() == 0)
m_aGoblinSkills[i].StartCooling(GetCoolTime(GP_CT_CAST_ELF_SKILL), GetCoolTime(GP_CT_CAST_ELF_SKILL));
if (m_aGoblinSkills[i] && m_aGoblinSkills[i]->GetCoolingCnt() == 0)
m_aGoblinSkills[i]->StartCooling(GetCoolTime(GP_CT_CAST_ELF_SKILL), GetCoolTime(GP_CT_CAST_ELF_SKILL));
}*/
/* for (i = 0; i < m_aPsSkills.Count; i++)
{
CECSkill pSkill = GetPassiveSkillByIndex(i);
if (pSkill && (pSkill.GetCommonCoolDown() & (1 << (pCmd.cooldown_index - GP_CT_SKILLCOMMONCOOLDOWN0))))
pSkill.StartCooling(GetCoolTime(pCmd.cooldown_index), GetCoolTime(pCmd.cooldown_index));
if (pSkill && (pSkill->GetCommonCoolDown() & (1 << (pCmd->cooldown_index - GP_CT_SKILLCOMMONCOOLDOWN0))))
pSkill->StartCooling(GetCoolTime(pCmd->cooldown_index), GetCoolTime(pCmd->cooldown_index));
}*/
}
@@ -662,7 +732,7 @@ namespace BrewMonster
}
/* else if (pSkill = CECComboSkillState::Instance().GetInherentSkillByID(idSkill))
{
pSkill.StartCooling(pCmd.cooldown_time, pCmd.cooldown_time);
pSkill->StartCooling(pCmd->cooldown_time, pCmd->cooldown_time);
}*/
else if (GetEquipSkillByID(idSkill) == null)
{
@@ -1881,18 +1951,7 @@ namespace BrewMonster
uint slot_amount = BitConverter.ToUInt32(data, 12);
byte where = data[16]; // Package index
byte index = data[17]; // Slot index in that package
// Create new inventory item data
var newItem = new EC_IvtrItem
{
Package = where,
Slot = index,
m_tid = type,
m_expire_date = expire_date,
State = 0,
m_iCount = (int)amount,
Crc = 0,
Content = null
};
var newItem = EC_IvtrItem.CreateItem(type, expire_date, (int)amount);
// Add item to inventory
var ivt = GetInventory(where);
@@ -1936,17 +1995,7 @@ namespace BrewMonster
}
// Create new inventory item data
var newItem = new EC_IvtrItem
{
Package = byPackage,
Slot = bySlot,
m_tid = tid,
m_expire_date = expire_date,
State = 0,
m_iCount = (int)iAmount,
Crc = 0,
Content = null
};
var newItem = EC_IvtrItem.CreateItem(tid, expire_date, (int)iAmount);
// Add item to inventory
var ivt = GetInventory(byPackage);
@@ -1983,17 +2032,7 @@ namespace BrewMonster
// Create new inventory item data
var taskNewItem = new EC_IvtrItem
{
Package = (byte)iPack,
Slot = iCmdLastSlot,
m_tid = idItem,
m_expire_date = iExpireDate,
State = 0,
m_iCount = (int)iAmount,
Crc = 0,
Content = null
};
var taskNewItem = EC_IvtrItem.CreateItem(idItem, iExpireDate, (int)iAmount);
// Add item to inventory
var task_ivt = GetInventory((byte)iPack);
@@ -2014,9 +2053,119 @@ namespace BrewMonster
}
break;
case CommandID.PRODUCE_ONCE:
{
// Parse cmd_produce_once struct data
cmd_produce_once produceCmd = GPDataTypeHelper.FromBytes<cmd_produce_once>(data);
int produceItemId = produceCmd.type;
int produceExpireDate = 0;
uint produceAmount = produceCmd.amount;
byte producePack = produceCmd.where;
byte produceSlot = produceCmd.index;
// TODO: Handle other pickup item commands if necessary
Debug.Log($"[PRODUCE_ONCE] Received: itemId={produceItemId}, amount={produceAmount}, pack={producePack}, slot={produceSlot}");
// Get inventory
var produce_ivt = GetInventory(producePack);
if (produce_ivt == null)
{
Debug.LogWarning($"[PRODUCE_ONCE] Invalid inventory package {producePack}");
return;
}
// Check if the slot already has an item
var existingItem = produce_ivt.GetItem(produceSlot, false);
if (existingItem != null)
{
if (existingItem.m_tid == produceItemId)
{
existingItem.m_iCount = (int)produceAmount;
Debug.Log($"[PRODUCE_ONCE] Updated existing item count at slot {produceSlot} to {produceAmount}");
}
else
{
Debug.LogWarning($"[PRODUCE_ONCE] Slot {produceSlot} already has different item (tid={existingItem.m_tid}), not overwriting with {produceItemId}");
return;
}
}
else
{
var produceNewItem = new EC_IvtrItem
{
Package = producePack,
Slot = produceSlot,
m_tid = produceItemId,
m_expire_date = produceExpireDate,
State = 0,
m_iCount = (int)produceAmount,
Crc = 0,
Content = null
};
produce_ivt.SetItem(produceSlot, produceNewItem);
Debug.Log($"[PRODUCE_ONCE] Created new item at slot {produceSlot} with count {produceAmount}");
}
// Trigger UI refresh
var produce_ui = GameObject.FindFirstObjectByType<EC_InventoryUI>();
if (produce_ui != null)
{
produce_ui.RefreshAll();
}
UpdateEquipSkins();
// Notify DlgProduce
var dlgProduce = GameObject.FindFirstObjectByType<DlgProduce>();
if (dlgProduce != null)
{
dlgProduce.OnProduceOnce(produceCmd);
}
}
break;
}
}
public void OnMsgHstProduceItem(in ECMSG Msg)
{
var data = Msg.dwParam1 as byte[];
int cmd = Convert.ToInt32(Msg.dwParam2);
// Get DlgProduce to notify
var dlgProduce = GameObject.FindFirstObjectByType<DlgProduce>();
if (dlgProduce == null)
{
Debug.LogWarning("[OnMsgHstProduceItem] DlgProduce not found");
return;
}
switch (cmd)
{
case CommandID.PRODUCE_START:
{
cmd_produce_start pCmd = GPDataTypeHelper.FromBytes<cmd_produce_start>(data);
Debug.Log($"[PRODUCE_START] type={pCmd.type}, use_time={pCmd.use_time}, count={pCmd.count}");
dlgProduce.OnProduceStart(pCmd);
}
break;
case CommandID.PRODUCE_END:
{
Debug.Log("[PRODUCE_END] Production ended");
dlgProduce.OnProduceEnd();
}
break;
case CommandID.PRODUCE_NULL:
{
cmd_produce_null pCmd = GPDataTypeHelper.FromBytes<cmd_produce_null>(data);
Debug.Log($"[PRODUCE_NULL] type={pCmd.type}");
dlgProduce.OnProduceNull(pCmd);
}
break;
default:
Debug.LogWarning($"[OnMsgHstProduceItem] Unknown command: {cmd}");
break;
}
}
@@ -2180,6 +2329,9 @@ namespace BrewMonster
try
{
var money = GPDataTypeHelper.FromBytes<CSNetwork.GPDataType.cmd_get_own_money>(data);
SetMoneyAmount(money.amount);
var ui = GameObject.FindFirstObjectByType<BrewMonster.Scripts.Managers.EC_InventoryUI>();
if (ui == null)
{
@@ -2436,7 +2588,7 @@ namespace BrewMonster
m_bEnterGame = false;
}
CECSkill GetNormalSkill(int id, bool bSenior = false /* false */)
public CECSkill GetNormalSkill(int id, bool bSenior = false /* false */)
{
CECSkill pSkill = null;
if (ElementSkill.GetType((uint)id) == (byte)CECSkill.SkillType.TYPE_PASSIVE ||
@@ -2480,6 +2632,7 @@ namespace BrewMonster
// roleName = Encoding.UTF8.GetString(role.name.ByteArray, 0, role.name.Length);
//}
SetPlayerInfor(new INFO(role.cid, role.crc_e, role.crc_c));
LoadResources();
await SetPlayerModel(UnityGameSession.Instance.GetRoleInfo().occupation,
UnityGameSession.Instance.GetRoleInfo().gender);
isDataAwaitToReady = true;
@@ -2554,7 +2707,6 @@ namespace BrewMonster
m_pWorkMan.StartWork_p1(pWork);
}*/
//m_GndInfo.bOnGround = GroundCheck(out lastGroundHit);
LoadResources();
if (m_pWorkMan == null)
{
return;
@@ -2592,13 +2744,13 @@ namespace BrewMonster
}*/
m_dwMoveRelDir = 0;
if (!CanDo(ActionCanDo.CANDO_MOVETO)) return;
if(joystick.Vertical > 0)
if (joystick.Vertical > 0)
{
if(joystick.Horizontal > 0)
if (joystick.Horizontal > 0)
{
m_dwMoveRelDir |= (uint)(MOVE_DIR.MD_FORWARD | MOVE_DIR.MD_RIGHT);
}
else if(joystick.Horizontal < 0)
else if (joystick.Horizontal < 0)
{
m_dwMoveRelDir |= (uint)(MOVE_DIR.MD_FORWARD | MOVE_DIR.MD_LEFT);
}
@@ -3061,8 +3213,6 @@ namespace BrewMonster
{
if (cooldown_index < 0)
{
// 更新所有装备技能
// Update all equipment skills
for (int i = 0; i < GetEquipSkillNum(); ++i)
{
@@ -3094,8 +3244,6 @@ namespace BrewMonster
}
else
{
// 更新指定技能
// Update specified skill
if (cooldown_index > (int)CoolTimeIndex.GP_CT_SKILL_START)
{
int idSkill = cooldown_index - (int)CoolTimeIndex.GP_CT_SKILL_START;
@@ -3655,11 +3803,6 @@ namespace BrewMonster
}
}
public EC_Inventory GetPack()
{
return m_packInventory;
}
private void LogInventoryPacket(string tag, byte[] buffer, int hostId)
{
if (buffer == null)
@@ -3770,7 +3913,10 @@ namespace BrewMonster
// Handle instant skills
if (m_pPrepSkill.IsInstant())
{
UnityGameSession.c2s_CmdCastInstantSkill(m_pPrepSkill.GetSkillID(), byPVPMask, 1, idTarget);
int countTarget = 1;
targetsCastSkill = new int[countTarget];
targetsCastSkill[0] = idTarget;
UnityGameSession.c2s_CmdCastInstantSkill(m_pPrepSkill.GetSkillID(), byPVPMask, countTarget, targetsCastSkill);
m_pPrepSkill = null;
}
// Handle flash move skills (瞬移技能)
@@ -3940,7 +4086,10 @@ namespace BrewMonster
{
// Regular skill casting
byte byPVPMask2 = glb_BuildPVPMask(bForceAttack);
UnityGameSession.c2s_CmdCastSkill(m_pPrepSkill.GetSkillID(), byPVPMask2, 1, idTarget);
int targets = 1;
targetsCastSkill = new int[targets];
targetsCastSkill[0] = idTarget;
UnityGameSession.c2s_CmdCastSkill(m_pPrepSkill.GetSkillID(), byPVPMask2, targets, targetsCastSkill);
}
return true;
@@ -4009,7 +4158,7 @@ namespace BrewMonster
{
// Use host player's equipment inventory (per-instance CECInventory)
var host = CECGameRun.Instance?.GetHostPlayer();
var equipInv = host?.EquipInventory;
var equipInv = host?.IvtrEquipPack;
pItem = equipInv?.GetItem(i, false);
if (pItem != null)
aNewEquips[i] = pItem.m_tid;
@@ -4109,6 +4258,7 @@ namespace BrewMonster
return null;
}
public int GetMaxLevelSofar() { return Math.Max(m_ReincarnationTome.max_level, m_BasicProps.iLevel); }
// C# conversion of CECHostPlayer::GetEquipSkillByID
// Assumes: GetEquipSkillNum() returns the count of equipment skills
@@ -4176,7 +4326,7 @@ namespace BrewMonster
Info.mp = m_BasicProps.iCurMP;
Info.ap = m_BasicProps.iCurAP;
Info.form = m_iShape; // Different from PW, no need to mask
Info.freepackage = m_packInventory.GetEmptySlotNum();
Info.freepackage = m_pPack.GetEmptySlotNum();
Info.move_env = GetMoveEnv();
Info.is_combat = IsFighting();
Info.hp = m_BasicProps.iCurHP;
@@ -4191,7 +4341,7 @@ namespace BrewMonster
Info.weapon = 0;
Info.arrow = 0;
EC_IvtrItem pWeaponItem = m_equipInventory.GetItem(EQUIPIVTR_WEAPON);
EC_IvtrItem pWeaponItem = m_pEquipPack.GetItem(EQUIPIVTR_WEAPON);
if (pWeaponItem != null && pWeaponItem is EC_IvtrEquip pWeaponEquip)
{
// Check if weapon has endurance
@@ -4204,7 +4354,7 @@ namespace BrewMonster
}
// Get remaining arrow number
EC_IvtrItem pArrowItem = m_equipInventory.GetItem(EQUIPIVTR_PROJECTILE);
EC_IvtrItem pArrowItem = m_pEquipPack.GetItem(EQUIPIVTR_PROJECTILE);
if (pArrowItem != null)
{
// TODO: Implement CanUseProjectile method to check requirements
@@ -5197,6 +5347,7 @@ namespace BrewMonster
// }
// UpdateMonsterSpiritGfx(dwDeltaTime);
}
public byte GetRealmLevel() { return m_RealmLevel; }
// Level up
public void LevelUp()
@@ -5408,7 +5559,7 @@ namespace BrewMonster
}
// Can jump or take off in water ?
bool IsSitting()
public bool IsSitting()
{
return (m_dwStates & PlayerNPCState.GP_STATE_SITDOWN) != 0 ? true : false;
}
@@ -5420,7 +5571,7 @@ namespace BrewMonster
}
// Is host player talking with NPC ?
bool IsTalkingWithNPC()
public bool IsTalkingWithNPC()
{
return m_bTalkWithNPC;
}
@@ -5782,13 +5933,13 @@ namespace BrewMonster
// Get cool time
public int GetCoolTime(int iIndex, ref int piMax /* NULL */)
{
// if (iIndex >= 0 && iIndex < GP_CT_MAX)
// {
// if (piMax>0)
// piMax = m_aCoolTimes[iIndex].iMaxTime;
//
// return m_aCoolTimes[iIndex].iCurTime;
// }
if (iIndex >= 0 && iIndex < (int)CoolTimeIndex.GP_CT_MAX)
{
if (piMax > 0)
piMax = m_aCoolTimes[iIndex].iMaxTime;
return m_aCoolTimes[iIndex].iCurTime;
}
return 0;
}
@@ -5926,7 +6077,27 @@ namespace BrewMonster
NameHostPlayer = name;
}
}
public struct REINCARNATION_TOME
{
public int tome_exp;
public char tome_active; // 1¼¤»î0δ¼¤»î
public int max_level; // ÀúÊ·×î¸ßµÈ¼¶
cmd_reincarnation_tome_info._entry[] reincarnations;
static int max_exp;
};
public struct cmd_reincarnation_tome_info
{
public int tome_exp;
public char tome_active; // 1¼¤»î0δ¼¤»î
public int count;
public struct _entry
{
int level;
int timestamp;
int exp;
}
public _entry[] records;
};
// Behavior id used by CanDo()
public static class ActionCanDo
@@ -5964,7 +6135,7 @@ namespace BrewMonster
}
else
{
if (PackInventory.CanAddItem(idItem, iAmount, false) >= 0)
if (IvtrPack.CanAddItem(idItem, iAmount, false) >= 0)
bCanPick = true;
}
@@ -5992,14 +6163,14 @@ namespace BrewMonster
if (idTool != 0)
{
int iIndex = PackInventory.FindItem(idTool);
int iIndex = IvtrPack.FindItem(idTool);
if (iIndex >= 0)
{
piPack = EC_Inventory.Inventory_type.IVTRTYPE_PACK;
piIndex = iIndex;
pidTool = idTool;
}
else if ((iIndex = TaskInventory.FindItem(idTool)) >= 0)
else if ((iIndex = IvtrTaskPack.FindItem(idTool)) >= 0)
{
piPack = EC_Inventory.Inventory_type.IVTRTYPE_TASKPACK;
piIndex = iIndex;
@@ -6079,31 +6250,7 @@ namespace BrewMonster
}
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct REINCARNATION_TOME
{
public int tome_exp;
public char tome_active; // 1已激活0未激活 / 1 activated 0 not activated
public int max_level; // 历史最高等级 / Historical highest level
public List<cmd_reincarnation_tome_info._entry> reincarnations;
public const int max_exp = 0; // TODO: Set actual value
public void Clear(){
tome_exp = 0;
tome_active = (char)0;
max_level = 0;
if (reincarnations != null)
{
reincarnations.Clear();
}
else
{
reincarnations = new List<cmd_reincarnation_tome_info._entry>();
}
}
};
REINCARNATION_TOME m_ReincarnationTome;
public int GetMaxLevelSofar() { return Math.Max(m_ReincarnationTome.max_level, m_BasicProps.iLevel);}
public CECCounter GetGatherCnt() { return m_GatherCnt; }
public void UpdateTimers(float dwDeltaTime)
@@ -6278,6 +6425,160 @@ namespace BrewMonster
}
}
// Remove skill reference / 删除技能引用
void RemoveSkillReference(int idSkill)
{
if (idSkill <= 0) return;
// Remove reference to self skill / 删除对技能的引用
if (m_pPrepSkill != null && m_pPrepSkill.GetSkillID() == idSkill)
m_pPrepSkill = null;
if (m_pCurSkill != null && m_pCurSkill.GetSkillID() == idSkill)
m_pCurSkill = null;
if (m_pComboSkill != null && m_pComboSkill.FindSkillID(idSkill))
ClearComboSkill();
if (m_pWorkMan != null)
{
CECHPWork pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT);
if (pWork != null)
{
CECHPWorkTrace pWorkTrace = pWork as CECHPWorkTrace;
if (pWorkTrace != null &&
pWorkTrace.GetTraceReason() == CECHPWorkTrace.Trace_reason.TRACE_SPELL &&
pWorkTrace.GetPrepSkill() != null &&
pWorkTrace.GetPrepSkill().GetSkillID() == idSkill)
pWorkTrace.Reset();
}
}
int i;
for (i = 0; i < HostCfgConstants.NUM_HOSTSCSETS1; i++)
{
if (m_aSCSets1[i] != null)
m_aSCSets1[i].RemoveSkillShortcut(idSkill);
}
for (i = 0; i < HostCfgConstants.NUM_HOSTSCSETS2; i++)
{
if (m_aSCSets2[i] != null)
m_aSCSets2[i].RemoveSkillShortcut(idSkill);
}
}
// Remove skill / 删除技能
void RemoveNormalSkill(int idSkill)
{
// Delete equipped skills / 删除装备技能
if (idSkill <= 0) return;
RemoveSkillReference(idSkill);
// Delete skill list pointer / 删除技能列表指针
int i;
for (i = 0; i < m_aPtSkills.Count; i++)
{
if (m_aPtSkills[i].GetSkillID() == idSkill)
{
m_aPtSkills.RemoveAt(i);
return;
}
}
for (i = 0; i < m_aPsSkills.Count; i++)
{
if (m_aPsSkills[i].GetSkillID() == idSkill)
{
m_aPsSkills.RemoveAt(i);
return;
}
}
for (i = 0; i < m_aGoblinSkills.Count; i++)
{
if (m_aGoblinSkills[i].GetSkillID() == idSkill)
{
m_aGoblinSkills.RemoveAt(i);
return;
}
}
}
// Clear combo skill / 清除连击技能
void ClearComboSkill()
{
if (m_pComboSkill != null)
{
m_pComboSkill = null;
}
}
// Replace specified skill with it's senior skill / 用高级技能替换指定的低级技能
void ReplaceJuniorSkill(CECSkill pSeniorSkill)
{
if (pSeniorSkill == null)
{
Debug.Assert(pSeniorSkill != null);
return;
}
SkillArrayWrapper juniorArray = pSeniorSkill.GetJunior();
if (juniorArray.Empty())
{
Debug.Assert(false);
return;
}
int i;
// Update shortcuts ... / 更新快捷方式...
for (i = 0; i < HostCfgConstants.NUM_HOSTSCSETS1; i++)
{
if (m_aSCSets1[i] != null)
m_aSCSets1[i].ReplaceSkillID(juniorArray, pSeniorSkill);
}
for (i = 0; i < HostCfgConstants.NUM_HOSTSCSETS2; i++)
{
if (m_aSCSets2[i] != null)
m_aSCSets2[i].ReplaceSkillID(juniorArray, pSeniorSkill);
}
// Update skill groups ... / 更新技能组...
// Note: Combo skill update logic may need to be added here
// Original C++ code had EC_VIDEO_SETTING and combo skill group logic
}
public int CheckSkillLearnCondition(int idSkill, bool bCheckBook)
{
int iLevel = 1;
CECSkill pSkill = GetNormalSkill(idSkill);
if (pSkill != null)
iLevel = pSkill.GetSkillLevel() + 1;
if (iLevel == 1 && bCheckBook)
{
// Do we have the skill book ?
int idBook = ElementSkill.GetRequiredBook((uint)idSkill, iLevel);
if (idBook != 0 /*&& m_pPack.FindItem(idBook) < 0*/)
return 8;
}
// Build player information
LearnRequirement Info;
Info.level = GetMaxLevelSofar();
Info.sp = m_BasicProps.iSP;
Info.money = (int)m_iMoneyCnt;
Info.profession = m_iProfession;
Info.rank = m_BasicProps.iLevel2;
Info.realm_level = GetRealmLevel();
return ElementSkill.LearnCondition((uint)idSkill, Info, iLevel);
}
private void OnMsgHstPressCancel(ECMSG Msg)
{
CECHPWork pCurWork = null;
@@ -6386,11 +6687,11 @@ namespace BrewMonster
if (!CanDo(ActionCanDo.CANDO_FLY))
return false;
EC_IvtrItem pItem = EquipInventory.GetItem(InventoryConst.EQUIPIVTR_FLYSWORD);
EC_IvtrItem pItem = IvtrEquipPack.GetItem(InventoryConst.EQUIPIVTR_FLYSWORD);
if (pItem == null)
return false;
if(pItem is EC_IvtrEquip)
if (pItem is EC_IvtrEquip)
{
if ((pItem as EC_IvtrEquip).IsDestroying())
return false;
@@ -6410,7 +6711,7 @@ namespace BrewMonster
return false;
}
UnityGameSession.c2s_CmdUseItem(InventoryConst.IVTRTYPE_EQUIPPACK, InventoryConst.EQUIPIVTR_FLYSWORD, pItem.GetTemplateID(), 1);
UnityGameSession.c2s_SendCmdUseItem(InventoryConst.IVTRTYPE_EQUIPPACK, InventoryConst.EQUIPIVTR_FLYSWORD, pItem.GetTemplateID(), 1);
return true;
}
@@ -6462,5 +6763,121 @@ namespace BrewMonster
m_bRushFly = pCmd.is_active != 0 ? true : false;
}
}
public EC_Inventory GetPack(int iPack)
{
EC_Inventory pInventory = null;
switch (iPack)
{
case Inventory_type.IVTRTYPE_PACK: pInventory = m_pPack; break;
case Inventory_type.IVTRTYPE_EQUIPPACK: pInventory = m_pEquipPack; break;
case Inventory_type.IVTRTYPE_TASKPACK: pInventory = m_pTaskPack; break;
//case Inventory_type.IVTRTYPE_TRASHBOX: pInventory = m_pTrashBoxPack; break;
//case Inventory_type.IVTRTYPE_TRASHBOX2: pInventory = m_pTrashBoxPack2; break;
//case Inventory_type.IVTRTYPE_TRASHBOX3: pInventory = m_pTrashBoxPack3; break;
//case Inventory_type.IVTRTYPE_ACCOUNT_BOX: pInventory = m_pAccountBoxPack; break;
//case Inventory_type.IVTRTYPE_GENERALCARD_BOX: pInventory = m_pGeneralCardPack; break;
//case IVTRTYPE_PACK_CLIENT_GENERALCAR.IVTRTYPE_CLIENT_GENERALCARD_PACK: pInventory = m_pClientGenCardPack; break;
default:
return null;
}
return pInventory;
}
public int GetEquippedSuiteItem(int idSuite, ref int[] aItems)
{
int i, iItemCnt = 0;
for(i = 0; i < m_pEquipPack.GetSize(); i++)
{
var pItem = m_pEquipPack.GetItem(i);
if(pItem == null || (pItem is not EC_IvtrWeapon && pItem is not EC_IvtrArmor))
{
continue;
}
EC_IvtrEquip pEquip = (EC_IvtrEquip)pItem;
if (pEquip == null)
{
continue;
}
if(pEquip.GetSuiteID() != idSuite)
{
continue;
}
int iReason = 0;
if(!CanUseEquipment(pEquip, ref iReason))
{
continue;
}
if(pEquip.CID == (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_GENERALCARD)
{
//TODO: Add general card Suite
}
if(aItems.Length > 0)
{
aItems[iItemCnt] = pEquip.GetTemplateID();
}
iItemCnt++;
}
return iItemCnt;
}
bool CanUseEquipment(EC_IvtrEquip pEquip, ref int piReason)
{
int iReason = 0;
if(pEquip == null)
{
iReason = 1;
goto End;
}
if(GetMaxLevelSofar() < pEquip.LevelReq||
m_ExtProps.bs.strength < pEquip.StrengthReq||
m_ExtProps.bs.agility < pEquip.AgilityReq||
m_ExtProps.bs.vitality < pEquip.VitalityReq||
m_ExtProps.bs.energy < pEquip.EnergyReq/*||
Reputation < pEquip.ReputationReq*/)//todo Add reputation check
{
iReason = 2;
goto End;
}
switch(pEquip.CID)//class id
{
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_ARROW:
break;
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_WING:
if (m_iProfession != (int)PROFESSION.PROF_ARCHOR && m_iProfession != (int)PROFESSION.PROF_ANGEL)
iReason = 3;
break;
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_FLYSWORD:
//TODO: Add flysword check
break;
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_FASHION:
//TODO: Add fashion check
break;
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_ARMOR:
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_DECORATION:
if ((pEquip.ProfReq & (1 << m_iProfession)) == 0)
iReason = 3;
break;
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_WEAPON:
if ((pEquip.ProfReq & (1 << m_iProfession)) == 0)
iReason = 3;
else
{
//TODO: check range weapon arrow
}
break;
case (int)EC_IvtrEquip.EQUIP_CLASS_ID.ICID_GENERALCARD:
// TODO: Add general card check
break;
default:
break;
}
End:
if(piReason > 0)
{
piReason = iReason;
}
return iReason == 0? true : false;
}
}
}
+1 -1
View File
@@ -147,7 +147,7 @@ namespace BrewMonster
{
// Use host player's equipment inventory (per-instance CECInventory)
var host = CECGameRun.Instance?.GetHostPlayer();
var equipInv = host?.EquipInventory;
var equipInv = host?.IvtrEquipPack;
pItem = equipInv?.GetItem(i, false);
if (pItem != null)
aNewEquips[i] = pItem.m_tid;
+96 -7
View File
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using BrewMonster;
using BrewMonster.Network;
using BrewMonster.UI;
using CSNetwork;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UIElements;
public class CECUIManager : MonoSingleton<CECUIManager>
{
@@ -21,20 +23,23 @@ public class CECUIManager : MonoSingleton<CECUIManager>
[SerializeField] private DialogScriptTableObject dialogResouce;
[SerializeField] private Canvas canvasDlg;
[SerializeField] private CDlgQuickBar cDlgQuickBar;
[SerializeField] private Button btnSecondClick;
[SerializeField] private UnityEngine.UI.Button btnSecondClick;
[SerializeField] CDlgQuickBar m_pDlgQuickBar1;
CDlgMessageBox m_pDlgMessageBox;
public CDlgSkillAction m_pDlgSkillAction;
protected override void Awake()
{
base.Awake();
EventBus.Subscribe<CECHostPlayer.NPCINFO>(ShowUINPC);
EventBus.Subscribe<NPCDiedEvent>(TryHideUINPC);
EventBus.Subscribe<MessageBoxEvent>(OnMessageBox);
gameUI = new CECGameUIMan();
gameUI.SetDependency(dialogResouce, canvasDlg);
gameUI.Init();
m_pDlgSkillAction = GetComponent<CDlgSkillAction>();
// Wire up second-click button / 连接第二次点击按钮
if (btnSecondClick != null)
{
@@ -53,7 +58,7 @@ public class CECUIManager : MonoSingleton<CECUIManager>
{
EventBus.Unsubscribe<CECHostPlayer.NPCINFO>(ShowUINPC);
EventBus.Unsubscribe<NPCDiedEvent>(TryHideUINPC);
EventBus.Unsubscribe<MessageBoxEvent>(OnMessageBox);
}
private void ShowUINPC(CECHostPlayer.NPCINFO obj)
@@ -65,7 +70,7 @@ public class CECUIManager : MonoSingleton<CECUIManager>
}
public CDlgQuickBar GetCDlgQuickBar()
{
return cDlgQuickBar;
return m_pDlgQuickBar1;
}
private void TryHideUINPC(NPCDiedEvent obj)
{
@@ -97,6 +102,80 @@ public class CECUIManager : MonoSingleton<CECUIManager>
Debug.LogWarning($"Không tìm thấy UI {componentName} đã spawn trong canvasDlg. Type found: {(type != null ? type.FullName : "null")}");
}
public CDlgMessageBox ShowMessageBox(string title, string message)
{
var msgBox = GetInGameUIMan().GetDialog("DlgMessageBox") as CDlgMessageBox;
if (msgBox != null)
{
msgBox.ShowMessageBox(title, message);
return msgBox;
}
else
{
Debug.LogError("DlgMessageBox not found in InGameUIMan");
}
return null;
}
private void OnMessageBox(MessageBoxEvent messageBoxEvent)
{
BMLogger.LogError("CECUIManager OnMessageBox called");
int iRetVal = messageBoxEvent.iRetVal;
AUIDialog pDlg = messageBoxEvent.pDlg;
if (pDlg == m_pDlgMessageBox)
{
OnNewMessageBox(iRetVal);
return;
}
UnityGameSession pSession = UnityGameSession.Instance;
CECHostPlayer pHost = CECGameRun.Instance.GetHostPlayer();
if (string.Equals(pDlg.GetName(), "Game_Quit", StringComparison.OrdinalIgnoreCase))
{
}
else if ((string.Equals(pDlg.GetName(), "Game_TeachSkill", StringComparison.OrdinalIgnoreCase) && DialogBoxCommandIDs.IDOK == iRetVal) ||
(string.Equals(pDlg.GetName(), "Game_LearnSkill", StringComparison.OrdinalIgnoreCase) && DialogBoxCommandIDs.IDOK == iRetVal))
{
if (string.Equals(pDlg.GetName(), "Game_TeachSkill", StringComparison.OrdinalIgnoreCase))
{
}
else if (string.Equals(pDlg.GetName(), "Game_LearnSkill", StringComparison.OrdinalIgnoreCase))
{
int skillID = (int)pDlg.GetData();
int nCondition = pHost.CheckSkillLearnCondition(skillID, true);
if (0 == nCondition)
{
UnityGameSession.c2s_SendCmdNPCSevLearnSkill(skillID);
}
/*else if (1 == nCondition)
AddChatMessage(GetStringFromTable(270), GP_CHAT_MISC);
else if (6 == nCondition)
AddChatMessage(GetStringFromTable(527), GP_CHAT_MISC);
else if (7 == nCondition)
AddChatMessage(GetStringFromTable(541), GP_CHAT_MISC);
else if (8 == nCondition)
AddChatMessage(GetStringFromTable(271), GP_CHAT_MISC);
else if (9 == nCondition)
AddChatMessage(GetStringFromTable(556), GP_CHAT_MISC);
else if (10 == nCondition)
AddChatMessage(GetStringFromTable(557), GP_CHAT_MISC);
else if (12 == nCondition)
AddChatMessage(GetStringFromTable(11168), GP_CHAT_MISC);*/
}
}
}
private bool OnNewMessageBox(int iRetVal)
{
return true;
}
private System.Type FindTypeByName(string componentName)
{
@@ -270,4 +349,14 @@ public class CECUIManager : MonoSingleton<CECUIManager>
}
}
}
public struct MessageBoxEvent
{
public int iRetVal;
public AUIDialog pDlg;
public MessageBoxEvent(int retVal, AUIDialog dlg)
{
iRetVal = retVal;
pDlg = dlg;
}
}
}
+19
View File
@@ -0,0 +1,19 @@
/*
* Dialog Box Command IDs
* Converted from Windows API definitions
*/
public static class DialogBoxCommandIDs
{
public const int IDOK = 1;
public const int IDCANCEL = 2;
public const int IDABORT = 3;
public const int IDRETRY = 4;
public const int IDIGNORE = 5;
public const int IDYES = 6;
public const int IDNO = 7;
public const int IDCLOSE = 8;
public const int IDHELP = 9;
public const int IDTRYAGAIN = 10;
public const int IDCONTINUE = 11;
public const int IDTIMEOUT = 32000;
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d1c0dbd48a553e9498f6b0d391ec9707
+8
View File
@@ -120,5 +120,13 @@ namespace BrewMonster
offset += size;
}
}
// Learn skill command / 学习技能命令
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct cmd_learn_skill
{
public int skill_id; // Skill ID / 技能ID
public int skill_level; // Skill level / 技能等级
}
}