Merge branch 'develop' of https://git.brew.monster/Unity/perfect-world-unity into update-in-game
This commit is contained in:
@@ -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,
|
||||
|
||||
+178
-24
@@ -771,7 +771,7 @@ namespace BrewMonster
|
||||
// Is skill cool time
|
||||
int idSkill = item.idx - (int)CoolTimeIndex.GP_CT_SKILL_START;
|
||||
|
||||
COOLTIME ct = m_skillCoolTime[idSkill];
|
||||
COOLTIME ct = default;
|
||||
ct.iCurTime = item.cooldown;
|
||||
ct.iMaxTime = item.max_cooltime;
|
||||
Mathf.Clamp(ct.iCurTime, 0, ct.iMaxTime);
|
||||
@@ -934,6 +934,13 @@ namespace BrewMonster
|
||||
bActionStartSkill = true;
|
||||
iActionTime = iWaitTime;
|
||||
Debug.Log($"Cast skill({m_pCurSkill.GetSkillID()})");
|
||||
|
||||
// Special logging for return-to-town skill (167)
|
||||
// 回城技能(167)的特殊日志
|
||||
if (m_pCurSkill.GetSkillID() == ID_RETURNTOWN_SKILL)
|
||||
{
|
||||
Debug.Log($"Return-to-town skill (167) cast - State2 should trigger SetReturntown(1) on server");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case int value2 when value2 == CommandID.SKILL_PERFORM:
|
||||
@@ -945,6 +952,15 @@ namespace BrewMonster
|
||||
if (m_pCurSkill != null && m_pCurSkill.IsDurative())
|
||||
m_bSpellDSkill = true;
|
||||
|
||||
// Special handling for return-to-town skill (167)
|
||||
// 回城技能(167)的特殊处理
|
||||
// When skill 167 reaches State2, server calls SetReturntown(1) which should trigger MSG_HST_GOTO
|
||||
// 当技能167到达State2时,服务器调用SetReturntown(1),这应该触发MSG_HST_GOTO
|
||||
if (m_pCurSkill != null && m_pCurSkill.GetSkillID() == ID_RETURNTOWN_SKILL)
|
||||
{
|
||||
Debug.Log($"Skill 167 (Return to Town) performed - waiting for MSG_HST_GOTO from server");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case int value2 when value2 == CommandID.HOST_STOP_SKILL:
|
||||
@@ -1386,27 +1402,27 @@ namespace BrewMonster
|
||||
}
|
||||
}
|
||||
// Restore and convert shortcuts after loading new skills
|
||||
/* if (hostPlayer.HostIsReady())
|
||||
{
|
||||
hostPlayer.ConvertSkillShortcut(skillSCConfigArray1);
|
||||
hostPlayer.AssignSkillShortcut(skillSCConfigArray1, hostPlayer.m_aSCSets1);
|
||||
hostPlayer.ConvertSkillShortcut(skillSCConfigArray2);
|
||||
hostPlayer.AssignSkillShortcut(skillSCConfigArray2, hostPlayer.m_aSCSets2);
|
||||
hostPlayer.ConvertComboSkill();
|
||||
hostPlayer.ValidateSkillGrpShortcut(skillGrpSCConfigArray1);
|
||||
hostPlayer.AssignSkillGrpShortcut(skillGrpSCConfigArray1, hostPlayer.m_aSCSets1);
|
||||
hostPlayer.ValidateSkillGrpShortcut(skillGrpSCConfigArray2);
|
||||
hostPlayer.AssignSkillGrpShortcut(skillGrpSCConfigArray2, hostPlayer.m_aSCSets2);
|
||||
}
|
||||
if (HostIsReady())
|
||||
{
|
||||
/* ConvertSkillShortcut(skillSCConfigArray1);
|
||||
AssignSkillShortcut(skillSCConfigArray1, hostPlayer.m_aSCSets1);*/
|
||||
/* ConvertSkillShortcut(skillSCConfigArray2);
|
||||
AssignSkillShortcut(skillSCConfigArray2, hostPlayer.m_aSCSets2);*/
|
||||
/* ConvertComboSkill();
|
||||
ValidateSkillGrpShortcut(skillGrpSCConfigArray1);
|
||||
AssignSkillGrpShortcut(skillGrpSCConfigArray1, hostPlayer.m_aSCSets1);
|
||||
ValidateSkillGrpShortcut(skillGrpSCConfigArray2);
|
||||
AssignSkillGrpShortcut(skillGrpSCConfigArray2, hostPlayer.m_aSCSets2);*/
|
||||
}
|
||||
|
||||
if (hostPlayer.HostIsReady())
|
||||
{
|
||||
// Update UI when profession changes, save all shortcut configurations
|
||||
// to remove effects from intermediate skills (invalid pointers)
|
||||
// C++: CECGameUIMan *pGameUIMan = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan();
|
||||
// pGameUIMan.UpdateSkillRelatedUI();
|
||||
hostPlayer.UpdateSkillRelatedUI();
|
||||
}*/
|
||||
if (HostIsReady())
|
||||
{
|
||||
// Update UI when profession changes, save all shortcut configurations
|
||||
// to remove effects from intermediate skills (invalid pointers)
|
||||
// C++: CECGameUIMan *pGameUIMan = g_pGame.GetGameRun().GetUIManager().GetInGameUIMan();
|
||||
// pGameUIMan.UpdateSkillRelatedUI();
|
||||
CECUIManager.Instance.UpdateSkillRelatedUI();
|
||||
}
|
||||
}
|
||||
|
||||
public bool HostIsReady()
|
||||
@@ -2447,9 +2463,76 @@ namespace BrewMonster
|
||||
{
|
||||
PopupManager.Instance.OnPlayerRevived();
|
||||
// p1 is a byte[] buffer; parse into cmd_notify_hostpos then set position
|
||||
// p1 是一个 byte[] 缓冲区;解析为 cmd_notify_hostpos 然后设置位置
|
||||
byte[] buf = (byte[])Msg.dwParam1;
|
||||
cmd_notify_hostpos pCmd = GPDataTypeHelper.FromBytes<cmd_notify_hostpos>(buf);
|
||||
SetPos(new Vector3(pCmd.vPos.x, pCmd.vPos.y, pCmd.vPos.z));
|
||||
|
||||
int idInst = pCmd.tag;
|
||||
Vector3 vPos = new Vector3(pCmd.vPos.x, pCmd.vPos.y, pCmd.vPos.z);
|
||||
int iLine = pCmd.line;
|
||||
|
||||
|
||||
// Call Goto method to properly handle teleportation
|
||||
// 调用 Goto 方法来正确处理传送
|
||||
if (!Goto(idInst, vPos, iLine))
|
||||
{
|
||||
Debug.LogError($"OnMsgHstGoto: Failed to teleport to instance {idInst}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Return to a target town through skill
|
||||
// 通过技能返回目标城镇
|
||||
// This method implements the Goto logic from the original C++ code
|
||||
// 此方法实现了原始 C++ 代码中的 Goto 逻辑
|
||||
private bool Goto(int idInst, Vector3 vPos, int iParallelWorldID)
|
||||
{
|
||||
// Jump to instance (change world/instance)
|
||||
// 跳转到实例(更改世界/实例)
|
||||
// Note: JumpToInstance is currently a stub in CECGameRun, so we skip the call for now
|
||||
// 注意:JumpToInstance 目前在 CECGameRun 中是一个存根,所以我们现在跳过调用
|
||||
// if (CECGameRun.Instance != null && !CECGameRun.Instance.JumpToInstance(idInst, vPos, iParallelWorldID))
|
||||
// {
|
||||
// Debug.LogError($"CECHostPlayer::Goto, Failed to jump to instance {idInst}");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// Stop all current work and goto specified position
|
||||
// 停止所有当前工作并转到指定位置
|
||||
if (m_pWorkMan != null)
|
||||
{
|
||||
// Stop auto-moving if active
|
||||
// 如果正在自动移动则停止
|
||||
// Note: IsAutoMoving check would go here if available
|
||||
// 注意:如果可用,IsAutoMoving 检查将放在这里
|
||||
|
||||
// Finish all work
|
||||
// 完成所有工作
|
||||
m_pWorkMan.FinishAllWork(true);
|
||||
}
|
||||
|
||||
// Add a little height to ensure player's AABB won't embed with building
|
||||
// 增加一点高度以确保玩家的 AABB 不会嵌入建筑物
|
||||
vPos.y += 0.1f;
|
||||
|
||||
// Ensure we are not under ground (terrain height check would go here)
|
||||
// 确保我们不会在地下(地形高度检查将放在这里)
|
||||
// Note: Terrain height check is skipped for now as it requires world access
|
||||
// 注意:暂时跳过地形高度检查,因为它需要世界访问
|
||||
|
||||
// Set position
|
||||
// 设置位置
|
||||
SetPos(vPos);
|
||||
|
||||
// Reset jump state if available
|
||||
// 如果可用则重置跳跃状态
|
||||
// ResetJump(); // Uncomment if ResetJump method exists
|
||||
|
||||
// Update camera if available
|
||||
// 如果可用则更新相机
|
||||
// UpdateFollowCamera(false, 10); // Uncomment if UpdateFollowCamera method exists
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnMsgHstStartAttack(in ECMSG Msg)
|
||||
@@ -3407,8 +3490,13 @@ namespace BrewMonster
|
||||
m_pActionSwitcher.PostMessge((int)EMsgActionSwitcher.MSG_CASTSKILL);
|
||||
|
||||
// Return-town skill is very special, handle it separately
|
||||
//if (idSkill == ID_RETURNTOWN_SKILL)
|
||||
// return ReturnToTargetTown(0, bCombo);
|
||||
// 回城技能非常特殊,单独处理
|
||||
Debug.Log($"ApplySkillShortcut: Checking skill {idSkill}, ID_RETURNTOWN_SKILL={ID_RETURNTOWN_SKILL}");
|
||||
if (idSkill == ID_RETURNTOWN_SKILL)
|
||||
{
|
||||
Debug.Log($"ApplySkillShortcut: Skill 167 detected, calling ReturnToTargetTown");
|
||||
return ReturnToTargetTown(0, bCombo);
|
||||
}
|
||||
|
||||
//if (idSkill == ID_SUMMONPLAYER_SKILL)
|
||||
// return SummonPlayer(idSelTarget, bCombo);
|
||||
@@ -4096,6 +4184,72 @@ namespace BrewMonster
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return to a target town through skill
|
||||
// 通过技能返回目标城镇
|
||||
private bool ReturnToTargetTown(int idTarget, bool bCombo = false)
|
||||
{
|
||||
|
||||
if (!CanDo(ActionCanDo.CANDO_SPELLMAGIC))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int idSkill = ID_RETURNTOWN_SKILL;
|
||||
CECSkill pSkill = GetPositiveSkillByID(idSkill);
|
||||
if (pSkill == null) pSkill = GetEquipSkillByID(idSkill);
|
||||
if (pSkill == null)
|
||||
{
|
||||
Debug.LogError("ReturnToTargetTown: Skill 167 not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!bCombo)
|
||||
{
|
||||
// ClearComboSkill(); // Uncomment if ClearComboSkill exists
|
||||
}
|
||||
|
||||
// Check skill cast condition (commented out in ApplySkillShortcut, so skip for now)
|
||||
// int iCon = CheckSkillCastCondition(pSkill);
|
||||
// if (iCon)
|
||||
// {
|
||||
// ProcessSkillCondition(iCon);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// If this skill is in cooling time or we are casting other skill, return
|
||||
// 如果此技能在冷却时间或我们正在施放其他技能,返回
|
||||
if (!pSkill.ReadyToCast() ||
|
||||
!m_pWorkMan.CanCastSkillImmediately(pSkill.GetSkillID()))
|
||||
{
|
||||
// If the current Work in m_pWorkMan is CECHPWorkSpell or CECHPWorkFly, it should be executed first
|
||||
// Otherwise, when receiving OBJECT_CAST_SKILL protocol, CECHPWorkSpell cannot be executed
|
||||
// This causes CECHostPlayer::IsSpellingMagic() to return false, causing the client to send c2s_CmdCancelAction
|
||||
// When this CECHPWorkSpell executes, it cannot respond
|
||||
// After this method is executed, we use the return to city mechanism
|
||||
// 如果 m_pWorkMan 中的当前 Work 是 CECHPWorkSpell 或 CECHPWorkFly,则应先执行
|
||||
// 否则,当收到 OBJECT_CAST_SKILL 协议时,CECHPWorkSpell 无法执行
|
||||
// 这会导致 CECHostPlayer::IsSpellingMagic() 返回 false,导致客户端发送 c2s_CmdCancelAction
|
||||
// 当此 CECHPWorkSpell 执行时,它无法响应
|
||||
// 在此方法执行完成后,我们使用回城机制
|
||||
Debug.LogError($"ReturnToTargetTown: Skill not ready - ReadyToCast={pSkill.ReadyToCast()}, CanCastSkillImmediately={m_pWorkMan.CanCastSkillImmediately(pSkill.GetSkillID())}");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pPrepSkill = pSkill;
|
||||
byte byPVPMask = glb_BuildPVPMask(false);
|
||||
|
||||
// Call c2s_CmdCastSkill with target parameter
|
||||
// 使用目标参数调用 c2s_CmdCastSkill
|
||||
int targets = 1;
|
||||
int[] targetsCastSkill = new int[targets];
|
||||
targetsCastSkill[0] = idTarget;
|
||||
UnityGameSession.c2s_CmdCastSkill(idSkill, byPVPMask, targets, targetsCastSkill);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public A3DVECTOR3 GetDir()
|
||||
{
|
||||
// Return forward direction from transform
|
||||
|
||||
@@ -116,6 +116,19 @@ public class CECUIManager : MonoSingleton<CECUIManager>
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public void UpdateSkillRelatedUI()
|
||||
{
|
||||
// ¸üм¼ÄÜÏà¹ØµÄ½çÃæÏÔʾ
|
||||
|
||||
if (m_pDlgQuickBar1)
|
||||
m_pDlgQuickBar1.UpdateShortcuts();
|
||||
|
||||
/* if (m_pDlgSkillEdit != null && m_pDlgSkillEdit->IsShow())
|
||||
{
|
||||
// ¼¼Äܱ༽çÃæÖ»ÔÚ Show(true) µÄʱºò²ÅÄܸüÐÂ
|
||||
m_pDlgSkillEdit->Show(false);
|
||||
}*/
|
||||
}
|
||||
|
||||
private void OnMessageBox(MessageBoxEvent messageBoxEvent)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user