diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 8c7433ca8..57ab11041 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -105,7 +105,7 @@ void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint3 if (eventType == SMART_EVENT_LINK)//special handling continue; - if (eventType == e/* && (!(*i).event.event_phase_mask || IsInPhase((*i).event.event_phase_mask)) && !((*i).event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE && (*i).runOnce)*/) + if (eventType == e) { ConditionList conds = sConditionMgr->GetConditionsForSmartEvent((*i).entryOrGuid, (*i).event_id, (*i).source_type); ConditionSourceInfo info = ConditionSourceInfo(unit, GetBaseObject(), me ? me->GetVictim() : nullptr); @@ -1496,6 +1496,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u unitTarget->AttackStop(); } } + + delete targets; break; } case SMART_ACTION_SUMMON_CREATURE: @@ -4456,6 +4458,16 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui ProcessAction(e, unit, var0, var1); break; } + case SMART_EVENT_EVENT_PHASE_CHANGE: + { + if (!IsInPhase(e.event.eventPhaseChange.phasemask)) + { + return; + } + + ProcessAction(e, GetLastInvoker()); + break; + } case SMART_EVENT_GAME_EVENT_START: case SMART_EVENT_GAME_EVENT_END: { @@ -5092,3 +5104,43 @@ Unit* SmartScript::GetLastInvoker(Unit* invoker) return ObjectAccessor::GetUnit(*invoker, mLastInvoker); return nullptr; } + +void SmartScript::IncPhase(uint32 p) +{ + // protect phase from overflowing + SetPhase(std::min(SMART_EVENT_PHASE_12, mEventPhase + p)); +} + +void SmartScript::DecPhase(uint32 p) +{ + if (p >= mEventPhase) + { + SetPhase(0); + } + else + { + SetPhase(mEventPhase - p); + } +} + +void SmartScript::SetPhase(uint32 p) +{ + uint32 oldPhase = mEventPhase; + + mEventPhase = p; + + if (oldPhase != mEventPhase) + { + ProcessEventsFor(SMART_EVENT_EVENT_PHASE_CHANGE); + } +} + +bool SmartScript::IsInPhase(uint32 p) const +{ + if (mEventPhase == 0) + { + return false; + } + + return ((1 << (mEventPhase - 1)) & p) != 0; +} diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index be075eb0b..8fc9136cd 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -258,26 +258,10 @@ public: void SetPhaseReset(bool allow) { _allowPhaseReset = allow; } private: - void IncPhase(uint32 p) - { - // Xinef: protect phase from overflowing - mEventPhase = std::min(SMART_EVENT_PHASE_12, mEventPhase + p); - } - - void DecPhase(uint32 p) - { - if (p >= mEventPhase) - mEventPhase = 0; - else - mEventPhase -= p; - } - bool IsInPhase(uint32 p) const - { - if (mEventPhase == 0) - return false; - return (1 << (mEventPhase - 1)) & p; - } - void SetPhase(uint32 p = 0) { mEventPhase = p; } + void IncPhase(uint32 p); + void DecPhase(uint32 p); + void SetPhase(uint32 p); + bool IsInPhase(uint32 p) const; SmartAIEventList mEvents; SmartAIEventList mInstallEvents; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 8868ffdb1..54f36d279 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -528,7 +528,7 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e) case SMART_EVENT_JUST_CREATED: return NO_PARAMS; case SMART_EVENT_GOSSIP_HELLO: return sizeof(SmartEvent::gossipHello); case SMART_EVENT_FOLLOW_COMPLETED: return NO_PARAMS; - // case SMART_EVENT_EVENT_PHASE_CHANGE: return sizeof(SmartEvent::eventPhaseChange); + case SMART_EVENT_EVENT_PHASE_CHANGE: return sizeof(SmartEvent::eventPhaseChange); case SMART_EVENT_IS_BEHIND_TARGET: return sizeof(SmartEvent::behindTarget); case SMART_EVENT_GAME_EVENT_START: return sizeof(SmartEvent::gameEvent); case SMART_EVENT_GAME_EVENT_END: return sizeof(SmartEvent::gameEvent); @@ -1076,6 +1076,27 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) } break; } + case SMART_EVENT_EVENT_PHASE_CHANGE: + { + if (!e.event.eventPhaseChange.phasemask) + { + LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has no param set, event won't be executed!.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); + return false; + } + + if (e.event.eventPhaseChange.phasemask > SMART_EVENT_PHASE_ALL) + { + LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses invalid phasemask {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.eventPhaseChange.phasemask); + return false; + } + + if (e.event.event_phase_mask && !(e.event.event_phase_mask & e.event.eventPhaseChange.phasemask)) + { + LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses event phasemask {} and incompatible event_param1 {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.event_phase_mask, e.event.eventPhaseChange.phasemask); + return false; + } + break; + } case SMART_EVENT_IS_BEHIND_TARGET: if (!IsMinMaxValid(e, e.event.behindTarget.cooldownMin, e.event.behindTarget.cooldownMax)) return false; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index a9ffa16ad..9290a6336 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -170,7 +170,7 @@ enum SMART_EVENT SMART_EVENT_JUST_CREATED = 63, // none SMART_EVENT_GOSSIP_HELLO = 64, // event_para_1 (only) 0 = no filter set, always execute action, 1 = GossipHello only filter set, skip action if reportUse, 2 = reportUse only filter set, skip action if GossipHello SMART_EVENT_FOLLOW_COMPLETED = 65, // none - SMART_EVENT_UNUSED_66 = 66, // UNUSED + SMART_EVENT_EVENT_PHASE_CHANGE = 66, // event phase mask (<= SMART_EVENT_PHASE_ALL) SMART_EVENT_IS_BEHIND_TARGET = 67, // cooldownMin, CooldownMax SMART_EVENT_GAME_EVENT_START = 68, // game_event.Entry SMART_EVENT_GAME_EVENT_END = 69, // game_event.Entry @@ -376,6 +376,17 @@ struct SmartEvent uint32 action; } gossip; + struct + { + uint32 spell; + uint32 effIndex; + } dummy; + + struct + { + uint32 phasemask; + } eventPhaseChange; + struct { uint32 cooldownMin; @@ -1677,7 +1688,7 @@ const uint32 SmartAIEventMask[SMART_EVENT_AC_END][2] = {SMART_EVENT_JUST_CREATED, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, {SMART_EVENT_GOSSIP_HELLO, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, {SMART_EVENT_FOLLOW_COMPLETED, SMART_SCRIPT_TYPE_MASK_CREATURE }, - {SMART_EVENT_UNUSED_66, 0}, + {SMART_EVENT_EVENT_PHASE_CHANGE, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, {SMART_EVENT_IS_BEHIND_TARGET, SMART_SCRIPT_TYPE_MASK_CREATURE }, {SMART_EVENT_GAME_EVENT_START, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, {SMART_EVENT_GAME_EVENT_END, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },