diff options
author | ariel- <ariel-@users.noreply.github.com> | 2017-06-03 10:21:06 +0200 |
---|---|---|
committer | Carbenium <carbenium@outlook.com> | 2020-07-16 20:59:25 +0200 |
commit | 259bde591444980c27a17524c140f078c4159f55 (patch) | |
tree | 60043db1cbdc52692608421e23bf2d0c01e0b047 /src | |
parent | eb7d09b0b7bf2e5cb3bb4ab0b5a1c6def37395f9 (diff) |
Core/SAI: Change SmartScript::GetTargets to return an ObjectList instead of a ObjectList*
Applied the same treatment to GetWorldObjectsInDist
Honestly no idea why the original idea insisted so much
on using pointers. No more missing null checks or deletes.
SmartAI's "ObjectList" is now a std::vector instead of a std::list
because no where it was being used as an actual list.
Original idea by DDuarte :P
(cherry picked from commit a97439e8d63c0a78bda8a6ed4801f122385936e3)
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartAI.cpp | 20 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.cpp | 1987 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.h | 42 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.cpp | 130 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.h | 84 |
5 files changed, 780 insertions, 1483 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 065ca31bee0..a99fb660383 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -236,12 +236,12 @@ void SmartAI::EndPath(bool fail) else GetScript()->SetPathId(0); - ObjectList* targets = GetScript()->GetTargetList(SMART_ESCORT_TARGETS); + ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS); if (targets && mEscortQuestID) { if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin()))) { - Player* player = (*targets->begin())->ToPlayer(); + Player* player = targets->front()->ToPlayer(); if (!fail && player->IsAtGroupRewardDistance(me) && !player->HasCorpse()) player->GroupEventHappens(mEscortQuestID, me); @@ -265,11 +265,11 @@ void SmartAI::EndPath(bool fail) } else { - for (ObjectList::iterator iter = targets->begin(); iter != targets->end(); ++iter) + for (WorldObject* target : *targets) { - if (GetScript()->IsPlayer((*iter))) + if (GetScript()->IsPlayer(target)) { - Player* player = (*iter)->ToPlayer(); + Player* player = target->ToPlayer(); if (!fail && player->IsAtGroupRewardDistance(me) && !player->HasCorpse()) player->AreaExploredOrEventHappens(mEscortQuestID); else if (fail) @@ -278,6 +278,7 @@ void SmartAI::EndPath(bool fail) } } } + if (mDespawnState == 1) StartDespawn(); } @@ -409,8 +410,7 @@ void SmartAI::UpdateAI(uint32 diff) bool SmartAI::IsEscortInvokerInRange() { - ObjectList* targets = GetScript()->GetTargetList(SMART_ESCORT_TARGETS); - if (targets) + if (ObjectVector const* targets = GetScript()->GetStoredTargetVector(SMART_ESCORT_TARGETS)) { float checkDist = me->GetInstanceScript() ? SMART_ESCORT_MAX_PLAYER_DIST * 2 : SMART_ESCORT_MAX_PLAYER_DIST; if (targets->size() == 1 && GetScript()->IsPlayer((*targets->begin()))) @@ -431,11 +431,11 @@ bool SmartAI::IsEscortInvokerInRange() } else { - for (ObjectList::iterator iter = targets->begin(); iter != targets->end(); ++iter) + for (WorldObject* target : *targets) { - if (GetScript()->IsPlayer((*iter))) + if (GetScript()->IsPlayer(target)) { - if (me->GetDistance((*iter)->ToPlayer()) <= checkDist) + if (me->GetDistance(target->ToPlayer()) <= checkDist) return true; } } diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index a1c6d3af9b6..39ce2b88022 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -50,7 +50,6 @@ SmartScript::SmartScript() sceneTemplate = nullptr; mEventPhase = 0; mPathId = 0; - mTargetStorage = new ObjectListMap(); mTextTimer = 0; mLastTextID = 0; mUseTextTimer = false; @@ -62,11 +61,6 @@ SmartScript::SmartScript() SmartScript::~SmartScript() { - for (ObjectListMap::iterator itr = mTargetStorage->begin(); itr != mTargetStorage->end(); ++itr) - delete itr->second; - - delete mTargetStorage; - mCounterList.clear(); } bool SmartScript::IsSmart(Creature* c /*= NULL*/) @@ -98,31 +92,6 @@ bool SmartScript::IsSmartGO(GameObject* g /*= NULL*/) return smart; } -void SmartScript::StoreTargetList(ObjectList* targets, uint32 id) -{ - if (!targets) - return; - - if (mTargetStorage->find(id) != mTargetStorage->end()) - { - // check if already stored - if ((*mTargetStorage)[id]->Equals(targets)) - return; - - delete (*mTargetStorage)[id]; - } - - (*mTargetStorage)[id] = new ObjectGuidList(targets, GetBaseObject()); -} - -ObjectList* SmartScript::GetTargetList(uint32 id) -{ - ObjectListMap::iterator itr = mTargetStorage->find(id); - if (itr != mTargetStorage->end()) - return (*itr).second->GetObjectList(); - return NULL; -} - void SmartScript::StoreCounter(uint32 id, uint32 value, uint32 reset) { CounterMap::iterator itr = mCounterList.find(id); @@ -231,7 +200,7 @@ void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint3 void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob, std::string const& varString) { - //calc random + // calc random if (e.GetEventType() != SMART_EVENT_LINK && e.event.event_chance < 100 && e.event.event_chance) { if (!roll_chance_i(e.event.event_chance)) @@ -245,38 +214,35 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (Unit* tempInvoker = GetLastInvoker()) TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: Invoker: %s (%s)", tempInvoker->GetName().c_str(), tempInvoker->GetGUID().ToString().c_str()); + ObjectVector targets; + GetTargets(targets, e, unit); + switch (e.GetActionType()) { case SMART_ACTION_TALK: { - ObjectList* targets = GetTargets(e, unit); Creature* talker = e.target.type == 0 ? me : nullptr; Unit* talkTarget = nullptr; - if (targets) + for (WorldObject* target : targets) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsCreature(target) && !target->ToCreature()->IsPet()) // Prevented sending text to pets. { - if (IsCreature(*itr) && !(*itr)->ToCreature()->IsPet()) // Prevented sending text to pets. - { - if (e.action.talk.useTalkTarget) - { - talker = me; - talkTarget = (*itr)->ToCreature(); - } - else - talker = (*itr)->ToCreature(); - break; - } - else if (IsPlayer(*itr)) + if (e.action.talk.useTalkTarget) { talker = me; - talkTarget = (*itr)->ToPlayer(); - break; + talkTarget = target->ToCreature(); } + else + talker = target->ToCreature(); + break; + } + else if (IsPlayer(target)) + { + talker = me; + talkTarget = target->ToPlayer(); + break; } - - delete targets; } if (!talkTarget) @@ -296,107 +262,79 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_SIMPLE_TALK: { - ObjectList* targets = GetTargets(e, unit); - if (targets) + for (WorldObject* target : targets) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsCreature(target)) + sCreatureTextMgr->SendChat(target->ToCreature(), uint8(e.action.talk.textGroupID), IsPlayer(GetLastInvoker()) ? GetLastInvoker() : 0); + else if (IsPlayer(target) && me) { - if (IsCreature(*itr)) - sCreatureTextMgr->SendChat((*itr)->ToCreature(), uint8(e.action.talk.textGroupID), IsPlayer(GetLastInvoker()) ? GetLastInvoker() : 0); - else if (IsPlayer(*itr) && me) - { - Unit* templastInvoker = GetLastInvoker(); - sCreatureTextMgr->SendChat(me, uint8(e.action.talk.textGroupID), IsPlayer(templastInvoker) ? templastInvoker : 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, (*itr)->ToPlayer()); - } - TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SIMPLE_TALK: talker: %s (%s), textGroupId: %u", - (*itr)->GetName().c_str(), (*itr)->GetGUID().ToString().c_str(), uint8(e.action.talk.textGroupID)); + Unit* templastInvoker = GetLastInvoker(); + sCreatureTextMgr->SendChat(me, uint8(e.action.talk.textGroupID), IsPlayer(templastInvoker) ? templastInvoker : 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, target->ToPlayer()); } - - delete targets; + TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SIMPLE_TALK: talker: %s (%s), textGroupId: %u", + target->GetName().c_str(), target->GetGUID().ToString().c_str(), uint8(e.action.talk.textGroupID)); } break; } case SMART_ACTION_PLAY_EMOTE: { - ObjectList* targets = GetTargets(e, unit); - if (targets) + for (WorldObject* target : targets) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsUnit(target)) { - if (IsUnit(*itr)) - { - (*itr)->ToUnit()->HandleEmoteCommand(e.action.emote.emote); - TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_PLAY_EMOTE: target: %s (%s), emote: %u", - (*itr)->GetName().c_str(), (*itr)->GetGUID().ToString().c_str(), e.action.emote.emote); - } + target->ToUnit()->HandleEmoteCommand(e.action.emote.emote); + TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_PLAY_EMOTE: target: %s (%s), emote: %u", + target->GetName().c_str(), target->GetGUID().ToString().c_str(), e.action.emote.emote); } - - delete targets; } break; } case SMART_ACTION_SOUND: { - ObjectList* targets = GetTargets(e, unit); - if (targets) + for (WorldObject* target : targets) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsUnit(target)) { - if (IsUnit(*itr)) - { - (*itr)->PlayDirectSound(e.action.sound.sound, e.action.sound.onlySelf ? (*itr)->ToPlayer() : nullptr); - TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SOUND: target: %s (%s), sound: %u, onlyself: %u", - (*itr)->GetName().c_str(), (*itr)->GetGUID().ToString().c_str(), e.action.sound.sound, e.action.sound.onlySelf); - } + target->PlayDirectSound(e.action.sound.sound, e.action.sound.onlySelf ? target->ToPlayer() : nullptr); + TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SOUND: target: %s (%s), sound: %u, onlyself: %u", + target->GetName().c_str(), target->GetGUID().ToString().c_str(), e.action.sound.sound, e.action.sound.onlySelf); } - - delete targets; } break; } case SMART_ACTION_SET_FACTION: { - ObjectList* targets = GetTargets(e, unit); - if (targets) + for (WorldObject* target : targets) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsCreature(target)) { - if (IsCreature(*itr)) + if (e.action.faction.factionID) { - if (e.action.faction.factionID) - { - (*itr)->ToCreature()->SetFaction(e.action.faction.factionID); - TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry %u, %s set faction to %u", - (*itr)->GetEntry(), (*itr)->GetGUID().ToString().c_str(), e.action.faction.factionID); - } - else + target->ToCreature()->SetFaction(e.action.faction.factionID); + TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry %u, %s set faction to %u", + target->GetEntry(), target->GetGUID().ToString().c_str(), e.action.faction.factionID); + } + else + { + if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(target->ToCreature()->GetEntry())) { - if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate((*itr)->ToCreature()->GetEntry())) + if (target->ToCreature()->GetFaction() != ci->faction) { - if ((*itr)->ToCreature()->GetFaction() != ci->faction) - { - (*itr)->ToCreature()->SetFaction(ci->faction); - TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry %u, %s set faction to %u", - (*itr)->GetEntry(), (*itr)->GetGUID().ToString().c_str(), ci->faction); - } + target->ToCreature()->SetFaction(ci->faction); + TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_FACTION: Creature entry %u, %s set faction to %u", + target->GetEntry(), target->GetGUID().ToString().c_str(), ci->faction); } } } } - - delete targets; } break; } case SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (!IsCreature(*itr)) + if (!IsCreature(target)) continue; if (e.action.morphOrMount.creature || e.action.morphOrMount.model) @@ -407,143 +345,99 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(e.action.morphOrMount.creature)) { CreatureModel const* model = ObjectMgr::ChooseDisplayId(ci); - (*itr)->ToCreature()->SetDisplayId(model->CreatureDisplayID, model->DisplayScale); + target->ToCreature()->SetDisplayId(model->CreatureDisplayID, model->DisplayScale); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, %s set displayid to %u", - (*itr)->GetEntry(), (*itr)->GetGUID().ToString().c_str(), model->CreatureDisplayID); + target->GetEntry(), target->GetGUID().ToString().c_str(), model->CreatureDisplayID); } } //if no param1, then use value from param2 (modelId) else { - (*itr)->ToCreature()->SetDisplayId(e.action.morphOrMount.model); + target->ToCreature()->SetDisplayId(e.action.morphOrMount.model); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, %s set displayid to %u", - (*itr)->GetEntry(), (*itr)->GetGUID().ToString().c_str(), e.action.morphOrMount.model); + target->GetEntry(), target->GetGUID().ToString().c_str(), e.action.morphOrMount.model); } } else { - (*itr)->ToCreature()->DeMorph(); + target->ToCreature()->DeMorph(); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, %s demorphs.", - (*itr)->GetEntry(), (*itr)->GetGUID().ToString().c_str()); + target->GetEntry(), target->GetGUID().ToString().c_str()); } } - - delete targets; break; } case SMART_ACTION_FAIL_QUEST: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsPlayer(*itr)) + if (IsPlayer(target)) { - (*itr)->ToPlayer()->FailQuest(e.action.quest.quest); + target->ToPlayer()->FailQuest(e.action.quest.quest); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_FAIL_QUEST: Player %s fails quest %u", - (*itr)->GetGUID().ToString().c_str(), e.action.quest.quest); + target->GetGUID().ToString().c_str(), e.action.quest.quest); } } - - delete targets; break; } case SMART_ACTION_OFFER_QUEST: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (Player* pTarget = (*itr)->ToPlayer()) + if (Player* player = target->ToPlayer()) { if (Quest const* q = sObjectMgr->GetQuestTemplate(e.action.questOffer.questID)) { if (me && e.action.questOffer.directAdd == 0) { - if (pTarget->CanTakeQuest(q, true)) - if (WorldSession* session = pTarget->GetSession()) + if (player->CanTakeQuest(q, true)) + { + if (WorldSession* session = player->GetSession()) { PlayerMenu menu(session); menu.SendQuestGiverQuestDetails(q, me->GetGUID(), true, false); - TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_OFFER_QUEST: Player %s - offering quest %u", pTarget->GetGUID().ToString().c_str(), e.action.questOffer.questID); + TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_OFFER_QUEST: Player %s - offering quest %u", player->GetGUID().ToString().c_str(), e.action.questOffer.questID); } + } } else { - (*itr)->ToPlayer()->AddQuestAndCheckCompletion(q, nullptr); - TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_ADD_QUEST: Player %s add quest %u", - (*itr)->GetGUID().ToString().c_str(), e.action.questOffer.questID); + player->AddQuestAndCheckCompletion(q, nullptr); + TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_OFFER_QUEST: Player %s - quest %u added", + player->GetGUID().ToString().c_str(), e.action.questOffer.questID); } } } } - - delete targets; break; } case SMART_ACTION_SET_REACT_STATE: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (!IsCreature(*itr)) + if (!IsCreature(target)) continue; - (*itr)->ToCreature()->SetReactState(ReactStates(e.action.react.state)); + target->ToCreature()->SetReactState(ReactStates(e.action.react.state)); } - - delete targets; break; } case SMART_ACTION_RANDOM_EMOTE: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + std::vector<uint32> emotes; + std::copy_if(e.action.randomEmote.emotes.begin(), e.action.randomEmote.emotes.end(), + std::back_inserter(emotes), [](uint32 emote) { return emote != 0; }); - uint32 emotes[SMART_ACTION_PARAM_COUNT]; - emotes[0] = e.action.randomEmote.emote1; - emotes[1] = e.action.randomEmote.emote2; - emotes[2] = e.action.randomEmote.emote3; - emotes[3] = e.action.randomEmote.emote4; - emotes[4] = e.action.randomEmote.emote5; - emotes[5] = e.action.randomEmote.emote6; - uint32 temp[SMART_ACTION_PARAM_COUNT]; - uint32 count = 0; - for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++) + for (WorldObject* target : targets) { - if (emotes[i]) + if (IsUnit(target)) { - temp[count] = emotes[i]; - ++count; - } - } - - if (count == 0) - { - delete targets; - break; - } - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsUnit(*itr)) - { - uint32 emote = temp[urand(0, count - 1)]; - (*itr)->ToUnit()->HandleEmoteCommand(emote); + uint32 emote = Trinity::Containers::SelectRandomContainerElement(emotes); + target->ToUnit()->HandleEmoteCommand(emote); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_RANDOM_EMOTE: Creature %s handle random emote %u", - (*itr)->GetGUID().ToString().c_str(), emote); + target->GetGUID().ToString().c_str(), emote); } } - - delete targets; break; } case SMART_ACTION_THREAT_ALL_PCT: @@ -552,7 +446,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u break; ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i) + for (auto i = threatList.begin(); i != threatList.end(); ++i) { if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) { @@ -569,72 +463,57 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!me) break; - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsUnit(*itr)) + if (IsUnit(target)) { - me->getThreatManager().modifyThreatPercent((*itr)->ToUnit(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); + me->getThreatManager().modifyThreatPercent(target->ToUnit(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_SINGLE_PCT: Creature %s modify threat for %s, value %i", - me->GetGUID().ToString().c_str(), (*itr)->GetGUID().ToString().c_str(), + me->GetGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); } } - - delete targets; break; } case SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { // Special handling for vehicles - if (IsUnit(*itr)) - if (Vehicle* vehicle = (*itr)->ToUnit()->GetVehicleKit()) + if (IsUnit(target)) + if (Vehicle* vehicle = target->ToUnit()->GetVehicleKit()) for (SeatMap::iterator it = vehicle->Seats.begin(); it != vehicle->Seats.end(); ++it) - if (Player* player = ObjectAccessor::GetPlayer(*(*itr), it->second.Passenger.Guid)) + if (Player* player = ObjectAccessor::GetPlayer(*target, it->second.Passenger.Guid)) player->AreaExploredOrEventHappens(e.action.quest.quest); - if (IsPlayer(*itr)) + if (IsPlayer(target)) { - (*itr)->ToPlayer()->AreaExploredOrEventHappens(e.action.quest.quest); + target->ToPlayer()->AreaExploredOrEventHappens(e.action.quest.quest); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS: %s credited quest %u", - (*itr)->GetGUID().ToString().c_str(), e.action.quest.quest); + target->GetGUID().ToString().c_str(), e.action.quest.quest); } } - - delete targets; break; } case SMART_ACTION_CAST: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) + if (targets.empty()) break; - if (e.action.cast.targetsLimit > 0 && targets->size() > e.action.cast.targetsLimit) - Trinity::Containers::RandomResize(*targets, e.action.cast.targetsLimit); + if (e.action.cast.targetsLimit > 0 && targets.size() > e.action.cast.targetsLimit) + Trinity::Containers::RandomResize(targets, e.action.cast.targetsLimit); - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { + // may be nullptr if (go) - { - // may be nullptr - go->CastSpell((*itr)->ToUnit(), e.action.cast.spell); - } + go->CastSpell(target->ToUnit(), e.action.cast.spell); - if (!IsUnit(*itr)) + if (!IsUnit(target)) continue; - if (!(e.action.cast.castFlags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell)) + if (!(e.action.cast.castFlags & SMARTCAST_AURA_NOT_PRESENT) || !target->ToUnit()->HasAura(e.action.cast.spell)) { TriggerCastFlags triggerFlag = TRIGGERED_NONE; if (e.action.cast.castFlags & SMARTCAST_TRIGGERED) @@ -655,7 +534,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u // If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed // unless target is outside spell range, out of mana, or LOS. - bool _allowMove = false; + bool allowMove = false; SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(e.action.cast.spell, me->GetMap()->GetDifficultyID()); std::vector<SpellPowerCost> costs = spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask()); bool hasPower = true; @@ -680,27 +559,25 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } - if (me->GetDistance(*itr) > spellInfo->GetMaxRange(true) || - me->GetDistance(*itr) < spellInfo->GetMinRange(true) || - !me->IsWithinLOSInMap(*itr) || !hasPower) - _allowMove = true; + if (me->GetDistance(target) > spellInfo->GetMaxRange(true) || + me->GetDistance(target) < spellInfo->GetMinRange(true) || + !me->IsWithinLOSInMap(target) || !hasPower) + allowMove = true; - ENSURE_AI(SmartAI, me->AI())->SetCombatMove(_allowMove); + ENSURE_AI(SmartAI, me->AI())->SetCombatMove(allowMove); } - me->CastSpell((*itr)->ToUnit(), e.action.cast.spell, triggerFlag); + me->CastSpell(target->ToUnit(), e.action.cast.spell, triggerFlag); } else if (go) - go->CastSpell((*itr)->ToUnit(), e.action.cast.spell, triggerFlag); + go->CastSpell(target->ToUnit(), e.action.cast.spell, triggerFlag); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CAST:: %s casts spell %u on target %s with castflags %u", - (me ? me->GetGUID() : go->GetGUID()).ToString().c_str(), e.action.cast.spell, (*itr)->GetGUID().ToString().c_str(), e.action.cast.castFlags); + (me ? me->GetGUID() : go->GetGUID()).ToString().c_str(), e.action.cast.spell, target->GetGUID().ToString().c_str(), e.action.cast.castFlags); } else - TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (%s) already has the aura", e.action.cast.spell, (*itr)->GetGUID().ToString().c_str()); + TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (%s) already has the aura", e.action.cast.spell, target->GetGUID().ToString().c_str()); } - - delete targets; break; } case SMART_ACTION_INVOKER_CAST: @@ -709,19 +586,18 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!tempLastInvoker) break; - ObjectList* targets = GetTargets(e, unit); - if (!targets) + if (targets.empty()) break; - if (e.action.cast.targetsLimit > 0 && targets->size() > e.action.cast.targetsLimit) - Trinity::Containers::RandomResize(*targets, e.action.cast.targetsLimit); + if (e.action.cast.targetsLimit > 0 && targets.size() > e.action.cast.targetsLimit) + Trinity::Containers::RandomResize(targets, e.action.cast.targetsLimit); - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (!IsUnit(*itr)) + if (!IsUnit(target)) continue; - if (!(e.action.cast.castFlags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell)) + if (!(e.action.cast.castFlags & SMARTCAST_AURA_NOT_PRESENT) || !target->ToUnit()->HasAura(e.action.cast.spell)) { if (e.action.cast.castFlags & SMARTCAST_INTERRUPT_PREVIOUS) tempLastInvoker->InterruptNonMeleeSpells(false); @@ -735,149 +611,111 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u triggerFlag = TRIGGERED_FULL_MASK; } - tempLastInvoker->CastSpell((*itr)->ToUnit(), e.action.cast.spell, triggerFlag); + tempLastInvoker->CastSpell(target->ToUnit(), e.action.cast.spell, triggerFlag); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_INVOKER_CAST: Invoker %s casts spell %u on target %s with castflags %u", - tempLastInvoker->GetGUID().ToString().c_str(), e.action.cast.spell, (*itr)->GetGUID().ToString().c_str(), e.action.cast.castFlags); + tempLastInvoker->GetGUID().ToString().c_str(), e.action.cast.spell, target->GetGUID().ToString().c_str(), e.action.cast.castFlags); } else - TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (%s) already has the aura", e.action.cast.spell, (*itr)->GetGUID().ToString().c_str()); + TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (%s) already has the aura", e.action.cast.spell, target->GetGUID().ToString().c_str()); } - - delete targets; break; } case SMART_ACTION_ADD_AURA: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsUnit(*itr)) + if (IsUnit(target)) { - (*itr)->ToUnit()->AddAura(e.action.cast.spell, (*itr)->ToUnit()); + target->ToUnit()->AddAura(e.action.cast.spell, target->ToUnit()); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_ADD_AURA: Adding aura %u to %s", - e.action.cast.spell, (*itr)->GetGUID().ToString().c_str()); + e.action.cast.spell, target->GetGUID().ToString().c_str()); } } - - delete targets; break; } case SMART_ACTION_ACTIVATE_GOBJECT: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsGameObject(*itr)) + if (IsGameObject(target)) { // Activate - (*itr)->ToGameObject()->SetLootState(GO_READY); - (*itr)->ToGameObject()->UseDoorOrButton(0, false, unit); + target->ToGameObject()->SetLootState(GO_READY); + target->ToGameObject()->UseDoorOrButton(0, false, unit); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_ACTIVATE_GOBJECT. %s (entry: %u) activated", - (*itr)->GetGUID().ToString().c_str(), (*itr)->GetEntry()); + target->GetGUID().ToString().c_str(), target->GetEntry()); } } - - delete targets; break; } case SMART_ACTION_RESET_GOBJECT: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsGameObject(*itr)) + if (IsGameObject(target)) { - (*itr)->ToGameObject()->ResetDoorOrButton(); + target->ToGameObject()->ResetDoorOrButton(); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_RESET_GOBJECT. %s (entry: %u) reset", - (*itr)->GetGUID().ToString().c_str(), (*itr)->GetEntry()); + target->GetGUID().ToString().c_str(), target->GetEntry()); } } - - delete targets; break; } case SMART_ACTION_SET_EMOTE_STATE: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsUnit(*itr)) + if (IsUnit(target)) { - (*itr)->ToUnit()->SetEmoteState(Emote(e.action.emote.emote)); + target->ToUnit()->SetEmoteState(Emote(e.action.emote.emote)); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_EMOTE_STATE. %s set emotestate to %u", - (*itr)->GetGUID().ToString().c_str(), e.action.emote.emote); + target->GetGUID().ToString().c_str(), e.action.emote.emote); } } - - delete targets; break; } case SMART_ACTION_SET_UNIT_FLAG: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsUnit(*itr)) + if (IsUnit(target)) { if (!e.action.unitFlag.type) { - (*itr)->ToUnit()->AddUnitFlag(UnitFlags(e.action.unitFlag.flag)); + target->ToUnit()->AddUnitFlag(UnitFlags(e.action.unitFlag.flag)); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. %s added flag %u to UNIT_FIELD_FLAGS", - (*itr)->GetGUID().ToString().c_str(), e.action.unitFlag.flag); + target->GetGUID().ToString().c_str(), e.action.unitFlag.flag); } else { - (*itr)->ToUnit()->AddUnitFlag2(UnitFlags2(e.action.unitFlag.flag)); + target->ToUnit()->AddUnitFlag2(UnitFlags2(e.action.unitFlag.flag)); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. %s added flag %u to UNIT_FIELD_FLAGS_2", - (*itr)->GetGUID().ToString().c_str(), e.action.unitFlag.flag); + target->GetGUID().ToString().c_str(), e.action.unitFlag.flag); } } } - - delete targets; break; } case SMART_ACTION_REMOVE_UNIT_FLAG: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsUnit(*itr)) + if (IsUnit(target)) { if (!e.action.unitFlag.type) { - (*itr)->ToUnit()->RemoveUnitFlag(UnitFlags(e.action.unitFlag.flag)); + target->ToUnit()->RemoveUnitFlag(UnitFlags(e.action.unitFlag.flag)); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. %s removed flag %u to UNIT_FIELD_FLAGS", - (*itr)->GetGUID().ToString().c_str(), e.action.unitFlag.flag); + target->GetGUID().ToString().c_str(), e.action.unitFlag.flag); } else { - (*itr)->ToUnit()->RemoveUnitFlag2(UnitFlags2(e.action.unitFlag.flag)); + target->ToUnit()->RemoveUnitFlag2(UnitFlags2(e.action.unitFlag.flag)); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. %s removed flag %u to UNIT_FIELD_FLAGS_2", - (*itr)->GetGUID().ToString().c_str(), e.action.unitFlag.flag); + target->GetGUID().ToString().c_str(), e.action.unitFlag.flag); } } } - - delete targets; break; } case SMART_ACTION_AUTO_ATTACK: @@ -978,33 +816,27 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_REMOVEAURASFROMSPELL: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (!IsUnit(*itr)) + if (!IsUnit(target)) continue; if (e.action.removeAura.spell) { if (e.action.removeAura.charges) { - if (Aura* aur = (*itr)->ToUnit()->GetAura(e.action.removeAura.spell)) + if (Aura* aur = target->ToUnit()->GetAura(e.action.removeAura.spell)) aur->ModCharges(-static_cast<int32>(e.action.removeAura.charges), AURA_REMOVE_BY_EXPIRE); } else - (*itr)->ToUnit()->RemoveAurasDueToSpell(e.action.removeAura.spell); + target->ToUnit()->RemoveAurasDueToSpell(e.action.removeAura.spell); } else - (*itr)->ToUnit()->RemoveAllAuras(); + target->ToUnit()->RemoveAllAuras(); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_REMOVEAURASFROMSPELL: %s, spell %u", - (*itr)->GetGUID().ToString().c_str(), e.action.removeAura.spell); + target->GetGUID().ToString().c_str(), e.action.removeAura.spell); } - - delete targets; break; } case SMART_ACTION_FOLLOW: @@ -1012,26 +844,23 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!IsSmart()) break; - ObjectList* targets = GetTargets(e, unit); - if (!targets) + if (targets.empty()) { ENSURE_AI(SmartAI, me->AI())->StopFollow(false); break; } - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsUnit(*itr)) + if (IsUnit(target)) { float angle = e.action.follow.angle > 6 ? (e.action.follow.angle * M_PI / 180.0f) : e.action.follow.angle; - ENSURE_AI(SmartAI, me->AI())->SetFollow((*itr)->ToUnit(), float(e.action.follow.dist) + 0.1f, angle, e.action.follow.credit, e.action.follow.entry, e.action.follow.creditType); + ENSURE_AI(SmartAI, me->AI())->SetFollow(target->ToUnit(), float(e.action.follow.dist) + 0.1f, angle, e.action.follow.credit, e.action.follow.entry, e.action.follow.creditType); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_FOLLOW: %s following target %s", - me->GetGUID().ToString().c_str(), (*itr)->GetGUID().ToString().c_str()); + me->GetGUID().ToString().c_str(), target->GetGUID().ToString().c_str()); break; } } - - delete targets; break; } case SMART_ACTION_RANDOM_PHASE: @@ -1039,28 +868,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!GetBaseObject()) break; - uint32 phases[SMART_ACTION_PARAM_COUNT]; - phases[0] = e.action.randomPhase.phase1; - phases[1] = e.action.randomPhase.phase2; - phases[2] = e.action.randomPhase.phase3; - phases[3] = e.action.randomPhase.phase4; - phases[4] = e.action.randomPhase.phase5; - phases[5] = e.action.randomPhase.phase6; - uint32 temp[SMART_ACTION_PARAM_COUNT]; - uint32 count = 0; - for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++) - { - if (phases[i] > 0) - { - temp[count] = phases[i]; - ++count; - } - } + std::vector<uint32> phases; + std::copy_if(e.action.randomPhase.phases.begin(), e.action.randomPhase.phases.end(), + std::back_inserter(phases), [](uint32 phase) { return phase != 0; }); - if (count == 0) - break; - - uint32 phase = temp[urand(0, count - 1)]; + uint32 phase = Trinity::Containers::SelectRandomContainerElement(phases); SetPhase(phase); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_RANDOM_PHASE: %s sets event phase to %u", GetBaseObject()->GetGUID().ToString().c_str(), phase); @@ -1093,26 +905,20 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } else // Specific target type { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsPlayer(*itr)) + if (IsPlayer(target)) { - (*itr)->ToPlayer()->KilledMonsterCredit(e.action.killedMonster.creature); + target->ToPlayer()->KilledMonsterCredit(e.action.killedMonster.creature); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_KILLEDMONSTER: %s, Killcredit: %u", - (*itr)->GetGUID().ToString().c_str(), e.action.killedMonster.creature); + target->GetGUID().ToString().c_str(), e.action.killedMonster.creature); } - else if (IsUnit(*itr)) // Special handling for vehicles - if (Vehicle* vehicle = (*itr)->ToUnit()->GetVehicleKit()) + else if (IsUnit(target)) // Special handling for vehicles + if (Vehicle* vehicle = target->ToUnit()->GetVehicleKit()) for (SeatMap::iterator seatItr = vehicle->Seats.begin(); seatItr != vehicle->Seats.end(); ++seatItr) - if (Player* player = ObjectAccessor::GetPlayer(*(*itr), seatItr->second.Passenger.Guid)) + if (Player* player = ObjectAccessor::GetPlayer(*target, seatItr->second.Passenger.Guid)) player->KilledMonsterCredit(e.action.killedMonster.creature); } - - delete targets; } break; } @@ -1165,29 +971,19 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u break; } - ObjectList* targets = GetTargets(e, unit); - if (!targets) + if (targets.empty()) break; - instance->SetGuidData(e.action.setInstanceData64.field, targets->front()->GetGUID()); + instance->SetGuidData(e.action.setInstanceData64.field, targets.front()->GetGUID()); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA64: Field: %u, data: %s", - e.action.setInstanceData64.field, targets->front()->GetGUID().ToString().c_str()); - - delete targets; + e.action.setInstanceData64.field, targets.front()->GetGUID().ToString().c_str()); break; } case SMART_ACTION_UPDATE_TEMPLATE: { - ObjectList* targets = GetTargets(e, unit); - - if (!targets) - break; - - for (WorldObject* target : *targets) + for (WorldObject* target : targets) if (IsCreature(target)) target->ToCreature()->UpdateEntry(e.action.updateTemplate.creature, target->ToCreature()->GetCreatureData(), e.action.updateTemplate.updateLevel != 0); - - delete targets; break; } case SMART_ACTION_DIE: @@ -1201,39 +997,31 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) + for (WorldObject* target : targets) + { + if (IsCreature(target)) { - (*itr)->ToCreature()->SetInCombatWithZone(); - TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: Creature %s, target: %s", me->GetGUID().ToString().c_str(), (*itr)->GetGUID().ToString().c_str()); + target->ToCreature()->SetInCombatWithZone(); + TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: Creature %s, target: %s", me->GetGUID().ToString().c_str(), target->GetGUID().ToString().c_str()); } - - delete targets; + } break; } case SMART_ACTION_CALL_FOR_HELP: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) + for (WorldObject* target : targets) + { + if (IsCreature(target)) { - (*itr)->ToCreature()->CallForHelp((float)e.action.callHelp.range); + target->ToCreature()->CallForHelp(float(e.action.callHelp.range)); if (e.action.callHelp.withEmote) { Trinity::BroadcastTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, BROADCAST_TEXT_CALL_FOR_HELP, me->getGender()); sCreatureTextMgr->SendChatPacket(me, builder, CHAT_MSG_MONSTER_EMOTE); } - TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_FOR_HELP: Creature %s, target: %s", me->GetGUID().ToString().c_str(), (*itr)->GetGUID().ToString().c_str()); + TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_FOR_HELP: Creature %s, target: %s", me->GetGUID().ToString().c_str(), target->GetGUID().ToString().c_str()); } - - delete targets; + } break; } case SMART_ACTION_SET_SHEATH: @@ -1248,78 +1036,53 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_FORCE_DESPAWN: { - ObjectList* targets = GetTargets(e, unit); - - if (!targets) - break; - // there should be at least a world update tick before despawn, to avoid breaking linked actions int32 const respawnDelay = std::max<int32>(e.action.forceDespawn.delay, 1); - for (WorldObject* target : *targets) + for (WorldObject* target : targets) { - if (Creature* creatureTarget = target->ToCreature()) + if (Creature* creature = target->ToCreature()) { - if (SmartAI* smartAI = CAST_AI(SmartAI, creatureTarget->AI())) + if (SmartAI* smartAI = CAST_AI(SmartAI, creature->AI())) { smartAI->SetDespawnTime(respawnDelay); smartAI->StartDespawn(); } else - creatureTarget->DespawnOrUnsummon(respawnDelay); + creature->DespawnOrUnsummon(respawnDelay); } - else if (GameObject* goTarget = target->ToGameObject()) - goTarget->SetRespawnTime(respawnDelay); + else if (GameObject* go = target->ToGameObject()) + go->SetRespawnTime(respawnDelay); } - - delete targets; break; } case SMART_ACTION_SET_INGAME_PHASE_ID: { - ObjectList* targets = GetTargets(e, unit); - - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { if (e.action.ingamePhaseId.apply == 1) - PhasingHandler::AddPhase(*itr, e.action.ingamePhaseId.id, true); + PhasingHandler::AddPhase(target, e.action.ingamePhaseId.id, true); else - PhasingHandler::RemovePhase(*itr, e.action.ingamePhaseId.id, true); + PhasingHandler::RemovePhase(target, e.action.ingamePhaseId.id, true); } - - delete targets; break; } case SMART_ACTION_SET_INGAME_PHASE_GROUP: { - ObjectList* targets = GetTargets(e, unit); - - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { if (e.action.ingamePhaseGroup.apply == 1) - PhasingHandler::AddPhaseGroup(*itr, e.action.ingamePhaseGroup.groupId, true); + PhasingHandler::AddPhaseGroup(target, e.action.ingamePhaseGroup.groupId, true); else - PhasingHandler::RemovePhaseGroup(*itr, e.action.ingamePhaseGroup.groupId, true); + PhasingHandler::RemovePhaseGroup(target, e.action.ingamePhaseGroup.groupId, true); } - - delete targets; break; } case SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (!IsUnit(*itr)) + if (!IsUnit(target)) continue; if (e.action.morphOrMount.creature || e.action.morphOrMount.model) @@ -1327,110 +1090,78 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (e.action.morphOrMount.creature > 0) { if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(e.action.morphOrMount.creature)) - (*itr)->ToUnit()->Mount(ObjectMgr::ChooseDisplayId(cInfo)->CreatureDisplayID); + target->ToUnit()->Mount(ObjectMgr::ChooseDisplayId(cInfo)->CreatureDisplayID); } else - (*itr)->ToUnit()->Mount(e.action.morphOrMount.model); + target->ToUnit()->Mount(e.action.morphOrMount.model); } else - (*itr)->ToUnit()->Dismount(); + target->ToUnit()->Dismount(); } - - delete targets; break; } case SMART_ACTION_SET_INVINCIBILITY_HP_LEVEL: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsCreature(*itr)) + if (IsCreature(target)) { - SmartAI* ai = CAST_AI(SmartAI, (*itr)->ToCreature()->AI()); + SmartAI* ai = CAST_AI(SmartAI, target->ToCreature()->AI()); if (!ai) continue; if (e.action.invincHP.percent) - ai->SetInvincibilityHpLevel((*itr)->ToCreature()->CountPctFromMaxHealth(e.action.invincHP.percent)); + ai->SetInvincibilityHpLevel(target->ToCreature()->CountPctFromMaxHealth(e.action.invincHP.percent)); else ai->SetInvincibilityHpLevel(e.action.invincHP.minHP); } } - - delete targets; break; } case SMART_ACTION_SET_DATA: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsCreature(*itr)) - (*itr)->ToCreature()->AI()->SetData(e.action.setData.field, e.action.setData.data); - else if (IsGameObject(*itr)) - (*itr)->ToGameObject()->AI()->SetData(e.action.setData.field, e.action.setData.data); + if (IsCreature(target)) + target->ToCreature()->AI()->SetData(e.action.setData.field, e.action.setData.data); + else if (IsGameObject(target)) + target->ToGameObject()->AI()->SetData(e.action.setData.field, e.action.setData.data); } - - delete targets; break; } case SMART_ACTION_MOVE_OFFSET: { - if (ObjectList* targets = GetTargets(e, unit)) + for (WorldObject* target : targets) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (!IsCreature(*itr)) - continue; + if (!IsCreature(target)) + continue; - if (!(e.event.event_flags & SMART_EVENT_FLAG_WHILE_CHARMED) && IsCharmedCreature(*itr)) - continue; + if (!(e.event.event_flags & SMART_EVENT_FLAG_WHILE_CHARMED) && IsCharmedCreature(target)) + continue; - Position pos = (*itr)->GetPosition(); + Position pos = target->GetPosition(); - // Use forward/backward/left/right cartesian plane movement - float x, y, z, o; - o = pos.GetOrientation(); - x = pos.GetPositionX() + (std::cos(o - (M_PI / 2))*e.target.x) + (std::cos(o)*e.target.y); - y = pos.GetPositionY() + (std::sin(o - (M_PI / 2))*e.target.x) + (std::sin(o)*e.target.y); - z = pos.GetPositionZ() + e.target.z; - (*itr)->ToCreature()->GetMotionMaster()->MovePoint(SMART_RANDOM_POINT, x, y, z); - } - - delete targets; + // Use forward/backward/left/right cartesian plane movement + float x, y, z, o; + o = pos.GetOrientation(); + x = pos.GetPositionX() + (std::cos(o - (M_PI / 2))*e.target.x) + (std::cos(o)*e.target.y); + y = pos.GetPositionY() + (std::sin(o - (M_PI / 2))*e.target.x) + (std::sin(o)*e.target.y); + z = pos.GetPositionZ() + e.target.z; + target->ToCreature()->GetMotionMaster()->MovePoint(SMART_RANDOM_POINT, x, y, z); } - break; } case SMART_ACTION_SET_VISIBILITY: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->SetVisible(e.action.visibility.state ? true : false); - - delete targets; + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->SetVisible(e.action.visibility.state ? true : false); break; } case SMART_ACTION_SET_ACTIVE: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - (*itr)->setActive(e.action.active.state ? true : false); - - delete targets; + for (WorldObject* target : targets) + target->setActive(e.action.active.state ? true : false); break; } case SMART_ACTION_ATTACK_START: @@ -1438,15 +1169,12 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!me) break; - ObjectList* targets = GetTargets(e, unit); - if (!targets) + if (targets.empty()) break; // attack random target - if (Unit * target = Trinity::Containers::SelectRandomContainerElement(*targets)->ToUnit()) + if (Unit * target = Trinity::Containers::SelectRandomContainerElement(targets)->ToUnit()) me->AI()->AttackStart(target); - - delete targets; break; } case SMART_ACTION_SUMMON_CREATURE: @@ -1455,24 +1183,17 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!summoner) break; - ObjectList* targets = GetTargets(e, unit); - - if (targets) + float x, y, z, o; + for (WorldObject* target : targets) { - float x, y, z, o; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - (*itr)->GetPosition(x, y, z, o); - x += e.target.x; - y += e.target.y; - z += e.target.z; - o += e.target.o; - if (Creature* summon = summoner->SummonCreature(e.action.summonCreature.creature, x, y, z, o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration)) - if (e.action.summonCreature.attackInvoker) - summon->AI()->AttackStart((*itr)->ToUnit()); - } - - delete targets; + target->GetPosition(x, y, z, o); + x += e.target.x; + y += e.target.y; + z += e.target.z; + o += e.target.o; + if (Creature* summon = summoner->SummonCreature(e.action.summonCreature.creature, x, y, z, o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration)) + if (e.action.summonCreature.attackInvoker) + summon->AI()->AttackStart(target->ToUnit()); } if (e.GetTargetType() != SMART_TARGET_POSITION) @@ -1489,20 +1210,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!summoner) break; - ObjectList* targets = GetTargets(e, unit); - if (targets) + for (WorldObject* target : targets) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - // allow gameobjects to summon gameobjects - //if (!IsUnit(*itr)) - // continue; - - Position pos = (*itr)->GetPositionWithOffset(Position(e.target.x, e.target.y, e.target.z, e.target.o)); - summoner->SummonGameObject(e.action.summonGO.entry, pos, QuaternionData::fromEulerAnglesZYX(pos.GetOrientation(), 0.f, 0.f), e.action.summonGO.despawnTime); - } - - delete targets; + Position pos = target->GetPositionWithOffset(Position(e.target.x, e.target.y, e.target.z, e.target.o)); + summoner->SummonGameObject(e.action.summonGO.entry, pos, QuaternionData::fromEulerAnglesZYX(pos.GetOrientation(), 0.f, 0.f), e.action.summonGO.despawnTime); } if (e.GetTargetType() != SMART_TARGET_POSITION) @@ -1513,19 +1224,13 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_KILL_UNIT: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (!IsUnit(*itr)) + if (!IsUnit(target)) continue; - (*itr)->ToUnit()->KillSelf(); + target->ToUnit()->KillSelf(); } - - delete targets; break; } case SMART_ACTION_INSTALL_AI_TEMPLATE: @@ -1535,59 +1240,40 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_ADD_ITEM: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (!IsPlayer(*itr)) + if (!IsPlayer(target)) continue; - (*itr)->ToPlayer()->AddItem(e.action.item.entry, e.action.item.count); + target->ToPlayer()->AddItem(e.action.item.entry, e.action.item.count); } - - delete targets; break; } case SMART_ACTION_REMOVE_ITEM: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (!IsPlayer(*itr)) + if (!IsPlayer(target)) continue; - (*itr)->ToPlayer()->DestroyItemCount(e.action.item.entry, e.action.item.count, true); + target->ToPlayer()->DestroyItemCount(e.action.item.entry, e.action.item.count, true); } - - delete targets; break; } case SMART_ACTION_STORE_TARGET_LIST: { - ObjectList* targets = GetTargets(e, unit); StoreTargetList(targets, e.action.storeTargets.id); break; } case SMART_ACTION_TELEPORT: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsPlayer(*itr)) - (*itr)->ToPlayer()->TeleportTo(e.action.teleport.mapID, e.target.x, e.target.y, e.target.z, e.target.o); - else if (IsCreature(*itr)) - (*itr)->ToCreature()->NearTeleportTo(e.target.x, e.target.y, e.target.z, e.target.o); + if (IsPlayer(target)) + target->ToPlayer()->TeleportTo(e.action.teleport.mapID, e.target.x, e.target.y, e.target.z, e.target.o); + else if (IsCreature(target)) + target->ToCreature()->NearTeleportTo(e.target.x, e.target.y, e.target.z, e.target.o); } - - delete targets; break; } case SMART_ACTION_SET_DISABLE_GRAVITY: @@ -1624,31 +1310,28 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_SET_COUNTER: { - if (ObjectList* targets = GetTargets(e, unit)) + if (!targets.empty()) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsCreature(*itr)) + if (IsCreature(target)) { - if (SmartAI* ai = CAST_AI(SmartAI, (*itr)->ToCreature()->AI())) + if (SmartAI* ai = CAST_AI(SmartAI, target->ToCreature()->AI())) ai->GetScript()->StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset); else TC_LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SET_COUNTER is not using SmartAI, skipping"); } - else if (IsGameObject(*itr)) + else if (IsGameObject(target)) { - if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, (*itr)->ToGameObject()->AI())) + if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, target->ToGameObject()->AI())) ai->GetScript()->StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset); else TC_LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SET_COUNTER is not using SmartGameObjectAI, skipping"); } } - - delete targets; } else StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset); - break; } case SMART_ACTION_WP_START: @@ -1660,22 +1343,13 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u uint32 entry = e.action.wpStart.pathID; bool repeat = e.action.wpStart.repeat != 0; - // ensure that SMART_ESCORT_TARGETS contains at least one player reference - bool stored = false; - ObjectList* targets = GetTargets(e, unit); - if (targets) + for (WorldObject* target : targets) { - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsPlayer(target)) { - if (IsPlayer(*itr)) - { - stored = true; - StoreTargetList(targets, SMART_ESCORT_TARGETS); - break; - } + StoreTargetList(targets, SMART_ESCORT_TARGETS); + break; } - if (!stored) - delete targets; } me->SetReactState((ReactStates)e.action.wpStart.reactState); @@ -1724,31 +1398,19 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u me->SetFacingTo((me->GetTransport() ? me->GetTransportHomePosition() : me->GetHomePosition()).GetOrientation()); else if (e.GetTargetType() == SMART_TARGET_POSITION) me->SetFacingTo(e.target.o); - else if (ObjectList* targets = GetTargets(e, unit)) - { - if (!targets->empty()) - me->SetFacingToObject(*targets->begin()); - - delete targets; - } - + else if (!targets.empty()) + me->SetFacingToObject(targets.front()); break; } case SMART_ACTION_PLAYMOVIE: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (!IsPlayer(*itr)) + if (!IsPlayer(target)) continue; - (*itr)->ToPlayer()->SendMovieStart(e.action.movie.entry); + target->ToPlayer()->SendMovieStart(e.action.movie.entry); } - - delete targets; break; } case SMART_ACTION_MOVE_TO_POS: @@ -1765,12 +1427,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u e.GetTargetType() == SMART_TARGET_OWNER_OR_SUMMONER || e.GetTargetType() == SMART_TARGET_ACTION_INVOKER || e.GetTargetType() == SMART_TARGET_CLOSEST_ENEMY || e.GetTargetType() == SMART_TARGET_CLOSEST_FRIENDLY)*/ { - if (ObjectList * targets = GetTargets(e, unit)) - { - // we want to move to random element - target = Trinity::Containers::SelectRandomContainerElement(*targets); - delete targets; - } + // we want to move to random element + if (!targets.empty()) + target = Trinity::Containers::SelectRandomContainerElement(targets); } if (!target) @@ -1794,82 +1453,60 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_RESPAWN_TARGET: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsCreature(*itr)) - (*itr)->ToCreature()->Respawn(); - else if (IsGameObject(*itr)) + if (IsCreature(target)) + target->ToCreature()->Respawn(); + else if (IsGameObject(target)) { // do not modify respawndelay of already spawned gameobjects - if ((*itr)->ToGameObject()->isSpawnedByDefault()) - (*itr)->ToGameObject()->Respawn(); + if (target->ToGameObject()->isSpawnedByDefault()) + target->ToGameObject()->Respawn(); else - (*itr)->ToGameObject()->SetRespawnTime(e.action.RespawnTarget.goRespawnTime); + target->ToGameObject()->SetRespawnTime(e.action.RespawnTarget.goRespawnTime); } } - - delete targets; break; } case SMART_ACTION_CLOSE_GOSSIP: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsPlayer(*itr)) - (*itr)->ToPlayer()->PlayerTalkClass->SendCloseGossip(); - - delete targets; + for (WorldObject* target : targets) + if (IsPlayer(target)) + target->ToPlayer()->PlayerTalkClass->SendCloseGossip(); break; } case SMART_ACTION_EQUIP: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (Creature* npc = (*itr)->ToCreature()) + if (Creature* npc = target->ToCreature()) { - EquipmentItem slot[3]; - int8 equipId = (int8)e.action.equip.entry; - if (equipId) + std::array<EquipmentItem, MAX_EQUIPMENT_ITEMS> slot; + if (int8 equipId = static_cast<int8>(e.action.equip.entry)) { - EquipmentInfo const* einfo = sObjectMgr->GetEquipmentInfo(npc->GetEntry(), equipId); - if (!einfo) + EquipmentInfo const* eInfo = sObjectMgr->GetEquipmentInfo(npc->GetEntry(), equipId); + if (!eInfo) { TC_LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info id %u for creature %u", equipId, npc->GetEntry()); break; } npc->SetCurrentEquipmentId(equipId); - slot[0] = einfo->Items[0]; - slot[1] = einfo->Items[1]; - slot[2] = einfo->Items[2]; + + std::copy(std::begin(eInfo->Items), std::end(eInfo->Items), std::begin(slot)); } else { - slot[0].ItemId = e.action.equip.slot1; - slot[1].ItemId = e.action.equip.slot2; - slot[2].ItemId = e.action.equip.slot3; + slot[0].ItemId = e.action.equip.slots[0]; + slot[1].ItemId = e.action.equip.slots[1]; + slot[2].ItemId = e.action.equip.slots[2]; } - if (!e.action.equip.mask || (e.action.equip.mask & 1)) - npc->SetVirtualItem(0, slot[0].ItemId, slot[0].AppearanceModId, slot[0].ItemVisual); - if (!e.action.equip.mask || (e.action.equip.mask & 2)) - npc->SetVirtualItem(1, slot[1].ItemId, slot[1].AppearanceModId, slot[1].ItemVisual); - if (!e.action.equip.mask || (e.action.equip.mask & 4)) - npc->SetVirtualItem(2, slot[2].ItemId, slot[2].AppearanceModId, slot[2].ItemVisual); + + for (uint32 i = 0; i < MAX_EQUIPMENT_ITEMS; ++i) + if (!e.action.equip.mask || (e.action.equip.mask & (1 << i))) + npc->SetVirtualItem(0, slot[i].ItemId, slot[i].AppearanceModId, slot[i].ItemVisual); } } - - delete targets; break; } case SMART_ACTION_CREATE_TIMED_EVENT: @@ -1913,35 +1550,29 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u break; case SMART_ACTION_OVERRIDE_SCRIPT_BASE_OBJECT: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsCreature(*itr)) + if (IsCreature(target)) { if (!meOrigGUID && me) meOrigGUID = me->GetGUID(); if (!goOrigGUID && go) goOrigGUID = go->GetGUID(); go = nullptr; - me = (*itr)->ToCreature(); + me = target->ToCreature(); break; } - else if (IsGameObject(*itr)) + else if (IsGameObject(target)) { if (!meOrigGUID && me) meOrigGUID = me->GetGUID(); if (!goOrigGUID && go) goOrigGUID = go->GetGUID(); - go = (*itr)->ToGameObject(); + go = target->ToGameObject(); me = nullptr; break; } } - - delete targets; break; } case SMART_ACTION_RESET_SCRIPT_BASE_OBJECT: @@ -1959,17 +1590,12 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u float attackDistance = float(e.action.setRangedMovement.distance); float attackAngle = float(e.action.setRangedMovement.angle) / 180.0f * float(M_PI); - ObjectList* targets = GetTargets(e, unit); - if (targets) - { - for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (Creature* target = (*itr)->ToCreature()) - if (IsSmart(target) && target->GetVictim()) - if (ENSURE_AI(SmartAI, target->AI())->CanCombatMove()) - target->GetMotionMaster()->MoveChase(target->GetVictim(), attackDistance, attackAngle); + for (WorldObject* target : targets) + if (Creature* creature = target->ToCreature()) + if (IsSmart(creature) && creature->GetVictim()) + if (ENSURE_AI(SmartAI, creature->AI())->CanCombatMove()) + creature->GetMotionMaster()->MoveChase(creature->GetVictim(), attackDistance, attackAngle); - delete targets; - } break; } case SMART_ACTION_CALL_TIMED_ACTIONLIST: @@ -1980,433 +1606,292 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u break; } - if (ObjectList* targets = GetTargets(e, unit)) + for (WorldObject* target : targets) { - for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (Creature* creature = target->ToCreature()) { - if (Creature* target = (*itr)->ToCreature()) - { - if (IsSmart(target)) - ENSURE_AI(SmartAI, target->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker()); - } - else if (GameObject* goTarget = (*itr)->ToGameObject()) - { - if (IsSmartGO(goTarget)) - ENSURE_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker()); - } + if (IsSmart(creature)) + ENSURE_AI(SmartAI, creature->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker()); + } + else if (GameObject* go = target->ToGameObject()) + { + if (IsSmartGO(go)) + ENSURE_AI(SmartGameObjectAI, go->AI())->SetScript9(e, e.action.timedActionList.id, GetLastInvoker()); } - - delete targets; } break; } case SMART_ACTION_SET_NPC_FLAG: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToUnit()->SetNpcFlags(NPCFlags(e.action.unitFlag.flag)); - - delete targets; + for (WorldObject* target : targets) + if (IsCreature(target)) + target->ToUnit()->SetNpcFlags(NPCFlags(e.action.unitFlag.flag)); break; } case SMART_ACTION_ADD_NPC_FLAG: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToUnit()->AddNpcFlag(NPCFlags(e.action.unitFlag.flag)); - - delete targets; + for (WorldObject* target : targets) + if (IsCreature(target)) + target->ToUnit()->AddNpcFlag(NPCFlags(e.action.unitFlag.flag)); break; } case SMART_ACTION_REMOVE_NPC_FLAG: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToUnit()->RemoveNpcFlag(NPCFlags(e.action.unitFlag.flag)); - - delete targets; + for (WorldObject* target : targets) + if (IsCreature(target)) + target->ToUnit()->RemoveNpcFlag(NPCFlags(e.action.unitFlag.flag)); break; } case SMART_ACTION_CROSS_CAST: { - ObjectList* casters = GetTargets(CreateSmartEvent(SMART_EVENT_UPDATE_IC, 0, 0, 0, 0, 0, 0, SMART_ACTION_NONE, 0, 0, 0, 0, 0, 0, (SMARTAI_TARGETS)e.action.crossCast.targetType, e.action.crossCast.targetParam1, e.action.crossCast.targetParam2, e.action.crossCast.targetParam3, 0), unit); - if (!casters) + if (targets.empty()) break; - ObjectList* targets = GetTargets(e, unit); - if (!targets) - { - delete casters; // casters already validated, delete now - break; - } + ObjectVector casters; + GetTargets(casters, CreateSmartEvent(SMART_EVENT_UPDATE_IC, 0, 0, 0, 0, 0, 0, SMART_ACTION_NONE, 0, 0, 0, 0, 0, 0, (SMARTAI_TARGETS)e.action.crossCast.targetType, e.action.crossCast.targetParam1, e.action.crossCast.targetParam2, e.action.crossCast.targetParam3, 0), unit); - for (ObjectList::const_iterator itr = casters->begin(); itr != casters->end(); ++itr) + for (WorldObject* caster : casters) { - if (!IsUnit(*itr)) + if (!IsUnit(caster)) continue; - Unit* targetUnit = (*itr)->ToUnit(); + Unit* casterUnit = caster->ToUnit(); bool interruptedSpell = false; - for (ObjectList::const_iterator it = targets->begin(); it != targets->end(); ++it) + for (WorldObject* target : targets) { - if (!IsUnit(*it)) + if (!IsUnit(target)) continue; - if (!(e.action.crossCast.castFlags & SMARTCAST_AURA_NOT_PRESENT) || !(*it)->ToUnit()->HasAura(e.action.crossCast.spell)) + if (!(e.action.crossCast.castFlags & SMARTCAST_AURA_NOT_PRESENT) || !target->ToUnit()->HasAura(e.action.crossCast.spell)) { if (!interruptedSpell && e.action.crossCast.castFlags & SMARTCAST_INTERRUPT_PREVIOUS) { - targetUnit->InterruptNonMeleeSpells(false); + casterUnit->InterruptNonMeleeSpells(false); interruptedSpell = true; } - targetUnit->CastSpell((*it)->ToUnit(), e.action.crossCast.spell, (e.action.crossCast.castFlags & SMARTCAST_TRIGGERED) != 0); + casterUnit->CastSpell(target->ToUnit(), e.action.crossCast.spell, (e.action.crossCast.castFlags & SMARTCAST_TRIGGERED) != 0); } else - TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (%s) already has the aura", e.action.crossCast.spell, (*it)->GetGUID().ToString().c_str()); + TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (%s) already has the aura", e.action.crossCast.spell, target->GetGUID().ToString().c_str()); } } - - delete targets; - delete casters; break; } case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST: { - uint32 actions[SMART_ACTION_PARAM_COUNT]; - actions[0] = e.action.randTimedActionList.entry1; - actions[1] = e.action.randTimedActionList.entry2; - actions[2] = e.action.randTimedActionList.entry3; - actions[3] = e.action.randTimedActionList.entry4; - actions[4] = e.action.randTimedActionList.entry5; - actions[5] = e.action.randTimedActionList.entry6; - uint32 temp[SMART_ACTION_PARAM_COUNT]; - uint32 count = 0; - for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++) - { - if (actions[i] > 0) - { - temp[count] = actions[i]; - ++count; - } - } + std::vector<uint32> actionLists; + std::copy_if(e.action.randTimedActionList.actionLists.begin(), e.action.randTimedActionList.actionLists.end(), + std::back_inserter(actionLists), [](uint32 actionList) { return actionList != 0; }); - if (count == 0) - break; - - uint32 id = temp[urand(0, count - 1)]; + uint32 id = Trinity::Containers::SelectRandomContainerElement(actionLists); if (e.GetTargetType() == SMART_TARGET_NONE) { TC_LOG_ERROR("sql.sql", "SmartScript: Entry " SI64FMTD " SourceType %u Event %u Action %u is using TARGET_NONE(0) for Script9 target. Please correct target_type in database.", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType()); break; } - ObjectList* targets = GetTargets(e, unit); - if (targets) + for (WorldObject* target : targets) { - for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (Creature* creature = target->ToCreature()) { - if (Creature* target = (*itr)->ToCreature()) - { - if (IsSmart(target)) - ENSURE_AI(SmartAI, target->AI())->SetScript9(e, id, GetLastInvoker()); - } - else if (GameObject* goTarget = (*itr)->ToGameObject()) - { - if (IsSmartGO(goTarget)) - ENSURE_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, id, GetLastInvoker()); - } + if (IsSmart(creature)) + ENSURE_AI(SmartAI, creature->AI())->SetScript9(e, id, GetLastInvoker()); + } + else if (GameObject* go = target->ToGameObject()) + { + if (IsSmartGO(go)) + ENSURE_AI(SmartGameObjectAI, go->AI())->SetScript9(e, id, GetLastInvoker()); } - - delete targets; } break; } case SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST: { - uint32 id = urand(e.action.randTimedActionList.entry1, e.action.randTimedActionList.entry2); + uint32 id = urand(e.action.randTimedActionList.actionLists[0], e.action.randTimedActionList.actionLists[1]); if (e.GetTargetType() == SMART_TARGET_NONE) { TC_LOG_ERROR("sql.sql", "SmartScript: Entry " SI64FMTD " SourceType %u Event %u Action %u is using TARGET_NONE(0) for Script9 target. Please correct target_type in database.", e.entryOrGuid, e.GetScriptType(), e.GetEventType(), e.GetActionType()); break; } - ObjectList* targets = GetTargets(e, unit); - if (targets) + for (WorldObject* target : targets) { - for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (Creature* creature = target->ToCreature()) { - if (Creature* target = (*itr)->ToCreature()) - { - if (IsSmart(target)) - ENSURE_AI(SmartAI, target->AI())->SetScript9(e, id, GetLastInvoker()); - } - else if (GameObject* goTarget = (*itr)->ToGameObject()) - { - if (IsSmartGO(goTarget)) - ENSURE_AI(SmartGameObjectAI, goTarget->AI())->SetScript9(e, id, GetLastInvoker()); - } + if (IsSmart(creature)) + ENSURE_AI(SmartAI, creature->AI())->SetScript9(e, id, GetLastInvoker()); + } + else if (GameObject* go = target->ToGameObject()) + { + if (IsSmartGO(go)) + ENSURE_AI(SmartGameObjectAI, go->AI())->SetScript9(e, id, GetLastInvoker()); } - - delete targets; } break; } case SMART_ACTION_ACTIVATE_TAXI: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsPlayer(*itr)) - (*itr)->ToPlayer()->ActivateTaxiPathTo(e.action.taxi.id); - - delete targets; + for (WorldObject* target : targets) + if (IsPlayer(target)) + target->ToPlayer()->ActivateTaxiPathTo(e.action.taxi.id); break; } case SMART_ACTION_RANDOM_MOVE: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - bool foundTarget = false; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsCreature((*itr))) + if (IsCreature((target))) { foundTarget = true; if (e.action.moveRandom.distance) - (*itr)->ToCreature()->GetMotionMaster()->MoveRandom((float)e.action.moveRandom.distance); + target->ToCreature()->GetMotionMaster()->MoveRandom(float(e.action.moveRandom.distance)); else - (*itr)->ToCreature()->GetMotionMaster()->MoveIdle(); + target->ToCreature()->GetMotionMaster()->MoveIdle(); } } if (!foundTarget && me && IsCreature(me)) { if (e.action.moveRandom.distance) - me->GetMotionMaster()->MoveRandom((float)e.action.moveRandom.distance); + me->GetMotionMaster()->MoveRandom(float(e.action.moveRandom.distance)); else me->GetMotionMaster()->MoveIdle(); } - - delete targets; break; } case SMART_ACTION_SET_UNIT_FIELD_BYTES_1: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) + for (WorldObject* target : targets) + if (IsUnit(target)) { switch (e.action.setunitByte.type) { case 0: - (*itr)->ToUnit()->SetStandState(UnitStandStateType(e.action.setunitByte.byte1)); + target->ToUnit()->SetStandState(UnitStandStateType(e.action.setunitByte.byte1)); break; case 1: // pet talent points break; case 2: - (*itr)->ToUnit()->AddVisFlags(UnitVisFlags(e.action.setunitByte.byte1)); + target->ToUnit()->AddVisFlags(UnitVisFlags(e.action.setunitByte.byte1)); break; case 3: // this is totally wrong to maintain compatibility with existing scripts // TODO: fix with animtier overhaul - (*itr)->ToUnit()->SetAnimTier(UnitBytes1_Flags(*(*itr)->ToUnit()->m_unitData->AnimTier | e.action.setunitByte.byte1), false); + target->ToUnit()->SetAnimTier(UnitBytes1_Flags(target->ToUnit()->m_unitData->AnimTier | e.action.setunitByte.byte1), false); break; } } - - delete targets; break; } case SMART_ACTION_REMOVE_UNIT_FIELD_BYTES_1: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) + for (WorldObject* target : targets) + if (IsUnit(target)) { switch (e.action.setunitByte.type) { case 0: - (*itr)->ToUnit()->SetStandState(UNIT_STAND_STATE_STAND); + target->ToUnit()->SetStandState(UNIT_STAND_STATE_STAND); break; case 1: // pet talent points break; case 2: - (*itr)->ToUnit()->RemoveVisFlags(UnitVisFlags(e.action.setunitByte.byte1)); + target->ToUnit()->RemoveVisFlags(UnitVisFlags(e.action.setunitByte.byte1)); break; case 3: - (*itr)->ToUnit()->SetAnimTier(UnitBytes1_Flags(*(*itr)->ToUnit()->m_unitData->AnimTier & ~e.action.setunitByte.byte1), false); + target->ToUnit()->SetAnimTier(UnitBytes1_Flags(target->ToUnit()->m_unitData->AnimTier & ~e.action.setunitByte.byte1), false); break; } } - - delete targets; break; } case SMART_ACTION_INTERRUPT_SPELL: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->InterruptNonMeleeSpells(e.action.interruptSpellCasting.withDelayed != 0, e.action.interruptSpellCasting.spell_id, e.action.interruptSpellCasting.withInstant != 0); - - delete targets; + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->InterruptNonMeleeSpells(e.action.interruptSpellCasting.withDelayed != 0, e.action.interruptSpellCasting.spell_id, e.action.interruptSpellCasting.withInstant != 0); break; } case SMART_ACTION_SEND_GO_CUSTOM_ANIM: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsGameObject(*itr)) - (*itr)->ToGameObject()->SendCustomAnim(e.action.sendGoCustomAnim.anim); - - delete targets; + for (WorldObject* target : targets) + if (IsGameObject(target)) + target->ToGameObject()->SendCustomAnim(e.action.sendGoCustomAnim.anim); break; } case SMART_ACTION_SET_DYNAMIC_FLAG: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; + for (WorldObject* target : targets) + target->SetDynamicFlags(e.action.unitFlag.flag); - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - (*itr)->SetDynamicFlags(e.action.unitFlag.flag); - - delete targets; break; } case SMART_ACTION_ADD_DYNAMIC_FLAG: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - (*itr)->AddDynamicFlag(e.action.unitFlag.flag); + for (WorldObject* target : targets) + target->AddDynamicFlag(e.action.unitFlag.flag); - delete targets; break; } case SMART_ACTION_REMOVE_DYNAMIC_FLAG: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - (*itr)->RemoveDynamicFlag(e.action.unitFlag.flag); + for (WorldObject* target : targets) + target->RemoveDynamicFlag(e.action.unitFlag.flag); - delete targets; break; } case SMART_ACTION_JUMP_TO_POS: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (Creature* creature = (*itr)->ToCreature()) - creature->GetMotionMaster()->MoveJump(e.target.x, e.target.y, e.target.z, 0.0f, (float)e.action.jump.speedxy, (float)e.action.jump.speedz); // @todo add optional jump orientation support? - } - - delete targets; + for (WorldObject* target : targets) + if (Creature* creature = target->ToCreature()) + creature->GetMotionMaster()->MoveJump(e.target.x, e.target.y, e.target.z, 0.0f, float(e.action.jump.speedxy), float(e.action.jump.speedz)); // @todo add optional jump orientation support? break; } case SMART_ACTION_GO_SET_LOOT_STATE: { - ObjectList* targets = GetTargets(e, unit); - - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsGameObject(*itr)) - (*itr)->ToGameObject()->SetLootState((LootState)e.action.setGoLootState.state); - - delete targets; + for (WorldObject* target : targets) + if (IsGameObject(target)) + target->ToGameObject()->SetLootState((LootState)e.action.setGoLootState.state); break; } case SMART_ACTION_GO_SET_GO_STATE: { - ObjectList* targets = GetTargets(e, unit); - - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsGameObject(*itr)) - (*itr)->ToGameObject()->SetGoState((GOState)e.action.goState.state); - - delete targets; + for (WorldObject* target : targets) + if (IsGameObject(target)) + target->ToGameObject()->SetGoState((GOState)e.action.goState.state); break; } case SMART_ACTION_SEND_TARGET_TO_TARGET: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - ObjectList* storedTargets = GetTargetList(e.action.sendTargetToTarget.id); + ObjectVector const* storedTargets = GetStoredTargetVector(e.action.sendTargetToTarget.id); if (!storedTargets) - { - delete targets; break; - } - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsCreature(*itr)) + if (IsCreature(target)) { - if (SmartAI* ai = CAST_AI(SmartAI, (*itr)->ToCreature()->AI())) - ai->GetScript()->StoreTargetList(new ObjectList(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list + if (SmartAI* ai = CAST_AI(SmartAI, target->ToCreature()->AI())) + ai->GetScript()->StoreTargetList(ObjectVector(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list else TC_LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SEND_TARGET_TO_TARGET is not using SmartAI, skipping"); } - else if (IsGameObject(*itr)) + else if (IsGameObject(target)) { - if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, (*itr)->ToGameObject()->AI())) - ai->GetScript()->StoreTargetList(new ObjectList(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list + if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, target->ToGameObject()->AI())) + ai->GetScript()->StoreTargetList(ObjectVector(*storedTargets), e.action.sendTargetToTarget.id); // store a copy of target list else TC_LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SEND_TARGET_TO_TARGET is not using SmartGameObjectAI, skipping"); } } - - delete targets; break; } case SMART_ACTION_SEND_GOSSIP_MENU: @@ -2417,19 +1902,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_SEND_GOSSIP_MENU: gossipMenuId %d, gossipNpcTextId %d", e.action.sendGossipMenu.gossipMenuId, e.action.sendGossipMenu.gossipNpcTextId); - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - // override default gossip if (me) ENSURE_AI(SmartAI, me->AI())->SetGossipReturn(true); else if (go) ENSURE_AI(SmartGameObjectAI, go->AI())->SetGossipReturn(true); - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (Player* player = (*itr)->ToPlayer()) + if (Player* player = target->ToPlayer()) { if (e.action.sendGossipMenu.gossipMenuId) player->PrepareGossipMenu(GetBaseObject(), e.action.sendGossipMenu.gossipMenuId, true); @@ -2439,24 +1920,18 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u player->PlayerTalkClass->SendGossipMenu(e.action.sendGossipMenu.gossipNpcTextId, GetBaseObject()->GetGUID()); } } - - delete targets; break; } case SMART_ACTION_SET_HOME_POS: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* target : targets) { - if (IsCreature(*itr)) + if (IsCreature(target)) { if (e.GetTargetType() == SMART_TARGET_SELF) - (*itr)->ToCreature()->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); + target->ToCreature()->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); else if (e.GetTargetType() == SMART_TARGET_POSITION) - (*itr)->ToCreature()->SetHomePosition(e.target.x, e.target.y, e.target.z, e.target.o); + target->ToCreature()->SetHomePosition(e.target.x, e.target.y, e.target.z, e.target.o); else if (e.GetTargetType() == SMART_TARGET_CREATURE_RANGE || e.GetTargetType() == SMART_TARGET_CREATURE_GUID || e.GetTargetType() == SMART_TARGET_CREATURE_DISTANCE || e.GetTargetType() == SMART_TARGET_GAMEOBJECT_RANGE || e.GetTargetType() == SMART_TARGET_GAMEOBJECT_GUID || e.GetTargetType() == SMART_TARGET_GAMEOBJECT_DISTANCE || @@ -2464,79 +1939,48 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u e.GetTargetType() == SMART_TARGET_OWNER_OR_SUMMONER || e.GetTargetType() == SMART_TARGET_ACTION_INVOKER || e.GetTargetType() == SMART_TARGET_CLOSEST_ENEMY || e.GetTargetType() == SMART_TARGET_CLOSEST_FRIENDLY) { - (*itr)->ToCreature()->SetHomePosition((*itr)->GetPositionX(), (*itr)->GetPositionY(), (*itr)->GetPositionZ(), (*itr)->GetOrientation()); + target->ToCreature()->SetHomePosition(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation()); } else TC_LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SET_HOME_POS is invalid, skipping"); } } - - delete targets; break; } case SMART_ACTION_SET_HEALTH_REGEN: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->setRegeneratingHealth(e.action.setHealthRegen.regenHealth != 0); - - delete targets; + for (WorldObject* target : targets) + if (IsCreature(target)) + target->ToCreature()->setRegeneratingHealth(e.action.setHealthRegen.regenHealth != 0); break; } case SMART_ACTION_SET_ROOT: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->SetControlled(e.action.setRoot.root != 0, UNIT_STATE_ROOT); - - delete targets; + for (WorldObject* target : targets) + if (IsCreature(target)) + target->ToCreature()->SetControlled(e.action.setRoot.root != 0, UNIT_STATE_ROOT); break; } case SMART_ACTION_SET_GO_FLAG: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsGameObject(*itr)) - (*itr)->ToGameObject()->SetFlags(GameObjectFlags(e.action.goFlag.flag)); + for (WorldObject* target : targets) + if (IsGameObject(target)) + target->ToGameObject()->SetFlags(GameObjectFlags(e.action.goFlag.flag)); - delete targets; break; } case SMART_ACTION_ADD_GO_FLAG: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsGameObject(*itr)) - (*itr)->ToGameObject()->AddFlag(GameObjectFlags(e.action.goFlag.flag)); - - delete targets; + for (WorldObject* target : targets) + if (IsGameObject(target)) + target->ToGameObject()->AddFlag(GameObjectFlags(e.action.goFlag.flag)); break; } case SMART_ACTION_REMOVE_GO_FLAG: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsGameObject(*itr)) - (*itr)->ToGameObject()->RemoveFlag(GameObjectFlags(e.action.goFlag.flag)); - - delete targets; + for (WorldObject* target : targets) + if (IsGameObject(target)) + target->ToGameObject()->RemoveFlag(GameObjectFlags(e.action.goFlag.flag)); break; } case SMART_ACTION_SUMMON_CREATURE_GROUP: @@ -2544,46 +1988,30 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u std::list<TempSummon*> summonList; GetBaseObject()->SummonCreatureGroup(e.action.creatureGroup.group, &summonList); - for (std::list<TempSummon*>::const_iterator itr = summonList.begin(); itr != summonList.end(); ++itr) + for (TempSummon* summon : summonList) if (unit && e.action.creatureGroup.attackInvoker) - (*itr)->AI()->AttackStart(unit); - + summon->AI()->AttackStart(unit); break; } case SMART_ACTION_SET_POWER: { - ObjectList* targets = GetTargets(e, unit); - - if (targets) - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->SetPower(Powers(e.action.power.powerType), e.action.power.newPower); - - delete targets; + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->SetPower(Powers(e.action.power.powerType), e.action.power.newPower); break; } case SMART_ACTION_ADD_POWER: { - ObjectList* targets = GetTargets(e, unit); - - if (targets) - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->SetPower(Powers(e.action.power.powerType), (*itr)->ToUnit()->GetPower(Powers(e.action.power.powerType)) + e.action.power.newPower); - - delete targets; + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->SetPower(Powers(e.action.power.powerType), target->ToUnit()->GetPower(Powers(e.action.power.powerType)) + e.action.power.newPower); break; } case SMART_ACTION_REMOVE_POWER: { - ObjectList* targets = GetTargets(e, unit); - - if (targets) - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->SetPower(Powers(e.action.power.powerType), (*itr)->ToUnit()->GetPower(Powers(e.action.power.powerType)) - e.action.power.newPower); - - delete targets; + for (WorldObject* target : targets) + if (IsUnit(target)) + target->ToUnit()->SetPower(Powers(e.action.power.powerType), target->ToUnit()->GetPower(Powers(e.action.power.powerType)) - e.action.power.newPower); break; } case SMART_ACTION_GAME_EVENT_STOP: @@ -2610,59 +2038,44 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_START_CLOSEST_WAYPOINT: { - uint32 waypoints[SMART_ACTION_PARAM_COUNT]; - waypoints[0] = e.action.closestWaypointFromList.wp1; - waypoints[1] = e.action.closestWaypointFromList.wp2; - waypoints[2] = e.action.closestWaypointFromList.wp3; - waypoints[3] = e.action.closestWaypointFromList.wp4; - waypoints[4] = e.action.closestWaypointFromList.wp5; - waypoints[5] = e.action.closestWaypointFromList.wp6; + std::vector<uint32> waypoints; + std::copy_if(e.action.closestWaypointFromList.wps.begin(), e.action.closestWaypointFromList.wps.end(), + std::back_inserter(waypoints), [](uint32 wp) { return wp != 0; }); + float distanceToClosest = std::numeric_limits<float>::max(); WayPoint* closestWp = nullptr; - ObjectList* targets = GetTargets(e, unit); - if (targets) + for (WorldObject* target : targets) { - for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (Creature* creature = target->ToCreature()) { - if (Creature* target = (*itr)->ToCreature()) + if (IsSmart(creature)) { - if (IsSmart(target)) + for (uint32 wp : waypoints) { - for (uint8 i = 0; i < SMART_ACTION_PARAM_COUNT; i++) - { - if (!waypoints[i]) - continue; - - WPPath* path = sSmartWaypointMgr->GetPath(waypoints[i]); - - if (!path || path->empty()) - continue; + WPPath* path = sSmartWaypointMgr->GetPath(wp); + if (!path || path->empty()) + continue; - WPPath::const_iterator itrWp = path->find(0); - - if (itrWp != path->end()) + auto itrWp = path->find(0); + if (itrWp != path->end()) + { + if (WayPoint* wp = itrWp->second) { - if (WayPoint* wp = itrWp->second) + float distToThisPath = creature->GetDistance(wp->x, wp->y, wp->z); + if (distToThisPath < distanceToClosest) { - float distToThisPath = target->GetDistance(wp->x, wp->y, wp->z); - - if (distToThisPath < distanceToClosest) - { - distanceToClosest = distToThisPath; - closestWp = wp; - } + distanceToClosest = distToThisPath; + closestWp = wp; } } } - - if (closestWp) - CAST_AI(SmartAI, target->AI())->StartPath(false, closestWp->id, true); } + + if (closestWp) + CAST_AI(SmartAI, creature->AI())->StartPath(false, closestWp->id, true); } } - - delete targets; } break; } @@ -2673,38 +2086,26 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u std::back_inserter(sounds), [](uint32 sound) { return sound != 0; }); bool onlySelf = e.action.randomSound.onlySelf != 0; - - if (ObjectList* targets = GetTargets(e, unit)) + for (WorldObject* const target : targets) { - for (WorldObject* const obj : *targets) + if (IsUnit(target)) { - if (IsUnit(obj)) - { - uint32 sound = Trinity::Containers::SelectRandomContainerElement(sounds); - obj->PlayDirectSound(sound, onlySelf ? obj->ToPlayer() : nullptr); - TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_RANDOM_SOUND: target: %s (%s), sound: %u, onlyself: %s", - obj->GetName().c_str(), obj->GetGUID().ToString().c_str(), sound, onlySelf ? "true" : "false"); - } + uint32 sound = Trinity::Containers::SelectRandomContainerElement(sounds); + target->PlayDirectSound(sound, onlySelf ? target->ToPlayer() : nullptr); + TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_RANDOM_SOUND: target: %s (%s), sound: %u, onlyself: %s", + target->GetName().c_str(), target->GetGUID().ToString().c_str(), sound, onlySelf ? "true" : "false"); } - - delete targets; - break; } + break; } /* fallthrough */ case SMART_ACTION_SET_CORPSE_DELAY: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* const target : targets) { - if (IsCreature(*itr)) - (*itr)->ToCreature()->SetCorpseDelay(e.action.corpseDelay.timer); + if (IsCreature(target)) + target->ToCreature()->SetCorpseDelay(e.action.corpseDelay.timer); } - - delete targets; break; } case SMART_ACTION_DISABLE_EVADE: @@ -2717,67 +2118,37 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_REMOVE_AURAS_BY_TYPE: // can be used to exit vehicle for example { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->RemoveAurasByType((AuraType)e.action.auraType.type); - - delete targets; + for (WorldObject* const target : targets) + if (IsUnit(target)) + target->ToUnit()->RemoveAurasByType((AuraType)e.action.auraType.type); break; } case SMART_ACTION_SET_SIGHT_DIST: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->m_SightDistance = e.action.sightDistance.dist; - - delete targets; + for (WorldObject* const target : targets) + if (IsCreature(target)) + target->ToCreature()->m_SightDistance = e.action.sightDistance.dist; break; } case SMART_ACTION_FLEE: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->GetMotionMaster()->MoveFleeing(me, e.action.flee.fleeTime); - - delete targets; + for (WorldObject* const target : targets) + if (IsCreature(target)) + target->ToCreature()->GetMotionMaster()->MoveFleeing(me, e.action.flee.fleeTime); break; } case SMART_ACTION_ADD_THREAT: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - me->AddThreat((*itr)->ToUnit(), (float)e.action.threatPCT.threatINC - (float)e.action.threatPCT.threatDEC); - - delete targets; + for (WorldObject* const target : targets) + if (IsUnit(target)) + me->AddThreat(target->ToUnit(), float(e.action.threatPCT.threatINC) - float(e.action.threatPCT.threatDEC)); break; } case SMART_ACTION_LOAD_EQUIPMENT: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsCreature(*itr)) - (*itr)->ToCreature()->LoadEquipment(e.action.loadEquipment.id, e.action.loadEquipment.force != 0); - - delete targets; + for (WorldObject* const target : targets) + if (IsCreature(target)) + target->ToCreature()->LoadEquipment(e.action.loadEquipment.id, e.action.loadEquipment.force != 0); break; } case SMART_ACTION_TRIGGER_RANDOM_TIMED_EVENT: @@ -2789,53 +2160,39 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u case SMART_ACTION_REMOVE_ALL_GAMEOBJECTS: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) - (*itr)->ToUnit()->RemoveAllGameObjects(); - - delete targets; + for (WorldObject* const target : targets) + if (IsUnit(target)) + target->ToUnit()->RemoveAllGameObjects(); break; } case SMART_ACTION_STOP_MOTION: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - if (IsUnit(*itr)) + for (WorldObject* const target : targets) + { + if (IsUnit(target)) { if (e.action.stopMotion.stopMovement) - (*itr)->ToUnit()->StopMoving(); + target->ToUnit()->StopMoving(); if (e.action.stopMotion.movementExpired) - (*itr)->ToUnit()->GetMotionMaster()->MovementExpired(); + target->ToUnit()->GetMotionMaster()->MovementExpired(); } - - delete targets; + } break; } case SMART_ACTION_PLAY_ANIMKIT: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* const target : targets) { - if (IsCreature(*itr)) + if (IsCreature(target)) { if (e.action.animKit.type == 0) - (*itr)->ToCreature()->PlayOneShotAnimKitId(e.action.animKit.animKit); + target->ToCreature()->PlayOneShotAnimKitId(e.action.animKit.animKit); else if (e.action.animKit.type == 1) - (*itr)->ToCreature()->SetAIAnimKitId(e.action.animKit.animKit); + target->ToCreature()->SetAIAnimKitId(e.action.animKit.animKit); else if (e.action.animKit.type == 2) - (*itr)->ToCreature()->SetMeleeAnimKitId(e.action.animKit.animKit); + target->ToCreature()->SetMeleeAnimKitId(e.action.animKit.animKit); else if (e.action.animKit.type == 3) - (*itr)->ToCreature()->SetMovementAnimKitId(e.action.animKit.animKit); + target->ToCreature()->SetMovementAnimKitId(e.action.animKit.animKit); else { TC_LOG_ERROR("sql.sql", "SmartScript: Invalid type for SMART_ACTION_PLAY_ANIMKIT, skipping"); @@ -2843,75 +2200,54 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_PLAY_ANIMKIT: target: %s (%s), AnimKit: %u, Type: %u", - (*itr)->GetName().c_str(), (*itr)->GetGUID().ToString().c_str(), e.action.animKit.animKit, e.action.animKit.type); + target->GetName().c_str(), target->GetGUID().ToString().c_str(), e.action.animKit.animKit, e.action.animKit.type); } } - delete targets; break; } case SMART_ACTION_SCENE_PLAY: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (WorldObject* target : *targets) + for (WorldObject* const target : targets) if (Player* playerTarget = target->ToPlayer()) playerTarget->GetSceneMgr().PlayScene(e.action.scene.sceneId); - delete targets; break; } case SMART_ACTION_SCENE_CANCEL: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (WorldObject* target : *targets) + for (WorldObject* const target : targets) if (Player* playerTarget = target->ToPlayer()) playerTarget->GetSceneMgr().CancelSceneBySceneId(e.action.scene.sceneId); - delete targets; break; } case SMART_ACTION_SET_MOVEMENT_SPEED: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - uint32 speedInteger = e.action.movementSpeed.speedInteger; uint32 speedFraction = e.action.movementSpeed.speedFraction; float speed = float(speedInteger) + float(speedFraction) / std::pow(10, std::floor(std::log10(float(speedFraction ? speedFraction : 1)) + 1)); - for (WorldObject* target : *targets) + for (WorldObject* const target : targets) if (IsCreature(target)) me->SetSpeed(UnitMoveType(e.action.movementSpeed.movementType), speed); - delete targets; break; } case SMART_ACTION_PLAY_SPELL_VISUAL_KIT: { - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + for (WorldObject* const target : targets) { - if (IsUnit(*itr)) + if (IsUnit(target)) { - (*itr)->ToUnit()->SendPlaySpellVisualKit(e.action.spellVisualKit.spellVisualKitId, e.action.spellVisualKit.kitType, + target->ToUnit()->SendPlaySpellVisualKit(e.action.spellVisualKit.spellVisualKitId, e.action.spellVisualKit.kitType, e.action.spellVisualKit.duration); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_PLAY_SPELL_VISUAL_KIT: target: %s (%s), SpellVisualKit: %u", - (*itr)->GetName().c_str(), (*itr)->GetGUID().ToString().c_str(), e.action.spellVisualKit.spellVisualKitId); + target->GetName().c_str(), target->GetGUID().ToString().c_str(), e.action.spellVisualKit.spellVisualKitId); } } - delete targets; break; } default: @@ -2945,11 +2281,13 @@ void SmartScript::InstallTemplate(SmartScriptHolder const& e) { if (!GetBaseObject()) return; - if (mTemplate) + + if (mTemplate != SMARTAI_TEMPLATE_BASIC) { TC_LOG_ERROR("sql.sql", "SmartScript::InstallTemplate: Entry " SI64FMTD " SourceType %u AI Template can not be set more then once, skipped.", e.entryOrGuid, e.GetScriptType()); return; } + mTemplate = (SMARTAI_TEMPLATE)e.action.installTtemplate.id; switch ((SMARTAI_TEMPLATE)e.action.installTtemplate.id) { @@ -3051,7 +2389,7 @@ SmartScriptHolder SmartScript::CreateSmartEvent(SMART_EVENT e, uint32 event_flag return script; } -ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*= nullptr*/) +void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, Unit* invoker /*= nullptr*/) const { Unit* scriptTrigger = nullptr; if (invoker) @@ -3060,29 +2398,27 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* scriptTrigger = tempLastInvoker; WorldObject* baseObject = GetBaseObject(); - - ObjectList* l = new ObjectList(); switch (e.GetTargetType()) { case SMART_TARGET_SELF: if (baseObject) - l->push_back(baseObject); + targets.push_back(baseObject); break; case SMART_TARGET_VICTIM: if (me) if (Unit* victim = me->GetVictim()) - l->push_back(victim); + targets.push_back(victim); break; case SMART_TARGET_HOSTILE_SECOND_AGGRO: if (me) { if (e.target.hostilRandom.powerType) { - if (Unit * u = me->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO, 1, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly != 0))) - l->push_back(u); + if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO, 1, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0))) + targets.push_back(u); } - else if (Unit * u = me->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO, 1, (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly != 0)) - l->push_back(u); + else if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO, 1, float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0)) + targets.push_back(u); } break; case SMART_TARGET_HOSTILE_LAST_AGGRO: @@ -3090,11 +2426,11 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* { if (e.target.hostilRandom.powerType) { - if (Unit * u = me->AI()->SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly != 0))) - l->push_back(u); + if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0))) + targets.push_back(u); } - else if (Unit * u = me->AI()->SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0, (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly != 0)) - l->push_back(u); + else if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0, float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0)) + targets.push_back(u); } break; case SMART_TARGET_HOSTILE_RANDOM: @@ -3102,11 +2438,11 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* { if (e.target.hostilRandom.powerType) { - if (Unit * u = me->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly != 0))) - l->push_back(u); + if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0))) + targets.push_back(u); } - else if (Unit * u = me->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly != 0)) - l->push_back(u); + else if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0)) + targets.push_back(u); } break; case SMART_TARGET_HOSTILE_RANDOM_NOT_TOP: @@ -3114,27 +2450,27 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* { if (e.target.hostilRandom.powerType) { - if (Unit * u = me->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly != 0))) - l->push_back(u); + if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0))) + targets.push_back(u); } - else if (Unit * u = me->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1, (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly != 0)) - l->push_back(u); + else if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1, float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0)) + targets.push_back(u); } break; case SMART_TARGET_FARTHEST: if (me) { - if (Unit * u = me->AI()->SelectTarget(SELECT_TARGET_FARTHEST, 0, FarthestTargetSelector(me, (float)e.target.farthest.maxDist, e.target.farthest.playerOnly != 0, e.target.farthest.isInLos != 0))) - l->push_back(u); + if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_FARTHEST, 0, FarthestTargetSelector(me, float(e.target.farthest.maxDist), e.target.farthest.playerOnly != 0, e.target.farthest.isInLos != 0))) + targets.push_back(u); } break; case SMART_TARGET_ACTION_INVOKER: if (scriptTrigger) - l->push_back(scriptTrigger); + targets.push_back(scriptTrigger); break; case SMART_TARGET_ACTION_INVOKER_VEHICLE: if (scriptTrigger && scriptTrigger->GetVehicle() && scriptTrigger->GetVehicle()->GetBase()) - l->push_back(scriptTrigger->GetVehicle()->GetBase()); + targets.push_back(scriptTrigger->GetVehicle()->GetBase()); break; case SMART_TARGET_INVOKER_PARTY: if (scriptTrigger) @@ -3146,90 +2482,86 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) if (Player* member = groupRef->GetSource()) if (member->IsInMap(player)) - l->push_back(member); + targets.push_back(member); } // We still add the player to the list if there is no group. If we do // this even if there is a group (thus the else-check), it will add the // same player to the list twice. We don't want that to happen. else - l->push_back(scriptTrigger); + targets.push_back(scriptTrigger); } } break; case SMART_TARGET_CREATURE_RANGE: { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist((float)e.target.unitRange.maxDist); - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) + ObjectVector units; + GetWorldObjectsInDist(units, static_cast<float>(e.target.unitRange.maxDist)); + + for (WorldObject* unit : units) { - if (!IsCreature(*itr)) + if (!IsCreature(unit)) continue; - if (me && me->GetGUID() == (*itr)->GetGUID()) + if (me && me->GetGUID() == unit->GetGUID()) continue; - if ((!e.target.unitRange.creature || (*itr)->ToCreature()->GetEntry() == e.target.unitRange.creature) && baseObject->IsInRange(*itr, float(e.target.unitRange.minDist), float(e.target.unitRange.maxDist))) - l->push_back(*itr); + if ((!e.target.unitRange.creature || unit->ToCreature()->GetEntry() == e.target.unitRange.creature) && baseObject->IsInRange(unit, float(e.target.unitRange.minDist), float(e.target.unitRange.maxDist))) + targets.push_back(unit); } - - delete units; break; } case SMART_TARGET_CREATURE_DISTANCE: { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist((float)e.target.unitDistance.dist); - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) + ObjectVector units; + GetWorldObjectsInDist(units, static_cast<float>(e.target.unitDistance.dist)); + + for (WorldObject* unit : units) { - if (!IsCreature(*itr)) + if (!IsCreature(unit)) continue; - if (me && me->GetGUID() == (*itr)->GetGUID()) + if (me && me->GetGUID() == unit->GetGUID()) continue; - if (!e.target.unitDistance.creature || (*itr)->ToCreature()->GetEntry() == e.target.unitDistance.creature) - l->push_back(*itr); + if (!e.target.unitDistance.creature || unit->ToCreature()->GetEntry() == e.target.unitDistance.creature) + targets.push_back(unit); } - - delete units; break; } case SMART_TARGET_GAMEOBJECT_DISTANCE: { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist((float)e.target.goDistance.dist); - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) + ObjectVector units; + GetWorldObjectsInDist(units, static_cast<float>(e.target.goDistance.dist)); + + for (WorldObject* unit : units) { - if (!IsGameObject(*itr)) + if (!IsGameObject(unit)) continue; - if (go && go->GetGUID() == (*itr)->GetGUID()) + if (go && go->GetGUID() == unit->GetGUID()) continue; - if (!e.target.goDistance.entry || (*itr)->ToGameObject()->GetEntry() == e.target.goDistance.entry) - l->push_back(*itr); + if (!e.target.goDistance.entry || unit->ToGameObject()->GetEntry() == e.target.goDistance.entry) + targets.push_back(unit); } - - delete units; break; } case SMART_TARGET_GAMEOBJECT_RANGE: { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist((float)e.target.goRange.maxDist); - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) + ObjectVector units; + GetWorldObjectsInDist(units, static_cast<float>(e.target.goRange.maxDist)); + + for (WorldObject* unit : units) { - if (!IsGameObject(*itr)) + if (!IsGameObject(unit)) continue; - if (go && go->GetGUID() == (*itr)->GetGUID()) + if (go && go->GetGUID() == unit->GetGUID()) continue; - if ((!e.target.goRange.entry && (*itr)->ToGameObject()->GetEntry() == e.target.goRange.entry) && baseObject->IsInRange(*itr, float(e.target.goRange.minDist), float(e.target.goRange.maxDist))) - l->push_back(*itr); + if ((!e.target.goRange.entry && unit->ToGameObject()->GetEntry() == e.target.goRange.entry) && baseObject->IsInRange(unit, float(e.target.goRange.minDist), float(e.target.goRange.maxDist))) + targets.push_back(unit); } - - delete units; break; } case SMART_TARGET_CREATURE_GUID: @@ -3242,7 +2574,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (Creature* target = FindCreatureNear(scriptTrigger ? scriptTrigger : baseObject, e.target.unitGUID.dbGuid)) if (!e.target.unitGUID.entry || target->GetEntry() == e.target.unitGUID.entry) - l->push_back(target); + targets.push_back(target); break; } case SMART_TARGET_GAMEOBJECT_GUID: @@ -3255,60 +2587,53 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (GameObject* target = FindGameObjectNear(scriptTrigger ? scriptTrigger : baseObject, e.target.goGUID.dbGuid)) if (!e.target.goGUID.entry || target->GetEntry() == e.target.goGUID.entry) - l->push_back(target); + targets.push_back(target); break; } case SMART_TARGET_PLAYER_RANGE: { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist((float)e.target.playerRange.maxDist); - if (!units->empty() && baseObject) - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) - if (IsPlayer(*itr) && baseObject->IsInRange(*itr, (float)e.target.playerRange.minDist, (float)e.target.playerRange.maxDist)) - l->push_back(*itr); + ObjectVector units; + GetWorldObjectsInDist(units, static_cast<float>(e.target.playerRange.maxDist)); - delete units; + if (!units.empty() && baseObject) + for (WorldObject* unit : units) + if (IsPlayer(unit) && baseObject->IsInRange(unit, float(e.target.playerRange.minDist), float(e.target.playerRange.maxDist))) + targets.push_back(unit); break; } case SMART_TARGET_PLAYER_DISTANCE: { - // will always return a valid pointer, even if empty list - ObjectList* units = GetWorldObjectsInDist((float)e.target.playerDistance.dist); - for (ObjectList::const_iterator itr = units->begin(); itr != units->end(); ++itr) - if (IsPlayer(*itr)) - l->push_back(*itr); + ObjectVector units; + GetWorldObjectsInDist(units, static_cast<float>(e.target.playerDistance.dist)); - delete units; + for (WorldObject* unit : units) + if (IsPlayer(unit)) + targets.push_back(unit); break; } case SMART_TARGET_STORED: { - ObjectListMap::iterator itr = mTargetStorage->find(e.target.stored.id); - if (itr != mTargetStorage->end()) - { - ObjectList* objectList = itr->second->GetObjectList(); - l->assign(objectList->begin(), objectList->end()); - } - + if (ObjectVector const* stored = GetStoredTargetVector(e.target.stored.id)) + targets.assign(stored->begin(), stored->end()); break; } case SMART_TARGET_CLOSEST_CREATURE: { if (Creature* target = baseObject->FindNearestCreature(e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100), !e.target.closest.dead)) - l->push_back(target); + targets.push_back(target); break; } case SMART_TARGET_CLOSEST_GAMEOBJECT: { if (GameObject* target = baseObject->FindNearestGameObject(e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100))) - l->push_back(target); + targets.push_back(target); break; } case SMART_TARGET_CLOSEST_PLAYER: { - if (WorldObject * obj = GetBaseObject()) - if (Player * target = obj->SelectNearestPlayer(float(e.target.playerDistance.dist))) - l->push_back(target); + if (WorldObject* obj = GetBaseObject()) + if (Player* target = obj->SelectNearestPlayer(float(e.target.playerDistance.dist))) + targets.push_back(target); break; } case SMART_TARGET_OWNER_OR_SUMMONER: @@ -3326,22 +2651,22 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* charmerOrOwnerGuid = me->GetCreatorGUID(); if (Unit* owner = ObjectAccessor::GetUnit(*me, charmerOrOwnerGuid)) - l->push_back(owner); + targets.push_back(owner); } else if (go) { - if (Unit * owner = ObjectAccessor::GetUnit(*go, go->GetOwnerGUID())) - l->push_back(owner); + if (Unit* owner = ObjectAccessor::GetUnit(*go, go->GetOwnerGUID())) + targets.push_back(owner); } // Get owner of owner - if (e.target.owner.useCharmerOrOwner && !l->empty()) + if (e.target.owner.useCharmerOrOwner && !targets.empty()) { - Unit* owner = l->front()->ToUnit(); - l->clear(); + Unit* owner = targets.front()->ToUnit(); + targets.clear(); - if (Unit * base = ObjectAccessor::GetUnit(*owner, owner->GetCharmerOrOwnerGUID())) - l->push_back(base); + if (Unit* base = ObjectAccessor::GetUnit(*owner, owner->GetCharmerOrOwnerGUID())) + targets.push_back(base); } break; } @@ -3349,11 +2674,11 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* { if (me) { - ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i) - if (Unit* temp = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) - if (e.target.hostilRandom.maxDist == 0 || me->IsWithinCombatRange(temp, (float)e.target.hostilRandom.maxDist)) - l->push_back(temp); + ThreatContainer::StorageType const& threatList = me->getThreatManager().getThreatList(); + for (HostileReference const* ref : threatList) + if (Unit* temp = ObjectAccessor::GetUnit(*me, ref->getUnitGuid())) + if (e.target.hostilRandom.maxDist == 0 || me->IsWithinCombatRange(temp, float(e.target.hostilRandom.maxDist))) + targets.push_back(temp); } break; } @@ -3361,14 +2686,14 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* { if (me) if (Unit* target = me->SelectNearestTarget(e.target.closestAttackable.maxDist, e.target.closestAttackable.playerOnly != 0)) - l->push_back(target); + targets.push_back(target); break; } case SMART_TARGET_CLOSEST_FRIENDLY: { if (me) if (Unit* target = DoFindClosestFriendlyInRange(e.target.closestFriendly.maxDist, e.target.closestFriendly.playerOnly != 0)) - l->push_back(target); + targets.push_back(target); break; } case SMART_TARGET_LOOT_RECIPIENTS: @@ -3380,12 +2705,12 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* for (GroupReference* it = lootGroup->GetFirstMember(); it != nullptr; it = it->next()) if (Player* recipient = it->GetSource()) if (recipient->IsInMap(me)) - l->push_back(recipient); + targets.push_back(recipient); } else { if (Player* recipient = me->GetLootRecipient()) - l->push_back(recipient); + targets.push_back(recipient); } } break; @@ -3395,7 +2720,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (me && me->IsVehicle()) { if (Unit* target = me->GetVehicleKit()->GetPassenger(e.target.vehicle.seat)) - l->push_back(target); + targets.push_back(target); } break; } @@ -3404,27 +2729,17 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* default: break; } - - if (l->empty()) - { - delete l; - l = nullptr; - } - - return l; } -ObjectList* SmartScript::GetWorldObjectsInDist(float dist) +void SmartScript::GetWorldObjectsInDist(ObjectVector& targets, float dist) const { - ObjectList* targets = new ObjectList(); WorldObject* obj = GetBaseObject(); - if (obj) - { - Trinity::AllWorldObjectsInRange u_check(obj, dist); - Trinity::WorldObjectListSearcher<Trinity::AllWorldObjectsInRange> searcher(obj, *targets, u_check); - Cell::VisitAllObjects(obj, searcher, dist); - } - return targets; + if (!obj) + return; + + Trinity::AllWorldObjectsInRange u_check(obj, dist); + Trinity::WorldObjectListSearcher<Trinity::AllWorldObjectsInRange> searcher(obj, targets, u_check); + Cell::VisitAllObjects(obj, searcher, dist); } void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob, std::string const& varString) @@ -3547,26 +2862,26 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if (!me || !me->IsInCombat()) return; - std::list<Creature*> pList; - DoFindFriendlyCC(pList, (float)e.event.friendlyCC.radius); - if (pList.empty()) + std::vector<Creature*> creatures; + DoFindFriendlyCC(creatures, float(e.event.friendlyCC.radius)); + if (creatures.empty()) { // if there are at least two same npcs, they will perform the same action immediately even if this is useless... RecalcTimer(e, 1000, 3000); return; } - ProcessTimedAction(e, e.event.friendlyCC.repeatMin, e.event.friendlyCC.repeatMax, Trinity::Containers::SelectRandomContainerElement(pList)); + ProcessTimedAction(e, e.event.friendlyCC.repeatMin, e.event.friendlyCC.repeatMax, Trinity::Containers::SelectRandomContainerElement(creatures)); break; } case SMART_EVENT_FRIENDLY_MISSING_BUFF: { - std::list<Creature*> pList; - DoFindFriendlyMissingBuff(pList, (float)e.event.missingBuff.radius, e.event.missingBuff.spell); + std::vector<Creature*> creatures; + DoFindFriendlyMissingBuff(creatures, float(e.event.missingBuff.radius), e.event.missingBuff.spell); - if (pList.empty()) + if (creatures.empty()) return; - ProcessTimedAction(e, e.event.missingBuff.repeatMin, e.event.missingBuff.repeatMax, Trinity::Containers::SelectRandomContainerElement(pList)); + ProcessTimedAction(e, e.event.missingBuff.repeatMin, e.event.missingBuff.repeatMax, Trinity::Containers::SelectRandomContainerElement(creatures)); break; } case SMART_EVENT_HAS_AURA: @@ -3872,8 +3187,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if (!me || !me->IsInCombat()) return; - ObjectList* _targets = nullptr; - + ObjectVector targets; switch (e.GetTargetType()) { case SMART_TARGET_CREATURE_RANGE: @@ -3883,37 +3197,30 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui case SMART_TARGET_CLOSEST_PLAYER: case SMART_TARGET_PLAYER_RANGE: case SMART_TARGET_PLAYER_DISTANCE: - _targets = GetTargets(e); + GetTargets(targets, e); break; default: return; } - if (!_targets) - return; - - Unit* target = nullptr; - - for (ObjectList::const_iterator itr = _targets->begin(); itr != _targets->end(); ++itr) + Unit* unitTarget = nullptr; + for (WorldObject* target : targets) { - if (IsUnit(*itr) && me->IsFriendlyTo((*itr)->ToUnit()) && (*itr)->ToUnit()->IsAlive() && (*itr)->ToUnit()->IsInCombat()) + if (IsUnit(target) && me->IsFriendlyTo(target->ToUnit()) && target->ToUnit()->IsAlive() && target->ToUnit()->IsInCombat()) { - uint32 healthPct = uint32((*itr)->ToUnit()->GetHealthPct()); - + uint32 healthPct = uint32(target->ToUnit()->GetHealthPct()); if (healthPct > e.event.friendlyHealthPct.maxHpPct || healthPct < e.event.friendlyHealthPct.minHpPct) continue; - target = (*itr)->ToUnit(); + unitTarget = target->ToUnit(); break; } } - delete _targets; - - if (!target) + if (!unitTarget) return; - ProcessTimedAction(e, e.event.friendlyHealthPct.repeatMin, e.event.friendlyHealthPct.repeatMax, target); + ProcessTimedAction(e, e.event.friendlyHealthPct.repeatMin, e.event.friendlyHealthPct.repeatMax, unitTarget); break; } case SMART_EVENT_DISTANCE_CREATURE: @@ -4143,7 +3450,7 @@ void SmartScript::RemoveStoredEvent(uint32 id) } } -WorldObject* SmartScript::GetBaseObject() +WorldObject* SmartScript::GetBaseObject() const { WorldObject* obj = nullptr; if (me) @@ -4396,7 +3703,7 @@ void SmartScript::OnMoveInLineOfSight(Unit* who) } // SmartScript end -Unit* SmartScript::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) +Unit* SmartScript::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) const { if (!me) return nullptr; @@ -4409,27 +3716,27 @@ Unit* SmartScript::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) return unit; } -void SmartScript::DoFindFriendlyCC(std::list<Creature*>& _list, float range) +void SmartScript::DoFindFriendlyCC(std::vector<Creature*>& creatures, float range) const { if (!me) return; Trinity::FriendlyCCedInRange u_check(me, range); - Trinity::CreatureListSearcher<Trinity::FriendlyCCedInRange> searcher(me, _list, u_check); + Trinity::CreatureListSearcher<Trinity::FriendlyCCedInRange> searcher(me, creatures, u_check); Cell::VisitGridObjects(me, searcher, range); } -void SmartScript::DoFindFriendlyMissingBuff(std::list<Creature*>& list, float range, uint32 spellid) +void SmartScript::DoFindFriendlyMissingBuff(std::vector<Creature*>& creatures, float range, uint32 spellid) const { if (!me) return; Trinity::FriendlyMissingBuffInRange u_check(me, range, spellid); - Trinity::CreatureListSearcher<Trinity::FriendlyMissingBuffInRange> searcher(me, list, u_check); + Trinity::CreatureListSearcher<Trinity::FriendlyMissingBuffInRange> searcher(me, creatures, u_check); Cell::VisitGridObjects(me, searcher, range); } -Unit* SmartScript::DoFindClosestFriendlyInRange(float range, bool playerOnly) +Unit* SmartScript::DoFindClosestFriendlyInRange(float range, bool playerOnly) const { if (!me) return nullptr; @@ -4470,7 +3777,7 @@ void SmartScript::SetScript9(SmartScriptHolder& e, uint32 entry) } } -Unit* SmartScript::GetLastInvoker(Unit* invoker) +Unit* SmartScript::GetLastInvoker(Unit* invoker) const { // Look for invoker only on map of base object... Prevents multithreaded crashes if (WorldObject* baseObject = GetBaseObject()) diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index ab35932d4ac..44575845049 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -43,20 +43,20 @@ class TC_GAME_API SmartScript void ProcessEventsFor(SMART_EVENT e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = nullptr, GameObject* gob = nullptr, std::string const& varString = ""); void ProcessEvent(SmartScriptHolder& e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = nullptr, GameObject* gob = nullptr, std::string const& varString = ""); bool CheckTimer(SmartScriptHolder const& e) const; - void RecalcTimer(SmartScriptHolder& e, uint32 min, uint32 max); + static void RecalcTimer(SmartScriptHolder& e, uint32 min, uint32 max); void UpdateTimer(SmartScriptHolder& e, uint32 const diff); - void InitTimer(SmartScriptHolder& e); + static void InitTimer(SmartScriptHolder& e); void ProcessAction(SmartScriptHolder& e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = nullptr, GameObject* gob = nullptr, std::string const& varString = ""); void ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = nullptr, GameObject* gob = nullptr, std::string const& varString = ""); - ObjectList* GetTargets(SmartScriptHolder const& e, Unit* invoker = nullptr); - ObjectList* GetWorldObjectsInDist(float dist); + void GetTargets(ObjectVector& targets, SmartScriptHolder const& e, Unit* invoker = nullptr) const; + void GetWorldObjectsInDist(ObjectVector& objects, float dist) const; void InstallTemplate(SmartScriptHolder const& e); - SmartScriptHolder CreateSmartEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 phaseMask = 0); + static SmartScriptHolder CreateSmartEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 phaseMask = 0); void AddEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, uint32 event_param5, SMART_ACTION action, uint32 action_param1, uint32 action_param2, uint32 action_param3, uint32 action_param4, uint32 action_param5, uint32 action_param6, SMARTAI_TARGETS t, uint32 target_param1, uint32 target_param2, uint32 target_param3, uint32 phaseMask = 0); void SetPathId(uint32 id) { mPathId = id; } uint32 GetPathId() const { return mPathId; } - WorldObject* GetBaseObject(); + WorldObject* GetBaseObject() const; WorldObject* GetBaseObjectOrUnit(Unit* unit); static bool IsUnit(WorldObject* obj); static bool IsPlayer(WorldObject* obj); @@ -67,16 +67,28 @@ class TC_GAME_API SmartScript void OnUpdate(const uint32 diff); void OnMoveInLineOfSight(Unit* who); - Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff); - void DoFindFriendlyCC(std::list<Creature*>& _list, float range); - void DoFindFriendlyMissingBuff(std::list<Creature*>& list, float range, uint32 spellid); - Unit* DoFindClosestFriendlyInRange(float range, bool playerOnly); + Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) const; + void DoFindFriendlyCC(std::vector<Creature*>& creatures, float range) const; + void DoFindFriendlyMissingBuff(std::vector<Creature*>& creatures, float range, uint32 spellid) const; + Unit* DoFindClosestFriendlyInRange(float range, bool playerOnly) const; bool IsSmart(Creature* c = NULL); bool IsSmartGO(GameObject* g = NULL); - void StoreTargetList(ObjectList* targets, uint32 id); - ObjectList* GetTargetList(uint32 id); + void StoreTargetList(ObjectVector const& targets, uint32 id) + { + // insert or replace + _storedTargets.erase(id); + _storedTargets.emplace(id, ObjectGuidVector(GetBaseObject(), targets)); + } + + ObjectVector const* GetStoredTargetVector(uint32 id) const + { + auto itr = _storedTargets.find(id); + if (itr != _storedTargets.end()) + return itr->second.GetObjectVector(); + return nullptr; + } void StoreCounter(uint32 id, uint32 value, uint32 reset); uint32 GetCounterValue(uint32 id) const; @@ -84,14 +96,12 @@ class TC_GAME_API SmartScript GameObject* FindGameObjectNear(WorldObject* searchObject, ObjectGuid::LowType guid) const; Creature* FindCreatureNear(WorldObject* searchObject, ObjectGuid::LowType guid) const; - ObjectListMap* mTargetStorage; - void OnReset(); void ResetBaseObject(); //TIMED_ACTIONLIST (script type 9 aka script9) void SetScript9(SmartScriptHolder& e, uint32 entry); - Unit* GetLastInvoker(Unit* invoker = nullptr); + Unit* GetLastInvoker(Unit* invoker = nullptr) const; ObjectGuid mLastInvoker; typedef std::unordered_map<uint32, uint32> CounterMap; CounterMap mCounterList; @@ -137,6 +147,8 @@ class TC_GAME_API SmartScript uint32 mTalkerEntry; bool mUseTextTimer; + ObjectVectorMap _storedTargets; + SMARTAI_TEMPLATE mTemplate; void InstallEvents(); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 7e660acf4a7..ec3cdbc9f19 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -1093,24 +1093,39 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) break; } case SMART_ACTION_RANDOM_EMOTE: - if (e.action.randomEmote.emote1 && !IsEmoteValid(e, e.action.randomEmote.emote1)) - return false; - - if (e.action.randomEmote.emote2 && !IsEmoteValid(e, e.action.randomEmote.emote2)) - return false; - - if (e.action.randomEmote.emote3 && !IsEmoteValid(e, e.action.randomEmote.emote3)) - return false; - - if (e.action.randomEmote.emote4 && !IsEmoteValid(e, e.action.randomEmote.emote4)) + { + if (std::all_of(e.action.randomEmote.emotes.begin(), e.action.randomEmote.emotes.end(), [](uint32 emote) { return emote == 0; })) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u does not have any non-zero emote", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); return false; + } - if (e.action.randomEmote.emote5 && !IsEmoteValid(e, e.action.randomEmote.emote5)) + for (uint32 emote : e.action.randomEmote.emotes) + if (emote && !IsEmoteValid(e, emote)) + return false; + break; + } + case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST: + { + if (std::all_of(e.action.randTimedActionList.actionLists.begin(), e.action.randTimedActionList.actionLists.end(), [](uint32 actionList) { return actionList == 0; })) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u does not have any non-zero action list", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); return false; - - if (e.action.randomEmote.emote6 && !IsEmoteValid(e, e.action.randomEmote.emote6)) + } + break; + } + case SMART_ACTION_START_CLOSEST_WAYPOINT: + { + if (std::all_of(e.action.closestWaypointFromList.wps.begin(), e.action.closestWaypointFromList.wps.end(), [](uint32 wp) { return wp == 0; })) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u does not have any non-zero waypoint id", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); return false; + } break; + } case SMART_ACTION_RANDOM_SOUND: { if (std::all_of(std::begin(e.action.randomSound.sounds), std::end(e.action.randomSound.sounds), [](uint32 sound) { return sound == 0; })) @@ -1194,32 +1209,34 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return false; break; case SMART_ACTION_RANDOM_PHASE: + { + if (std::all_of(e.action.randomPhase.phases.begin(), e.action.randomPhase.phases.end(), [](uint32 phase) { return phase == 0; })) { - if (e.action.randomPhase.phase1 >= SMART_EVENT_PHASE_MAX || - e.action.randomPhase.phase2 >= SMART_EVENT_PHASE_MAX || - e.action.randomPhase.phase3 >= SMART_EVENT_PHASE_MAX || - e.action.randomPhase.phase4 >= SMART_EVENT_PHASE_MAX || - e.action.randomPhase.phase5 >= SMART_EVENT_PHASE_MAX || - e.action.randomPhase.phase6 >= SMART_EVENT_PHASE_MAX) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u attempts to set invalid phase, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); - return false; - } + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u does not have any non-zero phase", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); + return false; + } + + if (std::any_of(e.action.randomPhase.phases.begin(), e.action.randomPhase.phases.end(), [](uint32 phase) { return phase >= SMART_EVENT_PHASE_MAX; })) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u attempts to set invalid phase, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); + return false; } break; + } case SMART_ACTION_RANDOM_PHASE_RANGE: //PhaseMin, PhaseMax + { + if (e.action.randomPhaseRange.phaseMin >= SMART_EVENT_PHASE_MAX || + e.action.randomPhaseRange.phaseMax >= SMART_EVENT_PHASE_MAX) { - if (e.action.randomPhaseRange.phaseMin >= SMART_EVENT_PHASE_MAX || - e.action.randomPhaseRange.phaseMax >= SMART_EVENT_PHASE_MAX) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u attempts to set invalid phase, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); - return false; - } - - if (!IsMinMaxValid(e, e.action.randomPhaseRange.phaseMin, e.action.randomPhaseRange.phaseMax)) - return false; - break; + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u attempts to set invalid phase, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); + return false; } + + if (!IsMinMaxValid(e, e.action.randomPhaseRange.phaseMin, e.action.randomPhaseRange.phaseMax)) + return false; + break; + } case SMART_ACTION_SUMMON_CREATURE: { if (!IsCreatureValid(e, e.action.summonCreature.creature)) @@ -1351,7 +1368,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) } case SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST: { - if (!IsMinMaxValid(e, e.action.randTimedActionList.entry1, e.action.randTimedActionList.entry2)) + if (!IsMinMaxValid(e, e.action.randTimedActionList.actionLists[0], e.action.randTimedActionList.actionLists[1])) return false; break; } @@ -1406,11 +1423,14 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) { if (e.GetScriptType() == SMART_SCRIPT_TYPE_CREATURE) { - int8 equipId = (int8)e.action.equip.entry; - if (equipId && !sObjectMgr->GetEquipmentInfo(e.entryOrGuid, equipId)) + if (int8 equipId = static_cast<int8>(e.action.equip.entry)) { - TC_LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info id %u for creature " SI64FMTD ", skipped.", equipId, e.entryOrGuid); - return false; + EquipmentInfo const* eInfo = sObjectMgr->GetEquipmentInfo(e.entryOrGuid, equipId); + if (!eInfo) + { + TC_LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info id %u for creature " SI64FMTD ", skipped.", equipId, e.entryOrGuid); + return false; + } } } break; @@ -1513,7 +1533,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) break; } - case SMART_ACTION_START_CLOSEST_WAYPOINT: case SMART_ACTION_FOLLOW: case SMART_ACTION_SET_ORIENTATION: case SMART_ACTION_STORE_TARGET_LIST: @@ -1559,7 +1578,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_SET_NPC_FLAG: case SMART_ACTION_ADD_NPC_FLAG: case SMART_ACTION_REMOVE_NPC_FLAG: - case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST: case SMART_ACTION_RANDOM_MOVE: case SMART_ACTION_SET_UNIT_FIELD_BYTES_1: case SMART_ACTION_REMOVE_UNIT_FIELD_BYTES_1: @@ -1698,35 +1716,3 @@ CacheSpellContainerBounds SmartAIMgr::GetCreateItemSpellContainerBounds(uint32 i { return CreateItemSpellStore.equal_range(itemId); } - -ObjectGuidList::ObjectGuidList(ObjectList* objectList, WorldObject* baseObject) -{ - ASSERT(objectList != NULL); - m_objectList = objectList; - m_baseObject = baseObject; - m_guidList = new GuidList(); - - for (ObjectList::iterator itr = objectList->begin(); itr != objectList->end(); ++itr) - { - m_guidList->push_back((*itr)->GetGUID()); - } -} - -ObjectList* ObjectGuidList::GetObjectList() -{ - if (m_baseObject) - { - //sanitize list using m_guidList - m_objectList->clear(); - - for (GuidList::iterator itr = m_guidList->begin(); itr != m_guidList->end(); ++itr) - { - if (WorldObject* obj = ObjectAccessor::GetWorldObject(*m_baseObject, *itr)) - m_objectList->push_back(obj); - else - TC_LOG_DEBUG("scripts.ai", "SmartScript::mTargetStorage stores a guid to an invalid object: %s", itr->ToString().c_str()); - } - } - - return m_objectList; -} diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index efd361cfb15..c3eea9fbaf4 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -18,13 +18,15 @@ #ifndef TRINITY_SMARTSCRIPTMGR_H #define TRINITY_SMARTSCRIPTMGR_H +#include "Creature.h" #include "Define.h" +#include "ObjectAccessor.h" #include "ObjectGuid.h" +#include "UnitDefines.h" #include <map> #include <string> #include <unordered_map> -class WorldObject; enum SpellEffIndex : uint8; struct WayPoint @@ -658,12 +660,7 @@ struct SmartAction struct { - uint32 emote1; - uint32 emote2; - uint32 emote3; - uint32 emote4; - uint32 emote5; - uint32 emote6; + std::array<uint32, SMART_ACTION_PARAM_COUNT> emotes; } randomEmote; struct @@ -756,12 +753,7 @@ struct SmartAction struct { - uint32 phase1; - uint32 phase2; - uint32 phase3; - uint32 phase4; - uint32 phase5; - uint32 phase6; + std::array<uint32, SMART_ACTION_PARAM_COUNT> phases; } randomPhase; struct @@ -960,9 +952,7 @@ struct SmartAction { uint32 entry; uint32 mask; - uint32 slot1; - uint32 slot2; - uint32 slot3; + std::array<uint32, MAX_EQUIPMENT_ITEMS> slots; } equip; struct @@ -996,12 +986,7 @@ struct SmartAction struct { - uint32 entry1; - uint32 entry2; - uint32 entry3; - uint32 entry4; - uint32 entry5; - uint32 entry6; + std::array<uint32, SMART_ACTION_PARAM_COUNT> actionLists; } randTimedActionList; struct @@ -1111,12 +1096,7 @@ struct SmartAction struct { - uint32 wp1; - uint32 wp2; - uint32 wp3; - uint32 wp4; - uint32 wp5; - uint32 wp6; + std::array<uint32, SMART_ACTION_PARAM_COUNT> wps; } closestWaypointFromList; struct @@ -1569,31 +1549,43 @@ struct SmartScriptHolder typedef std::unordered_map<uint32, WayPoint*> WPPath; -typedef std::list<WorldObject*> ObjectList; +typedef std::vector<WorldObject*> ObjectVector; -class ObjectGuidList +class ObjectGuidVector { - ObjectList* m_objectList; - GuidList* m_guidList; - WorldObject* m_baseObject; + public: + ObjectGuidVector(WorldObject* baseObject, ObjectVector const& objectVector) : _baseObject(baseObject), _objectVector(objectVector) + { + _guidVector.reserve(_objectVector.size()); + for (WorldObject* obj : _objectVector) + _guidVector.push_back(obj->GetGUID()); + } -public: - ObjectGuidList(ObjectList* objectList, WorldObject* baseObject); + ObjectVector const* GetObjectVector() const + { + UpdateObjects(); + return &_objectVector; + } - ObjectList* GetObjectList(); + ~ObjectGuidVector() { } - bool Equals(ObjectList* objectList) - { - return m_objectList == objectList; - } + private: + WorldObject* const _baseObject; + mutable ObjectVector _objectVector; - ~ObjectGuidList() - { - delete m_objectList; - delete m_guidList; - } + GuidVector _guidVector; + + //sanitize vector using _guidVector + void UpdateObjects() const + { + _objectVector.clear(); + + for (ObjectGuid const& guid : _guidVector) + if (WorldObject* obj = ObjectAccessor::GetWorldObject(*_baseObject, guid)) + _objectVector.push_back(obj); + } }; -typedef std::unordered_map<uint32, ObjectGuidList*> ObjectListMap; +typedef std::unordered_map<uint32, ObjectGuidVector> ObjectVectorMap; class TC_GAME_API SmartWaypointMgr { |