test buff skill

This commit is contained in:
VDH
2025-12-02 16:46:47 +07:00
parent 16ca5b87b8
commit 5c42c9792b
46 changed files with 4198 additions and 3538 deletions
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b61cfcd2a7b14114a8a64b79ad4e26ec
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BrewMonster.Assets.PerfectWorld.Scripts.Common
namespace BrewMonster
{
public abstract class Singleton<T> where T : class, new()
{
@@ -1,5 +1,4 @@
using BrewMonster.Assets.PerfectWorld.Scripts.Common;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -1,7 +1,6 @@
using BrewMonster.Scripts.Player;
using CSNetwork.GPDataType;
using NUnit.Framework;
using PerfectWorld.Scripts.Player;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
@@ -823,7 +823,7 @@ public class CECAttackEvent
}
else
{
CECNPC pNPC = EC_ManMessageMono.Instance?._CECNPCMan?.GetNPC(m_idHost);
CECNPC pNPC = EC_ManMessageMono.Instance?.CECNPCMan?.GetNPC(m_idHost);
if (pNPC == null)
return true;
@@ -908,7 +908,7 @@ public class CECAttackEvent
}
else if (GPDataTypeHelper.ISNPCID(nID))
{
CECNPC pNPC = EC_ManMessageMono.Instance?._CECNPCMan?.GetNPCFromAll(nID);
CECNPC pNPC = EC_ManMessageMono.Instance?.CECNPCMan?.GetNPCFromAll(nID);
if (pNPC != null)
{
vPos = pNPC.GetPosVector3();
@@ -948,10 +948,10 @@ public class CECAttackEvent
{
CECNPC pNPC = null;
if ((data.dwModifier & (uint)MOD.MOD_SUCCESS) != 0)
pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPCFromAll(idTarget);
pNPC = EC_ManMessageMono.Instance.CECNPCMan.GetNPCFromAll(idTarget);
else
{
pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPCFromAll(idTarget);
pNPC = EC_ManMessageMono.Instance.CECNPCMan.GetNPCFromAll(idTarget);
if (!pNPC)
return true;
@@ -115,3 +115,4 @@ namespace BrewMonster.Managers
@@ -1,5 +1,4 @@
using BrewMonster;
using BrewMonster.Assets.PerfectWorld.Scripts.Common;
using BrewMonster.Managers;
using BrewMonster.Network;
using CSNetwork.GPDataType;
@@ -19,7 +18,7 @@ namespace BrewMonster
public CECSkillGfxEvent(GfxMoveMode mode) : base(mode)
{
m_pPlayerMan = EC_ManMessageMono.Instance?.GetECManPlayer;
m_pNPCMan = EC_ManMessageMono.Instance?._CECNPCMan;
m_pNPCMan = EC_ManMessageMono.Instance?.CECNPCMan;
}
/// <summary>
@@ -584,7 +583,7 @@ namespace BrewMonster
// m_pPlayerMan = pGameRun?.GetWorld()?.GetPlayerMan();
// m_pNPCMan = pGameRun?.GetWorld()?.GetNPCMan();
m_pPlayerMan = EC_ManMessageMono.Instance?.GetECManPlayer;
m_pNPCMan = EC_ManMessageMono.Instance?._CECNPCMan;
m_pNPCMan = EC_ManMessageMono.Instance?.CECNPCMan;
}
/// <summary>
@@ -1,5 +1,4 @@
using CSNetwork.GPDataType;
using PerfectWorld.Scripts.Player;
using System;
using System.Collections.Generic;
@@ -24,7 +23,7 @@ namespace BrewMonster.Scripts
public override void Start()
{
GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND;
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_ATTACK_1 + UnityEngine.Random.Range(0, 3));
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_ATTACK_1 + UnityEngine.Random.Range(0, 3));
GetPlayer().EnterFightState();
}
public override void Tick(float dwDeltaTime)
@@ -128,18 +127,18 @@ namespace BrewMonster.Scripts
GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND;
if (m_dwParam != 0)
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SITDOWN_LOOP);
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_SITDOWN_LOOP);
else
{
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SITDOWN);
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SITDOWN_LOOP, true, 200, true);
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_SITDOWN);
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_SITDOWN_LOOP, true, 200, true);
}
break;
case Idle_work_type.IDLE_REVIVE:
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_REVIVE);
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_REVIVE);
break;
case Idle_work_type.IDLE_BOOTH:
@@ -346,7 +345,7 @@ namespace BrewMonster.Scripts
}
private EC_ElsePlayer m_pElsePlayer;
private WorkList[] m_WorkStack = new WorkList[Work_type.NUM_WORKTYPE]
private WorkList[] m_WorkStack = new WorkList[Work_type.NUM_WORKTYPE]
{
new List<CECEPWork>(),
new List<CECEPWork>(),
@@ -726,7 +725,7 @@ namespace BrewMonster.Scripts
m_dwParam = dwParam;
}
void Start()
public void Start()
{
GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND;
@@ -744,28 +743,28 @@ namespace BrewMonster.Scripts
if (m_dwParam != null)
{
if (iFlag == 1)
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_WATERDIE_LOOP);
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_WATERDIE_LOOP);
else if (iFlag == 2)
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_AIRDIE);
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_AIRDIE);
else
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_GROUNDDIE_LOOP);
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_GROUNDDIE_LOOP);
}
else
{
if (iFlag == 1)
{
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_WATERDIE);
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_WATERDIE_LOOP, true, 200, true);
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_WATERDIE);
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_WATERDIE_LOOP, true, 200, true);
}
else if (iFlag == 2)
{
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_AIRDIE_ST);
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_AIRDIE, true, 200, true);
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_AIRDIE_ST);
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_AIRDIE, true, 200, true);
}
else
{
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_GROUNDDIE);
GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_GROUNDDIE_LOOP, true, 200, true);
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_GROUNDDIE);
GetPlayer().PlayAction((int)PLAYER_ACTION_TYPE.ACT_GROUNDDIE_LOOP, true, 200, true);
}
}
}
@@ -13,12 +13,12 @@ namespace BrewMonster
public int m_nMemNum;
public int GetLevel() { return m_nLev; }
}
}
public class CECFactionMan
{
Dictionary<uint, Faction_Info> m_FactionMap;
public List<int> m_alliance = new List<int>();
public Faction_Info GetFaction(uint uId, bool bRequestFromServer)
{
if (!m_FactionMap.TryGetValue(uId, out var it))
@@ -30,5 +30,18 @@ namespace BrewMonster
return it;
}
public bool IsFactionAlliance(int fid)
{
if (fid == 0)
return false;
foreach (var f in m_alliance)
{
if (f == fid)
return true;
}
return false;
}
}
}
@@ -326,6 +326,10 @@ namespace BrewMonster.Scripts
}
return true;
}
public bool CanCastSkillImmediately(int idSkill)
{
return !IsSpellingMagic() && !HasWorkRunningOnPriority(Work_priority.PRIORITY_2);
}
bool CanRunSimultaneously(CECHPWork pWork1, CECHPWork pWork2)
{
if (pWork1.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS &&
@@ -4,7 +4,6 @@ using BrewMonster.Network;
using BrewMonster.Scripts;
using CSNetwork.GPDataType;
using PerfectWorld.Scripts.Managers;
using PerfectWorld.Scripts.Player;
using UnityEngine;
class CECHPWorkPostTickCommand1 : CECHPWorkPostTickRunWorkCommand
@@ -89,7 +88,7 @@ class CECHPWorkMelee : CECHPWork
}
else if (GPDataTypeHelper.ISNPCID(m_idTarget))
{
CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(m_idTarget);
CECNPC pNPC = EC_ManMessageMono.Instance.CECNPCMan.GetNPC(m_idTarget);
if (!pNPC || pNPC.IsDead()) // Taget has missed ?
return true;
@@ -150,7 +149,7 @@ class CECHPWorkMelee : CECHPWork
protected virtual void OnFirstTick()
{
m_pHost.m_iMoveMode = (int)MoveMode.MOVE_STAND;
m_pHost.PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_ATTACK_1 + Random.Range(0, 3), true, 200, false);
m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_ATTACK_1 + Random.Range(0, 3), true, 200, false);
m_idTarget = m_pHost.m_idSelTarget;
}
@@ -28,12 +28,12 @@ namespace BrewMonster.Scripts
base.Reset();
m_bMeetSlide = false;
m_iPoseAction = (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_STAND;
m_iPoseAction = (int)PLAYER_ACTION_TYPE.ACT_STAND;
m_bSession = false;
m_bWaterStop = false;
m_bMoving = false;
m_bStopSlide = false;
m_iCurAction = (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_STAND;
m_iCurAction = (int)PLAYER_ACTION_TYPE.ACT_STAND;
}
// Copy work data
@@ -62,7 +62,7 @@ namespace BrewMonster.Scripts
m_pHost.PlayAction(m_iPoseAction, true);
if (!bSession && iAction != (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_EXP_KISS)
if (!bSession && iAction != (int)PLAYER_ACTION_TYPE.ACT_EXP_KISS)
m_pHost.PlayAction(m_pHost.GetMoveStandAction(false, false), true, 300, true);
}
@@ -107,7 +107,7 @@ namespace BrewMonster.Scripts
// Work is cancel
public override void Cancel()
{
m_iPoseAction = (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_STAND;
m_iPoseAction = (int)PLAYER_ACTION_TYPE.ACT_STAND;
m_bSession = false;
m_pHost.m_bPrepareFight = false;
base.Cancel();
@@ -116,7 +116,7 @@ namespace BrewMonster.Scripts
// Doing session pose?
public bool DoingSessionPose()
{
return (m_iPoseAction != (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_STAND && m_bSession);
return (m_iPoseAction != (int)PLAYER_ACTION_TYPE.ACT_STAND && m_bSession);
}
// Tick routine
@@ -154,7 +154,7 @@ namespace BrewMonster.Scripts
}
// Play appropriate actions
if (m_iPoseAction == (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_STAND)
if (m_iPoseAction == (int)PLAYER_ACTION_TYPE.ACT_STAND)
{
bool bFight = m_pHost.IsFighting() || m_pHost.m_bPrepareFight;
m_iCurAction = m_pHost.GetMoveStandAction(false, bFight);
@@ -170,7 +170,7 @@ namespace BrewMonster.Scripts
Tick_FlySwim(fDeltaTime);*/
}
if (m_iPoseAction == (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_STAND && m_oldAction != m_iCurAction)
if (m_iPoseAction == (int)PLAYER_ACTION_TYPE.ACT_STAND && m_oldAction != m_iCurAction)
{
// Chariot war special case omitted for now
m_pHost.PlayAction(m_iCurAction, false, 300);
@@ -195,7 +195,7 @@ namespace BrewMonster.Scripts
if (m_bStopSlide)
return true;
m_iCurAction = (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_JUMP_LOOP;
m_iCurAction = (int)PLAYER_ACTION_TYPE.ACT_JUMP_LOOP;
m_bMeetSlide = true;
m_bMoving = true;
File diff suppressed because it is too large Load Diff
@@ -5,7 +5,6 @@ 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;
@@ -5,7 +5,6 @@ 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;
@@ -90,8 +89,8 @@ namespace PerfectWorld.Scripts.Managers
//if (pPlayer && !pPlayer.IsAboutToDie())
// pPlayer.Killed(pCmd.idKiller);
EventBus.PublishChannel(pPlayer.GetCharacterID(), new CECPlayer.ClearComActFlagAllRankNodesEvent(true));
pPlayer.PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_GROUNDDIE);
EventBus.PublishChannel(pPlayer.GetCharacterID(), new ClearComActFlagAllRankNodesEvent(true));
pPlayer.PlayAction((int)PLAYER_ACTION_TYPE.ACT_GROUNDDIE);
}
private void OnMsgPlayerRevive(ECMSG Msg)
@@ -1,6 +1,5 @@
using CSNetwork.GPDataType;
using BrewMonster.Scripts.Player;
using PerfectWorld.Scripts.Player;
namespace BrewMonster.Scripts
{
@@ -1,11 +1,15 @@
partial class CECPlayer
namespace BrewMonster
{
protected int m_iMoneyCnt; // Amount of money the player has
public int GetMoneyAmount(){ return m_iMoneyCnt; }
public byte GetShapeMask()
partial class CECPlayer
{
// restore the original data from 8~15 bit
return (byte)((m_iShape & 0xff00) >> 8);
protected int m_iMoneyCnt; // Amount of money the player has
public int GetMoneyAmount() { return m_iMoneyCnt; }
public byte GetShapeMask()
{
// restore the original data from 8~15 bit
return (byte)((m_iShape & 0xff00) >> 8);
}
}
}
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -1,4 +1,5 @@
using BrewMonster.Scripts.Ornament;
using BrewMonster.Scripts;
using BrewMonster.Scripts.Ornament;
using BrewMonster.Scripts.Player;
using BrewMonster.Scripts.World;
using CSNetwork.GPDataType;
@@ -6,7 +7,7 @@ using System;
using UnityEngine;
using WORD = System.UInt16;
namespace BrewMonster.Scripts
namespace BrewMonster
{
public static class EC_CDR
{
+1 -1
View File
@@ -244,7 +244,7 @@ public class CECNPC : CECObject
// Attack target is host's pet
else if (GPDataTypeHelper.ISNPCID(pCmd.target_id))
{
var pTarget = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(pCmd.target_id);
var pTarget = EC_ManMessageMono.Instance.CECNPCMan.GetNPC(pCmd.target_id);
if (pTarget != null && pTarget.GetMasterID() == pHost.GetCharacterID())
iDamage = pCmd.damage;
}
@@ -919,7 +919,7 @@ namespace CSNetwork.GPDataType
}
// PVP mask
[Flags]
public enum PVPMask
public enum PVPMask : byte
{
GP_PVPMASK_FORCE = 0x0001, // Ç¿Á¦¹¥»÷
GP_PVPMASK_NOMAFIA = 0x0002,
@@ -28,16 +28,16 @@ namespace BrewMonster.Managers
public EC_ManMatter EC_ManMatter;
public EC_ManPlayer GetECManPlayer { get => EC_ManPlayer;}
public EC_ManMatter GetECManMatter { get => EC_ManMatter;}
public CECNPCMan _CECNPCMan { get; private set; }
public CECNPCMan CECNPCMan { get; private set; }
private void Awake()
{
instance = this;
//TODO: Remove later
EC_ManPlayer = new EC_ManPlayer();
_CECNPCMan = new CECNPCMan();
CECNPCMan = new CECNPCMan();
EC_ManMessage.RegisterHandler(EC_ManPlayer);
EC_ManMessage.RegisterHandler(_CECNPCMan);
EC_ManMessage.RegisterHandler(CECNPCMan);
EC_ManMatter = new EC_ManMatter();
EC_ManMessage.RegisterHandler(EC_ManMatter);
Debug.Log($"EC_ManMessage RegisterHandlerRegisterHandlerRegisterHandler");
@@ -52,7 +52,7 @@ namespace BrewMonster.Managers
private void Update()
{
EC_ManMessage.Tick();
_CECNPCMan.Tick();
CECNPCMan.Tick();
}
// Get object by specified ID
@@ -63,7 +63,7 @@ namespace BrewMonster.Managers
if (GPDataTypeHelper.ISNPCID((int)idObject))
{
if (!(pObject = _CECNPCMan.GetNPC((int)idObject)))
if (!(pObject = CECNPCMan.GetNPC((int)idObject)))
return null;
if ((iAliveFlag == 1 && (pObject as CECNPC).IsDead()) ||
@@ -1,6 +1,5 @@
using BrewMonster.Scripts.Player;
using UnityEngine;
using static CECPlayer;
namespace BrewMonster
{
@@ -1,6 +1,5 @@
using BrewMonster.Scripts.Player;
using UnityEngine;
using static CECPlayer;
namespace BrewMonster
{
@@ -2,189 +2,192 @@ using System;
// CECPlayerActionController
// 玩家动作控制器 / Player action controller
public class CECPlayerActionController
namespace BrewMonster
{
// Action channels for split-body animation (kept for parity with C++)
// 动作通道(保留与C++一致的接口语义) / Channels kept to mirror C++ API
public const int ACT_CHANNEL_UPPERBODY = 0;
public const int ACT_CHANNEL_LOWERBODY = 1;
public const int ACT_CHANNEL_WOUND = 2;
public class CECPlayerActionController
{
// Action channels for split-body animation (kept for parity with C++)
// 动作通道(保留与C++一致的接口语义) / Channels kept to mirror C++ API
public const int ACT_CHANNEL_UPPERBODY = 0;
public const int ACT_CHANNEL_LOWERBODY = 1;
public const int ACT_CHANNEL_WOUND = 2;
private CECPlayer m_pPlayer;
private CECModel m_pPlayerModel;
private bool m_bSupportCastSkillWhenMove;
private CECPlayerActionPlayPolicy m_actionPlayPolicy;
private bool m_bSkillAttackActionPlayed;
private CECPlayer m_pPlayer;
private CECModel m_pPlayerModel;
private bool m_bSupportCastSkillWhenMove;
private CECPlayerActionPlayPolicy m_actionPlayPolicy;
private bool m_bSkillAttackActionPlayed;
public CECPlayerActionController()
{
m_pPlayer = null;
m_pPlayerModel = null;
m_bSupportCastSkillWhenMove = false;
m_actionPlayPolicy = null;
m_bSkillAttackActionPlayed = false;
}
public CECPlayerActionController()
{
m_pPlayer = null;
m_pPlayerModel = null;
m_bSupportCastSkillWhenMove = false;
m_actionPlayPolicy = null;
m_bSkillAttackActionPlayed = false;
}
~CECPlayerActionController()
{
ReleaseActionPlayPolicy();
}
~CECPlayerActionController()
{
ReleaseActionPlayPolicy();
}
public void Bind(CECPlayer player, CECModel playerModel)
{
if (player == null)
{
return;
}
if (player == m_pPlayer && playerModel == m_pPlayerModel)
{
return;
}
public void Bind(CECPlayer player, CECModel playerModel)
{
if (player == null)
{
return;
}
if (player == m_pPlayer && playerModel == m_pPlayerModel)
{
return;
}
ReleaseActionPlayPolicy();
m_pPlayer = player;
m_pPlayerModel = playerModel;
ReleaseActionPlayPolicy();
m_pPlayer = player;
m_pPlayerModel = playerModel;
// 是否支持移动中施法(当前C#端未实现,统一设为false)
// Support cast-while-move (not implemented in C# port -> false)
m_bSupportCastSkillWhenMove = false;
// 是否支持移动中施法(当前C#端未实现,统一设为false)
// Support cast-while-move (not implemented in C# port -> false)
m_bSupportCastSkillWhenMove = false;
if (!m_bSupportCastSkillWhenMove)
{
// 如果不支持,仍保留“受击”通道逻辑钩子(在C#里留空)
// If not supported, keep the hook for wound channel (no-op in C#)
}
if (!m_bSupportCastSkillWhenMove)
{
// 如果不支持,仍保留“受击”通道逻辑钩子(在C#里留空)
// If not supported, keep the hook for wound channel (no-op in C#)
}
InitializeActionPlayPolicy();
}
InitializeActionPlayPolicy();
}
public bool SupportCastSkillWhenMove()
{
return m_bSupportCastSkillWhenMove;
}
public bool SupportCastSkillWhenMove()
{
return m_bSupportCastSkillWhenMove;
}
public bool CanCombineWithMoveForSkill(int idSkill)
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.CanCombineWithMoveForSkill(idSkill);
}
public bool CanCombineWithMoveForSkill(int idSkill)
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.CanCombineWithMoveForSkill(idSkill);
}
private void InitializeActionPlayPolicy()
{
// 当前C#只提供默认策略(不拆分上下半身)
// Use default policy in this C# port
m_actionPlayPolicy = new CECPlayerActionPlayPolicy(m_pPlayer, m_pPlayerModel);
}
private void InitializeActionPlayPolicy()
{
// 当前C#只提供默认策略(不拆分上下半身)
// Use default policy in this C# port
m_actionPlayPolicy = new CECPlayerActionPlayPolicy(m_pPlayer, m_pPlayerModel);
}
private void ReleaseActionPlayPolicy()
{
m_actionPlayPolicy = null;
}
private void ReleaseActionPlayPolicy()
{
m_actionPlayPolicy = null;
}
// Build channels (C# no-op, return false to indicate not supported here)
// 构建动作通道(C#未实现,返回false)
private bool BuildChannelForCastSkillWhenMove()
{
return false;
}
// Build channels (C# no-op, return false to indicate not supported here)
// 构建动作通道(C#未实现,返回false)
private bool BuildChannelForCastSkillWhenMove()
{
return false;
}
public bool PlayNonSkillActionWithName(int iAction, string szActName, bool bRestart = true, int nTransTime = 200, bool bNoFx = false, bool[] pActFlag = null, uint dwFlagMode = 0)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlayNonSkillActionWithName(iAction, szActName, bRestart, nTransTime, bNoFx, pActFlag, dwFlagMode);
}
public bool PlayNonSkillActionWithName(int iAction, string szActName, bool bRestart = true, int nTransTime = 200, bool bNoFx = false, bool[] pActFlag = null, uint dwFlagMode = 0)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlayNonSkillActionWithName(iAction, szActName, bRestart, nTransTime, bNoFx, pActFlag, dwFlagMode);
}
public bool QueueNonSkillActionWithName(int iAction, string szActName, int nTransTime = 200, bool bForceStopPrevAct = false, bool bNoFx = false, bool bResetSpeed = false, bool bResetActFlag = false, bool[] pNewActFlag = null, uint dwNewFlagMode = 0)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.QueueNonSkillActionWithName(iAction, szActName, nTransTime, bForceStopPrevAct, bNoFx, bResetSpeed, bResetActFlag, pNewActFlag, dwNewFlagMode);
}
public bool QueueNonSkillActionWithName(int iAction, string szActName, int nTransTime = 200, bool bForceStopPrevAct = false, bool bNoFx = false, bool bResetSpeed = false, bool bResetActFlag = false, bool[] pNewActFlag = null, uint dwNewFlagMode = 0)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.QueueNonSkillActionWithName(iAction, szActName, nTransTime, bForceStopPrevAct, bNoFx, bResetSpeed, bResetActFlag, pNewActFlag, dwNewFlagMode);
}
public bool PlaySkillCastActionWithName(int idSkill, string szActName, bool bNoFX = false)
{
if (m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlaySkillCastActionWithName(idSkill, szActName, bNoFX))
{
m_bSkillAttackActionPlayed = false;
return true;
}
return false;
}
public bool PlaySkillCastActionWithName(int idSkill, string szActName, bool bNoFX = false)
{
if (m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlaySkillCastActionWithName(idSkill, szActName, bNoFX))
{
m_bSkillAttackActionPlayed = false;
return true;
}
return false;
}
public bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX = false, bool[] pActFlag = null, uint dwFlagMode = 0)
{
if (m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, pActFlag, dwFlagMode))
{
m_bSkillAttackActionPlayed = true;
return true;
}
return false;
}
public bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX = false, bool[] pActFlag = null, uint dwFlagMode = 0)
{
if (m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, pActFlag, dwFlagMode))
{
m_bSkillAttackActionPlayed = true;
return true;
}
return false;
}
public bool QueueSkillAttackActionWithName(int idSkill, string szActName, int nTransTime = 200, bool bNoFX = false, bool bResetSpeed = false, bool bResetActFlag = false, bool[] pNewActFlag = null, uint dwNewFlagMode = 0)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.QueueSkillAttackActionWithName(idSkill, szActName, nTransTime, bNoFX, bResetSpeed, bResetActFlag, pNewActFlag, dwNewFlagMode);
}
public bool QueueSkillAttackActionWithName(int idSkill, string szActName, int nTransTime = 200, bool bNoFX = false, bool bResetSpeed = false, bool bResetActFlag = false, bool[] pNewActFlag = null, uint dwNewFlagMode = 0)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.QueueSkillAttackActionWithName(idSkill, szActName, nTransTime, bNoFX, bResetSpeed, bResetActFlag, pNewActFlag, dwNewFlagMode);
}
public bool PlayWoundActionWithName(string szActName)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlayWoundActionWithName(szActName);
}
public bool PlayWoundActionWithName(string szActName)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlayWoundActionWithName(szActName);
}
public void ClearComActFlagAllRankNodes(bool bSignalCurrent)
{
if (m_actionPlayPolicy != null)
{
m_actionPlayPolicy.ClearComActFlagAllRankNodes(bSignalCurrent);
}
}
public void ClearComActFlagAllRankNodes(bool bSignalCurrent)
{
if (m_actionPlayPolicy != null)
{
m_actionPlayPolicy.ClearComActFlagAllRankNodes(bSignalCurrent);
}
}
public void StopChannelAction()
{
if (m_actionPlayPolicy != null)
{
m_actionPlayPolicy.StopChannelAction();
}
}
public void StopChannelAction()
{
if (m_actionPlayPolicy != null)
{
m_actionPlayPolicy.StopChannelAction();
}
}
public void StopSkillCastAction()
{
if (m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction() && !m_bSkillAttackActionPlayed)
{
m_actionPlayPolicy.StopSkillAction();
// LOG kept minimal in C#
}
}
public void StopSkillCastAction()
{
if (m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction() && !m_bSkillAttackActionPlayed)
{
m_actionPlayPolicy.StopSkillAction();
// LOG kept minimal in C#
}
}
public void StopSkillAttackAction()
{
if (m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction() && m_bSkillAttackActionPlayed)
{
m_actionPlayPolicy.StopSkillAction();
// LOG kept minimal in C#
}
}
public void StopSkillAttackAction()
{
if (m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction() && m_bSkillAttackActionPlayed)
{
m_actionPlayPolicy.StopSkillAction();
// LOG kept minimal in C#
}
}
public bool IsPlayingAction(int iAction)
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingAction(iAction);
}
public bool IsPlayingAction(int iAction)
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingAction(iAction);
}
public bool IsPlayingCastingSkillAction()
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction();
}
public bool IsPlayingCastingSkillAction()
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction();
}
public bool IsPlayingMoveAction()
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingMoveAction();
}
public bool IsPlayingMoveAction()
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingMoveAction();
}
public int GetLowerBodyAction()
{
return m_actionPlayPolicy != null ? m_actionPlayPolicy.GetLowerBodyAction() : -1;
}
}
public int GetLowerBodyAction()
{
return m_actionPlayPolicy != null ? m_actionPlayPolicy.GetLowerBodyAction() : -1;
}
}
}
@@ -1,340 +1,343 @@
using System;
/*public class CECPlayerActionController
namespace BrewMonster
{
// Action channels for split-body animation (kept for parity with C++)
// 动作通道(保留与C++一致的接口语义) / Channels kept to mirror C++ API
public const int ACT_CHANNEL_UPPERBODY = 0;
public const int ACT_CHANNEL_LOWERBODY = 1;
public const int ACT_CHANNEL_WOUND = 2;
private CECPlayer m_pPlayer;
private CECModel m_pPlayerModel;
private bool m_bSupportCastSkillWhenMove;
private CECPlayerActionPlayPolicy m_actionPlayPolicy;
private bool m_bSkillAttackActionPlayed;
public CECPlayerActionController()
/*public class CECPlayerActionController
{
m_pPlayer = null;
m_pPlayerModel = null;
m_bSupportCastSkillWhenMove = false;
m_actionPlayPolicy = null;
m_bSkillAttackActionPlayed = false;
}
// Action channels for split-body animation (kept for parity with C++)
// 动作通道(保留与C++一致的接口语义) / Channels kept to mirror C++ API
public const int ACT_CHANNEL_UPPERBODY = 0;
public const int ACT_CHANNEL_LOWERBODY = 1;
public const int ACT_CHANNEL_WOUND = 2;
~CECPlayerActionController()
{
ReleaseActionPlayPolicy();
}
private CECPlayer m_pPlayer;
private CECModel m_pPlayerModel;
private bool m_bSupportCastSkillWhenMove;
private CECPlayerActionPlayPolicy m_actionPlayPolicy;
private bool m_bSkillAttackActionPlayed;
public void Bind(CECPlayer player, CECModel playerModel)
{
if (player == null)
{
return;
}
if (player == m_pPlayer && playerModel == m_pPlayerModel)
{
return;
}
ReleaseActionPlayPolicy();
m_pPlayer = player;
m_pPlayerModel = playerModel;
// 是否支持移动中施法(当前C#端未实现,统一设为false)
// Support cast-while-move (not implemented in C# port -> false)
m_bSupportCastSkillWhenMove = false;
if (!m_bSupportCastSkillWhenMove)
{
// 如果不支持,仍保留“受击”通道逻辑钩子(在C#里留空)
// If not supported, keep the hook for wound channel (no-op in C#)
}
InitializeActionPlayPolicy();
}
public bool SupportCastSkillWhenMove()
{
return m_bSupportCastSkillWhenMove;
}
public bool CanCombineWithMoveForSkill(int idSkill)
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.CanCombineWithMoveForSkill(idSkill);
}
private void InitializeActionPlayPolicy()
{
// 当前C#只提供默认策略(不拆分上下半身)
// Use default policy in this C# port
m_actionPlayPolicy = new CECPlayerActionPlayPolicy(m_pPlayer, m_pPlayerModel);
}
private void ReleaseActionPlayPolicy()
{
m_actionPlayPolicy = null;
}
// Build channels (C# no-op, return false to indicate not supported here)
// 构建动作通道(C#未实现,返回false)
private bool BuildChannelForCastSkillWhenMove()
{
return false;
}
public bool PlayNonSkillActionWithName(int iAction, string szActName, bool bRestart = true, int nTransTime = 200, bool bNoFx = false, bool[] pActFlag = null, uint dwFlagMode = 0)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlayNonSkillActionWithName(iAction, szActName, bRestart, nTransTime, bNoFx, pActFlag, dwFlagMode);
}
public bool QueueNonSkillActionWithName(int iAction, string szActName, int nTransTime = 200, bool bForceStopPrevAct = false, bool bNoFx = false, bool bResetSpeed = false, bool bResetActFlag = false, bool[] pNewActFlag = null, uint dwNewFlagMode = 0)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.QueueNonSkillActionWithName(iAction, szActName, nTransTime, bForceStopPrevAct, bNoFx, bResetSpeed, bResetActFlag, pNewActFlag, dwNewFlagMode);
}
public bool PlaySkillCastActionWithName(int idSkill, string szActName, bool bNoFX = false)
{
if (m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlaySkillCastActionWithName(idSkill, szActName, bNoFX))
public CECPlayerActionController()
{
m_pPlayer = null;
m_pPlayerModel = null;
m_bSupportCastSkillWhenMove = false;
m_actionPlayPolicy = null;
m_bSkillAttackActionPlayed = false;
}
~CECPlayerActionController()
{
ReleaseActionPlayPolicy();
}
public void Bind(CECPlayer player, CECModel playerModel)
{
if (player == null)
{
return;
}
if (player == m_pPlayer && playerModel == m_pPlayerModel)
{
return;
}
ReleaseActionPlayPolicy();
m_pPlayer = player;
m_pPlayerModel = playerModel;
// 是否支持移动中施法(当前C#端未实现,统一设为false)
// Support cast-while-move (not implemented in C# port -> false)
m_bSupportCastSkillWhenMove = false;
if (!m_bSupportCastSkillWhenMove)
{
// 如果不支持,仍保留“受击”通道逻辑钩子(在C#里留空)
// If not supported, keep the hook for wound channel (no-op in C#)
}
InitializeActionPlayPolicy();
}
public bool SupportCastSkillWhenMove()
{
return m_bSupportCastSkillWhenMove;
}
public bool CanCombineWithMoveForSkill(int idSkill)
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.CanCombineWithMoveForSkill(idSkill);
}
private void InitializeActionPlayPolicy()
{
// 当前C#只提供默认策略(不拆分上下半身)
// Use default policy in this C# port
m_actionPlayPolicy = new CECPlayerActionPlayPolicy(m_pPlayer, m_pPlayerModel);
}
private void ReleaseActionPlayPolicy()
{
m_actionPlayPolicy = null;
}
// Build channels (C# no-op, return false to indicate not supported here)
// 构建动作通道(C#未实现,返回false)
private bool BuildChannelForCastSkillWhenMove()
{
return false;
}
public bool PlayNonSkillActionWithName(int iAction, string szActName, bool bRestart = true, int nTransTime = 200, bool bNoFx = false, bool[] pActFlag = null, uint dwFlagMode = 0)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlayNonSkillActionWithName(iAction, szActName, bRestart, nTransTime, bNoFx, pActFlag, dwFlagMode);
}
public bool QueueNonSkillActionWithName(int iAction, string szActName, int nTransTime = 200, bool bForceStopPrevAct = false, bool bNoFx = false, bool bResetSpeed = false, bool bResetActFlag = false, bool[] pNewActFlag = null, uint dwNewFlagMode = 0)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.QueueNonSkillActionWithName(iAction, szActName, nTransTime, bForceStopPrevAct, bNoFx, bResetSpeed, bResetActFlag, pNewActFlag, dwNewFlagMode);
}
public bool PlaySkillCastActionWithName(int idSkill, string szActName, bool bNoFX = false)
{
if (m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlaySkillCastActionWithName(idSkill, szActName, bNoFX))
{
m_bSkillAttackActionPlayed = false;
return true;
}
return false;
}
public bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX = false, bool[] pActFlag = null, uint dwFlagMode = 0)
{
if (m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, pActFlag, dwFlagMode))
{
m_bSkillAttackActionPlayed = true;
return true;
}
return false;
}
public bool QueueSkillAttackActionWithName(int idSkill, string szActName, int nTransTime = 200, bool bNoFX = false, bool bResetSpeed = false, bool bResetActFlag = false, bool[] pNewActFlag = null, uint dwNewFlagMode = 0)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.QueueSkillAttackActionWithName(idSkill, szActName, nTransTime, bNoFX, bResetSpeed, bResetActFlag, pNewActFlag, dwNewFlagMode);
}
public bool PlayWoundActionWithName(string szActName)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlayWoundActionWithName(szActName);
}
public void ClearComActFlagAllRankNodes(bool bSignalCurrent)
{
if (m_actionPlayPolicy != null)
{
m_actionPlayPolicy.ClearComActFlagAllRankNodes(bSignalCurrent);
}
}
public void StopChannelAction()
{
if (m_actionPlayPolicy != null)
{
m_actionPlayPolicy.StopChannelAction();
}
}
public void StopSkillCastAction()
{
if (m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction() && !m_bSkillAttackActionPlayed)
{
m_actionPlayPolicy.StopSkillAction();
// LOG kept minimal in C#
}
}
public void StopSkillAttackAction()
{
if (m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction() && m_bSkillAttackActionPlayed)
{
m_actionPlayPolicy.StopSkillAction();
// LOG kept minimal in C#
}
}
public bool IsPlayingAction(int iAction)
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingAction(iAction);
}
public bool IsPlayingCastingSkillAction()
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction();
}
public bool IsPlayingMoveAction()
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingMoveAction();
}
public int GetLowerBodyAction()
{
return m_actionPlayPolicy != null ? m_actionPlayPolicy.GetLowerBodyAction() : -1;
}
}*/
public class CECPlayerActionPlayPolicy
{
protected readonly CECPlayer m_pPlayer;
protected readonly CECModel m_pPlayerModel;
// 简单状态记录以支持“是否在施法中”的判断
// Simple state to support IsPlayingCastingSkillAction
private bool m_isCastingSkill;
public CECPlayerActionPlayPolicy(CECPlayer pPlayer, CECModel pPlayerModel)
{
m_pPlayer = pPlayer;
m_pPlayerModel = pPlayerModel;
m_isCastingSkill = false;
}
public virtual bool CanCombineWithMoveForSkill(int idSkill)
{
return false;
}
public CECPlayer GetPlayer()
{
return m_pPlayer;
}
public CECModel GetModel()
{
return m_pPlayerModel;
}
public bool IsMoving()
{
return IsPlayingMoveAction() && (m_pPlayer != null && m_pPlayer.IsWorkMoveRunning());
}
public static bool IsMoveAction(int action)
{
return action == (int)PLAYER_ACTION_TYPE.ACT_RUN
|| action == (int)PLAYER_ACTION_TYPE.ACT_WALK
|| action == (int)PLAYER_ACTION_TYPE.ACT_FLY
|| action == (int)PLAYER_ACTION_TYPE.ACT_FLY_SWORD
|| action == (int)PLAYER_ACTION_TYPE.ACT_SWIM
|| action == (int)PLAYER_ACTION_TYPE.ACT_SWIM_FOR_MOVESKILL;
}
public bool IsPlayingCastingSkillAction()
{
return m_isCastingSkill;
}
// Non-skill action
public virtual bool PlayNonSkillActionWithName(int iAction, string szActName, bool bRestart, int nTransTime, bool bNoFx, bool[] pActFlag, uint dwFlagMode)
{
if (m_pPlayer == null || string.IsNullOrEmpty(szActName))
{
return false;
}
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new PlayActionEvent(szActName));
return true;
}
return false;
}
public bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX = false, bool[] pActFlag = null, uint dwFlagMode = 0)
{
if (m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, pActFlag, dwFlagMode))
public virtual bool QueueNonSkillActionWithName(int iAction, string szActName, int nTransTime, bool bForceStopPrevAct, bool bNoFx, bool bResetSpeed, bool bResetActFlag, bool[] pNewActFlag, uint dwNewFlagMode)
{
m_bSkillAttackActionPlayed = true;
// 当前实现:直接播放(队列行为由上层系统处理)
// Current: just play, queue behavior handled by upper systems
return PlayNonSkillActionWithName(iAction, szActName, false, nTransTime, bNoFx, pNewActFlag, dwNewFlagMode);
}
// Skill actions
public virtual bool PlaySkillCastActionWithName(int idSkill, string szActName, bool bNoFX)
{
if (m_pPlayer == null || string.IsNullOrEmpty(szActName))
{
return false;
}
if (IsMoving())
{
return false;
}
m_isCastingSkill = true;
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new PlayActionEvent(szActName));
return true;
}
return false;
}
public bool QueueSkillAttackActionWithName(int idSkill, string szActName, int nTransTime = 200, bool bNoFX = false, bool bResetSpeed = false, bool bResetActFlag = false, bool[] pNewActFlag = null, uint dwNewFlagMode = 0)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.QueueSkillAttackActionWithName(idSkill, szActName, nTransTime, bNoFX, bResetSpeed, bResetActFlag, pNewActFlag, dwNewFlagMode);
}
public bool PlayWoundActionWithName(string szActName)
{
return m_actionPlayPolicy != null
&& m_actionPlayPolicy.PlayWoundActionWithName(szActName);
}
public void ClearComActFlagAllRankNodes(bool bSignalCurrent)
{
if (m_actionPlayPolicy != null)
public virtual bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX, bool[] pActFlag, uint dwFlagMode)
{
m_actionPlayPolicy.ClearComActFlagAllRankNodes(bSignalCurrent);
if (m_pPlayer == null || string.IsNullOrEmpty(szActName))
{
return false;
}
if (IsMoving())
{
return false;
}
m_isCastingSkill = true;
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new PlayActionEvent(szActName));
return true;
}
public virtual bool QueueSkillAttackActionWithName(int idSkill, string szActName, int nTransTime, bool bNoFX, bool bResetSpeed, bool bResetActFlag, bool[] pNewActFlag, uint dwNewFlagMode)
{
return PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, pNewActFlag, dwNewFlagMode);
}
public virtual bool PlayWoundActionWithName(string szActName)
{
if (m_pPlayer == null || string.IsNullOrEmpty(szActName))
{
return false;
}
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new PlayActionEvent(szActName));
return true;
}
public virtual void ClearComActFlagAllRankNodes(bool bSignalCurrent)
{
if (m_pPlayer != null)
{
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new ClearComActFlagAllRankNodesEvent(bSignalCurrent));
}
}
public virtual void StopChannelAction()
{
// 在C#端没有底层通道概念,做成清旗标即可
// No channel concept here; clear act flags as a substitute
ClearComActFlagAllRankNodes(true);
}
public virtual void StopSkillAction()
{
m_isCastingSkill = false;
StopChannelAction();
}
public virtual bool IsPlayingAction(int iAction)
{
// C#动画系统由上层驱动,这里不跟踪具体动作,统一返回false
// Not tracked here; return false by default
return false;
}
public virtual bool IsPlayingMoveAction()
{
return false;
}
public virtual int GetLowerBodyAction()
{
return -1;
}
}
public void StopChannelAction()
{
if (m_actionPlayPolicy != null)
{
m_actionPlayPolicy.StopChannelAction();
}
}
public void StopSkillCastAction()
{
if (m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction() && !m_bSkillAttackActionPlayed)
{
m_actionPlayPolicy.StopSkillAction();
// LOG kept minimal in C#
}
}
public void StopSkillAttackAction()
{
if (m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction() && m_bSkillAttackActionPlayed)
{
m_actionPlayPolicy.StopSkillAction();
// LOG kept minimal in C#
}
}
public bool IsPlayingAction(int iAction)
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingAction(iAction);
}
public bool IsPlayingCastingSkillAction()
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction();
}
public bool IsPlayingMoveAction()
{
return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingMoveAction();
}
public int GetLowerBodyAction()
{
return m_actionPlayPolicy != null ? m_actionPlayPolicy.GetLowerBodyAction() : -1;
}
}*/
public class CECPlayerActionPlayPolicy
{
protected readonly CECPlayer m_pPlayer;
protected readonly CECModel m_pPlayerModel;
// 简单状态记录以支持“是否在施法中”的判断
// Simple state to support IsPlayingCastingSkillAction
private bool m_isCastingSkill;
public CECPlayerActionPlayPolicy(CECPlayer pPlayer, CECModel pPlayerModel)
{
m_pPlayer = pPlayer;
m_pPlayerModel = pPlayerModel;
m_isCastingSkill = false;
}
public virtual bool CanCombineWithMoveForSkill(int idSkill)
{
return false;
}
public CECPlayer GetPlayer()
{
return m_pPlayer;
}
public CECModel GetModel()
{
return m_pPlayerModel;
}
public bool IsMoving()
{
return IsPlayingMoveAction() && (m_pPlayer != null && m_pPlayer.IsWorkMoveRunning());
}
public static bool IsMoveAction(int action)
{
return action == (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_RUN
|| action == (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_WALK
|| action == (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_FLY
|| action == (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_FLY_SWORD
|| action == (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SWIM
|| action == (int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SWIM_FOR_MOVESKILL;
}
public bool IsPlayingCastingSkillAction()
{
return m_isCastingSkill;
}
// Non-skill action
public virtual bool PlayNonSkillActionWithName(int iAction, string szActName, bool bRestart, int nTransTime, bool bNoFx, bool[] pActFlag, uint dwFlagMode)
{
if (m_pPlayer == null || string.IsNullOrEmpty(szActName))
{
return false;
}
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new PlayActionEvent(szActName));
return true;
}
public virtual bool QueueNonSkillActionWithName(int iAction, string szActName, int nTransTime, bool bForceStopPrevAct, bool bNoFx, bool bResetSpeed, bool bResetActFlag, bool[] pNewActFlag, uint dwNewFlagMode)
{
// 当前实现:直接播放(队列行为由上层系统处理)
// Current: just play, queue behavior handled by upper systems
return PlayNonSkillActionWithName(iAction, szActName, false, nTransTime, bNoFx, pNewActFlag, dwNewFlagMode);
}
// Skill actions
public virtual bool PlaySkillCastActionWithName(int idSkill, string szActName, bool bNoFX)
{
if (m_pPlayer == null || string.IsNullOrEmpty(szActName))
{
return false;
}
if (IsMoving())
{
return false;
}
m_isCastingSkill = true;
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new PlayActionEvent(szActName));
return true;
}
public virtual bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX, bool[] pActFlag, uint dwFlagMode)
{
if (m_pPlayer == null || string.IsNullOrEmpty(szActName))
{
return false;
}
if (IsMoving())
{
return false;
}
m_isCastingSkill = true;
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new PlayActionEvent(szActName));
return true;
}
public virtual bool QueueSkillAttackActionWithName(int idSkill, string szActName, int nTransTime, bool bNoFX, bool bResetSpeed, bool bResetActFlag, bool[] pNewActFlag, uint dwNewFlagMode)
{
return PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, pNewActFlag, dwNewFlagMode);
}
public virtual bool PlayWoundActionWithName(string szActName)
{
if (m_pPlayer == null || string.IsNullOrEmpty(szActName))
{
return false;
}
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new PlayActionEvent(szActName));
return true;
}
public virtual void ClearComActFlagAllRankNodes(bool bSignalCurrent)
{
if (m_pPlayer != null)
{
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new CECPlayer.ClearComActFlagAllRankNodesEvent(bSignalCurrent));
}
}
public virtual void StopChannelAction()
{
// 在C#端没有底层通道概念,做成清旗标即可
// No channel concept here; clear act flags as a substitute
ClearComActFlagAllRankNodes(true);
}
public virtual void StopSkillAction()
{
m_isCastingSkill = false;
StopChannelAction();
}
public virtual bool IsPlayingAction(int iAction)
{
// C#动画系统由上层驱动,这里不跟踪具体动作,统一返回false
// Not tracked here; return false by default
return false;
}
public virtual bool IsPlayingMoveAction()
{
return false;
}
public virtual int GetLowerBodyAction()
{
return -1;
}
}
}
@@ -13,9 +13,8 @@ using System.Data;
using System.Text;
using BrewMonster.PerfectWorld.Scripts.Vfx;
using UnityEngine;
using static CECNPC;
namespace PerfectWorld.Scripts.Player
namespace BrewMonster
{
public class EC_ElsePlayer : CECPlayer
{
@@ -624,26 +623,6 @@ namespace PerfectWorld.Scripts.Player
APPEAR_RUNINTOVIEW, // Player run into view
APPEAR_GHOST, // Player is in ghost state, in player list but not active
};
public struct OtherPlayer_Move_Info
{
// Bounding sphere of avator
public A3DVECTOR3 vCenter;
public A3DVECTOR3 vExts;
public float fStepHeight;
// Velocity
public A3DVECTOR3 vVelocity;
// time span ( sec )
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
}
public class A3DAABB
{
public A3DVECTOR3 Center;
@@ -0,0 +1,533 @@
// Filename : CECCastSkillWhenMove.cs
// Creator : Xu Wenbin
// Date : 2014/8/1
// Converted to C# from C++ by AI Assistant
using BrewMonster.Scripts.Skills;
using System.Linq;
namespace BrewMonster
{
// Constants from EC_RoleTypes.h
public static class RoleTypes
{
// 职业 // Profession
public const int PROF_WARRIOR = 0; // 武侠 // Warrior
public const int PROF_MAGE = 1; // 法师 // Mage
public const int PROF_MONK = 2; // 巫师 // Monk
public const int PROF_HAG = 3; // 妖精 // Hag
public const int PROF_ORC = 4; // 妖兽 // Orc
public const int PROF_GHOST = 5; // 刺客 // Ghost
public const int PROF_ARCHOR = 6; // 羽芒 // Archer
public const int PROF_ANGEL = 7; // 羽灵 // Angel
public const int PROF_JIANLING = 8; // 剑灵 // Jianling
public const int PROF_MEILING = 9; // 魅灵 // Meiling
public const int PROF_YEYING = 10; // 夜影 // Yeying
public const int PROF_YUEXIAN = 11; // 月仙 // Yuexian
public const int NUM_PROFESSION = 12;
// 性别 // Gender
public const int GENDER_MALE = 0;
public const int GENDER_FEMALE = 1;
public const int NUM_GENDER = 2;
}
// Constants from EC_Player.h
public static class PlayerModelType
{
public const int PLAYERMODEL_MAJOR = 0; // 主模型 // Major model
public const int PLAYERMODEL_PROFESSION = 1; // 职业变身 // Profession transformation
public const int PLAYERMODEL_DUMMYTYPE2 = 2; // Buff相关 // Buff related
public const int PLAYERMODEL_DUMMYTYPE3 = 3; // 未使用 // Not used
public const int PLAYERMODEL_MAX = 4;
public const int PLAYERMODEL_TYPEALL = unchecked((int)0xffffffff);
}
// Constants from EC_Resource.h
public static class ResourceModel
{
public const int RES_MOD_YUEXIAN_M = 0; // 月仙男标准模型 // Yuexian male standard model
public const int RES_MOD_YUEXIAN_F = 1; // 月仙女标准模型 // Yuexian female standard model
public const int RES_MOD_YUEXIAN_RESHAPE_M = 2; // 月仙男职业变身 // Yuexian male profession reshape
public const int RES_MOD_YUEXIAN_RESHAPE_F = 3; // 月仙女职业变身 // Yuexian female profession reshape
}
/// <summary>
/// 移动施法管理类 // Cast Skill When Move Manager
/// </summary>
public class CECCastSkillWhenMove : Singleton<CECCastSkillWhenMove>
{
// 朦胧 // Oboro
// 标准男性 UpperBody // Standard male upper body bones
private static readonly string[] s_szOboroMaleStandardUpperBodyBonesName = {
"Bip01 shangshen",
"Bip01 Spine",
"Bip01 Spine1",
"Bip01 Spine2",
"Bip01 Neck",
"Bip01 Head",
"Bip01 L Clavicle",
"Bip01 L UpperArm",
"Bip01 L Forearm",
"Bip01 L Hand",
"Bip01 L Finger0",
"Bip01 L Finger01",
"Bip01 L Finger1",
"Bip01 L Finger11",
"Bip01 R Clavicle",
"Bip01 R UpperArm",
"Bip01 R Forearm",
"Bip01 R Hand",
"Bip01 R Finger0",
"Bip01 R Finger01",
"Bip01 R Finger1",
"Bip01 R Finger11",
"Bone05",
};
// 标准男性 LowerBody // Standard male lower body bones
private static readonly string[] s_szOboroMaleStandardLowerBodyBonesName = {
"Bip01",
"Bip01 Pelvis",
"Bip01 xiashen",
"Bip01 L Thigh",
"Bip01 L Calf",
"Bip01 L Foot",
"Bip01 L Toe0",
"Bip01 R Thigh",
"Bip01 R Calf",
"Bip01 R Foot",
"Bip01 R Toe0",
"Bone01",
"Bone02",
"Bone03",
"Bone04",
};
// 职业变身男性 UpperBody // Profession reshape male upper body bones
private static readonly string[] s_szOboroMaleShape1UpperBodyBonesName = {
"Bip01 shangshen",
"Bip01 Spine",
"Bip01 Spine1",
"Bip01 Spine2",
"Bip01 Neck",
"Bip01 Head",
"Bip01 L Clavicle",
"Bip01 L UpperArm",
"Bip01 L Forearm",
"Bip01 L Hand",
"Bip01 L Finger0",
"Bip01 L Finger01",
"Bip01 L Finger1",
"Bip01 L Finger11",
"Bip01 R Clavicle",
"Bip01 R UpperArm",
"Bip01 R Forearm",
"Bip01 R Hand",
"Bip01 R Finger0",
"Bip01 R Finger01",
"Bip01 R Finger1",
"Bip01 R Finger11",
"Bone05",
"Bone13",
"Bone14",
"Bone15",
"Bone16",
"Bone17",
"Bone18",
};
// 职业变身男性 LowerBody // Profession reshape male lower body bones
private static readonly string[] s_szOboroMaleShape1LowerBodyBonesName = {
"Bip01",
"Bip01 Pelvis",
"Bip01 xiashen",
"Bip01 L Thigh",
"Bip01 L Calf",
"Bip01 L Foot",
"Bip01 L Toe0",
"Bip01 R Thigh",
"Bip01 R Calf",
"Bip01 R Foot",
"Bip01 R Toe0",
"Bone06",
"Bone07",
"Bone08",
"Bone09",
"Bone10",
"Bone11",
"Bone12",
"Bone19",
"Bone20",
"Bone21",
};
// 标准女性 UpperBody // Standard female upper body bones
private static readonly string[] s_szOboroFemaleStandardUpperBodyBonesName = {
"Bip01 Spine shangshen",
"Bip01 Spine",
"Bip01 Spine1",
"Bip01 Spine2",
"Bip01 Neck",
"Bip01 Head",
"Bip01 Ponytail1",
"Bip01 Ponytail11",
"Bip01 Ponytail12",
"Bip01 L Clavicle",
"Bip01 L UpperArm",
"Bip01 L Forearm",
"Bip01 L Hand",
"Bip01 L Finger0",
"Bip01 L Finger01",
"Bip01 L Finger1",
"Bip01 L Finger11",
"Bip01 R Clavicle",
"Bip01 R UpperArm",
"Bip01 R Forearm",
"Bip01 R Hand",
"Bip01 R Finger0",
"Bip01 R Finger01",
"Bip01 R Finger1",
"Bip01 R Finger11",
"Bone05",
"Bone01",
};
// 标准女性 LowerBody // Standard female lower body bones
private static readonly string[] s_szOboroFemaleStandardLowerBodyBonesName = {
"Bip01",
"Bip01 Pelvis",
"Bip01 Spine xiashen",
"Bip01 L Thigh",
"Bip01 L Calf",
"Bip01 L Foot",
"Bip01 L Toe0",
"Bip01 R Thigh",
"Bip01 R Calf",
"Bip01 R Foot",
"Bip01 R Toe0",
"Bone08",
"Bone09",
"Bone10",
"Bone02",
"Bone03",
"Bone04",
};
// 职业变身女性 UpperBody // Profession reshape female upper body bones
private static readonly string[] s_szOboroFemaleShape1UpperBodyBonesName = {
"Bip01 Spine shangshen",
"Bip01 Spine",
"Bip01 Spine1",
"Bip01 Spine2",
"Bip01 Neck",
"Bip01 Head",
"Bip01 Ponytail1",
"Bip01 Ponytail11",
"Bip01 Ponytail12",
"Bip01 L Clavicle",
"Bip01 L UpperArm",
"Bip01 L Forearm",
"Bip01 L Hand",
"Bip01 L Finger0",
"Bip01 L Finger01",
"Bip01 L Finger1",
"Bip01 L Finger11",
"Bip01 R Clavicle",
"Bip01 R UpperArm",
"Bip01 R Forearm",
"Bip01 R Hand",
"Bip01 R Finger0",
"Bip01 R Finger01",
"Bip01 R Finger1",
"Bip01 R Finger11",
"Bone05",
"Bone01",
"Bone14",
"Bone15",
"Bone16",
"Bone17",
"Bone18",
"Bone19",
"Bone20",
"Bone21",
"Bone22",
"Bone23",
"Bone24",
};
// 职业变身女性 LowerBody // Profession reshape female lower body bones
private static readonly string[] s_szOboroFemaleShape1LowerBodyBonesName = {
"Bip01",
"Bip01 Pelvis",
"Bip01 Spine xiashen",
"Bip01 L Thigh",
"Bip01 L Calf",
"Bip01 L Foot",
"Bip01 L Toe0",
"Bip01 R Thigh",
"Bip01 R Calf",
"Bip01 R Foot",
"Bip01 R Toe0",
"Bone08",
"Bone09",
"Bone10",
"Bone02",
"Bone03",
"Bone04",
"Bone06",
"Bone07",
"Bone11",
"Bone12",
"Bone13",
};
/// <summary>
/// 玩家信息 // Player information
/// </summary>
public class PlayerInfo
{
public int profession; // 职业 // Profession
public int gender; // 性别 // Gender
public int shapeType; // 变身类型 // Shape type
public int shapeID; // 变身ID // Shape ID
public PlayerInfo(int profession, int gender, int shapeType, int shapeID)
{
this.profession = profession;
this.gender = gender;
this.shapeType = shapeType;
this.shapeID = shapeID;
}
public PlayerInfo(CECPlayer pPlayer)
{
if (pPlayer != null)
{
this.profession = pPlayer.GetProfession();
this.gender = pPlayer.GetGender();
this.shapeType = pPlayer.GetShapeType();
this.shapeID = pPlayer.GetShapeID();
}
}
}
// Singleton instance
private static readonly object s_lock = new object();
// Private constructor for singleton
public CECCastSkillWhenMove()
{
}
/// <summary>
/// 获取单例实例 // Get singleton instance
/// </summary>
/// <summary>
/// 检查模型是否支持移动施法 // Check if model supports casting while moving
/// </summary>
private bool HasModelSupport(PlayerInfo player)
{
if (player.profession == RoleTypes.PROF_YUEXIAN)
{
switch (player.shapeType)
{
case PlayerModelType.PLAYERMODEL_MAJOR: // 标准模型 // Standard model
return true;
case PlayerModelType.PLAYERMODEL_PROFESSION: // 职业变身模型 // Profession reshape model
if (player.gender == RoleTypes.GENDER_MALE)
{
return player.shapeID == ResourceModel.RES_MOD_YUEXIAN_RESHAPE_M; // 男职业变身 // Male profession reshape
}
else
{
return player.shapeID == ResourceModel.RES_MOD_YUEXIAN_RESHAPE_F; // 女职业变身 // Female profession reshape
}
}
}
// 支持移动施法的ecm模型 // ecm models that support casting while moving
// 注意夜影 PROF_YEYING 模型也支持,但他们没有任何移动施法的技能,故此处不加,以避免不必要的开销
// Note: PROF_YEYING models also support this, but they don't have any moving cast skills, so not added here to avoid unnecessary overhead
return false;
}
/// <summary>
/// 检查技能是否支持移动施法 // Check if skill supports casting while moving
/// </summary>
private bool IsSkillSupported(int idSkill, PlayerInfo player)
{
// 支持移动施法的技能ID // Skill IDs that support casting while moving
return ElementSkill.IsMovingSkill((uint)idSkill);
}
/// <summary>
/// 检查技能动作是否支持移动施法 // Check if skill action supports casting while moving
/// </summary>
private bool HasActionSupport(int idSkill, PlayerInfo player)
{
if (HasModelSupport(player))
{
const int SKILL_COUNT = 19;
int[] s_skills = new int[SKILL_COUNT] {
2571, 2572, 2579, 2580, 2588, 2591, // 2571素罗闪 2572朱雀闪 2579辞诗箫 2580沐仙曲 2588霜雪铃 2591夕月飞星
2627, 2619, 2620, 2621, 2622, 2787, // 2627镜花水月 2619天·素罗闪 2620地·素罗闪 2621天·朱雀闪 2622地·朱雀闪 2787天·辞诗箫
2788, 2789, 2790, 2805, 2806, 2811, // 2788地·辞诗箫 2789天·沐仙曲 2790地·沐仙曲 2805天·霜雪铃 2806地·霜雪铃 2811天·夕月飞星
2812 // 2812地·夕月飞星
};
return s_skills.Contains(idSkill);
}
return false;
}
/// <summary>
/// 获取上半身骨骼名称 // Get upper body bones name
/// </summary>
private bool GetUpperBodyBonesName(PlayerInfo player, out int bonesNameCount, out string[] szBonesName)
{
bonesNameCount = 0;
szBonesName = null;
bool result = false;
if (HasModelSupport(player))
{
switch (player.shapeType)
{
case PlayerModelType.PLAYERMODEL_MAJOR:
if (RoleTypes.GENDER_MALE == player.gender)
{
szBonesName = s_szOboroMaleStandardUpperBodyBonesName;
bonesNameCount = s_szOboroMaleStandardUpperBodyBonesName.Length;
}
else
{
szBonesName = s_szOboroFemaleStandardUpperBodyBonesName;
bonesNameCount = s_szOboroFemaleStandardUpperBodyBonesName.Length;
}
break;
case PlayerModelType.PLAYERMODEL_PROFESSION:
if (RoleTypes.GENDER_MALE == player.gender)
{
if (ResourceModel.RES_MOD_YUEXIAN_RESHAPE_M == player.shapeID)
{
szBonesName = s_szOboroMaleShape1UpperBodyBonesName;
bonesNameCount = s_szOboroMaleShape1UpperBodyBonesName.Length;
}
}
else
{
if (ResourceModel.RES_MOD_YUEXIAN_RESHAPE_F == player.shapeID)
{
szBonesName = s_szOboroFemaleShape1UpperBodyBonesName;
bonesNameCount = s_szOboroFemaleShape1UpperBodyBonesName.Length;
}
}
break;
default:
// ASSERT(false);
break;
}
result = true;
}
return result;
}
/// <summary>
/// 获取下半身骨骼名称 // Get lower body bones name
/// </summary>
private bool GetLowerBodyBonesName(PlayerInfo player, out int bonesNameCount, out string[] szBonesName)
{
bonesNameCount = 0;
szBonesName = null;
bool result = false;
if (HasModelSupport(player))
{
switch (player.shapeType)
{
case PlayerModelType.PLAYERMODEL_MAJOR:
if (RoleTypes.GENDER_MALE == player.gender)
{
szBonesName = s_szOboroMaleStandardLowerBodyBonesName;
bonesNameCount = s_szOboroMaleStandardLowerBodyBonesName.Length;
}
else
{
szBonesName = s_szOboroFemaleStandardLowerBodyBonesName;
bonesNameCount = s_szOboroFemaleStandardLowerBodyBonesName.Length;
}
break;
case PlayerModelType.PLAYERMODEL_PROFESSION:
if (RoleTypes.GENDER_MALE == player.gender)
{
if (ResourceModel.RES_MOD_YUEXIAN_RESHAPE_M == player.shapeID)
{
szBonesName = s_szOboroMaleShape1LowerBodyBonesName;
bonesNameCount = s_szOboroMaleShape1LowerBodyBonesName.Length;
}
}
else
{
if (ResourceModel.RES_MOD_YUEXIAN_RESHAPE_F == player.shapeID)
{
szBonesName = s_szOboroFemaleShape1LowerBodyBonesName;
bonesNameCount = s_szOboroFemaleShape1LowerBodyBonesName.Length;
}
}
break;
default:
// ASSERT(false);
break;
}
result = true;
}
return result;
}
// Public methods that accept CECPlayer
/// <summary>
/// 检查玩家模型是否支持移动施法 // Check if player model supports casting while moving
/// </summary>
public bool HasModelSupport(CECPlayer pPlayer)
{
return pPlayer != null && HasModelSupport(new PlayerInfo(pPlayer));
}
/// <summary>
/// 检查技能是否支持移动施法 // Check if skill supports casting while moving
/// </summary>
public bool IsSkillSupported(int idSkill, CECPlayer pPlayer)
{
return pPlayer != null && IsSkillSupported(idSkill, new PlayerInfo(pPlayer));
}
/// <summary>
/// 检查技能动作是否支持移动施法 // Check if skill action supports casting while moving
/// </summary>
public bool HasActionSupport(int idSkill, CECPlayer pPlayer)
{
return pPlayer != null && HasActionSupport(idSkill, new PlayerInfo(pPlayer));
}
/// <summary>
/// 获取玩家上半身骨骼名称 // Get player upper body bones name
/// </summary>
public bool GetUpperBodyBonesName(CECPlayer pPlayer, out int bonesNameCount, out string[] szBonesName)
{
bonesNameCount = 0;
szBonesName = null;
return pPlayer != null && GetUpperBodyBonesName(new PlayerInfo(pPlayer), out bonesNameCount, out szBonesName);
}
/// <summary>
/// 获取玩家下半身骨骼名称 // Get player lower body bones name
/// </summary>
public bool GetLowerBodyBonesName(CECPlayer pPlayer, out int bonesNameCount, out string[] szBonesName)
{
bonesNameCount = 0;
szBonesName = null;
return pPlayer != null && GetLowerBodyBonesName(new PlayerInfo(pPlayer), out bonesNameCount, out szBonesName);
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1f189ae1325aa9e40a4e2aadce181e65
@@ -17,7 +17,7 @@ namespace BrewMonster.Scripts.Skills
TYPE_PASSIVE = 5, // Passive //
TYPE_ENABLED = 6, // Enabled //
TYPE_LIVE = 7, // Live //
TYPE_JUMP = 8, // Jump // ˲
TYPE_FLASHMOVE = 8, // Jump // ˲
TYPE_PRODUCE = 9, // Production (Crafting) // ()
TYPE_BLESSPET = 10, // Pet Blessing // ף
TYPE_NEUTRALBLESS = 11, // Neutral Blessing // ף
@@ -25,12 +25,12 @@ namespace BrewMonster.Scripts.Skills
public enum range_type
{
TYPE_POINT = 0, //
TYPE_LINE = 1, //
TYPE_SELFSPHERE = 2, // Ϊĵ
TYPE_TARGETSPHERE = 3, // ĿΪĵ
TYPE_TAPER = 4, // Բ׶
TYPE_SLEF = 5, //
RANGE_POINT = 0, // µã
RANGE_LINE, // Ïß
RANGE_SELFSPHERE, // ×ÔÉíΪÖÐÐĵÄÇò
RANGE_TARGETSPHERE, // Ä¿±êΪÖÐÐĵÄÇò
RANGE_TAPER, // Ô²×¶
RANGE_SLEF, // ×ÔÉí
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
@@ -274,9 +274,17 @@ namespace BrewMonster.Scripts.Skills
public virtual bool IsAllowWater() { return true; }
public virtual bool IsAllowAir() { return true; }
public virtual bool GetNotuseInCombat() { return false; }
//Ƿƶʩ
//Ƿƶʩ // Whether it's a moving skill
public virtual bool IsMovingSkill() { return false; }
// ܷڵǰ״̬ʹ
// ǷΪƶʩ // Check if skill ID is a moving skill
public static bool IsMovingSkill(uint id)
{
SkillStub s = SkillStub.GetStub(id);
if (s != null)
return s.IsMovingSkill();
return false;
}
// ܷڵǰ״̬ʹ // Whether skill can be used in current form state
public bool IsValidForm(byte form)
{
byte form_type = (byte)((form & FORM_MASK_HIGH) >> 6);
@@ -1,5 +1,4 @@
using BrewMonster.Assets.PerfectWorld.Scripts.Common;
using CSNetwork.GPDataType;
using CSNetwork.GPDataType;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -222,3 +222,4 @@ namespace BrewMonster
@@ -222,3 +222,4 @@ namespace BrewMonster
@@ -319,3 +319,4 @@ namespace BrewMonster
@@ -313,3 +313,4 @@ namespace BrewMonster
@@ -324,3 +324,4 @@ namespace BrewMonster
@@ -317,3 +317,4 @@ namespace BrewMonster
@@ -227,3 +227,4 @@ namespace BrewMonster
@@ -1,5 +1,4 @@
using BrewMonster.Assets.PerfectWorld.Scripts.Common;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -188,7 +188,7 @@ namespace BrewMonster.UI
}
if (HasTracedTask())
{
CECNPC pNPC = (EC_ManMessageMono.Instance._CECNPCMan.SeekOutNPC(m_iTracedTaskNPCID));
CECNPC pNPC = (EC_ManMessageMono.Instance.CECNPCMan.SeekOutNPC(m_iTracedTaskNPCID));
if (pNPC)
{
if (pEssence.id == pNPC.GetNPCID())
@@ -44,7 +44,6 @@ namespace BrewMonster
private void UpdateHostPlayerInfoUI(cmd_self_info_00 obj)
{
BMLogger.LogError("Update HUD Player Info");
healthText.text = $"{obj.iHP}/{obj.iMaxHP}";
manaText.text = $"{obj.iMP}/{obj.iMaxMP}";
expText.text = $"{((float)obj.iExp/neededExp)*100}%";
+30 -1
View File
@@ -1,6 +1,8 @@
using BrewMonster;
using BrewMonster.Assets.PerfectWorld.Scripts.Common;
using BrewMonster.Managers;
using BrewMonster.Scripts.Ornament;
using CSNetwork.GPDataType;
using PerfectWorld.Scripts.Managers.BrewMonster.Managers;
using UnityEngine;
@@ -26,5 +28,32 @@ namespace BrewMonster.Scripts.World
{
return m_pOnmtMan;
}
public CECObject GetObject(int idObject, int iAliveFlag)
{
CECObject pObject = null;
if (GPDataTypeHelper.ISNPCID(idObject))
{
if (!(pObject = EC_ManMessageMono.Instance.CECNPCMan.GetNPC(idObject)))
return null;
if ((iAliveFlag == 1 && ((CECNPC)pObject).IsDead()) ||
(iAliveFlag == 2 && !((CECNPC)pObject).IsDead()))
return null;
}
else if (GPDataTypeHelper.ISPLAYERID(idObject))
{
if (!(pObject = EC_ManMessageMono.Instance.GetECManPlayer.GetPlayer(idObject)))
return null;
if ((iAliveFlag == 1 && ((CECPlayer)pObject).IsDead()) ||
(iAliveFlag == 2 && !((CECPlayer)pObject).IsDead()))
return null;
}
else if (GPDataTypeHelper.ISMATTERID(idObject))
pObject = EC_ManMessageMono.Instance.GetECManMatter.GetMatter(idObject);
return pObject;
}
}
}
+159 -160
View File
@@ -12,7 +12,6 @@ using CSNetwork.GPDataType;
using CSNetwork.Protocols.RPCData;
using ModelRenderer.Scripts.GameData;
using PerfectWorld.Scripts.Managers;
using PerfectWorld.Scripts.Player;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
@@ -22,7 +21,7 @@ using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Host_work_ID = BrewMonster.Scripts.CECHPWork.Host_work_ID;
using Trace_reason = CECHPWorkTrace.Trace_reason;
using Trace_reason = BrewMonster.CECHPWorkTrace.Trace_reason;
namespace BrewMonster
{
@@ -287,7 +286,7 @@ namespace BrewMonster
int idObject = CECObject.GetObjectID(clickedObject);
if (idObject != 0)
{
CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(idObject);
CECNPC pNPC = EC_ManMessageMono.Instance.CECNPCMan.GetNPC(idObject);
if (pNPC != null)
{
if (!pNPC.IsDead() && m_idSelTarget == idObject)
@@ -664,7 +663,7 @@ namespace BrewMonster
// Mark host player as corpse so CECPlayer.IsDead() returns true
m_dwStates |= (uint)PlayerNPCState.GP_STATE_CORPSE;
EventBus.PublishChannel(GetCharacterID(), new CECPlayer.ClearComActFlagAllRankNodesEvent(true));
EventBus.PublishChannel(GetCharacterID(), new ClearComActFlagAllRankNodesEvent(true));
PlayAction((int)PLAYER_ACTION_TYPE.ACT_GROUNDDIE);
if (PopupManager.Instance != null)
{
@@ -767,7 +766,7 @@ namespace BrewMonster
}
else if (GPDataTypeHelper.ISNPCID(pCmd.idAttacker))
{
CECNPC pAttacker = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(pCmd.idAttacker);
CECNPC pAttacker = EC_ManMessageMono.Instance.CECNPCMan.GetNPC(pCmd.idAttacker);
if (pAttacker)
{
pAttacker.OnMsgAttackHostResult(GetCharacterID(), pCmd.iDamage, pCmd.attack_flag, pCmd.speed);
@@ -1388,12 +1387,12 @@ namespace BrewMonster
//CECHPWorkDead pWork = (CECHPWorkDead*)m_pWorkMan->CreateWork(CECHPWork.Host_work_ID.WORK_DEAD);
//pWork->SetBeDeadFlag(true);
//m_pWorkMan->StartWork_p0(pWork);
EventBus.PublishChannel(GetCharacterID(), new CECPlayer.ClearComActFlagAllRankNodesEvent(true));
PlayAction((int)PLAYER_ACTION_TYPE.ACT_GROUNDDIE);
if (PopupManager.Instance != null)
{
PopupManager.Instance.OnPlayerDied();
}
EventBus.PublishChannel(GetCharacterID(), new ClearComActFlagAllRankNodesEvent(true));
PlayAction((int)PLAYER_ACTION_TYPE.ACT_GROUNDDIE);
if (PopupManager.Instance != null)
{
PopupManager.Instance.OnPlayerDied();
}
}
else
{
@@ -1989,41 +1988,41 @@ namespace BrewMonster
// If host has set bless skill filter only to himself, bless skill couldn't add to other players
byte byBLSMask = EC_Utility.glb_BuildBLSMask();
/* if (pSkill->GetRangeType() == CECSkill::RANGE_POINT)
if (pSkill.GetRangeType() == (int)range_type.RANGE_POINT)
{
if (!IsTeamMember(idCastTarget))
{
if (byBLSMask & GP_BLSMASK_SELF)
if ((byBLSMask & (byte)PVPMask.GP_BLSMASK_SELF) != 0)
idCastTarget = m_PlayerInfo.cid;
else
{
CECElsePlayer* pPlayer = (CECElsePlayer*)g_pGame->GetGameRun()->GetWorld()->GetPlayerMan()->GetPlayer(idCastTarget);
if (!pPlayer)
EC_ElsePlayer pPlayer = (EC_ElsePlayer)EC_ManMessageMono.Instance.GetECManPlayer.GetPlayer(idCastTarget);
if (pPlayer == null)
{
// Ä¿±êÏûʧ
return false;
}
if (pPlayer->IsInvader() || pPlayer->IsPariah())
if (pPlayer.IsInvader() || pPlayer.IsPariah())
{
if (byBLSMask & GP_BLSMASK_NORED)
if ((byBLSMask & (byte)PVPMask.GP_BLSMASK_NORED) != 0)
idCastTarget = m_PlayerInfo.cid;
}
if (!IsFactionMember(pPlayer->GetFactionID()))
if (!IsFactionMember(pPlayer.GetFactionID()))
{
if (byBLSMask & GP_BLSMASK_NOMAFIA)
if ((byBLSMask & (byte)PVPMask.GP_BLSMASK_NOMAFIA) != 0)
idCastTarget = m_PlayerInfo.cid;
}
if (!IsFactionAllianceMember(pPlayer->GetFactionID()))
if (!IsFactionAllianceMember(pPlayer.GetFactionID()))
{
if (byBLSMask & GP_BLSMASK_NOALLIANCE)
if ((byBLSMask & (byte)PVPMask.GP_BLSMASK_NOALLIANCE) != 0)
idCastTarget = m_PlayerInfo.cid;
}
if (GetForce() != pPlayer->GetForce())
if (GetForce() != pPlayer.GetForce())
{
if (byBLSMask & GP_BLSMASK_NOFORCE)
if ((byBLSMask & (byte)PVPMask.GP_BLSMASK_NOFORCE) != 0)
idCastTarget = m_PlayerInfo.cid;
}
}
@@ -2037,133 +2036,136 @@ namespace BrewMonster
// If host is in battle, bless skill couldn't add to enemies
if (IsInBattle())
{
CECElsePlayer* pPlayer = m_pPlayerMan->GetElsePlayer(idCastTarget);
EC_ElsePlayer pPlayer = EC_ManMessageMono.Instance.GetECManPlayer.GetElsePlayer(idCastTarget);
if (!InSameBattleCamp(pPlayer))
idCastTarget = m_PlayerInfo.cid;
}*/
}
}
}
//else if (pSkill->GetType() == CECSkill::TYPE_BLESSPET)
//{
// CECPet* pPet = g_pGame->GetGameRun()->GetWorld()->GetNPCMan()->GetPetByID(idSelTarget);
// if (!pPet || pPet->GetMasterID() == GetCharacterID())
// {
// // Spell skill on host's pet
// CECPetData* pPetData = m_pPetCorral->GetActivePet();
// if (!pPetData ||
// pPetData->GetClass() != GP_PET_CLASS_COMBAT &&
// pPetData->GetClass() != GP_PET_CLASS_SUMMON &&
// pPetData->GetClass() != GP_PET_CLASS_EVOLUTION)
// return false;
/* else if (pSkill.GetType() == CECSkill::TYPE_BLESSPET)
{
CECPet* pPet = g_pGame->GetGameRun()->GetWorld()->GetNPCMan()->GetPetByID(idSelTarget);
if (!pPet || pPet->GetMasterID() == GetCharacterID())
{
// Spell skill on host's pet
CECPetData* pPetData = m_pPetCorral->GetActivePet();
if (!pPetData ||
pPetData->GetClass() != GP_PET_CLASS_COMBAT &&
pPetData->GetClass() != GP_PET_CLASS_SUMMON &&
pPetData->GetClass() != GP_PET_CLASS_EVOLUTION)
return false;
// idCastTarget = m_pPetCorral->GetActivePetNPCID();
// }
// // Only fighting pet can be blessed.
// if (pPet && !pPet->CanBeAttacked())
// return false;
//}
//else
//{
// if (iTargetType != 0 && !idCastTarget)
// return false;
//}
//// iTargetType == 4 means target must be pet. The problem is that pet will
//// disappear from world after it died, so GetWorld()->GetObject() will return
//// NULL when host spells revive-pet skill on his dead pet. So, the target
//// type of revive-pet skill should be 0
//if (iTargetType)
//{
// // Target shoundn't be a corpse ?
// int iAliveFlag = 0;
// if (iTargetType == 1)
// iAliveFlag = 1;
// else if (iTargetType == 2)
// iAliveFlag = 2;
// CECObject* pObject = g_pGame->GetGameRun()->GetWorld()->GetObject(idCastTarget, iAliveFlag);
// if (!pObject)
// return false;
//}
//if (!IsMeleeing() && !IsSpellingMagic() &&
// (!iTargetType || idCastTarget == m_PlayerInfo.cid))
//{
// // Cast this skill need't checking cast distance
// if (!pSkill->ReadyToCast())
// return false;
// // Prepare to cast skill, if skill isn't INSTANT and FLASHMOVE,
// // we must stop moving and stand
// if (!pSkill->IsInstant() && pSkill->GetType() != CECSkill::TYPE_FLASHMOVE)
// {
// if (!NaturallyStopMoving())
// return false; // Couldn't stop naturally, so cancel casting skill
// }
// else if (pSkill->GetType() == CECSkill::TYPE_FLASHMOVE)
// {
// if (!CanDo(CANDO_FLASHMOVE))
// return false;
// }
m_pPrepSkill = pSkill;
//CastSkill(m_idSelTarget, bForceAttack);
//}
//else if (IsSpellingMagic() && m_pCurSkill == pSkill)
//{
// // If we are casting the same skill and it's in cooling time
// return false;
//}
//else // Have to trace selected object before cast skill
//{
// if (!pSkill->ReadyToCast())
// return false;
// if (CECCastSkillWhenMove::Instance().IsSkillSupported(pSkill->GetSkillID(), this) &&
// m_pWorkMan->IsMovingToPosition() &&
// m_pWorkMan->CanCastSkillImmediately(pSkill->GetSkillID()))
// {
// m_pPrepSkill = pSkill;
// return CastSkill(idCastTarget, bForceAttack);
// }
// else
// {
bool bTraceOK = false;
bool bUseAutoPF = false;
/* CECPlayerWrapper* pWrapper = CECAutoPolicy::GetInstance().GetPlayerWrapper();
if (CECAutoPolicy::GetInstance().IsAutoPolicyEnabled() && pWrapper->GetAttackError() >= 2)
bUseAutoPF = true;*/
if (idCastTarget == 0)
idCastTarget = m_pPetCorral->GetActivePetNPCID();
}
// Only fighting pet can be blessed.
if (pPet && !pPet->CanBeAttacked())
return false;
}*/
else
{
idCastTarget = GetCharacterID(); // ±ÜÃâË²ÒÆµÈ¼¼ÄÜʱ idCastTarget Ϊ0µ¼Ö CECWorkTrace::CreateTraceTarget ·µ»Ø¿Õ
}
CECHPWork pWork = m_pWorkMan.GetWork(Host_work_ID.WORK_TRACEOBJECT);
if (pWork != null)
{
CECHPWorkTrace pWorkTrace = (CECHPWorkTrace)(pWork);
if (pWorkTrace.GetTraceReason() == Trace_reason.TRACE_SPELL &&
pWorkTrace.GetTarget() == idCastTarget &&
pWorkTrace.GetPrepSkill() == pSkill)
return false; // We are just doing the same thing
pWorkTrace.SetTraceTarget(pWorkTrace.CreatTraceTarget(idCastTarget, Trace_reason.TRACE_SPELL, bForceAttack), bUseAutoPF);
pWorkTrace.SetPrepSkill(pSkill);
bTraceOK = true;
}
else if (m_pWorkMan.CanStartWork(Host_work_ID.WORK_TRACEOBJECT))
{
CECHPWorkTrace pWork2 = (CECHPWorkTrace)m_pWorkMan.CreateWork(Host_work_ID.WORK_TRACEOBJECT);
pWork2.SetTraceTarget(pWork2.CreatTraceTarget(idCastTarget, Trace_reason.TRACE_SPELL, bForceAttack), bUseAutoPF);
pWork2.SetPrepSkill(pSkill);
m_pWorkMan.StartWork_p1(pWork2);
bTraceOK = true;
if (iTargetType != 0 && idCastTarget == 0)
return false;
}
if (!bTraceOK) return false;
// }
//}
// iTargetType == 4 means target must be pet. The problem is that pet will
// disappear from world after it died, so GetWorld()->GetObject() will return
// NULL when host spells revive-pet skill on his dead pet. So, the target
// type of revive-pet skill should be 0
if (iTargetType != 0)
{
// Target shoundn't be a corpse ?
int iAliveFlag = 0;
if (iTargetType == 1)
iAliveFlag = 1;
else if (iTargetType == 2)
iAliveFlag = 2;
CECObject pObject = EC_Game.GetGameRun().GetWorld().GetObject(idCastTarget, iAliveFlag);
if (!pObject)
return false;
}
if (!IsMeleeing() && !IsSpellingMagic() &&
(iTargetType == 0 || idCastTarget == m_PlayerInfo.cid))
{
// Cast this skill need't checking cast distance
if (!pSkill.ReadyToCast())
return false;
// Prepare to cast skill, if skill isn't INSTANT and FLASHMOVE,
// we must stop moving and stand
if (!pSkill.IsInstant() && pSkill.GetType() != (int)skill_type.TYPE_FLASHMOVE)
{
/* if (!NaturallyStopMoving())
return false; */ // Couldn't stop naturally, so cancel casting skill
}
else if (pSkill.GetType() == (int)skill_type.TYPE_FLASHMOVE)
{
if (!CanDo(ActionCanDo.CANDO_FLASHMOVE))
return false;
}
BMLogger.LogError("HoangDev: ApplySkillShortcut - PATH 1: Calling CastSkill (self-cast)");
m_pPrepSkill = pSkill;
CastSkill(m_idSelTarget, bForceAttack);
}
else if (IsSpellingMagic() && m_pCurSkill == pSkill)
{
// If we are casting the same skill and it's in cooling time
return false;
}
else // Have to trace selected object before cast skill
{
if (!pSkill.ReadyToCast())
return false;
if (CECCastSkillWhenMove.Instance.IsSkillSupported(pSkill.GetSkillID(), this) &&
m_pWorkMan.IsMovingToPosition() &&
m_pWorkMan.CanCastSkillImmediately(pSkill.GetSkillID()))
{
m_pPrepSkill = pSkill;
return CastSkill(idCastTarget, bForceAttack);
}
else
{
bool bTraceOK = false;
bool bUseAutoPF = false;
/* CECPlayerWrapper pWrapper = CECAutoPolicy::GetInstance().GetPlayerWrapper();
if (CECAutoPolicy::GetInstance().IsAutoPolicyEnabled() && pWrapper->GetAttackError() >= 2)
bUseAutoPF = true;*/
if (idCastTarget == 0)
{
idCastTarget = GetCharacterID(); // ±ÜÃâË²ÒÆµÈ¼¼ÄÜʱ idCastTarget Ϊ0µ¼Ö CECWorkTrace::CreateTraceTarget ·µ»Ø¿Õ
}
CECHPWork pWork = m_pWorkMan.GetWork(Host_work_ID.WORK_TRACEOBJECT);
if (pWork != null)
{
CECHPWorkTrace pWorkTrace = (CECHPWorkTrace)(pWork);
if (pWorkTrace.GetTraceReason() == Trace_reason.TRACE_SPELL &&
pWorkTrace.GetTarget() == idCastTarget &&
pWorkTrace.GetPrepSkill() == pSkill)
return false; // We are just doing the same thing
pWorkTrace.SetTraceTarget(pWorkTrace.CreatTraceTarget(idCastTarget, Trace_reason.TRACE_SPELL, bForceAttack), bUseAutoPF);
pWorkTrace.SetPrepSkill(pSkill);
bTraceOK = true;
}
else if (m_pWorkMan.CanStartWork(Host_work_ID.WORK_TRACEOBJECT))
{
CECHPWorkTrace pWork2 = (CECHPWorkTrace)m_pWorkMan.CreateWork(Host_work_ID.WORK_TRACEOBJECT);
pWork2.SetTraceTarget(pWork2.CreatTraceTarget(idCastTarget, Trace_reason.TRACE_SPELL, bForceAttack), bUseAutoPF);
pWork2.SetPrepSkill(pSkill);
m_pWorkMan.StartWork_p1(pWork2);
bTraceOK = true;
}
if (!bTraceOK) return false;
// }
//}
}
}
return true;
}
public void PrepareNPCService(int idSev)
@@ -2465,7 +2467,7 @@ namespace BrewMonster
}
else if (GPDataTypeHelper.ISNPCID(idTarget))
{
CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(idTarget);
CECNPC pNPC = EC_ManMessageMono.Instance.CECNPCMan.GetNPC(idTarget);
if (pNPC != null)
{
if (CanSafelySelect(pNPC) && !pNPC.IsDead())
@@ -2772,6 +2774,7 @@ namespace BrewMonster
// }
// return fSpeedSev;
//}
public bool IsMeleeing() { return m_bMelee; }
private void OnMsgHstNPCGreeting(ECMSG Msg)
{
@@ -2793,7 +2796,7 @@ namespace BrewMonster
// return;
//}
CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(pCmd.idObject);
CECNPC pNPC = EC_ManMessageMono.Instance.CECNPCMan.GetNPC(pCmd.idObject);
if (!pNPC || !pNPC.IsServerNPC())
{
return;
@@ -2962,7 +2965,18 @@ namespace BrewMonster
}
return bInWar;
}
public bool IsFactionMember(int idTargetFaction)
{
// µ±Ç°ÊôÓÚij°ïÅÉ£¬ÇÒ¶Ô·½ÊôÓÚͬһ°ïÅÉʱ·µ»Ø true
return GetFactionID() != 0 && GetFactionID() == idTargetFaction;
}
public bool IsFactionAllianceMember(int idTargetFaction)
{
// µ±Ç°ÊôÓÚij°ïÅÉ£¬¶Ô·½ÊôÓÚͬһ°ïÅÉ¡¢»òÕßÊôÓÚͬÃ˰ïÅÉ
return GetFactionID() != 0
&& idTargetFaction != 0
&& (GetFactionID() == idTargetFaction || EC_Game.GetFactionMan().IsFactionAlliance(idTargetFaction));
}
public int GetCountry() { return m_idCountry; }
// Get battle info.
@@ -3153,7 +3167,7 @@ namespace BrewMonster
if (GPDataTypeHelper.ISNPCID(idHitObject))
{
// NPC handling
CECNPC pNPC = EC_ManMessageMono.Instance?._CECNPCMan?.GetNPC(idHitObject);
CECNPC pNPC = EC_ManMessageMono.Instance?.CECNPCMan?.GetNPC(idHitObject);
if (pNPC != null && !pNPC.IsDead())
{
m_idCurHover = idHitObject;
@@ -3308,21 +3322,6 @@ namespace BrewMonster
}
};
// PVP infomation
public struct PVPINFO
{
public bool bEnable; // PVP switch
public uint dwCoolTime;
public uint dwMaxCoolTime;
public bool bFreePVP; // Free PVP flag, ignore bEnable flag
public bool bInPVPCombat; // true, in PVP combat
public int iDuelState; // Duel state
public int idDuelOpp; // Duel opponent
public int iDuelTimeCnt; // Duel time counter
public int iDuelRlt; // Duel result. 0, no defined; 1-win; 2-lose; 3-draw
};
// Current ground information
public struct GNDINFO
{
public float fGndHei; // Ground height
+413 -410
View File
@@ -6,46 +6,48 @@ using BrewMonster.Scripts.Managers;
using ModelRenderer.Scripts.GameData;
using UnityEngine;
public partial class CECPlayer
namespace BrewMonster
{
public const int NUM_PROFESSION = (int)Profession.NUM_PROFESSION;
public const int NUM_GENDER = (int)Gender.NUM_GENDER;
public static readonly string _left_hand_weapon = "LeftHand";
public static readonly string _right_hand_weapon = "RightHand";
public static readonly string _wing = "Wing";
public static readonly string _wing2 = "Wing2";
public const string _cc_ride = "CC_Ride";
public static readonly string _cc_ride2 = "CC_Ride2";
public const string _hh_ride = "HH_Ride";
public const string _hanger_ride = "Rider";
public static readonly string _hanger_ride2 = "Rider2";
public static readonly string _hanger_hug = "Hug";
public static readonly string _hh_bind = "HH_Bind";
public static readonly string _cc_bind = "CC_Bind";
public const string _cc_fenghuolun = "CC_feijian";
public const string _hh_left_foot = "HH_左脚";
public const string _hh_right_foot = "HH_右脚";
public static readonly string _hh_left_shoulder_weapon = "HH_leftsword";
public static readonly string _hh_right_shoulder_weapon = "HH_rightsword";
public static readonly string _hh_left_hand_weapon = "HH_lefthandweapon";
public static readonly string _hh_right_hand_weapon = "HH_righthandweapon";
public static readonly string _hh_qiu = "HH_qiu";
public static readonly string _hh_right_hand_nickle_weapon = "HH_weapon";
public static readonly string _cc_weapon = "CC_weapon";
public static readonly string _cc_qiu = "CC_qiu";
public static readonly string _hh_qiu_base = "HH_base";
public static readonly string[] _multiobject_effect = { "绿色连线.gfx", "红色连线.gfx", "黑色连线.gfx" };
public static readonly string[] _equipment_skin =
public partial class CECPlayer
{
public const int NUM_PROFESSION = (int)Profession.NUM_PROFESSION;
public const int NUM_GENDER = (int)Gender.NUM_GENDER;
public static readonly string _left_hand_weapon = "LeftHand";
public static readonly string _right_hand_weapon = "RightHand";
public static readonly string _wing = "Wing";
public static readonly string _wing2 = "Wing2";
public const string _cc_ride = "CC_Ride";
public static readonly string _cc_ride2 = "CC_Ride2";
public const string _hh_ride = "HH_Ride";
public const string _hanger_ride = "Rider";
public static readonly string _hanger_ride2 = "Rider2";
public static readonly string _hanger_hug = "Hug";
public static readonly string _hh_bind = "HH_Bind";
public static readonly string _cc_bind = "CC_Bind";
public const string _cc_fenghuolun = "CC_feijian";
public const string _hh_left_foot = "HH_左脚";
public const string _hh_right_foot = "HH_右脚";
public static readonly string _hh_left_shoulder_weapon = "HH_leftsword";
public static readonly string _hh_right_shoulder_weapon = "HH_rightsword";
public static readonly string _hh_left_hand_weapon = "HH_lefthandweapon";
public static readonly string _hh_right_hand_weapon = "HH_righthandweapon";
public static readonly string _hh_qiu = "HH_qiu";
public static readonly string _hh_right_hand_nickle_weapon = "HH_weapon";
public static readonly string _cc_weapon = "CC_weapon";
public static readonly string _cc_qiu = "CC_qiu";
public static readonly string _hh_qiu_base = "HH_base";
public static readonly string[] _multiobject_effect = { "绿色连线.gfx", "红色连线.gfx", "黑色连线.gfx" };
public static readonly string[] _equipment_skin =
{
"models/players/装备/男/{0}/男通用{1}",
"models/players/装备/女/{0}/女通用{1}",
"models/players/装备/男/{0}/男通用{1}",
@@ -62,7 +64,7 @@ public partial class CECPlayer
"models/players/装备/女/{0}/女通用{1}",
"models/players/装备/男/{0}/男通用{1}",
"models/players/装备/女/{0}/女通用{1}",
"models/players/装备/男/{0}/男通用{1}",
"models/players/装备/女/{0}/女通用{1}",
"models/players/装备/男/{0}/男通用{1}",
@@ -74,419 +76,420 @@ public partial class CECPlayer
};
// Skin index
public enum SkinIndex
{
SKIN_BODY_INDEX = 0,
SKIN_UPPER_BODY_INDEX,
SKIN_WRIST_INDEX,
SKIN_LOWER_INDEX,
SKIN_FOOT_INDEX,
SKIN_HEAD_INDEX,
SKIN_FASHION_UPPER_BODY_INDEX,
SKIN_FASHION_WRIST_INDEX,
SKIN_FASHION_LOWER_INDEX,
SKIN_FASHION_FOOT_INDEX,
NUM_SKIN_INDEX,
}
// Wing types
public enum WingType
{
WINGTYPE_WING, // 锟斤拷锟斤拷锟斤拷锟斤拷锟酵o拷锟斤拷锟??????
WINGTYPE_FLYSWORD, // 锟斤拷锟斤拷锟斤拷锟斤拷锟酵o拷锟缴斤拷
WINGTYPE_DOUBLEWHEEL, // 锟斤拷锟斤拷锟斤拷锟斤拷锟酵o拷双锟脚凤拷锟斤拷锟斤?
}
private static readonly SkinIndex[] _location_skin_map =
{
SkinIndex.SKIN_BODY_INDEX,
SkinIndex.SKIN_UPPER_BODY_INDEX,
SkinIndex.SKIN_WRIST_INDEX,
SkinIndex.SKIN_LOWER_INDEX,
SkinIndex.SKIN_FOOT_INDEX,
SkinIndex.SKIN_UPPER_BODY_INDEX,
SkinIndex.SKIN_UPPER_BODY_INDEX,
SkinIndex.SKIN_LOWER_INDEX,
SkinIndex.SKIN_UPPER_BODY_INDEX
};
// The skeleton builder holds the reference to the player's bones
// We use this to setup the bones for the equipment skinned mesh renderers
private SkeletonBuilder _skeletonBuilder;
private PlayerDefaultEquipments _playerDefaultEquipments;
// Track instantiated armor objects for each slot
private GameObject _currentUpperArmor;
private GameObject _currentLowerArmor;
private GameObject _currentWristArmor;
private GameObject _currentFootArmor;
// Track instantiated weapon objects
private GameObject _currentRightHandWeapon;
private GameObject _currentLeftHandWeapon;
private PlayerDefaultEquipments PlayerDefaultEquipments
{
get
// Skin index
public enum SkinIndex
{
if (_playerDefaultEquipments == null)
SKIN_BODY_INDEX = 0,
SKIN_UPPER_BODY_INDEX,
SKIN_WRIST_INDEX,
SKIN_LOWER_INDEX,
SKIN_FOOT_INDEX,
SKIN_HEAD_INDEX,
SKIN_FASHION_UPPER_BODY_INDEX,
SKIN_FASHION_WRIST_INDEX,
SKIN_FASHION_LOWER_INDEX,
SKIN_FASHION_FOOT_INDEX,
NUM_SKIN_INDEX,
}
// Wing types
public enum WingType
{
WINGTYPE_WING, // 锟斤拷锟斤拷锟斤拷锟斤拷锟酵o拷锟斤拷锟??????
WINGTYPE_FLYSWORD, // 锟斤拷锟斤拷锟斤拷锟斤拷锟酵o拷锟缴斤拷
WINGTYPE_DOUBLEWHEEL, // 锟斤拷锟斤拷锟斤拷锟斤拷锟酵o拷双锟脚凤拷锟斤拷锟斤?
}
private static readonly SkinIndex[] _location_skin_map =
{
SkinIndex.SKIN_BODY_INDEX,
SkinIndex.SKIN_UPPER_BODY_INDEX,
SkinIndex.SKIN_WRIST_INDEX,
SkinIndex.SKIN_LOWER_INDEX,
SkinIndex.SKIN_FOOT_INDEX,
SkinIndex.SKIN_UPPER_BODY_INDEX,
SkinIndex.SKIN_UPPER_BODY_INDEX,
SkinIndex.SKIN_LOWER_INDEX,
SkinIndex.SKIN_UPPER_BODY_INDEX
};
// The skeleton builder holds the reference to the player's bones
// We use this to setup the bones for the equipment skinned mesh renderers
private SkeletonBuilder _skeletonBuilder;
private PlayerDefaultEquipments _playerDefaultEquipments;
// Track instantiated armor objects for each slot
private GameObject _currentUpperArmor;
private GameObject _currentLowerArmor;
private GameObject _currentWristArmor;
private GameObject _currentFootArmor;
// Track instantiated weapon objects
private GameObject _currentRightHandWeapon;
private GameObject _currentLeftHandWeapon;
private PlayerDefaultEquipments PlayerDefaultEquipments
{
get
{
_playerDefaultEquipments = GetComponentInChildren<PlayerDefaultEquipments>();
if (_playerDefaultEquipments == null)
{
_playerDefaultEquipments = GetComponentInChildren<PlayerDefaultEquipments>();
}
return _playerDefaultEquipments;
}
return _playerDefaultEquipments;
}
}
public bool UpdateEquipSkins()
{
int[] aNewEquips = new int[InventoryConst.IVTRSIZE_EQUIPPACK];
EC_IvtrItem pItem = null;
for (int i = 0; i < InventoryConst.IVTRSIZE_EQUIPPACK; i++)
public bool UpdateEquipSkins()
{
// Use host player's equipment inventory (per-instance CECInventory)
var host = CECGameRun.Instance?.GetHostPlayer();
var equipInv = host?.EquipInventory;
pItem = equipInv?.GetItem(i, false);
if (pItem != null)
aNewEquips[i] = pItem.m_tid;
}
int[] aNewEquips = new int[InventoryConst.IVTRSIZE_EQUIPPACK];
EC_IvtrItem pItem = null;
for (int i = 0; i < InventoryConst.IVTRSIZE_EQUIPPACK; i++)
{
// Use host player's equipment inventory (per-instance CECInventory)
var host = CECGameRun.Instance?.GetHostPlayer();
var equipInv = host?.EquipInventory;
pItem = equipInv?.GetItem(i, false);
if (pItem != null)
aNewEquips[i] = pItem.m_tid;
}
ShowEquipments(aNewEquips, true, true);
return true;
}
public async void ShowEquipments(int[] pEquipmentID, bool bLoadAtOnce, bool bForceLoad)
{
var elemendataman = BrewMonster.ElementDataManProvider.GetElementDataMan();
DATA_TYPE DataType = default;
bool useDefaultUpper = false;
bool useDefaultLower = false;
bool useDefaultWrist = false;
bool useDefaultFoot = false;
for (int i = 0; i < InventoryConst.IVTRSIZE_EQUIPPACK; i++)
public async void ShowEquipments(int[] pEquipmentID, bool bLoadAtOnce, bool bForceLoad)
{
//TODO: The equipment ids store the stone information, we need to extract the stone information from the equipment id.
/*
int idEquipment = pEquipmentID[i];
if((i >= EQUIPIVTR_FASHION_BODY && i <= EQUIPIVTR_FASHION_WRIST ) ||
i == EQUIPIVTR_FASHION_HEAD || i == EQUIPIVTR_FASHION_WEAPON)
{
WORD wColor = (idEquipment & 0xffff0000) >> 16;
idEquipment &= 0x0000ffff;
color = FASHION_WORDCOLOR_TO_A3DCOLOR(wColor);
}
else
{
if( i == EQUIPIVTR_WEAPON )
{
pResult->stoneWeapon = (idEquipment & 0xffff0000) >> 16;
}
if( i == EQUIPIVTR_BODY )
{
pResult->stoneUpperBody = (idEquipment & 0xffff0000) >> 16;
}
if( i == EQUIPIVTR_WRIST )
{
pResult->stoneWrist = (idEquipment & 0xffff0000) >> 16;
}
if( i == EQUIPIVTR_LEG )
{
pResult->stoneLowerBody = (idEquipment & 0xffff0000) >> 16;
}
if( i == EQUIPIVTR_FOOT )
{
pResult->stoneFoot = (idEquipment & 0xffff0000) >> 16;
}
idEquipment &= 0x0000ffff;
}
*/
if (pEquipmentID[i] != m_aEquips[i])
var elemendataman = BrewMonster.ElementDataManProvider.GetElementDataMan();
DATA_TYPE DataType = default;
bool useDefaultUpper = false;
bool useDefaultLower = false;
bool useDefaultWrist = false;
bool useDefaultFoot = false;
for (int i = 0; i < InventoryConst.IVTRSIZE_EQUIPPACK; i++)
{
m_aEquips[i] = pEquipmentID[i]; // store the current equipment id
// new equipment. Need to load and equip to host player
var equipData = elemendataman.get_data_ptr((uint)pEquipmentID[i], ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
object subTypeData = null;
switch (DataType)
//TODO: The equipment ids store the stone information, we need to extract the stone information from the equipment id.
/*
int idEquipment = pEquipmentID[i];
if((i >= EQUIPIVTR_FASHION_BODY && i <= EQUIPIVTR_FASHION_WRIST ) ||
i == EQUIPIVTR_FASHION_HEAD || i == EQUIPIVTR_FASHION_WEAPON)
{
case DATA_TYPE.DT_WEAPON_ESSENCE:
var weaponData = (WEAPON_ESSENCE)equipData;
subTypeData = elemendataman.get_data_ptr((uint)weaponData.id_sub_type, ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
if (subTypeData != null && DataType == DATA_TYPE.DT_WEAPON_SUB_TYPE)
{
var subTypeDataWeapon = (WEAPON_SUB_TYPE)subTypeData;
m_uAttackType = subTypeDataWeapon.action_type;
m_ExtProps.ak.AttackRange = weaponData.attack_range;
}
string fileModelRight = AFile.NormalizePath(weaponData.FileModelRight, true).ToLower();
string fileModelLeft = AFile.NormalizePath(weaponData.FileModelLeft, true).ToLower();
// BMLogger.Log($"ShowEquipments():: Weapon Essence: {fileModelRight} -- {fileModelLeft}");
// Destroy existing right hand weapon before creating new one
if (_currentRightHandWeapon != null)
{
Destroy(_currentRightHandWeapon);
_currentRightHandWeapon = null;
}
// Destroy existing left hand weapon before creating new one
if (_currentLeftHandWeapon != null)
{
Destroy(_currentLeftHandWeapon);
_currentLeftHandWeapon = null;
}
GameObject weaponPrefab = null;
if (!string.IsNullOrEmpty(fileModelRight))
{
weaponPrefab = await AddressableManager.Instance.LoadPrefabAsync(fileModelRight);
var weaponObject = Instantiate(weaponPrefab);
if (weaponObject != null)
WORD wColor = (idEquipment & 0xffff0000) >> 16;
idEquipment &= 0x0000ffff;
color = FASHION_WORDCOLOR_TO_A3DCOLOR(wColor);
}
else
{
if( i == EQUIPIVTR_WEAPON )
{
pResult->stoneWeapon = (idEquipment & 0xffff0000) >> 16;
}
if( i == EQUIPIVTR_BODY )
{
pResult->stoneUpperBody = (idEquipment & 0xffff0000) >> 16;
}
if( i == EQUIPIVTR_WRIST )
{
pResult->stoneWrist = (idEquipment & 0xffff0000) >> 16;
}
if( i == EQUIPIVTR_LEG )
{
pResult->stoneLowerBody = (idEquipment & 0xffff0000) >> 16;
}
if( i == EQUIPIVTR_FOOT )
{
pResult->stoneFoot = (idEquipment & 0xffff0000) >> 16;
}
idEquipment &= 0x0000ffff;
}
*/
if (pEquipmentID[i] != m_aEquips[i])
{
m_aEquips[i] = pEquipmentID[i]; // store the current equipment id
// new equipment. Need to load and equip to host player
var equipData = elemendataman.get_data_ptr((uint)pEquipmentID[i], ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
object subTypeData = null;
switch (DataType)
{
case DATA_TYPE.DT_WEAPON_ESSENCE:
var weaponData = (WEAPON_ESSENCE)equipData;
subTypeData = elemendataman.get_data_ptr((uint)weaponData.id_sub_type, ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
if (subTypeData != null && DataType == DATA_TYPE.DT_WEAPON_SUB_TYPE)
{
weaponObject.transform.SetParent(FindChildObjectRecursive(transform, _hh_right_hand_weapon).transform);
weaponObject.transform.localPosition = weaponPrefab.transform.localPosition;
weaponObject.transform.localRotation = weaponPrefab.transform.localRotation;
weaponObject.transform.localScale = Vector3.one;
weaponObject.SetActive(true);
_currentRightHandWeapon = weaponObject;
var subTypeDataWeapon = (WEAPON_SUB_TYPE)subTypeData;
m_uAttackType = subTypeDataWeapon.action_type;
m_ExtProps.ak.AttackRange = weaponData.attack_range;
}
}
string fileModelRight = AFile.NormalizePath(weaponData.FileModelRight, true).ToLower();
string fileModelLeft = AFile.NormalizePath(weaponData.FileModelLeft, true).ToLower();
// BMLogger.Log($"ShowEquipments():: Weapon Essence: {fileModelRight} -- {fileModelLeft}");
if (!string.IsNullOrEmpty(fileModelLeft))
{
weaponPrefab = await AddressableManager.Instance.LoadPrefabAsync(fileModelLeft);
var weaponObject = Instantiate(weaponPrefab);
if (weaponObject != null)
// Destroy existing right hand weapon before creating new one
if (_currentRightHandWeapon != null)
{
weaponObject.transform.SetParent(FindChildObjectRecursive(transform, _hh_left_hand_weapon).transform);
weaponObject.transform.localPosition = weaponPrefab.transform.localPosition;
weaponObject.transform.localRotation = weaponPrefab.transform.localRotation;
weaponObject.transform.localScale = Vector3.one;
weaponObject.SetActive(true);
_currentLeftHandWeapon = weaponObject;
}
}
break;
case DATA_TYPE.DT_ARMOR_ESSENCE:
var pArmor = (ARMOR_ESSENCE)equipData;
var nLocation = pArmor.equip_location;
// BMLogger.Log($"ShowEquipments():: Armor Essence: {pArmor.RealName}");
var armorSkinPath = _GenEquipmentSkinPath(UnityGameSession.Instance.GetRoleInfo().occupation, UnityGameSession.Instance.GetRoleInfo().gender, pArmor.RealName);
if (!armorSkinPath.EndsWith(".ecm"))
{
armorSkinPath += ".ecm";
}
var armorPrefab = await AddressableManager.Instance.LoadPrefabAsync(armorSkinPath);
if (armorPrefab != null)
{
// Destroy existing armor for this slot before creating new one
switch (nLocation)
{
case (uint)SkinIndex.SKIN_UPPER_BODY_INDEX:
if (_currentUpperArmor != null)
{
Destroy(_currentUpperArmor);
_currentUpperArmor = null;
}
break;
case (uint)SkinIndex.SKIN_LOWER_INDEX:
if (_currentLowerArmor != null)
{
Destroy(_currentLowerArmor);
_currentLowerArmor = null;
}
break;
case (uint)SkinIndex.SKIN_WRIST_INDEX:
if (_currentWristArmor != null)
{
Destroy(_currentWristArmor);
_currentWristArmor = null;
}
break;
case (uint)SkinIndex.SKIN_FOOT_INDEX:
if (_currentFootArmor != null)
{
Destroy(_currentFootArmor);
_currentFootArmor = null;
}
break;
Destroy(_currentRightHandWeapon);
_currentRightHandWeapon = null;
}
var armorObject = Instantiate(armorPrefab);
armorObject.transform.SetParent(GetSkeletonBuilder()?.transform);
armorObject.transform.localPosition = Vector3.zero;
armorObject.transform.localRotation = Quaternion.identity;
armorObject.transform.localScale = Vector3.one;
var skinnedMeshRenderer = armorObject.GetComponent<SkinnedMeshRenderer>();
var skinnedMeshRenderereFromDataList = armorObject.GetComponentsInChildren<SkinnedMeshRenderFromData>();
foreach (var skinnedMeshRenderereFromData in skinnedMeshRenderereFromDataList)
// Destroy existing left hand weapon before creating new one
if (_currentLeftHandWeapon != null)
{
if (skinnedMeshRenderereFromData != null)
Destroy(_currentLeftHandWeapon);
_currentLeftHandWeapon = null;
}
GameObject weaponPrefab = null;
if (!string.IsNullOrEmpty(fileModelRight))
{
weaponPrefab = await AddressableManager.Instance.LoadPrefabAsync(fileModelRight);
var weaponObject = Instantiate(weaponPrefab);
if (weaponObject != null)
{
skinnedMeshRenderereFromData._skinnedMeshRenderer.bones = GetSkeletonBuilder().GetBones(skinnedMeshRenderereFromData.BoneNames);
skinnedMeshRenderereFromData._skinnedMeshRenderer.rootBone = skinnedMeshRenderereFromData._skinnedMeshRenderer.bones[^1];
weaponObject.transform.SetParent(FindChildObjectRecursive(transform, _hh_right_hand_weapon).transform);
weaponObject.transform.localPosition = weaponPrefab.transform.localPosition;
weaponObject.transform.localRotation = weaponPrefab.transform.localRotation;
weaponObject.transform.localScale = Vector3.one;
weaponObject.SetActive(true);
_currentRightHandWeapon = weaponObject;
}
}
// Store the armor object for this slot
switch (nLocation)
if (!string.IsNullOrEmpty(fileModelLeft))
{
case (uint)SkinIndex.SKIN_UPPER_BODY_INDEX:
_currentUpperArmor = armorObject;
useDefaultUpper = false;
break;
case (uint)SkinIndex.SKIN_LOWER_INDEX:
_currentLowerArmor = armorObject;
useDefaultLower = false;
break;
case (uint)SkinIndex.SKIN_WRIST_INDEX:
_currentWristArmor = armorObject;
useDefaultWrist = false;
break;
case (uint)SkinIndex.SKIN_FOOT_INDEX:
_currentFootArmor = armorObject;
useDefaultFoot = false;
break;
weaponPrefab = await AddressableManager.Instance.LoadPrefabAsync(fileModelLeft);
var weaponObject = Instantiate(weaponPrefab);
if (weaponObject != null)
{
weaponObject.transform.SetParent(FindChildObjectRecursive(transform, _hh_left_hand_weapon).transform);
weaponObject.transform.localPosition = weaponPrefab.transform.localPosition;
weaponObject.transform.localRotation = weaponPrefab.transform.localRotation;
weaponObject.transform.localScale = Vector3.one;
weaponObject.SetActive(true);
_currentLeftHandWeapon = weaponObject;
}
}
}
else
{
// disable/enable the default equipment
switch (nLocation)
{
case (uint)SkinIndex.SKIN_UPPER_BODY_INDEX:
useDefaultUpper = true;
break;
case (uint)SkinIndex.SKIN_LOWER_INDEX:
useDefaultLower = true;
break;
case (uint)SkinIndex.SKIN_WRIST_INDEX:
useDefaultWrist = true;
break;
case (uint)SkinIndex.SKIN_FOOT_INDEX:
useDefaultFoot = true;
break;
}
}
break;
break;
case DATA_TYPE.DT_ARMOR_ESSENCE:
var pArmor = (ARMOR_ESSENCE)equipData;
var nLocation = pArmor.equip_location;
// BMLogger.Log($"ShowEquipments():: Armor Essence: {pArmor.RealName}");
default:
break;
var armorSkinPath = _GenEquipmentSkinPath(UnityGameSession.Instance.GetRoleInfo().occupation, UnityGameSession.Instance.GetRoleInfo().gender, pArmor.RealName);
if (!armorSkinPath.EndsWith(".ecm"))
{
armorSkinPath += ".ecm";
}
var armorPrefab = await AddressableManager.Instance.LoadPrefabAsync(armorSkinPath);
if (armorPrefab != null)
{
// Destroy existing armor for this slot before creating new one
switch (nLocation)
{
case (uint)SkinIndex.SKIN_UPPER_BODY_INDEX:
if (_currentUpperArmor != null)
{
Destroy(_currentUpperArmor);
_currentUpperArmor = null;
}
break;
case (uint)SkinIndex.SKIN_LOWER_INDEX:
if (_currentLowerArmor != null)
{
Destroy(_currentLowerArmor);
_currentLowerArmor = null;
}
break;
case (uint)SkinIndex.SKIN_WRIST_INDEX:
if (_currentWristArmor != null)
{
Destroy(_currentWristArmor);
_currentWristArmor = null;
}
break;
case (uint)SkinIndex.SKIN_FOOT_INDEX:
if (_currentFootArmor != null)
{
Destroy(_currentFootArmor);
_currentFootArmor = null;
}
break;
}
var armorObject = Instantiate(armorPrefab);
armorObject.transform.SetParent(GetSkeletonBuilder()?.transform);
armorObject.transform.localPosition = Vector3.zero;
armorObject.transform.localRotation = Quaternion.identity;
armorObject.transform.localScale = Vector3.one;
var skinnedMeshRenderer = armorObject.GetComponent<SkinnedMeshRenderer>();
var skinnedMeshRenderereFromDataList = armorObject.GetComponentsInChildren<SkinnedMeshRenderFromData>();
foreach (var skinnedMeshRenderereFromData in skinnedMeshRenderereFromDataList)
{
if (skinnedMeshRenderereFromData != null)
{
skinnedMeshRenderereFromData._skinnedMeshRenderer.bones = GetSkeletonBuilder().GetBones(skinnedMeshRenderereFromData.BoneNames);
skinnedMeshRenderereFromData._skinnedMeshRenderer.rootBone = skinnedMeshRenderereFromData._skinnedMeshRenderer.bones[^1];
}
}
// Store the armor object for this slot
switch (nLocation)
{
case (uint)SkinIndex.SKIN_UPPER_BODY_INDEX:
_currentUpperArmor = armorObject;
useDefaultUpper = false;
break;
case (uint)SkinIndex.SKIN_LOWER_INDEX:
_currentLowerArmor = armorObject;
useDefaultLower = false;
break;
case (uint)SkinIndex.SKIN_WRIST_INDEX:
_currentWristArmor = armorObject;
useDefaultWrist = false;
break;
case (uint)SkinIndex.SKIN_FOOT_INDEX:
_currentFootArmor = armorObject;
useDefaultFoot = false;
break;
}
}
else
{
// disable/enable the default equipment
switch (nLocation)
{
case (uint)SkinIndex.SKIN_UPPER_BODY_INDEX:
useDefaultUpper = true;
break;
case (uint)SkinIndex.SKIN_LOWER_INDEX:
useDefaultLower = true;
break;
case (uint)SkinIndex.SKIN_WRIST_INDEX:
useDefaultWrist = true;
break;
case (uint)SkinIndex.SKIN_FOOT_INDEX:
useDefaultFoot = true;
break;
}
}
break;
default:
break;
}
}
}
if (m_aEquips[i] == 0)
{
switch (i)
if (m_aEquips[i] == 0)
{
case InventoryConst.EQUIPIVTR_WEAPON:
// Destroy weapons when weapon slot is empty
if (_currentRightHandWeapon != null)
{
Destroy(_currentRightHandWeapon);
_currentRightHandWeapon = null;
}
if (_currentLeftHandWeapon != null)
{
Destroy(_currentLeftHandWeapon);
_currentLeftHandWeapon = null;
}
break;
case InventoryConst.EQUIPIVTR_BODY:
useDefaultUpper = true;
break;
case InventoryConst.EQUIPIVTR_LEG:
useDefaultLower = true;
break;
case InventoryConst.EQUIPIVTR_WRIST:
useDefaultWrist = true;
break;
case InventoryConst.EQUIPIVTR_FOOT:
useDefaultFoot = true;
break;
switch (i)
{
case InventoryConst.EQUIPIVTR_WEAPON:
// Destroy weapons when weapon slot is empty
if (_currentRightHandWeapon != null)
{
Destroy(_currentRightHandWeapon);
_currentRightHandWeapon = null;
}
if (_currentLeftHandWeapon != null)
{
Destroy(_currentLeftHandWeapon);
_currentLeftHandWeapon = null;
}
break;
case InventoryConst.EQUIPIVTR_BODY:
useDefaultUpper = true;
break;
case InventoryConst.EQUIPIVTR_LEG:
useDefaultLower = true;
break;
case InventoryConst.EQUIPIVTR_WRIST:
useDefaultWrist = true;
break;
case InventoryConst.EQUIPIVTR_FOOT:
useDefaultFoot = true;
break;
}
}
}
// enable/disable the default equipment
// If using default, destroy non-default equipment if it exists
if (useDefaultUpper)
{
if (_currentUpperArmor != null)
{
Destroy(_currentUpperArmor);
_currentUpperArmor = null;
}
}
PlayerDefaultEquipments.DefaultUpper.SetActive(useDefaultUpper);
if (useDefaultLower)
{
if (_currentLowerArmor != null)
{
Destroy(_currentLowerArmor);
_currentLowerArmor = null;
}
}
PlayerDefaultEquipments.DefaultLower.SetActive(useDefaultLower);
if (useDefaultWrist)
{
if (_currentWristArmor != null)
{
Destroy(_currentWristArmor);
_currentWristArmor = null;
}
}
PlayerDefaultEquipments.DefaultWirst.SetActive(useDefaultWrist);
if (useDefaultFoot)
{
if (_currentFootArmor != null)
{
Destroy(_currentFootArmor);
_currentFootArmor = null;
}
}
PlayerDefaultEquipments.DefaultFoot.SetActive(useDefaultFoot);
}
// enable/disable the default equipment
// If using default, destroy non-default equipment if it exists
if (useDefaultUpper)
#region Helper Methods
private GameObject FindChildObjectRecursive(Transform parent, string name)
{
if (_currentUpperArmor != null)
foreach (Transform child in parent)
{
Destroy(_currentUpperArmor);
_currentUpperArmor = null;
if (child.name == name)
{
return child.gameObject;
}
var childObject = FindChildObjectRecursive(child, name);
if (childObject != null)
{
return childObject;
}
}
return null;
}
PlayerDefaultEquipments.DefaultUpper.SetActive(useDefaultUpper);
if (useDefaultLower)
private SkeletonBuilder GetSkeletonBuilder()
{
if (_currentLowerArmor != null)
if (_skeletonBuilder == null)
{
Destroy(_currentLowerArmor);
_currentLowerArmor = null;
_skeletonBuilder = GetComponentInChildren<SkeletonBuilder>();
}
return _skeletonBuilder;
}
PlayerDefaultEquipments.DefaultLower.SetActive(useDefaultLower);
if (useDefaultWrist)
#endregion
public static string _GenEquipmentSkinPath(int nProfession, int nGender, string szSkinName)
{
if (_currentWristArmor != null)
{
Destroy(_currentWristArmor);
_currentWristArmor = null;
}
return string.Format(_equipment_skin[nProfession * NUM_GENDER + nGender], szSkinName, szSkinName);
}
PlayerDefaultEquipments.DefaultWirst.SetActive(useDefaultWrist);
if (useDefaultFoot)
{
if (_currentFootArmor != null)
{
Destroy(_currentFootArmor);
_currentFootArmor = null;
}
}
PlayerDefaultEquipments.DefaultFoot.SetActive(useDefaultFoot);
}
#region Helper Methods
private GameObject FindChildObjectRecursive(Transform parent, string name)
{
foreach (Transform child in parent)
{
if (child.name == name)
{
return child.gameObject;
}
var childObject = FindChildObjectRecursive(child, name);
if (childObject != null)
{
return childObject;
}
}
return null;
}
private SkeletonBuilder GetSkeletonBuilder()
{
if (_skeletonBuilder == null)
{
_skeletonBuilder = GetComponentInChildren<SkeletonBuilder>();
}
return _skeletonBuilder;
}
#endregion
public static string _GenEquipmentSkinPath(int nProfession, int nGender, string szSkinName)
{
return string.Format(_equipment_skin[nProfession * NUM_GENDER + nGender], szSkinName, szSkinName);
}
}
}
-1
View File
@@ -9,7 +9,6 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using static CECPlayer;
public static class EC_Utility
{
+148 -146
View File
@@ -5,163 +5,165 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using static CECPlayer;
public class PlayerVisual : MonoBehaviour
namespace BrewMonster
{
[SerializeField] NamedAnimancerComponent namedAnimancer;
[SerializeField] private INFO _playerInfo;
private Dictionary<string, AnimancerState> _activeStates = new();
[SerializeField] private AnimancerState _currentState;
[SerializeField] private Queue<string> _animationQueue = new Queue<string>();
[SerializeField] private List<string> _animationList = new List<string>();
[SerializeField] private bool isHit;
[SerializeField] private int id;
private const float FadeTime = 0.1f;
private const FadeMode FadeMode = Animancer.FadeMode.FixedDuration;
QueueActionEvent queueActionEvent;
private void PlayActionEventHandler(PlayActionEvent @event)
public class PlayerVisual : MonoBehaviour
{
if (_animationQueue.Count > 0)
[SerializeField] NamedAnimancerComponent namedAnimancer;
[SerializeField] private INFO _playerInfo;
private Dictionary<string, AnimancerState> _activeStates = new();
[SerializeField] private AnimancerState _currentState;
[SerializeField] private Queue<string> _animationQueue = new Queue<string>();
[SerializeField] private List<string> _animationList = new List<string>();
[SerializeField] private bool isHit;
[SerializeField] private int id;
private const float FadeTime = 0.1f;
private const FadeMode FadeMode = Animancer.FadeMode.FixedDuration;
QueueActionEvent queueActionEvent;
private void PlayActionEventHandler(PlayActionEvent @event)
{
_animationQueue.Enqueue(@event.AnimationName);
return;
if (_animationQueue.Count > 0)
{
_animationQueue.Enqueue(@event.AnimationName);
return;
}
InternalPlayAnimation(@event.AnimationName);
}
InternalPlayAnimation(@event.AnimationName);
}
public void InitPlayerEventDoneHandler()
{
namedAnimancer = GetComponentInChildren<NamedAnimancerComponent>();
if (namedAnimancer == null)
public void InitPlayerEventDoneHandler()
{
BrewMonster.BMLogger.LogWarning("InitPlayerEventDoneHandler animancer == null");
return;
}
var player = GetComponentInParent<CECPlayer>();
if (player == null)
{
BMLogger.LogWarning("player == null");
return;
namedAnimancer = GetComponentInChildren<NamedAnimancerComponent>();
if (namedAnimancer == null)
{
BrewMonster.BMLogger.LogWarning("InitPlayerEventDoneHandler animancer == null");
return;
}
var player = GetComponentInParent<CECPlayer>();
if (player == null)
{
BMLogger.LogWarning("player == null");
return;
}
_playerInfo = player.GetPlayInfo();
id = _playerInfo.cid;
EventBus.SubscribeChannel<PlayActionEvent>(_playerInfo.cid, PlayActionEventHandler);
EventBus.SubscribeChannelClass<QueueActionEvent>(_playerInfo.cid, QueueActionEventHandler);
EventBus.SubscribeChannel<ClearComActFlagAllRankNodesEvent>(_playerInfo.cid, ClearComActFlagAllRankNodesEventHandler);
}
_playerInfo = player.GetPlayInfo();
id = _playerInfo.cid;
EventBus.SubscribeChannel<PlayActionEvent>(_playerInfo.cid, PlayActionEventHandler);
EventBus.SubscribeChannelClass<QueueActionEvent>(_playerInfo.cid, QueueActionEventHandler);
EventBus.SubscribeChannel<ClearComActFlagAllRankNodesEvent>(_playerInfo.cid, ClearComActFlagAllRankNodesEventHandler);
}
// public void InitElsePlayerEventDoneHandler(INFO playerInfo)
// {
// namedAnimancer = GetComponentInChildren<NamedAnimancerComponent>();
// if (namedAnimancer == null)
// {
// BrewMonster.BMLogger.LogError("animancer == null");
// return;
// }
// //var player = GetComponentInParent<CECPlayer>();
// //if (player == null)
// //{
// // BrewMonster.BMLogger.LogError("player == null");
// // return;
// //}
// _playerInfo = playerInfo;//player.GetPlayInfo();
// EventBus.SubscribeChannel<PlayActionEvent>(_playerInfo.cid, PlayActionEventHandler);
// EventBus.SubscribeChannelClass<QueueActionEvent>(_playerInfo.cid, QueueActionEventHandler);
// EventBus.SubscribeChannel<CleearComActFlagAllRankNodesEvent>(_playerInfo.cid, CleearComActFlagAllRankNodesEventHandler);
// }
private void ClearComActFlagAllRankNodesEventHandler(ClearComActFlagAllRankNodesEvent @event)
{
_animationQueue.Clear();
_animationList = _animationQueue.ToList();
if (isHit)
{
ApplyDamage();
}
//todo: this is dummy to force change to idle state
// EventBus.PublishChannel(_playerInfo.cid, new PlayActionEvent("站立_通用"));
}
private void QueueActionEventHandler(QueueActionEvent @event)
{
if (!EnqueueAnimation(@event))
{
BMLogger.LogError("HoangDev : EnqueueAnimation Failed");
}
}
private void Update()
{
PlayNext();
}
public bool EnqueueAnimation(QueueActionEvent @event)
{
if (namedAnimancer == null) return false;
_animationQueue.Enqueue(@event.AnimationName);
_animationList = _animationQueue.ToList();
if (!isHit)
{
queueActionEvent = @event;
isHit = @event.IsHitAnim;
}
return true;
}
private void PlayNext()
{
if (_animationQueue.Count == 0)
{
return;
}
// if (_currentState == null)
// public void InitElsePlayerEventDoneHandler(INFO playerInfo)
// {
// _animationQueue.Dequeue();
// return;
// namedAnimancer = GetComponentInChildren<NamedAnimancerComponent>();
// if (namedAnimancer == null)
// {
// BrewMonster.BMLogger.LogError("animancer == null");
// return;
// }
// //var player = GetComponentInParent<CECPlayer>();
// //if (player == null)
// //{
// // BrewMonster.BMLogger.LogError("player == null");
// // return;
// //}
// _playerInfo = playerInfo;//player.GetPlayInfo();
// EventBus.SubscribeChannel<PlayActionEvent>(_playerInfo.cid, PlayActionEventHandler);
// EventBus.SubscribeChannelClass<QueueActionEvent>(_playerInfo.cid, QueueActionEventHandler);
// EventBus.SubscribeChannel<CleearComActFlagAllRankNodesEvent>(_playerInfo.cid, CleearComActFlagAllRankNodesEventHandler);
// }
if (_currentState!=null && _currentState.NormalizedTime < 1f) return;
if (isHit)// have it relative to check _currentState == null?
{
ApplyDamage();
}
string animName = _animationQueue.Dequeue();
_animationList = _animationQueue.ToList();
InternalPlayAnimation(animName);
}
void ApplyDamage()
{
if(queueActionEvent == null) return;
isHit = false;
queueActionEvent.SetFlag(true, queueActionEvent.AttackEvent);
queueActionEvent = null;
}
private void OnDestroy()
{
EventBus.UnsubscribeChannel<PlayActionEvent>(_playerInfo.cid, PlayActionEventHandler);
EventBus.UnsubscribeChannelClass<QueueActionEvent>(_playerInfo.cid, QueueActionEventHandler);
EventBus.UnsubscribeChannel<ClearComActFlagAllRankNodesEvent>(_playerInfo.cid, ClearComActFlagAllRankNodesEventHandler);
// EventBus.UnsubscribeAllInChannel(_playerInfo.cid);
}
public bool IsAnimationExist(string animationName)
{
return namedAnimancer.States.TryGet("ActionName", out var existingState) ? true : false;
}
/// <summary>
/// play an animation with name
/// </summary>
/// <param name="animationName"></param>
/// <param name="duration"></param>
/// <param name="fadeMode"></param>
private void InternalPlayAnimation(string animationName, float duration = FadeTime, FadeMode fadeMode = FadeMode)
{
_currentState = namedAnimancer.TryPlay(animationName, duration, fadeMode);
if (_currentState == null)
private void ClearComActFlagAllRankNodesEventHandler(ClearComActFlagAllRankNodesEvent @event)
{
BMLogger.LogError($"Null animation with name: {animationName}");
_animationQueue.Clear();
_animationList = _animationQueue.ToList();
if (isHit)
{
ApplyDamage();
}
//todo: this is dummy to force change to idle state
// EventBus.PublishChannel(_playerInfo.cid, new PlayActionEvent("站立_通用"));
}
private void QueueActionEventHandler(QueueActionEvent @event)
{
if (!EnqueueAnimation(@event))
{
BMLogger.LogError("HoangDev : EnqueueAnimation Failed");
}
}
private void Update()
{
PlayNext();
}
public bool EnqueueAnimation(QueueActionEvent @event)
{
if (namedAnimancer == null) return false;
_animationQueue.Enqueue(@event.AnimationName);
_animationList = _animationQueue.ToList();
if (!isHit)
{
queueActionEvent = @event;
isHit = @event.IsHitAnim;
}
return true;
}
private void PlayNext()
{
if (_animationQueue.Count == 0)
{
return;
}
// if (_currentState == null)
// {
// _animationQueue.Dequeue();
// return;
// }
if (_currentState != null && _currentState.NormalizedTime < 1f) return;
if (isHit)// have it relative to check _currentState == null?
{
ApplyDamage();
}
string animName = _animationQueue.Dequeue();
_animationList = _animationQueue.ToList();
InternalPlayAnimation(animName);
}
void ApplyDamage()
{
if (queueActionEvent == null) return;
isHit = false;
queueActionEvent.SetFlag(true, queueActionEvent.AttackEvent);
queueActionEvent = null;
}
private void OnDestroy()
{
EventBus.UnsubscribeChannel<PlayActionEvent>(_playerInfo.cid, PlayActionEventHandler);
EventBus.UnsubscribeChannelClass<QueueActionEvent>(_playerInfo.cid, QueueActionEventHandler);
EventBus.UnsubscribeChannel<ClearComActFlagAllRankNodesEvent>(_playerInfo.cid, ClearComActFlagAllRankNodesEventHandler);
// EventBus.UnsubscribeAllInChannel(_playerInfo.cid);
}
public bool IsAnimationExist(string animationName)
{
return namedAnimancer.States.TryGet("ActionName", out var existingState) ? true : false;
}
/// <summary>
/// play an animation with name
/// </summary>
/// <param name="animationName"></param>
/// <param name="duration"></param>
/// <param name="fadeMode"></param>
private void InternalPlayAnimation(string animationName, float duration = FadeTime, FadeMode fadeMode = FadeMode)
{
_currentState = namedAnimancer.TryPlay(animationName, duration, fadeMode);
if (_currentState == null)
{
BMLogger.LogError($"Null animation with name: {animationName}");
}
}
}
}
}