diff --git a/Assets/PerfectWorld/Scripts/AnimTestScene/LogPanelAnimeScene.cs b/Assets/PerfectWorld/Scripts/AnimTestScene/LogPanelAnimeScene.cs index 2152dd4f7a..6a871c273c 100644 --- a/Assets/PerfectWorld/Scripts/AnimTestScene/LogPanelAnimeScene.cs +++ b/Assets/PerfectWorld/Scripts/AnimTestScene/LogPanelAnimeScene.cs @@ -132,7 +132,6 @@ namespace BrewMonster public void LogPlayAttackEffectGfx(CECHostPlayer player, int skillId, int section = 0) { - Debug.Log("LogPlayAttackEffectGfx: " + skillId + " " + section); if (player == null) return; AddGfxEventsFromComAct(player.GetSkillAttackComActRise(skillId, section), "Attack"); @@ -152,18 +151,14 @@ namespace BrewMonster { if (string.IsNullOrEmpty(label) || comAct?.m_EventInfoLst == null) { - Debug.Log("AddGfxEventsFromComAct: " + label + " " + comAct?.m_strName); return; } - Debug.Log("AddGfxEventsFromComAct: " + label + " " + comAct?.m_strName + " " + comAct.m_EventInfoLst.Count); var seen = new HashSet(); foreach (var ev in comAct.m_EventInfoLst) { - Debug.Log("AddGfxEventsFromComAct: " + label + " " + comAct?.m_strName); if (ev is not FX_BASE_INFO gfx || gfx.m_strFilePaths == null) { - Debug.Log("AddGfxEventsFromComAct Failed: " + label + " " + ev?.GetType().Name); continue; } @@ -173,7 +168,6 @@ namespace BrewMonster { continue; } - Debug.Log("AddGfxEventsFromComAct: " + label + " " + path); if (string.IsNullOrWhiteSpace(path)) continue; diff --git a/Assets/PerfectWorld/Scripts/Debug/SkillTriggerPanel.cs b/Assets/PerfectWorld/Scripts/Debug/SkillTriggerPanel.cs index d6ff8e07ec..a6595c94b1 100644 --- a/Assets/PerfectWorld/Scripts/Debug/SkillTriggerPanel.cs +++ b/Assets/PerfectWorld/Scripts/Debug/SkillTriggerPanel.cs @@ -67,6 +67,14 @@ namespace BrewMonster [SerializeField] private LogPanelAnimeScene logPanelAnimeScene; + [Header("Channeling (time_type = 2)")] + [Tooltip("Stops durative/channeling skill repeat and allows other skills again.")] + [SerializeField] private Button channelCancelButton; + + private Coroutine _channelingCoroutine; + private int _channelingSkillId; + private bool _isChanneling; + /// /// World position of the draggable target marker, read by CECSkillGfxMan.get_pos_by_id. /// 可拖动目标标记的世界坐标,由 CECSkillGfxMan.get_pos_by_id 读取。 @@ -79,11 +87,19 @@ namespace BrewMonster private void Awake() { Instance = this; +<<<<<<< HEAD SkillStubs.Init(); +======= + if (channelCancelButton != null) + channelCancelButton.onClick.AddListener(CancelChanneling); +>>>>>>> 6fde1d1583 (Add requirement for play skill) } private void OnDestroy() { + if (channelCancelButton != null) + channelCancelButton.onClick.RemoveListener(CancelChanneling); + StopChanneling(); if (Instance == this) Instance = null; } @@ -455,10 +471,81 @@ namespace BrewMonster return root.GetComponentInChildren(); } + /// + /// Stops channeling repeat and clears pending attack events (wire to cancel button). + /// 停止引导重复并清理挂起的攻击事件(绑定到取消按钮)。 + /// + public void CancelChanneling() + { + StopChanneling(); + } + + private void StopChanneling() + { + _isChanneling = false; + _channelingSkillId = 0; + + if (_channelingCoroutine != null) + { + StopCoroutine(_channelingCoroutine); + _channelingCoroutine = null; + } + + if (player == null) + return; + + player.StopSkillAttackAction(); + EventBus.PublishChannel(player.GetCharacterID(), new ClearComActFlagAllRankNodesEvent(true)); + + CECAttackerEvents attackerEvents = + CECAttacksMan.Instance?.FindAttackByAttacker(player.GetPlayerInfo().cid); + if (attackerEvents) + attackerEvents.Signal(); + } + + /// + /// Durative skill: block other skills while an attack event has not fired yet. + /// 引导技能:攻击事件尚未触发时,阻止其它技能。 + /// + private bool ShouldBlockOtherSkillTrigger(CECSkill skill) + { + if (!_isChanneling || skill == null) + return false; + + if (skill.GetSkillID() == _channelingSkillId) + return false; + + return HasPendingChannelAttackEvent(); + } + + private bool HasPendingChannelAttackEvent() + { + if (!_isChanneling || player == null) + return false; + + CECAttackerEvents attackerEvents = + CECAttacksMan.Instance?.FindAttackByAttacker(player.GetPlayerInfo().cid); + if (!attackerEvents) + return false; + + CECAttackEvent pAttack = attackerEvents.Find(_channelingSkillId, 0); + return pAttack != null && !pAttack.m_bDoFired; + } + public void LocalCastSkill(CECSkill skill) { if (player == null || skill == null) return; + + if (ShouldBlockOtherSkillTrigger(skill)) + { + Debug.LogWarning($"[SkillTriggerPanel] Blocked skill {skill.GetSkillID()} — channeling skill {_channelingSkillId} attack event pending."); + return; + } + + if (_isChanneling) + StopChanneling(); + logPanelAnimeScene.Reset(); int skillId = skill.GetSkillID(); logPanelAnimeScene.AddCopyTextButton("ID", skillId.ToString()); @@ -493,56 +580,112 @@ namespace BrewMonster // Debug.LogWarning($"[SkillTriggerPanel] composerMan is null — VFX skipped for skill {skillId}."); // } - // 3. After 2s, play the release / 施放起+落 attack animation chain (local-only). - // 2 秒后播放施放攻击动画链(仅本地)。 - StartCoroutine(DelayedPlaySkillAttackAction(player, skillId)); + // 3. After delay, play the release / 施放起+落 attack animation chain (local-only). + // 延迟后播放施放攻击动画链(仅本地) + if (skill.IsDurative()) + { + _isChanneling = true; + _channelingSkillId = skillId; + _channelingCoroutine = StartCoroutine(ChannelingSkillRoutine(player, skillId)); + } + else + { + StartCoroutine(DelayedPlaySkillAttackAction(player, skillId, 2f, replayAttackAnim: false)); + } } - private IEnumerator DelayedPlaySkillAttackAction(CECHostPlayer hostPlayer, int skillId) + /// + /// Durative (time_type = 2): first hit at 1s, then every 2s until cancel. + /// 引导技能:1 秒首次命中,之后每 2 秒重复,直到按下取消。 + /// + private IEnumerator ChannelingSkillRoutine(CECHostPlayer hostPlayer, int skillId) { - - int attackTime = 0; yield return new WaitForSeconds(1f); + if (!_isChanneling || hostPlayer == null) + yield break; + + TriggerLocalSkillAttack(hostPlayer, skillId, replayAttackAnim: false); + + while (_isChanneling && hostPlayer != null) + { + yield return new WaitForSeconds(5f); + if (!_isChanneling || hostPlayer == null) + yield break; + + while (_isChanneling && HasPendingChannelAttackEvent()) + yield return null; + + if (!_isChanneling || hostPlayer == null) + yield break; + + TriggerLocalSkillAttack(hostPlayer, skillId, replayAttackAnim: true); + } + } + + private IEnumerator DelayedPlaySkillAttackAction(CECHostPlayer hostPlayer, int skillId, float delaySecs, bool replayAttackAnim) + { + yield return new WaitForSeconds(delaySecs); if (hostPlayer == null) yield break; + TriggerLocalSkillAttack(hostPlayer, skillId, replayAttackAnim); + } + + /// + /// Local-only skill hit: mirrors for debug panel. + /// When is true (channeling tick), signal prior attack so anim replays. + /// 本地技能命中:与 PlayAttackEffect 一致;引导重复 tick 时先 Signal 再重播攻击动作。 + /// + private void TriggerLocalSkillAttack(CECHostPlayer hostPlayer, int skillId, bool replayAttackAnim) + { + int attackTime = 0; CECAttackEvent pAttack = null; - // first try to find if there is already a skill attack event in attackman + int targetId = targetMarker != null + ? targetMarker.GetNPCID() + : EncodeDebugNpcId(); + CECAttackerEvents attackerEvents = CECAttacksMan.Instance.FindAttackByAttacker(hostPlayer.GetPlayerInfo().cid); if (attackerEvents) { pAttack = attackerEvents.Find(skillId, 0); if (pAttack != null) { - // Ãæ¹¥»÷µÄ·ÇµÚÒ»´ÎÉ˺¦ÏûÏ¢ - pAttack.AddTarget(DEBUG_TARGET_ID, 1, 1); - goto EXIT; + if (replayAttackAnim) + attackerEvents.Signal(); + else + { + // 面攻击的非第一次伤害消息 / Non-first hit on same attack event + pAttack.AddTarget(targetId, 1, 1); + if (attackTime != 0) + attackTime = 0; + return; + } } else { attackerEvents.Signal(); } } + if (ElementSkill.IsGoblinSkill((uint)skillId) && - ElementSkill.GetType((uint)skillId) == 2) + ElementSkill.GetType((uint)skillId) == 2) { pAttack = CECAttacksMan.Instance.AddSkillAttack( - hostPlayer.GetPlayerInfo().cid, hostPlayer.GetPlayerInfo().cid, hostPlayer.GetPlayerInfo().cid, hostPlayer.GetWeaponID(), skillId, 0, 0x0200, 0); + hostPlayer.GetPlayerInfo().cid, hostPlayer.GetPlayerInfo().cid, hostPlayer.GetPlayerInfo().cid, + hostPlayer.GetWeaponID(), skillId, 0, 0x0200, 0); } else { - // begin a skill attack pAttack = CECAttacksMan.Instance.AddSkillAttack( - hostPlayer.GetPlayerInfo().cid, targetMarker.GetNPCID(), targetMarker.GetNPCID(), hostPlayer.GetWeaponID(), skillId, 0, 0x0200, 0); + hostPlayer.GetPlayerInfo().cid, targetId, targetId, + hostPlayer.GetWeaponID(), skillId, 0, 0x0200, 0); } - - bool ok = hostPlayer.PlaySkillAttackAction(skillId, 0, ref attackTime,0, pAttack); + bool ok = hostPlayer.PlaySkillAttackAction(skillId, 0, ref attackTime, 0, pAttack); if (!ok) - BMLogger.LogWarning($"[SkillTriggerPanel] PlaySkillAttackAction returned false for skill {skillId} after delay — attack anim may not play."); - EXIT: - // // For skill attacking, time is always set to 0 + BMLogger.LogWarning($"[SkillTriggerPanel] PlaySkillAttackAction returned false for skill {skillId} — attack anim may not play."); + if (attackTime != 0) attackTime = 0; } diff --git a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs index 79ad2101aa..4cf7fd433f 100644 --- a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs @@ -2752,7 +2752,7 @@ namespace BrewMonster } } - if (!PlaySkillAttackActionWithName(idSkill, szAct, bHideFX, attackEvent)) + if (!PlaySkillAttackActionWithName(idSkill, szAct, bHideFX, attackEvent,(uint)COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX)) { return false; } @@ -2798,7 +2798,7 @@ namespace BrewMonster } } - if (!PlaySkillAttackActionWithName(idSkill, szAct, bHideFX, attackEvent)) + if (!PlaySkillAttackActionWithName(idSkill, szAct, bHideFX, attackEvent, (uint)COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX)) { return false; } @@ -2836,10 +2836,10 @@ namespace BrewMonster if (pTeam == null) return false; return pTeam.GetMemberByID(idPlayer) != null; } - public bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX = false, CECAttackEvent attackEvent = null) + public bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX = false, CECAttackEvent attackEvent = null, uint dwFlagMode = 0) { return m_pActionController != null - && m_pActionController.PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, attackEvent, 0); + && m_pActionController.PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, attackEvent, dwFlagMode); } public bool QueueSkillAttackActionWithName(int idSkill, string szActName, int nTransTime = 200, bool bNoFX = false, bool bResetSpeed = false, bool bResetActFlag = false, CECAttackEvent attackEvent = null, uint dwNewFlagMode = 0) diff --git a/Assets/PerfectWorld/Scripts/NPC/CECModel.cs b/Assets/PerfectWorld/Scripts/NPC/CECModel.cs index aa203a45fa..bb6e58d1f6 100644 --- a/Assets/PerfectWorld/Scripts/NPC/CECModel.cs +++ b/Assets/PerfectWorld/Scripts/NPC/CECModel.cs @@ -67,6 +67,7 @@ public class FX_BINDING_BASE m_pDynData = pDynData; } public virtual bool IsStop() { return false; } + public virtual bool IsStart() {return false;} public virtual void Stop() {} public virtual void Render() {} public virtual void UpdateParam(CECModel pECModel, int nDeltaTime) {} @@ -117,10 +118,6 @@ public class GFX_BINDING : FX_BINDING_BASE // Let the effect run one full loop cycle, then stop emitting. / 再播完一整圈循环后停发粒子 // Longest main.duration under this GFX (loop period per particle system). / 取挂点下所有粒子的 duration 最大值作为一整圈时长 float oneLoop = 0f; - foreach (ParticleSystem psChild in go.GetComponentsInChildren(true)) - oneLoop = Mathf.Max(oneLoop, psChild.main.duration); - if (oneLoop > 2f) - oneLoop = 2f; await UniTask.Delay(TimeSpan.FromSeconds(oneLoop), delayType, cancellationToken: ct); if (_ps != null && _ps.IsAlive(true)) _ps.Stop(true, ParticleSystemStopBehavior.StopEmitting); @@ -156,6 +153,10 @@ public class GFX_BINDING : FX_BINDING_BASE if (!isStartPlaying) return false; return _ps == null || !_ps.isPlaying; + } + public override bool IsStart() + { + return isStartPlaying; } public override void Render() { if (m_pGfx == null) @@ -168,10 +169,6 @@ public class GFX_BINDING : FX_BINDING_BASE if (!string.IsNullOrEmpty(fx.m_strHookName)) { hookT = host.GetHook(fx.m_strHookName, true); -#if UNITY_EDITOR - if (hookT == null) - BMLogger.LogWarning($"[GFX_BINDING.Render] Hook '{fx.m_strHookName}' not found; GFX stays on character root."); -#endif } Quaternion eventLocalRot = _prefabLocalRot * @@ -188,7 +185,6 @@ public class GFX_BINDING : FX_BINDING_BASE m_pGfx.transform.SetParent(hookT, false); else { - // Keep under model root; align to hook world pose once (no bone follow). / 不切到挂点,仅取挂点世界位姿对齐一次(不随骨骼动) m_pGfx.transform.SetPositionAndRotation( hookT.TransformPoint(hookLocalPos), hookT.rotation * eventLocalRot); @@ -225,8 +221,21 @@ public class GFX_BINDING : FX_BINDING_BASE if (m_pInfo != null && m_pInfo.m_dwStartTime <= nDeltaTime && !isStartPlaying) { Render(); - if (_ps != null) - m_pInfo.m_dwTimeSpan = (int)(_ps.main.duration * 1000); + + var PSes = m_pGfx.GetComponentsInChildren(); + float span = -1; + foreach(var PS in PSes) + { + var duration = PS.main.duration; + //remove default duration and get max duration + if( duration!= 5 && duration > span && span !=100000) + { + span = duration; + } + } + m_dwTimeSpan = (int)span *1000; + m_pInfo.m_dwTimeSpan = (int)m_pInfo.m_dwStartTime + (int)span *1000; + } } public void SetGfx(GameObject gfx, Quaternion prefabRotation, Vector3 prefabPosition) { @@ -419,7 +428,7 @@ public class A3DCombActDynData else if (prefab == null) { Debug.LogWarning("Missing gfx prefab, using placeholder: " + path); - string path2 = "gfx/NullDefault"; + string path2 = "gfx/人物/技能/妖兽/NullDefault.gfx"; GameObject prefab2 = await AddressableManager.Instance.LoadPrefabAsync(path2); var gfx = GameObject.Instantiate(prefab2, m_pECModel.transform); gfx.SetActive(false); @@ -498,6 +507,7 @@ public class A3DCombActDynData } public void Stop(bool bStopAct, bool bForceStopFx = false ) { + Debug.Log("[DefaultPolicy]Stop: " + m_pAct?.m_strName + " bStopAct: " + bStopAct + " bForceStopFx: " + bForceStopFx); RemoveAllActiveFx(); if (ActiveAttackEvent != null) { @@ -617,24 +627,36 @@ public class A3DCombActDynData static bool IsFxEnd(FX_BINDING_BASE pFx, int dwTimeSpan) { - uint dwMax = 0xFFFFFFFF; + int dwMax = -1; if (pFx.IsStop()) return true; - - // if (pFx.GetInfo().m_dwTimeSpan == dwMax) - // return false; + if (!pFx.IsStart()) + return false; + if (pFx.GetInfo().m_dwTimeSpan > 10000 || pFx.GetInfo().m_dwTimeSpan == dwMax) + return false; return false; - //return dwTimeSpan >= pFx->GetInfo()->GetStartTime() + pFx->GetInfo()->GetTimeSpan(); + // Debug.Log( $"Span: {dwTimeSpan} TickTill{pFx.GetInfo().m_dwStartTime + pFx.GetInfo().m_dwTimeSpan}"); + // return dwTimeSpan >= pFx.GetInfo().m_dwStartTime + pFx.GetInfo().m_dwTimeSpan; + } + + bool IsCurActFinished(ACTION_INFO pCur) + { + return !pCur.IsInfinite() || m_nCurActLoop >= m_arrActLoopNum[m_nCurActIndex].GetLoopNum(); + } + bool IsAllEventFinished() { return m_ActFxArray.Count == 0 ; } + public bool IsActionStopped() + { + return m_pAct.m_ActLst.Count == 0 || (m_pAct.m_nLoops != -1 && m_nCurLoop >= m_pAct.m_nLoops); + } + public bool IsAllFinished() + { + return IsActionStopped() && IsAllEventFinished(); + } + bool IsActionFinished() + { + return m_dwTimeSpan >= m_dwDynComActSpan; } - bool IsCurActFinished(ACTION_INFO pCur) - { - return !pCur.IsInfinite() || m_nCurActLoop >= m_arrActLoopNum[m_nCurActIndex].GetLoopNum(); - } - public bool IsActionStopped() - { - return m_pAct.m_ActLst.Count == 0 || (m_pAct.m_nLoops != -1 && m_nCurLoop >= m_pAct.m_nLoops); - } void LoopCurAct(ACTION_INFO pCur, uint dwDeltaTime) { m_dwTimeSpan = (int)(pCur.m_dwStartTime + m_dwTimeSpan - pCur.m_dwEndTime); // °Ñʱ¼äÉè»ØÈ¥ @@ -655,6 +677,7 @@ public class A3DCombActDynData { if(fx != null) { + Debug.Log("RemoveAllActiveFx: " + fx.GetInfo()?.m_pAct?.m_strName); fx.Stop(); } } @@ -1493,7 +1516,7 @@ public class CECModel pNode.m_pActive.Play(nChannel, fWeight, nTransTime, 0, bRestart, m_bAbsTrack, bNoFx, bForceStop,pNode.m_Rank); m_bAbsTrack = false; pNode.m_pActFlag = false; - pNode.m_dwFlagMode = 2;//COMACT_FLAG_MODE_ONCE_IGNOREGFX; + pNode.m_dwFlagMode = (int)dwFlagMode; return true; } @@ -1505,7 +1528,7 @@ public class CECModel } return m_pMapModel.m_ActionMap.TryGetValue(szActName, out A3DCombinedAction combinedAction) ? combinedAction : null; } - //Final trigger function + //Final trigger function public int GetComActTimeSpanByName(string szActName) { A3DCombinedAction combinedAction = GetComActByName(szActName); @@ -1582,9 +1605,33 @@ public class CECModel EventBus.PublishChannel(iNFO.nid, new QueueNPCActionEvent(szActName)); return true; } + public void StopAllActions(bool bStopFx) + { + //ResetMaterialScale(); + StopChannelAction(0, true, bStopFx); + //StopChildrenAct(); + } + + public void StopChannelAction(int nChannel, byte rank, bool bStopAct, bool bStopFx = false) + { + ChannelAct ca = m_ChannelActs[nChannel]; + ChannelActNode pNode = ca.RemoveNodeByRank(rank); + + if (pNode != null) + { + pNode.m_pActive.Stop(bStopAct, bStopFx); + } + } + public void StopChannelAction(int nChannel, bool bStopAct, bool bStopFx = false) { - //TODO: Implement StopChannelAction + ChannelAct ca = m_ChannelActs[nChannel]; + foreach (var node in ca.m_RankNodes) + { + Debug.Log("[DefaultPolicy]StopChannelAction: " + node.m_pActive?.GetComAct()?.m_strName); + node.m_pActive.Stop(bStopAct, bStopFx); + } + ca.m_RankNodes.Clear(); } public bool IsActionStopped(int nChannel =0) { @@ -1623,9 +1670,15 @@ public class CECModel var node = rankNodes[n]; bool bActFinished = false; if (node.m_dwFlagMode == COMACT_FLAG_MODE_ONCE_IGNOREGFX || node.m_dwFlagMode == COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX) + { + BMLogger.Log("[DefaultPolicy] Checking IsActionStopped: " + node.m_pActive?.GetComAct()?.m_strName); bActFinished = node.m_pActive.IsActionStopped(); + } else - bActFinished = node.m_pActive.IsActionStopped(); + { + BMLogger.Log("[DefaultPolicy] Checking IsAllFinished: " + node.m_pActive?.GetComAct()?.m_strName); + bActFinished = node.m_pActive.IsAllFinished(); + } if (bActFinished) { if (node.m_dwFlagMode != COMACT_FLAG_MODE_NONE && node.m_pActFlag) diff --git a/Assets/PerfectWorld/Scripts/Players/CECPlayerActionController.cs b/Assets/PerfectWorld/Scripts/Players/CECPlayerActionController.cs index 439e9558f5..e224259cd8 100644 --- a/Assets/PerfectWorld/Scripts/Players/CECPlayerActionController.cs +++ b/Assets/PerfectWorld/Scripts/Players/CECPlayerActionController.cs @@ -165,6 +165,8 @@ namespace BrewMonster public void StopSkillAttackAction() { + BMLogger.Log("[DefaultPolicy]StopSkillAttackAction: " + m_bSkillAttackActionPlayed); + BMLogger.Log("[DefaultPolicy]IsPlayingCastingSkillAction: " + m_actionPlayPolicy.IsPlayingCastingSkillAction()); if (m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction() && m_bSkillAttackActionPlayed) { m_actionPlayPolicy.StopSkillAction(); diff --git a/Assets/PerfectWorld/Scripts/Players/CECPlayerActionPlayPolicy.cs b/Assets/PerfectWorld/Scripts/Players/CECPlayerActionPlayPolicy.cs index 3b9f7b0da7..a9a757ad91 100644 --- a/Assets/PerfectWorld/Scripts/Players/CECPlayerActionPlayPolicy.cs +++ b/Assets/PerfectWorld/Scripts/Players/CECPlayerActionPlayPolicy.cs @@ -235,7 +235,7 @@ namespace BrewMonster public bool IsPlayingCastingSkillAction() { - return m_isCastingSkill; + return IsPlayingAction((int)PLAYER_ACTION_TYPE.ACT_CASTSKILL); } // Non-skill action @@ -379,44 +379,26 @@ namespace BrewMonster if (IsMoving()){ return false; } + BMLogger.Log("[DefaultPolicy] PlaySkillCastActionWithName:" + szActName); ClearComActFlagAllRankNodes(true); bool check = GetModel()!=null - && GetModel().PlayActionByName(szActName, 1.0f, true, 200, true); - if (!check) - { - // BMLogger.LogError($"Fall back to base implementation: {szActName} failed"); - //fallback to base implementation(which is non policy based) - base.PlaySkillCastActionWithName(idSkill, szActName, bNoFX); - } + && GetModel().PlayActionByName(szActName, 1.0f, true, 200, true, (uint)PLAYER_ACTION_TYPE.ACT_CASTSKILL, bNoFX); return check; } public override bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX, CECAttackEvent attackEvent, uint dwFlagMode){ if (IsMoving()){ return false; } - //LOG_DEBUG_INFO(AString().Format("PlaySkillAttackActionWithName:%s", szActName)); + BMLogger.Log("[DefaultPolicy] Checking PlaySkillAttackActionWithName:" + szActName); ClearComActFlagAllRankNodes(true); bool check = GetModel() != null && GetModel().PlayActionByName(szActName, 1.0f, true, 200, true, (uint)PLAYER_ACTION_TYPE.ACT_CASTSKILL, bNoFX, attackEvent, dwFlagMode); - if (!check) - { - //BMLogger.LogError($"Fall back to base implementation: {szActName} failed"); - //fallback to base implementation(which is non policy based) - base.PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, attackEvent, dwFlagMode); - } return check; } public override bool QueueSkillAttackActionWithName(int idSkill, string szActName, int nTransTime, bool bNoFX, bool bResetSpeed, bool bResetActFlag, CECAttackEvent attackEvent, uint dwNewFlagMode){ - //LOG_DEBUG_INFO(AString().Format("QueueSkillAttackActionWithName:%s", szActName)); bool check = GetModel()!=null && GetModel().QueueAction(szActName, nTransTime, (int)PLAYER_ACTION_TYPE.ACT_CASTSKILL, false, false, bNoFX, bResetSpeed, bResetActFlag, attackEvent, dwNewFlagMode); - if (!check) - { - //BMLogger.LogError($"Fall back to base implementation: {szActName} failed"); - //fallback to base implementation(which is non policy based) - base.QueueSkillAttackActionWithName(idSkill, szActName, nTransTime, bNoFX, bResetSpeed, bResetActFlag, attackEvent, dwNewFlagMode); - } return check; } public override bool PlayWoundActionWithName(string szActName){ @@ -433,12 +415,14 @@ namespace BrewMonster } public override void StopChannelAction(){ if (GetModel()!=null){ + BMLogger.Log("[DefaultPolicy]StopChannelAction: " + GetModel().GetCurActionUserData()); ClearComActFlagAllRankNodes(true); GetModel().StopChannelAction(0, true); } } public override void StopSkillAction(){ if (GetModel()!=null && IsPlayingCastingSkillAction()){ + BMLogger.Log("[DefaultPolicy]StopSkillAction: " + GetModel().GetCurActionUserData()); StopChannelAction(); } }