aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/AI/SmartScripts
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2017-06-19 23:20:06 -0300
committerariel- <ariel-@users.noreply.github.com>2017-06-19 23:20:06 -0300
commit85a7d5ce9ac68b30da2277cc91d4b70358f1880d (patch)
treedf3d2084ee2e35008903c03178039b9c986e2d08 /src/server/game/AI/SmartScripts
parent052fc24315ace866ea1cf610e85df119b68100c9 (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.cpp29
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.h24
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp243
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.h213
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp222
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h215
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();