diff options
| author | ariel- <ariel-@users.noreply.github.com> | 2017-06-19 23:20:06 -0300 |
|---|---|---|
| committer | ariel- <ariel-@users.noreply.github.com> | 2017-06-19 23:20:06 -0300 |
| commit | 85a7d5ce9ac68b30da2277cc91d4b70358f1880d (patch) | |
| tree | df3d2084ee2e35008903c03178039b9c986e2d08 /src/server/game/AI/SmartScripts | |
| parent | 052fc24315ace866ea1cf610e85df119b68100c9 (diff) | |
Core: ported headers cleanup from master branch
Diffstat (limited to 'src/server/game/AI/SmartScripts')
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartAI.cpp | 29 | ||||
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartAI.h | 24 | ||||
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.cpp | 243 | ||||
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.h | 213 | ||||
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.cpp | 222 | ||||
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.h | 215 |
6 files changed, 496 insertions, 450 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index df5fe1d6b7b..682f92f1ee6 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -15,15 +15,16 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "DatabaseEnv.h" -#include "ObjectMgr.h" -#include "ObjectDefines.h" -#include "GridDefines.h" -#include "GridNotifiers.h" -#include "SpellMgr.h" -#include "Cell.h" -#include "Group.h" #include "SmartAI.h" +#include "Creature.h" +#include "DBCStructure.h" +#include "GameObject.h" +#include "Group.h" +#include "Log.h" +#include "MotionMaster.h" +#include "ObjectAccessor.h" +#include "PetDefines.h" +#include "Player.h" #include "ScriptMgr.h" #include "Vehicle.h" @@ -530,7 +531,7 @@ void SmartAI::MoveInLineOfSight(Unit* who) CreatureAI::MoveInLineOfSight(who); } -bool SmartAI::CanAIAttack(const Unit* /*who*/) const +bool SmartAI::CanAIAttack(Unit const* /*who*/) const { return !(me->HasReactState(REACT_PASSIVE)); } @@ -663,12 +664,12 @@ void SmartAI::AttackStart(Unit* who) } } -void SmartAI::SpellHit(Unit* unit, const SpellInfo* spellInfo) +void SmartAI::SpellHit(Unit* unit, SpellInfo const* spellInfo) { GetScript()->ProcessEventsFor(SMART_EVENT_SPELLHIT, unit, 0, 0, false, spellInfo); } -void SmartAI::SpellHitTarget(Unit* target, const SpellInfo* spellInfo) +void SmartAI::SpellHitTarget(Unit* target, SpellInfo const* spellInfo) { GetScript()->ProcessEventsFor(SMART_EVENT_SPELLHIT_TARGET, target, 0, 0, false, spellInfo); } @@ -816,7 +817,7 @@ bool SmartAI::GossipSelect(Player* player, uint32 menuId, uint32 gossipListId) return _gossipReturn; } -bool SmartAI::GossipSelectCode(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/, const char* /*code*/) +bool SmartAI::GossipSelectCode(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/, char const* /*code*/) { return false; } @@ -1005,7 +1006,7 @@ bool SmartGameObjectAI::GossipSelect(Player* player, uint32 sender, uint32 actio } // Called when a player selects a gossip with a code in the gameobject's gossip menu. -bool SmartGameObjectAI::GossipSelectCode(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/, const char* /*code*/) +bool SmartGameObjectAI::GossipSelectCode(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/, char const* /*code*/) { return false; } @@ -1055,7 +1056,7 @@ void SmartGameObjectAI::EventInform(uint32 eventId) GetScript()->ProcessEventsFor(SMART_EVENT_GO_EVENT_INFORM, nullptr, eventId); } -void SmartGameObjectAI::SpellHit(Unit* unit, const SpellInfo* spellInfo) +void SmartGameObjectAI::SpellHit(Unit* unit, SpellInfo const* spellInfo) { GetScript()->ProcessEventsFor(SMART_EVENT_SPELLHIT, unit, 0, 0, false, spellInfo); } diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index e295f1bc7c4..b5ed74c4edb 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -18,15 +18,13 @@ #ifndef TRINITY_SMARTAI_H #define TRINITY_SMARTAI_H -#include "Common.h" -#include "Creature.h" +#include "Define.h" #include "CreatureAI.h" -#include "Unit.h" -#include "Spell.h" - -#include "SmartScript.h" -#include "SmartScriptMgr.h" #include "GameObjectAI.h" +#include "Position.h" +#include "SmartScript.h" + +struct WayPoint; enum SmartEscortState { @@ -100,10 +98,10 @@ class TC_GAME_API SmartAI : public CreatureAI void MoveInLineOfSight(Unit* who) override; // Called when hit by a spell - void SpellHit(Unit* unit, const SpellInfo* spellInfo) override; + void SpellHit(Unit* unit, SpellInfo const* spellInfo) override; // Called when spell hits a target - void SpellHitTarget(Unit* target, const SpellInfo* spellInfo) override; + void SpellHitTarget(Unit* target, SpellInfo const* spellInfo) override; // Called at any Damage from any attacker (before damage apply) void DamageTaken(Unit* doneBy, uint32& damage) override; @@ -142,7 +140,7 @@ class TC_GAME_API SmartAI : public CreatureAI void OnCharmed(bool apply) override; // Called when victim is in line of sight - bool CanAIAttack(const Unit* who) const override; + bool CanAIAttack(Unit const* who) const override; // Used in scripts to share variables void DoAction(int32 param = 0) override; @@ -180,7 +178,7 @@ class TC_GAME_API SmartAI : public CreatureAI bool GossipHello(Player* player) override; bool GossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override; - bool GossipSelectCode(Player* player, uint32 menuId, uint32 gossipListId, const char* code) override; + bool GossipSelectCode(Player* player, uint32 menuId, uint32 gossipListId, char const* code) override; void QuestAccept(Player* player, Quest const* quest) override; void QuestReward(Player* player, Quest const* quest, uint32 opt) override; void OnGameEvent(bool start, uint16 eventId) override; @@ -262,7 +260,7 @@ class TC_GAME_API SmartGameObjectAI : public GameObjectAI bool GossipHello(Player* player) override; bool OnReportUse(Player* player) override; bool GossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override; - bool GossipSelectCode(Player* player, uint32 menuId, uint32 gossipListId, const char* code) override; + bool GossipSelectCode(Player* player, uint32 menuId, uint32 gossipListId, char const* code) override; void QuestAccept(Player* player, Quest const* quest) override; void QuestReward(Player* player, Quest const* quest, uint32 opt) override; void Destroyed(Player* player, uint32 eventId) override; @@ -271,7 +269,7 @@ class TC_GAME_API SmartGameObjectAI : public GameObjectAI void OnGameEvent(bool start, uint16 eventId) override; void OnLootStateChanged(uint32 state, Unit* unit) override; void EventInform(uint32 eventId) override; - void SpellHit(Unit* unit, const SpellInfo* spellInfo) override; + void SpellHit(Unit* unit, SpellInfo const* spellInfo) override; void SetGossipReturn(bool val) { _gossipReturn = val; } diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 6dc0bd62256..fe86978b0db 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -15,27 +15,31 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Cell.h" +#include "SmartScript.h" #include "CellImpl.h" #include "ChatTextBuilder.h" +#include "Creature.h" #include "CreatureTextMgr.h" -#include "DatabaseEnv.h" +#include "CreatureTextMgrImpl.h" +#include "GameEventMgr.h" +#include "GameObject.h" #include "GossipDef.h" -#include "GridDefines.h" -#include "GridNotifiers.h" #include "GridNotifiersImpl.h" #include "Group.h" #include "InstanceScript.h" #include "Language.h" -#include "ObjectDefines.h" +#include "Log.h" +#include "Map.h" +#include "MotionMaster.h" +#include "ObjectAccessor.h" #include "ObjectMgr.h" -#include "ScriptedCreature.h" -#include "ScriptedGossip.h" +#include "Random.h" #include "SmartAI.h" -#include "SmartScript.h" +#include "SpellAuras.h" #include "SpellMgr.h" +#include "TemporarySummon.h" #include "Vehicle.h" -#include "GameEventMgr.h" +#include <G3D/Quat.h> SmartScript::SmartScript() { @@ -57,6 +61,97 @@ SmartScript::~SmartScript() { } +bool SmartScript::IsSmart(Creature* c /*= nullptr*/) +{ + bool smart = true; + if (c && c->GetAIName() != "SmartAI") + smart = false; + + if (!me || me->GetAIName() != "SmartAI") + smart = false; + + if (!smart) + TC_LOG_ERROR("sql.sql", "SmartScript: Action target Creature (GUID: %u Entry: %u) is not using SmartAI, action called by Creature (GUID: %u Entry: %u) skipped to prevent crash.", c ? c->GetSpawnId() : 0, c ? c->GetEntry() : 0, me ? me->GetSpawnId() : 0, me ? me->GetEntry() : 0); + + return smart; +} + +bool SmartScript::IsSmartGO(GameObject* g /*= nullptr*/) +{ + bool smart = true; + if (g && g->GetAIName() != "SmartGameObjectAI") + smart = false; + + if (!go || go->GetAIName() != "SmartGameObjectAI") + smart = false; + if (!smart) + TC_LOG_ERROR("sql.sql", "SmartScript: Action target GameObject (GUID: %u Entry: %u) is not using SmartGameObjectAI, action called by GameObject (GUID: %u Entry: %u) skipped to prevent crash.", g ? g->GetSpawnId() : 0, g ? g->GetEntry() : 0, go ? go->GetSpawnId() : 0, go ? go->GetEntry() : 0); + + return smart; +} + +void SmartScript::StoreTargetList(ObjectVector const& targets, uint32 id) +{ + // insert or replace + _storedTargets.erase(id); + _storedTargets.emplace(id, ObjectGuidVector(targets)); +} + +ObjectVector const* SmartScript::GetStoredTargetVector(uint32 id, WorldObject const& ref) const +{ + auto itr = _storedTargets.find(id); + if (itr != _storedTargets.end()) + return itr->second.GetObjectVector(ref); + return nullptr; +} + +void SmartScript::StoreCounter(uint32 id, uint32 value, uint32 reset) +{ + CounterMap::iterator itr = mCounterList.find(id); + if (itr != mCounterList.end()) + { + if (reset == 0) + itr->second += value; + else + itr->second = value; + } + else + mCounterList.insert(std::make_pair(id, value)); + + ProcessEventsFor(SMART_EVENT_COUNTER_SET, nullptr, id); +} + +uint32 SmartScript::GetCounterValue(uint32 id) const +{ + CounterMap::const_iterator itr = mCounterList.find(id); + if (itr != mCounterList.end()) + return itr->second; + return 0; +} + +GameObject* SmartScript::FindGameObjectNear(WorldObject* searchObject, ObjectGuid::LowType guid) const +{ + auto bounds = searchObject->GetMap()->GetGameObjectBySpawnIdStore().equal_range(guid); + if (bounds.first == bounds.second) + return nullptr; + + return bounds.first->second; +} + +Creature* SmartScript::FindCreatureNear(WorldObject* searchObject, ObjectGuid::LowType guid) const +{ + auto bounds = searchObject->GetMap()->GetCreatureBySpawnIdStore().equal_range(guid); + if (bounds.first == bounds.second) + return nullptr; + + auto creatureItr = std::find_if(bounds.first, bounds.second, [](Map::CreatureBySpawnIdContainer::value_type const& pair) + { + return pair.second->IsAlive(); + }); + + return creatureItr != bounds.second ? creatureItr->second : bounds.first->second; +} + void SmartScript::OnReset() { ResetBaseObject(); @@ -73,7 +168,37 @@ void SmartScript::OnReset() mCounterList.clear(); } -void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob) +void SmartScript::ResetBaseObject() +{ + WorldObject* lookupRoot = me; + if (!lookupRoot) + lookupRoot = go; + + if (lookupRoot) + { + if (!meOrigGUID.IsEmpty()) + { + if (Creature* m = ObjectAccessor::GetCreature(*lookupRoot, meOrigGUID)) + { + me = m; + go = nullptr; + } + } + + if (!goOrigGUID.IsEmpty()) + { + if (GameObject* o = ObjectAccessor::GetGameObject(*lookupRoot, goOrigGUID)) + { + me = nullptr; + go = o; + } + } + } + goOrigGUID.Clear(); + meOrigGUID.Clear(); +} + +void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob) { for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i) { @@ -87,7 +212,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) +void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob) { // calc random if (e.GetEventType() != SMART_EVENT_LINK && e.event.event_chance < 100 && e.event.event_chance) @@ -314,7 +439,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u case SMART_ACTION_RANDOM_EMOTE: { std::vector<uint32> emotes; - std::copy_if(e.action.randomEmote.emotes.begin(), e.action.randomEmote.emotes.end(), + std::copy_if(std::begin(e.action.randomEmote.emotes), std::end(e.action.randomEmote.emotes), std::back_inserter(emotes), [](uint32 emote) { return emote != 0; }); for (WorldObject* target : targets) @@ -736,7 +861,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u break; std::vector<uint32> phases; - std::copy_if(e.action.randomPhase.phases.begin(), e.action.randomPhase.phases.end(), + std::copy_if(std::begin(e.action.randomPhase.phases), std::end(e.action.randomPhase.phases), std::back_inserter(phases), [](uint32 phase) { return phase != 0; }); uint32 phase = Trinity::Containers::SelectRandomContainerElement(phases); @@ -1064,14 +1189,14 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u for (WorldObject* target : targets) { Position pos = target->GetPositionWithOffset(Position(e.target.x, e.target.y, e.target.z, e.target.o)); - G3D::Quat rot = G3D::Matrix3::fromEulerAnglesZYX(pos.GetOrientation(), 0.f, 0.f); + QuaternionData rot = QuaternionData::fromEulerAnglesZYX(pos.GetOrientation(), 0.f, 0.f); GetBaseObject()->SummonGameObject(e.action.summonGO.entry, pos, rot, e.action.summonGO.despawnTime); } if (e.GetTargetType() != SMART_TARGET_POSITION) break; - G3D::Quat rot = G3D::Matrix3::fromEulerAnglesZYX(e.target.o, 0.f, 0.f); + QuaternionData rot = QuaternionData::fromEulerAnglesZYX(e.target.o, 0.f, 0.f); GetBaseObject()->SummonGameObject(e.action.summonGO.entry, Position(e.target.x, e.target.y, e.target.z, e.target.o), rot, e.action.summonGO.despawnTime); break; } @@ -1350,7 +1475,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u std::copy(std::begin(eInfo->ItemEntry), std::end(eInfo->ItemEntry), std::begin(slot)); } else - std::copy(std::begin(e.action.equip.slots), std::end(e.action.equip.slots), std::begin(slot)); + { + slot[0] = e.action.equip.slot1; + slot[1] = e.action.equip.slot2; + slot[2] = e.action.equip.slot3; + } for (uint32 i = 0; i < MAX_EQUIPMENT_ITEMS; ++i) if (!e.action.equip.mask || (e.action.equip.mask & (1 << i))) @@ -1498,7 +1627,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u break; ObjectVector casters; - GetTargets(casters, CreateEvent(SMART_EVENT_UPDATE_IC, 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); + GetTargets(casters, CreateSmartEvent(SMART_EVENT_UPDATE_IC, 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 (WorldObject* caster : casters) { @@ -1533,7 +1662,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST: { std::vector<uint32> actionLists; - std::copy_if(e.action.randTimedActionList.actionLists.begin(), e.action.randTimedActionList.actionLists.end(), + std::copy_if(std::begin(e.action.randTimedActionList.actionLists), std::end(e.action.randTimedActionList.actionLists), std::back_inserter(actionLists), [](uint32 actionList) { return actionList != 0; }); uint32 id = Trinity::Containers::SelectRandomContainerElement(actionLists); @@ -1738,9 +1867,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (e.action.sendGossipMenu.gossipMenuId) player->PrepareGossipMenu(GetBaseObject(), e.action.sendGossipMenu.gossipMenuId, true); else - ClearGossipMenuFor(player); + player->PlayerTalkClass->ClearMenus(); - SendGossipMenuFor(player, e.action.sendGossipMenu.gossipNpcTextId, GetBaseObject()->GetGUID()); + player->PlayerTalkClass->SendGossipMenu(e.action.sendGossipMenu.gossipNpcTextId, GetBaseObject()->GetGUID()); } } break; @@ -1861,7 +1990,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u case SMART_ACTION_START_CLOSEST_WAYPOINT: { std::vector<uint32> waypoints; - std::copy_if(e.action.closestWaypointFromList.wps.begin(), e.action.closestWaypointFromList.wps.end(), + std::copy_if(std::begin(e.action.closestWaypointFromList.wps), std::end(e.action.closestWaypointFromList.wps), std::back_inserter(waypoints), [](uint32 wp) { return wp != 0; }); float distanceToClosest = std::numeric_limits<float>::max(); @@ -1904,7 +2033,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u case SMART_ACTION_RANDOM_SOUND: { std::vector<uint32> sounds; - std::copy_if(e.action.randomSound.sounds.begin(), e.action.randomSound.sounds.end(), + std::copy_if(std::begin(e.action.randomSound.sounds), std::end(e.action.randomSound.sounds), std::back_inserter(sounds), [](uint32 sound) { return sound != 0; }); bool onlySelf = e.action.randomSound.onlySelf != 0; @@ -1975,7 +2104,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u case SMART_ACTION_TRIGGER_RANDOM_TIMED_EVENT: { uint32 eventId = urand(e.action.randomTimedEvent.minId, e.action.randomTimedEvent.maxId); - ProcessEventsFor((SMART_EVENT)SMART_EVENT_TIMED_EVENT_TRIGGERED, NULL, eventId); + ProcessEventsFor((SMART_EVENT)SMART_EVENT_TIMED_EVENT_TRIGGERED, nullptr, eventId); break; } @@ -2015,7 +2144,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } } -void SmartScript::ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob) +void SmartScript::ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob) { // We may want to execute action rarely and because of this if condition is not fulfilled the action will be rechecked in a long time if (sConditionMgr->IsObjectMeetingSmartEventConditions(e.entryOrGuid, e.event_id, e.source_type, unit, GetBaseObject())) @@ -2105,10 +2234,10 @@ void SmartScript::InstallTemplate(SmartScriptHolder const& e) void SmartScript::AddEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, 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) { - mInstallEvents.push_back(CreateEvent(e, event_flags, event_param1, event_param2, event_param3, event_param4, action, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6, t, target_param1, target_param2, target_param3, phaseMask)); + mInstallEvents.push_back(CreateSmartEvent(e, event_flags, event_param1, event_param2, event_param3, event_param4, action, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6, t, target_param1, target_param2, target_param3, phaseMask)); } -SmartScriptHolder SmartScript::CreateEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, 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) +SmartScriptHolder SmartScript::CreateSmartEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, 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) { SmartScriptHolder script; script.event.type = e; @@ -2373,13 +2502,13 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, } case SMART_TARGET_CLOSEST_CREATURE: { - if (Creature* target = GetClosestCreatureWithEntry(baseObject, e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100), !e.target.closest.dead)) + if (Creature* target = baseObject->FindNearestCreature(e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100), !e.target.closest.dead)) targets.push_back(target); break; } case SMART_TARGET_CLOSEST_GAMEOBJECT: { - if (GameObject* target = GetClosestGameObjectWithEntry(baseObject, e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100))) + if (GameObject* target = baseObject->FindNearestGameObject(e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100))) targets.push_back(target); break; } @@ -2496,7 +2625,7 @@ void SmartScript::GetWorldObjectsInDist(ObjectVector& targets, float dist) const Cell::VisitAllObjects(obj, searcher, dist); } -void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob) +void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob) { if (!e.active && e.GetEventType() != SMART_EVENT_LINK) return; @@ -3182,6 +3311,62 @@ void SmartScript::InstallEvents() } } +void SmartScript::RemoveStoredEvent(uint32 id) +{ + if (!mStoredEvents.empty()) + { + for (auto i = mStoredEvents.begin(); i != mStoredEvents.end(); ++i) + { + if (i->event_id == id) + { + mStoredEvents.erase(i); + return; + } + } + } +} + +WorldObject* SmartScript::GetBaseObject() const +{ + WorldObject* obj = nullptr; + if (me) + obj = me; + else if (go) + obj = go; + return obj; +} + +bool SmartScript::IsUnit(WorldObject* obj) +{ + return obj && (obj->GetTypeId() == TYPEID_UNIT || obj->GetTypeId() == TYPEID_PLAYER); +} + +bool SmartScript::IsPlayer(WorldObject* obj) +{ + return obj && obj->GetTypeId() == TYPEID_PLAYER; +} + +bool SmartScript::IsCreature(WorldObject* obj) +{ + return obj && obj->GetTypeId() == TYPEID_UNIT; +} + +bool SmartScript::IsCharmedCreature(WorldObject* obj) +{ + if (!obj) + return false; + + if (Creature* creatureObj = obj->ToCreature()) + return creatureObj->IsCharmed(); + + return false; +} + +bool SmartScript::IsGameObject(WorldObject* obj) +{ + return obj && obj->GetTypeId() == TYPEID_GAMEOBJECT; +} + void SmartScript::OnUpdate(uint32 const diff) { if ((mScriptType == SMART_SCRIPT_TYPE_CREATURE || mScriptType == SMART_SCRIPT_TYPE_GAMEOBJECT) && !GetBaseObject()) diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index cf10f7d15f4..b0269bc45c2 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -18,15 +18,16 @@ #ifndef TRINITY_SMARTSCRIPT_H #define TRINITY_SMARTSCRIPT_H -#include "Common.h" -#include "Creature.h" -#include "CreatureAI.h" -#include "Unit.h" -#include "Spell.h" -#include "GridNotifiers.h" - +#include "Define.h" #include "SmartScriptMgr.h" -//#include "SmartAI.h" + +class Creature; +class GameObject; +class Player; +class SpellInfo; +class Unit; +class WorldObject; +struct AreaTriggerEntry; class TC_GAME_API SmartScript { @@ -38,61 +39,27 @@ class TC_GAME_API SmartScript void GetScript(); void FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at); - void ProcessEventsFor(SMART_EVENT e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = nullptr, GameObject* gob = nullptr); - void ProcessEvent(SmartScriptHolder& e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = nullptr, GameObject* gob = nullptr); + void ProcessEventsFor(SMART_EVENT e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, SpellInfo const* spell = nullptr, GameObject* gob = nullptr); + void ProcessEvent(SmartScriptHolder& e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, SpellInfo const* spell = nullptr, GameObject* gob = nullptr); bool CheckTimer(SmartScriptHolder const& e) const; static void RecalcTimer(SmartScriptHolder& e, uint32 min, uint32 max); void UpdateTimer(SmartScriptHolder& e, uint32 const diff); 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); - 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); + void ProcessAction(SmartScriptHolder& e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, SpellInfo const* spell = nullptr, GameObject* gob = nullptr); + void ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, SpellInfo const* spell = nullptr, GameObject* gob = nullptr); void GetTargets(ObjectVector& targets, SmartScriptHolder const& e, Unit* invoker = nullptr) const; void GetWorldObjectsInDist(ObjectVector& objects, float dist) const; void InstallTemplate(SmartScriptHolder const& e); - static SmartScriptHolder CreateEvent(SMART_EVENT e, uint32 event_flags, uint32 event_param1, uint32 event_param2, uint32 event_param3, uint32 event_param4, 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, 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, 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() const - { - WorldObject* obj = nullptr; - if (me) - obj = me; - else if (go) - obj = go; - return obj; - } - - static bool IsUnit(WorldObject* obj) - { - return obj && (obj->GetTypeId() == TYPEID_UNIT || obj->GetTypeId() == TYPEID_PLAYER); - } - - static bool IsPlayer(WorldObject* obj) - { - return obj && obj->GetTypeId() == TYPEID_PLAYER; - } - - static bool IsCreature(WorldObject* obj) - { - return obj && obj->GetTypeId() == TYPEID_UNIT; - } - - static bool IsCharmedCreature(WorldObject* obj) - { - if (!obj) - return false; - - if (Creature* creatureObj = obj->ToCreature()) - return creatureObj->IsCharmed(); - - return false; - } - - static bool IsGameObject(WorldObject* obj) - { - return obj && obj->GetTypeId() == TYPEID_GAMEOBJECT; - } + WorldObject* GetBaseObject() const; + static bool IsUnit(WorldObject* obj); + static bool IsPlayer(WorldObject* obj); + static bool IsCreature(WorldObject* obj); + static bool IsCharmedCreature(WorldObject* obj); + static bool IsGameObject(WorldObject* obj); void OnUpdate(const uint32 diff); void OnMoveInLineOfSight(Unit* who); @@ -102,127 +69,20 @@ class TC_GAME_API SmartScript void DoFindFriendlyMissingBuff(std::vector<Creature*>& creatures, float range, uint32 spellid) const; Unit* DoFindClosestFriendlyInRange(float range, bool playerOnly) const; - void StoreTargetList(ObjectVector const& targets, uint32 id) - { - // insert or replace - _storedTargets.erase(id); - _storedTargets.emplace(id, ObjectGuidVector(targets)); - } - - bool IsSmart(Creature* c = nullptr) - { - bool smart = true; - if (c && c->GetAIName() != "SmartAI") - smart = false; - - if (!me || me->GetAIName() != "SmartAI") - smart = false; - - if (!smart) - TC_LOG_ERROR("sql.sql", "SmartScript: Action target Creature (GUID: %u Entry: %u) is not using SmartAI, action called by Creature (GUID: %u Entry: %u) skipped to prevent crash.", c ? c->GetSpawnId() : 0, c ? c->GetEntry() : 0, me ? me->GetSpawnId() : 0, me ? me->GetEntry() : 0); + bool IsSmart(Creature* c = nullptr); + bool IsSmartGO(GameObject* g = nullptr); - return smart; - } + void StoreTargetList(ObjectVector const& targets, uint32 id); + ObjectVector const* GetStoredTargetVector(uint32 id, WorldObject const& ref) const; - bool IsSmartGO(GameObject* g = nullptr) - { - bool smart = true; - if (g && g->GetAIName() != "SmartGameObjectAI") - smart = false; + void StoreCounter(uint32 id, uint32 value, uint32 reset); + uint32 GetCounterValue(uint32 id) const; - if (!go || go->GetAIName() != "SmartGameObjectAI") - smart = false; - if (!smart) - TC_LOG_ERROR("sql.sql", "SmartScript: Action target GameObject (GUID: %u Entry: %u) is not using SmartGameObjectAI, action called by GameObject (GUID: %u Entry: %u) skipped to prevent crash.", g ? g->GetSpawnId() : 0, g ? g->GetEntry() : 0, go ? go->GetSpawnId() : 0, go ? go->GetEntry() : 0); - - return smart; - } - - ObjectVector const* GetStoredTargetVector(uint32 id, WorldObject const& ref) const - { - auto itr = _storedTargets.find(id); - if (itr != _storedTargets.end()) - return itr->second.GetObjectVector(ref); - return nullptr; - } - - void StoreCounter(uint32 id, uint32 value, uint32 reset) - { - CounterMap::iterator itr = mCounterList.find(id); - if (itr != mCounterList.end()) - { - if (reset == 0) - itr->second += value; - else - itr->second = value; - } - else - mCounterList.insert(std::make_pair(id, value)); - - ProcessEventsFor(SMART_EVENT_COUNTER_SET, nullptr, id); - } - - uint32 GetCounterValue(uint32 id) const - { - CounterMap::const_iterator itr = mCounterList.find(id); - if (itr != mCounterList.end()) - return itr->second; - return 0; - } - - GameObject* FindGameObjectNear(WorldObject* searchObject, ObjectGuid::LowType guid) const - { - auto bounds = searchObject->GetMap()->GetGameObjectBySpawnIdStore().equal_range(guid); - if (bounds.first == bounds.second) - return nullptr; - - return bounds.first->second; - } - - Creature* FindCreatureNear(WorldObject* searchObject, ObjectGuid::LowType guid) const - { - auto bounds = searchObject->GetMap()->GetCreatureBySpawnIdStore().equal_range(guid); - if (bounds.first == bounds.second) - return nullptr; - - auto creatureItr = std::find_if(bounds.first, bounds.second, [](Map::CreatureBySpawnIdContainer::value_type const& pair) - { - return pair.second->IsAlive(); - }); - - return creatureItr != bounds.second ? creatureItr->second : bounds.first->second; - } + GameObject* FindGameObjectNear(WorldObject* searchObject, ObjectGuid::LowType guid) const; + Creature* FindCreatureNear(WorldObject* searchObject, ObjectGuid::LowType guid) const; void OnReset(); - void ResetBaseObject() - { - WorldObject* lookupRoot = me; - if (!lookupRoot) - lookupRoot = go; - - if (lookupRoot) - { - if (!meOrigGUID.IsEmpty()) - { - if (Creature* m = ObjectAccessor::GetCreature(*lookupRoot, meOrigGUID)) - { - me = m; - go = nullptr; - } - } - - if (!goOrigGUID.IsEmpty()) - { - if (GameObject* o = ObjectAccessor::GetGameObject(*lookupRoot, goOrigGUID)) - { - me = nullptr; - go = o; - } - } - } - goOrigGUID.Clear(); - meOrigGUID.Clear(); - } + void ResetBaseObject(); //TIMED_ACTIONLIST (script type 9 aka script9) void SetScript9(SmartScriptHolder& e, uint32 entry); @@ -265,20 +125,7 @@ class TC_GAME_API SmartScript SMARTAI_TEMPLATE mTemplate; void InstallEvents(); - void RemoveStoredEvent(uint32 id) - { - if (!mStoredEvents.empty()) - { - for (auto i = mStoredEvents.begin(); i != mStoredEvents.end(); ++i) - { - if (i->event_id == id) - { - mStoredEvents.erase(i); - return; - } - } - } - } + void RemoveStoredEvent(uint32 id); }; #endif diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index d2910208155..31282a934ac 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -15,18 +15,20 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "SmartScriptMgr.h" +#include "CreatureTextMgr.h" #include "DatabaseEnv.h" -#include "ObjectMgr.h" -#include "GridDefines.h" -#include "GridNotifiers.h" -#include "InstanceScript.h" -#include "SpellMgr.h" -#include "Cell.h" +#include "DBCStores.h" #include "GameEventMgr.h" -#include "CreatureTextMgr.h" +#include "InstanceScript.h" +#include "Log.h" +#include "MotionMaster.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" #include "SpellInfo.h" - -#include "SmartScriptMgr.h" +#include "SpellMgr.h" +#include "Timer.h" +#include "UnitDefines.h" SmartWaypointMgr* SmartWaypointMgr::instance() { @@ -380,6 +382,43 @@ void SmartAIMgr::LoadSmartAIFromDB() UnLoadHelperStores(); } +SmartAIEventList SmartAIMgr::GetScript(int32 entry, SmartScriptType type) +{ + SmartAIEventList temp; + if (mEventMap[uint32(type)].find(entry) != mEventMap[uint32(type)].end()) + return mEventMap[uint32(type)][entry]; + else + { + if (entry > 0)//first search is for guid (negative), do not drop error if not found + TC_LOG_DEBUG("scripts.ai", "SmartAIMgr::GetScript: Could not load Script for Entry %d ScriptType %u.", entry, uint32(type)); + return temp; + } +} + +SmartScriptHolder& SmartAIMgr::FindLinkedSourceEvent(SmartAIEventList& list, uint32 eventId) +{ + SmartAIEventList::iterator itr = std::find_if(list.begin(), list.end(), + [eventId](SmartScriptHolder& source) { return source.link == eventId; }); + + if (itr != list.end()) + return *itr; + + static SmartScriptHolder SmartScriptHolderDummy; + return SmartScriptHolderDummy; +} + +SmartScriptHolder& SmartAIMgr::FindLinkedEvent(SmartAIEventList& list, uint32 link) +{ + SmartAIEventList::iterator itr = std::find_if(list.begin(), list.end(), + [link](SmartScriptHolder& linked) { return linked.event_id == link && linked.GetEventType() == SMART_EVENT_LINK; }); + + if (itr != list.end()) + return *itr; + + static SmartScriptHolder SmartScriptHolderDummy; + return SmartScriptHolderDummy; +} + bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e) { if (std::abs(e.target.o) > 2 * float(M_PI)) @@ -463,6 +502,116 @@ bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e) return true; } +bool SmartAIMgr::IsMinMaxValid(SmartScriptHolder const& e, uint32 min, uint32 max) +{ + if (max < min) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses min/max params wrong (%u/%u), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), min, max); + return false; + } + return true; +} + +bool SmartAIMgr::NotNULL(SmartScriptHolder const& e, uint32 data) +{ + if (!data) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u Parameter can not be NULL, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); + return false; + } + return true; +} + +bool SmartAIMgr::IsCreatureValid(SmartScriptHolder const& e, uint32 entry) +{ + if (!sObjectMgr->GetCreatureTemplate(entry)) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Creature entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); + return false; + } + return true; +} + +bool SmartAIMgr::IsQuestValid(SmartScriptHolder const& e, uint32 entry) +{ + if (!sObjectMgr->GetQuestTemplate(entry)) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Quest entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); + return false; + } + return true; +} + +bool SmartAIMgr::IsGameObjectValid(SmartScriptHolder const& e, uint32 entry) +{ + if (!sObjectMgr->GetGameObjectTemplate(entry)) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent GameObject entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); + return false; + } + return true; +} + +bool SmartAIMgr::IsSpellValid(SmartScriptHolder const& e, uint32 entry) +{ + if (!sSpellMgr->GetSpellInfo(entry)) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Spell entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); + return false; + } + return true; +} + +bool SmartAIMgr::IsItemValid(SmartScriptHolder const& e, uint32 entry) +{ + if (!sItemStore.LookupEntry(entry)) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Item entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); + return false; + } + return true; +} + +bool SmartAIMgr::IsTextEmoteValid(SmartScriptHolder const& e, uint32 entry) +{ + if (!sEmotesTextStore.LookupEntry(entry)) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Text Emote entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); + return false; + } + return true; +} + +bool SmartAIMgr::IsEmoteValid(SmartScriptHolder const& e, uint32 entry) +{ + if (!sEmotesStore.LookupEntry(entry)) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Emote entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); + return false; + } + return true; +} + +bool SmartAIMgr::IsAreaTriggerValid(SmartScriptHolder const& e, uint32 entry) +{ + if (!sAreaTriggerStore.LookupEntry(entry)) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent AreaTrigger entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); + return false; + } + return true; +} + +bool SmartAIMgr::IsSoundValid(SmartScriptHolder const& e, uint32 entry) +{ + if (!sSoundEntriesStore.LookupEntry(entry)) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Sound entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); + return false; + } + return true; +} + bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) { if (e.event.type >= SMART_EVENT_END) @@ -916,7 +1065,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) } case SMART_ACTION_RANDOM_EMOTE: { - if (std::all_of(e.action.randomEmote.emotes.begin(), e.action.randomEmote.emotes.end(), [](uint32 emote) { return emote == 0; })) + if (std::all_of(std::begin(e.action.randomEmote.emotes), std::end(e.action.randomEmote.emotes), [](uint32 emote) { return emote == 0; })) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u does not have any non-zero emote", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); @@ -930,7 +1079,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) } 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; })) + if (std::all_of(std::begin(e.action.randTimedActionList.actionLists), std::end(e.action.randTimedActionList.actionLists), [](uint32 actionList) { return actionList == 0; })) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u does not have any non-zero action list", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); @@ -940,7 +1089,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) } 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; })) + if (std::all_of(std::begin(e.action.closestWaypointFromList.wps), std::end(e.action.closestWaypointFromList.wps), [](uint32 wp) { return wp == 0; })) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u does not have any non-zero waypoint id", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); @@ -950,7 +1099,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) } case SMART_ACTION_RANDOM_SOUND: { - if (std::all_of(e.action.randomSound.sounds.begin(), e.action.randomSound.sounds.end(), [](uint32 sound) { return sound == 0; })) + if (std::all_of(std::begin(e.action.randomSound.sounds), std::end(e.action.randomSound.sounds), [](uint32 sound) { return sound == 0; })) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u does not have any non-zero sound", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); @@ -1032,14 +1181,14 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) 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 (std::all_of(std::begin(e.action.randomPhase.phases), std::end(e.action.randomPhase.phases), [](uint32 phase) { return phase == 0; })) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d 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; })) + if (std::any_of(std::begin(e.action.randomPhase.phases), std::end(e.action.randomPhase.phases), [](uint32 phase) { return phase >= SMART_EVENT_PHASE_MAX; })) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u attempts to set invalid phase, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); return false; @@ -1164,21 +1313,21 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return false; break; case SMART_ACTION_WP_START: + { + if (!sSmartWaypointMgr->GetPath(e.action.wpStart.pathID)) { - if (!sSmartWaypointMgr->GetPath(e.action.wpStart.pathID)) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Creature %d Event %u Action %u uses non-existent WaypointPath id %u, skipped.", e.entryOrGuid, e.event_id, e.GetActionType(), e.action.wpStart.pathID); - return false; - } - if (e.action.wpStart.quest && !IsQuestValid(e, e.action.wpStart.quest)) - return false; - if (e.action.wpStart.reactState > REACT_AGGRESSIVE) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Creature %d Event %u Action %u uses invalid React State %u, skipped.", e.entryOrGuid, e.event_id, e.GetActionType(), e.action.wpStart.reactState); - return false; - } - break; + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Creature %d Event %u Action %u uses non-existent WaypointPath id %u, skipped.", e.entryOrGuid, e.event_id, e.GetActionType(), e.action.wpStart.pathID); + return false; + } + if (e.action.wpStart.quest && !IsQuestValid(e, e.action.wpStart.quest)) + return false; + if (e.action.wpStart.reactState > REACT_AGGRESSIVE) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Creature %d Event %u Action %u uses invalid React State %u, skipped.", e.entryOrGuid, e.event_id, e.GetActionType(), e.action.wpStart.reactState); + return false; } + break; + } case SMART_ACTION_CREATE_TIMED_EVENT: { if (!IsMinMaxValid(e, e.action.timeEvent.min, e.action.timeEvent.max)) @@ -1419,7 +1568,7 @@ void SmartAIMgr::LoadHelperStores() { uint32 oldMSTime = getMSTime(); - SpellInfo const* spellInfo = NULL; + SpellInfo const* spellInfo = nullptr; for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i) { spellInfo = sSpellMgr->GetSpellInfo(i); @@ -1473,3 +1622,18 @@ CacheSpellContainerBounds SmartAIMgr::GetCreateItemSpellContainerBounds(uint32 i return CreateItemSpellStore.equal_range(itemId); } +ObjectGuidVector::ObjectGuidVector(ObjectVector const& objectVector) : _objectVector(objectVector) +{ + _guidVector.reserve(_objectVector.size()); + for (WorldObject* obj : _objectVector) + _guidVector.push_back(obj->GetGUID()); +} + +void ObjectGuidVector::UpdateObjects(WorldObject const& ref) const +{ + _objectVector.clear(); + + for (ObjectGuid const& guid : _guidVector) + if (WorldObject* obj = ObjectAccessor::GetWorldObject(ref, guid)) + _objectVector.push_back(obj); +} diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 29b76ae0dd9..7a1433bc7fb 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -18,14 +18,14 @@ #ifndef TRINITY_SMARTSCRIPTMGR_H #define TRINITY_SMARTSCRIPTMGR_H -#include "Common.h" -#include "Creature.h" -#include "CreatureAI.h" -#include "Unit.h" -#include "Spell.h" +#include "Define.h" +#include "ObjectGuid.h" +#include <map> +#include <string> +#include <unordered_map> -//#include "SmartScript.h" -//#include "SmartAI.h" +class WorldObject; +enum SpellEffIndex : uint8; struct WayPoint { @@ -646,7 +646,7 @@ struct SmartAction struct { - std::array<uint32, SMART_ACTION_PARAM_COUNT> emotes; + uint32 emotes[SMART_ACTION_PARAM_COUNT]; } randomEmote; struct @@ -739,7 +739,7 @@ struct SmartAction struct { - std::array<uint32, SMART_ACTION_PARAM_COUNT> phases; + uint32 phases[SMART_ACTION_PARAM_COUNT]; } randomPhase; struct @@ -930,7 +930,9 @@ struct SmartAction { uint32 entry; uint32 mask; - std::array<uint32, MAX_EQUIPMENT_ITEMS> slots; + uint32 slot1; + uint32 slot2; + uint32 slot3; } equip; struct @@ -964,7 +966,7 @@ struct SmartAction struct { - std::array<uint32, SMART_ACTION_PARAM_COUNT> actionLists; + uint32 actionLists[SMART_ACTION_PARAM_COUNT]; } randTimedActionList; struct @@ -1074,12 +1076,12 @@ struct SmartAction struct { - std::array<uint32, SMART_ACTION_PARAM_COUNT> wps; + uint32 wps[SMART_ACTION_PARAM_COUNT]; } closestWaypointFromList; struct { - std::array<uint32, SMART_ACTION_PARAM_COUNT - 1> sounds; + uint32 sounds[SMART_ACTION_PARAM_COUNT - 1]; uint32 onlySelf; } randomSound; @@ -1500,12 +1502,7 @@ typedef std::vector<WorldObject*> ObjectVector; class ObjectGuidVector { public: - explicit ObjectGuidVector(ObjectVector const& objectVector) : _objectVector(objectVector) - { - _guidVector.reserve(_objectVector.size()); - for (WorldObject* obj : _objectVector) - _guidVector.push_back(obj->GetGUID()); - } + explicit ObjectGuidVector(ObjectVector const& objectVector); ObjectVector const* GetObjectVector(WorldObject const& ref) const { @@ -1520,14 +1517,7 @@ class ObjectGuidVector mutable ObjectVector _objectVector; //sanitize vector using _guidVector - void UpdateObjects(WorldObject const& ref) const - { - _objectVector.clear(); - - for (ObjectGuid const& guid : _guidVector) - if (WorldObject* obj = ObjectAccessor::GetWorldObject(ref, guid)) - _objectVector.push_back(obj); - } + void UpdateObjects(WorldObject const& ref) const; }; typedef std::unordered_map<uint32, ObjectGuidVector> ObjectVectorMap; @@ -1575,42 +1565,11 @@ class TC_GAME_API SmartAIMgr void LoadSmartAIFromDB(); - SmartAIEventList GetScript(int32 entry, SmartScriptType type) - { - SmartAIEventList temp; - if (mEventMap[uint32(type)].find(entry) != mEventMap[uint32(type)].end()) - return mEventMap[uint32(type)][entry]; - else - { - if (entry > 0)//first search is for guid (negative), do not drop error if not found - TC_LOG_DEBUG("scripts.ai", "SmartAIMgr::GetScript: Could not load Script for Entry %d ScriptType %u.", entry, uint32(type)); - return temp; - } - } + SmartAIEventList GetScript(int32 entry, SmartScriptType type); - static SmartScriptHolder& FindLinkedSourceEvent(SmartAIEventList& list, uint32 eventId) - { - SmartAIEventList::iterator itr = std::find_if(list.begin(), list.end(), - [eventId](SmartScriptHolder& source) { return source.link == eventId; }); + static SmartScriptHolder& FindLinkedSourceEvent(SmartAIEventList& list, uint32 eventId); - if (itr != list.end()) - return *itr; - - static SmartScriptHolder SmartScriptHolderDummy; - return SmartScriptHolderDummy; - } - - static SmartScriptHolder& FindLinkedEvent(SmartAIEventList& list, uint32 link) - { - SmartAIEventList::iterator itr = std::find_if(list.begin(), list.end(), - [link](SmartScriptHolder& linked) { return linked.event_id == link && linked.GetEventType() == SMART_EVENT_LINK; }); - - if (itr != list.end()) - return *itr; - - static SmartScriptHolder SmartScriptHolderDummy; - return SmartScriptHolderDummy; - } + static SmartScriptHolder& FindLinkedEvent(SmartAIEventList& list, uint32 link); private: //event stores @@ -1619,127 +1578,19 @@ class TC_GAME_API SmartAIMgr bool IsEventValid(SmartScriptHolder& e); bool IsTargetValid(SmartScriptHolder const& e); - bool IsMinMaxValid(SmartScriptHolder const& e, uint32 min, uint32 max) - { - if (max < min) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses min/max params wrong (%u/%u), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), min, max); - return false; - } - return true; - } - - /*inline bool IsPercentValid(SmartScriptHolder e, int32 pct) - { - if (pct < -100 || pct > 100) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u has invalid Percent set (%d), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), pct); - return false; - } - return true; - }*/ - - bool NotNULL(SmartScriptHolder const& e, uint32 data) - { - if (!data) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u Parameter can not be NULL, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); - return false; - } - return true; - } - - bool IsCreatureValid(SmartScriptHolder const& e, uint32 entry) - { - if (!sObjectMgr->GetCreatureTemplate(entry)) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Creature entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); - return false; - } - return true; - } - - bool IsQuestValid(SmartScriptHolder const& e, uint32 entry) - { - if (!sObjectMgr->GetQuestTemplate(entry)) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Quest entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); - return false; - } - return true; - } - - bool IsGameObjectValid(SmartScriptHolder const& e, uint32 entry) - { - if (!sObjectMgr->GetGameObjectTemplate(entry)) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent GameObject entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); - return false; - } - return true; - } - - bool IsSpellValid(SmartScriptHolder const& e, uint32 entry) - { - if (!sSpellMgr->GetSpellInfo(entry)) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Spell entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); - return false; - } - return true; - } - - bool IsItemValid(SmartScriptHolder const& e, uint32 entry) - { - if (!sItemStore.LookupEntry(entry)) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Item entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); - return false; - } - return true; - } - - bool IsTextEmoteValid(SmartScriptHolder const& e, uint32 entry) - { - if (!sEmotesTextStore.LookupEntry(entry)) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Text Emote entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); - return false; - } - return true; - } - - bool IsEmoteValid(SmartScriptHolder const& e, uint32 entry) - { - if (!sEmotesStore.LookupEntry(entry)) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Emote entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); - return false; - } - return true; - } - - bool IsAreaTriggerValid(SmartScriptHolder const& e, uint32 entry) - { - if (!sAreaTriggerStore.LookupEntry(entry)) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent AreaTrigger entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); - return false; - } - return true; - } - - bool IsSoundValid(SmartScriptHolder const& e, uint32 entry) - { - if (!sSoundEntriesStore.LookupEntry(entry)) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Sound entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); - return false; - } - return true; - } - - bool IsTextValid(SmartScriptHolder const& e, uint32 id); + static bool IsMinMaxValid(SmartScriptHolder const& e, uint32 min, uint32 max); + + static bool NotNULL(SmartScriptHolder const& e, uint32 data); + static bool IsCreatureValid(SmartScriptHolder const& e, uint32 entry); + static bool IsQuestValid(SmartScriptHolder const& e, uint32 entry); + static bool IsGameObjectValid(SmartScriptHolder const& e, uint32 entry); + static bool IsSpellValid(SmartScriptHolder const& e, uint32 entry); + static bool IsItemValid(SmartScriptHolder const& e, uint32 entry); + static bool IsTextEmoteValid(SmartScriptHolder const& e, uint32 entry); + static bool IsEmoteValid(SmartScriptHolder const& e, uint32 entry); + static bool IsAreaTriggerValid(SmartScriptHolder const& e, uint32 entry); + static bool IsSoundValid(SmartScriptHolder const& e, uint32 entry); + static bool IsTextValid(SmartScriptHolder const& e, uint32 id); // Helpers void LoadHelperStores(); |
