diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartAI.cpp | 4 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartAI.h | 2 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.cpp | 34 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.h | 2 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.cpp | 9 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.h | 9 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 14 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.h | 1 |
8 files changed, 66 insertions, 9 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 9ab51c65463..066747b0610 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -869,9 +869,9 @@ void SmartAI::StopFollow(bool complete) GetScript()->ProcessEventsFor(SMART_EVENT_FOLLOW_COMPLETED, player); } -void SmartAI::SetTimedActionList(SmartScriptHolder& e, uint32 entry, Unit* invoker) +void SmartAI::SetTimedActionList(SmartScriptHolder& e, uint32 entry, Unit* invoker, uint32 startFromEventId) { - GetScript()->SetTimedActionList(e, entry, invoker); + GetScript()->SetTimedActionList(e, entry, invoker, startFromEventId); } void SmartAI::OnGameEvent(bool start, uint16 eventId) diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index c40fe78d179..6d0c766d650 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -71,7 +71,7 @@ class TC_GAME_API SmartAI : public CreatureAI void WaypointReached(uint32 nodeId, uint32 pathId) override; void WaypointPathEnded(uint32 nodeId, uint32 pathId) override; - void SetTimedActionList(SmartScriptHolder& e, uint32 entry, Unit* invoker); + void SetTimedActionList(SmartScriptHolder& e, uint32 entry, Unit* invoker, uint32 startFromEventId = 0); SmartScript* GetScript() { return &_script; } // Called at reaching home after evade, InitializeAI(), EnterEvadeMode() for resetting variables diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 515c71b6a30..5968b4e8791 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2522,6 +2522,26 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } break; } + case SMART_ACTION_BECOME_PERSONAL_CLONE_FOR_PLAYER: + { + for (WorldObject* target : targets) + { + if (!IsPlayer(target)) + continue; + + ObjectGuid privateObjectOwner = target->GetGUID(); + if (Creature* summon = GetBaseObject()->SummonPersonalClone((TempSummonType)e.action.becomePersonalClone.type, e.action.becomePersonalClone.duration, 0, 0, privateObjectOwner)) + { + if (IsSmart(summon)) + ENSURE_AI(SmartAI, summon->AI())->SetTimedActionList(e, e.entryOrGuid, target->ToUnit(), e.event_id + 1); + + } + } + + // action list will continue on personal clones + Trinity::Containers::EraseIf(mTimedActionList, [e](SmartScriptHolder const& script) { return script.event_id > e.event_id; }); + break; + } default: TC_LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry " SI64FMTD " SourceType %u, Event %u, Unhandled Action type %u", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); break; @@ -3936,17 +3956,20 @@ void SmartScript::OnUpdate(uint32 const diff) if (!mTimedActionList.empty()) { isProcessingTimedActionList = true; - for (SmartScriptHolder& scriptholder : mTimedActionList) + + for (size_t i = 0; i < mTimedActionList.size(); ++i) { - if (scriptholder.enableTimed) + SmartScriptHolder& scriptHolder = mTimedActionList[i]; + if (scriptHolder.enableTimed) { - UpdateTimer(scriptholder, diff); + UpdateTimer(scriptHolder, diff); needCleanup = false; } } isProcessingTimedActionList = false; } + if (needCleanup) mTimedActionList.clear(); @@ -4188,7 +4211,7 @@ Unit* SmartScript::DoFindClosestFriendlyInRange(float range, bool playerOnly) co return unit; } -void SmartScript::SetTimedActionList(SmartScriptHolder& e, uint32 entry, Unit* invoker) +void SmartScript::SetTimedActionList(SmartScriptHolder& e, uint32 entry, Unit* invoker, uint32 startFromEventId) { //do NOT clear mTimedActionList if it's being iterated because it will invalidate the iterator and delete // any SmartScriptHolder contained like the "e" parameter passed to this function @@ -4206,6 +4229,9 @@ void SmartScript::SetTimedActionList(SmartScriptHolder& e, uint32 entry, Unit* i mTimedActionList = sSmartScriptMgr->GetScript(entry, SMART_SCRIPT_TYPE_TIMED_ACTIONLIST); if (mTimedActionList.empty()) return; + + Trinity::Containers::EraseIf(mTimedActionList, [startFromEventId](SmartScriptHolder const& script) { return script.event_id < startFromEventId; }); + mTimedActionListInvoker = invoker ? invoker->GetGUID() : ObjectGuid::Empty; for (SmartAIEventList::iterator i = mTimedActionList.begin(); i != mTimedActionList.end(); ++i) { diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index e75d2bb48a3..55061ab40ef 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -91,7 +91,7 @@ class TC_GAME_API SmartScript void OnReset(); void ResetBaseObject(); - void SetTimedActionList(SmartScriptHolder& e, uint32 entry, Unit* invoker); + void SetTimedActionList(SmartScriptHolder& e, uint32 entry, Unit* invoker, uint32 startFromEventId = 0); Unit* GetLastInvoker(Unit* invoker = nullptr) const; ObjectGuid mLastInvoker; typedef std::unordered_map<uint32, uint32> CounterMap; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index d393b412958..40167bceb31 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -1838,6 +1838,15 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_DESPAWN_SPAWNGROUP: case SMART_ACTION_ADD_TO_STORED_TARGET_LIST: break; + case SMART_ACTION_BECOME_PERSONAL_CLONE_FOR_PLAYER: + { + if (e.action.becomePersonalClone.type < TEMPSUMMON_TIMED_OR_DEAD_DESPAWN || e.action.becomePersonalClone.type > TEMPSUMMON_MANUAL_DESPAWN) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses incorrect TempSummonType %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.becomePersonalClone.type); + return false; + } + break; + } default: TC_LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type(%u), event_type(%u), Entry " SI64FMTD " SourceType %u Event %u, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id); return false; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 0473febc762..87ea61dd5c4 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -613,7 +613,8 @@ enum SMART_ACTION SMART_ACTION_SET_UNINTERACTIBLE = 146, // 0/1 SMART_ACTION_ACTIVATE_GAMEOBJECT = 147, // GameObjectActions SMART_ACTION_ADD_TO_STORED_TARGET_LIST = 148, // varID - SMART_ACTION_END = 149 + SMART_ACTION_BECOME_PERSONAL_CLONE_FOR_PLAYER = 149, // summonType 1-8, duration in ms + SMART_ACTION_END = 150 }; enum class SmartActionSummonCreatureFlags @@ -1241,6 +1242,12 @@ struct SmartAction uint32 id; } addToStoredTargets; + struct + { + uint32 type; + uint32 duration; + } becomePersonalClone; + //! Note for any new future actions //! All parameters must have type uint32 diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 4a89ecb2674..0587493d994 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1866,6 +1866,20 @@ TempSummon* WorldObject::SummonCreature(uint32 id, float x, float y, float z, fl return SummonCreature(id, { x,y,z,o }, despawnType, despawnTime, 0, 0, privateObjectOwner); } +TempSummon* WorldObject::SummonPersonalClone(TempSummonType despawnType, uint32 despawnTime, uint32 vehId, uint32 spellId, ObjectGuid privateObjectOwner) +{ + if (Map* map = FindMap()) + { + if (TempSummon* summon = map->SummonCreature(GetEntry(), GetPosition(), nullptr, despawnTime, this, spellId, vehId, privateObjectOwner)) + { + summon->SetTempSummonType(despawnType); + return summon; + } + } + + return nullptr; +} + GameObject* WorldObject::SummonGameObject(uint32 entry, Position const& pos, QuaternionData const& rot, uint32 respawnTime, GOSummonType summonType) { if (!IsInWorld()) diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index eac830cfedc..5187ebd25c5 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -571,6 +571,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation TempSummon* SummonCreature(uint32 entry, Position const& pos, TempSummonType despawnType = TEMPSUMMON_MANUAL_DESPAWN, uint32 despawnTime = 0, uint32 vehId = 0, uint32 spellId = 0, ObjectGuid privateObjectOwner = ObjectGuid::Empty); TempSummon* SummonCreature(uint32 entry, Position const& pos, TempSummonType despawnType, Milliseconds despawnTime, uint32 vehId = 0, uint32 spellId = 0, ObjectGuid privateObjectOwner = ObjectGuid::Empty) { return SummonCreature(entry, pos, despawnType, uint32(despawnTime.count()), vehId, spellId, privateObjectOwner); } TempSummon* SummonCreature(uint32 entry, float x, float y, float z, float o = 0, TempSummonType despawnType = TEMPSUMMON_MANUAL_DESPAWN, uint32 despawnTime = 0, ObjectGuid privateObjectOwner = ObjectGuid::Empty); + TempSummon* SummonPersonalClone(TempSummonType despawnType = TEMPSUMMON_MANUAL_DESPAWN, uint32 despawnTime = 0, uint32 vehId = 0, uint32 spellId = 0, ObjectGuid privateObjectOwner = ObjectGuid::Empty); GameObject* SummonGameObject(uint32 entry, Position const& pos, QuaternionData const& rot, uint32 respawnTime /* s */, GOSummonType summonType = GO_SUMMON_TIMED_OR_CORPSE_DESPAWN); GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, QuaternionData const& rot, uint32 respawnTime /* s */, GOSummonType summonType = GO_SUMMON_TIMED_OR_CORPSE_DESPAWN); Creature* SummonTrigger(float x, float y, float z, float ang, uint32 dur, CreatureAI* (*GetAI)(Creature*) = nullptr); |