From 97ee7c437d342ca064fd1099b01ed7a8c34febf3 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Fri, 24 Jul 2020 18:08:59 -0400 Subject: [PATCH] Core/SmartAI: implemented SMART_EVENT_EVENT_PHASE_CHANGE Port From (https://github.com/TrinityCore/TrinityCore/commit/593d3243d4b8301fe03634d279b51a68b5d9effd) --- Source/Framework/Constants/SmartAIConst.cs | 4 +- Source/Game/AI/SmartScripts/SmartAIManager.cs | 37 ++++++++++++++++++- Source/Game/AI/SmartScripts/SmartScript.cs | 24 ++++++++++-- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/Source/Framework/Constants/SmartAIConst.cs b/Source/Framework/Constants/SmartAIConst.cs index 168936936..c240bb7fa 100644 --- a/Source/Framework/Constants/SmartAIConst.cs +++ b/Source/Framework/Constants/SmartAIConst.cs @@ -69,7 +69,7 @@ namespace Framework.Constants Count = 12 } - public enum PhaseBits + public enum SmartEventPhaseBits { PhaseAlwaysBit = 0, Phase1Bit = 1, @@ -204,7 +204,7 @@ namespace Framework.Constants JustCreated = 63, // None GossipHello = 64, // noReportUse (for GOs) FollowCompleted = 65, // None - Unused66 = 66, + PhaseChange = 66, IsBehindTarget = 67, // Cooldownmin, Cooldownmax GameEventStart = 68, // GameEvent.Entry GameEventEnd = 69, // GameEvent.Entry diff --git a/Source/Game/AI/SmartScripts/SmartAIManager.cs b/Source/Game/AI/SmartScripts/SmartAIManager.cs index 8211fcfb0..1c4f4235e 100644 --- a/Source/Game/AI/SmartScripts/SmartAIManager.cs +++ b/Source/Game/AI/SmartScripts/SmartAIManager.cs @@ -459,7 +459,7 @@ namespace Game.AI Log.outError(LogFilter.ScriptsAi, "SmartAIMgr: EntryOrGuid {0} using event({1}) has invalid action type ({2}), skipped.", e.entryOrGuid, e.event_id, e.GetActionType()); return false; } - if (e.Event.event_phase_mask > (uint)PhaseBits.All) + if (e.Event.event_phase_mask > (uint)SmartEventPhaseBits.All) { Log.outError(LogFilter.ScriptsAi, "SmartAIMgr: EntryOrGuid {0} using event({1}) has invalid phase mask ({2}), skipped.", e.entryOrGuid, e.event_id, e.Event.event_phase_mask); return false; @@ -650,6 +650,27 @@ namespace Game.AI return false; break; } + case SmartEvents.PhaseChange: + { + if (e.Event.eventPhaseChange.phasemask == 0) + { + Log.outError(LogFilter.Sql, $"SmartAIMgr: {e} has no param set, event won't be executed!."); + return false; + } + + if (e.Event.eventPhaseChange.phasemask > (uint)SmartEventPhaseBits.All) + { + Log.outError(LogFilter.Sql, $"SmartAIMgr: {e} uses invalid phasemask {e.Event.eventPhaseChange.phasemask}, skipped."); + return false; + } + + if (e.Event.event_phase_mask != 0 && (e.Event.event_phase_mask & e.Event.eventPhaseChange.phasemask) == 0) + { + Log.outError(LogFilter.Sql, $"SmartAIMgr: {e} uses event phasemask {e.Event.event_phase_mask} and incompatible event_param1 {e.Event.eventPhaseChange.phasemask}, skipped."); + return false; + } + break; + } case SmartEvents.IsBehindTarget: { if (!IsMinMaxValid(e, e.Event.behindTarget.cooldownMin, e.Event.behindTarget.cooldownMax)) @@ -1644,7 +1665,7 @@ namespace Game.AI { SmartEvents.JustCreated, SmartScriptTypeMaskId.Creature + SmartScriptTypeMaskId.Gameobject }, { SmartEvents.GossipHello, SmartScriptTypeMaskId.Creature + SmartScriptTypeMaskId.Gameobject }, { SmartEvents.FollowCompleted, SmartScriptTypeMaskId.Creature }, - { SmartEvents.Unused66, SmartScriptTypeMaskId.None }, + { SmartEvents.PhaseChange, SmartScriptTypeMaskId.Creature + SmartScriptTypeMaskId.Gameobject }, { SmartEvents.IsBehindTarget, SmartScriptTypeMaskId.Creature }, { SmartEvents.GameEventStart, SmartScriptTypeMaskId.Creature + SmartScriptTypeMaskId.Gameobject }, { SmartEvents.GameEventEnd, SmartScriptTypeMaskId.Creature + SmartScriptTypeMaskId.Gameobject }, @@ -1704,6 +1725,11 @@ namespace Game.AI public SmartActions GetActionType() { return Action.type; } public SmartTargets GetTargetType() { return Target.type; } + public override string ToString() + { + return $"Entry {entryOrGuid} SourceType {GetScriptType()} Event {event_id} Action {GetActionType()}"; + } + public int entryOrGuid; public SmartScriptType source_type; public uint event_id; @@ -1816,6 +1842,9 @@ namespace Game.AI [FieldOffset(16)] public Dummy dummy; + [FieldOffset(16)] + public EventPhaseChange eventPhaseChange; + [FieldOffset(16)] public BehindTarget behindTarget; @@ -2010,6 +2039,10 @@ namespace Game.AI public uint spell; public uint effIndex; } + public struct EventPhaseChange + { + public uint phasemask; + } public struct BehindTarget { public uint cooldownMin; diff --git a/Source/Game/AI/SmartScripts/SmartScript.cs b/Source/Game/AI/SmartScripts/SmartScript.cs index 2796c43f9..58616c69b 100644 --- a/Source/Game/AI/SmartScripts/SmartScript.cs +++ b/Source/Game/AI/SmartScripts/SmartScript.cs @@ -3187,6 +3187,14 @@ namespace Game.AI ProcessAction(e, unit, var0, var1); break; } + case SmartEvents.PhaseChange: + { + if (!IsInPhase(e.Event.eventPhaseChange.phasemask)) + return; + + ProcessAction(e, GetLastInvoker()); + break; + } case SmartEvents.GameEventStart: case SmartEvents.GameEventEnd: { @@ -3990,15 +3998,24 @@ namespace Game.AI void IncPhase(uint p) { // protect phase from overflowing - mEventPhase = Math.Min((uint)SmartPhase.Phase12, mEventPhase + p); + SetPhase(Math.Min((uint)SmartPhase.Phase12, mEventPhase + p)); } void DecPhase(uint p) { if (p >= mEventPhase) - mEventPhase = 0; + SetPhase(0); else - mEventPhase -= p; + SetPhase(mEventPhase - p); + } + void SetPhase(uint p) + { + uint oldPhase = mEventPhase; + + mEventPhase = p; + + if (oldPhase != mEventPhase) + ProcessEventsFor(SmartEvents.PhaseChange); } bool IsInPhase(uint p) { @@ -4007,7 +4024,6 @@ namespace Game.AI return ((1 << (int)(mEventPhase - 1)) & p) != 0; } - void SetPhase(uint p = 0) { mEventPhase = p; } void RemoveStoredEvent(uint id) {