aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/database/Database/Implementation/WorldDatabase.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp35
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp98
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.h24
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp68
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h38
-rw-r--r--src/server/game/Entities/Player/SceneMgr.cpp12
-rw-r--r--src/server/game/Entities/Player/SceneMgr.h1
8 files changed, 230 insertions, 48 deletions
diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp
index edb13804a89..def1e948a06 100644
--- a/src/server/database/Database/Implementation/WorldDatabase.cpp
+++ b/src/server/database/Database/Implementation/WorldDatabase.cpp
@@ -26,7 +26,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_DEL_CRELINKED_RESPAWN, "DELETE FROM linked_respawn WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_REP_CREATURE_LINKED_RESPAWN, "REPLACE INTO linked_respawn (guid, linkedGuid) VALUES (?, ?)", CONNECTION_ASYNC);
PrepareStatement(WORLD_SEL_CREATURE_TEXT, "SELECT entry, groupid, id, text, type, language, probability, emote, duration, sound, BroadcastTextId, TextRange FROM creature_text", CONNECTION_SYNCH);
- PrepareStatement(WORLD_SEL_SMART_SCRIPTS, "SELECT entryorguid, source_type, id, link, event_type, event_phase_mask, event_chance, event_flags, event_param1, event_param2, event_param3, event_param4, action_type, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6, target_type, target_param1, target_param2, target_param3, target_x, target_y, target_z, target_o FROM smart_scripts ORDER BY entryorguid, source_type, id, link", CONNECTION_SYNCH);
+ PrepareStatement(WORLD_SEL_SMART_SCRIPTS, "SELECT entryorguid, source_type, id, link, event_type, event_phase_mask, event_chance, event_flags, event_param1, event_param2, event_param3, event_param4, event_param_string, action_type, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6, target_type, target_param1, target_param2, target_param3, target_x, target_y, target_z, target_o FROM smart_scripts ORDER BY entryorguid, source_type, id, link", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_SMARTAI_WP, "SELECT entry, pointid, position_x, position_y, position_z FROM waypoints ORDER BY entry, pointid", CONNECTION_SYNCH);
PrepareStatement(WORLD_DEL_GAMEOBJECT, "DELETE FROM gameobject WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_DEL_EVENT_GAMEOBJECT, "DELETE FROM game_event_gameobject WHERE guid = ?", CONNECTION_ASYNC);
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 5decf1e87c7..6d27b39ea40 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -979,7 +979,42 @@ class SmartTrigger : public AreaTriggerScript
}
};
+class SmartScene : public SceneScript
+{
+public:
+ SmartScene() : SceneScript("SmartScene") { }
+
+ void OnSceneStart(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* sceneTemplate) override
+ {
+ SmartScript smartScript;
+ smartScript.OnInitialize(nullptr, nullptr, sceneTemplate);
+ smartScript.ProcessEventsFor(SMART_EVENT_SCENE_START, player);
+ }
+
+ void OnSceneTriggerEvent(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* sceneTemplate, std::string const& triggerName) override
+ {
+ SmartScript smartScript;
+ smartScript.OnInitialize(nullptr, nullptr, sceneTemplate);
+ smartScript.ProcessEventsFor(SMART_EVENT_SCENE_TRIGGER, player, 0, 0, false, nullptr, nullptr, triggerName);
+ }
+
+ void OnSceneCancel(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* sceneTemplate) override
+ {
+ SmartScript smartScript;
+ smartScript.OnInitialize(nullptr, nullptr, sceneTemplate);
+ smartScript.ProcessEventsFor(SMART_EVENT_SCENE_CANCEL, player);
+ }
+
+ void OnSceneComplete(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* sceneTemplate) override
+ {
+ SmartScript smartScript;
+ smartScript.OnInitialize(nullptr, nullptr, sceneTemplate);
+ smartScript.ProcessEventsFor(SMART_EVENT_SCENE_COMPLETE, player);
+ }
+};
+
void AddSC_SmartScripts()
{
new SmartTrigger();
+ new SmartScene();
}
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index a36d05709c1..bd7088054e1 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -42,6 +42,7 @@ SmartScript::SmartScript()
go = nullptr;
me = nullptr;
trigger = nullptr;
+ sceneTemplate = nullptr;
mEventPhase = 0;
mPathId = 0;
mTargetStorage = new ObjectListMap();
@@ -80,7 +81,7 @@ 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::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob, std::string const& varString)
{
for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i)
{
@@ -90,11 +91,11 @@ void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint3
if (eventType == e /*&& (!i->event.event_phase_mask || IsInPhase(i->event.event_phase_mask)) && !(i->event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE && i->runOnce)*/)
if (sConditionMgr->IsObjectMeetingSmartEventConditions(i->entryOrGuid, i->event_id, i->source_type, unit, GetBaseObject()))
- ProcessEvent(*i, unit, var0, var1, bvar, spell, gob);
+ ProcessEvent(*i, unit, var0, var1, bvar, spell, gob, varString);
}
}
-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, const SpellInfo* spell, GameObject* gob, std::string const& varString)
{
//calc random
if (e.GetEventType() != SMART_EVENT_LINK && e.event.event_chance < 100 && e.event.event_chance)
@@ -1264,7 +1265,12 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
}
case SMART_ACTION_SUMMON_CREATURE:
{
+ WorldObject* summoner = GetBaseObjectOrUnit(unit);
+ if (!summoner)
+ break;
+
ObjectList* targets = GetTargets(e, unit);
+
if (targets)
{
float x, y, z, o;
@@ -1275,7 +1281,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
y += e.target.y;
z += e.target.z;
o += e.target.o;
- if (Creature* summon = GetBaseObject()->SummonCreature(e.action.summonCreature.creature, x, y, z, o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration))
+ if (Creature* summon = summoner->SummonCreature(e.action.summonCreature.creature, x, y, z, o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration))
if (e.action.summonCreature.attackInvoker)
summon->AI()->AttackStart((*itr)->ToUnit());
}
@@ -1286,14 +1292,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (e.GetTargetType() != SMART_TARGET_POSITION)
break;
- if (Creature* summon = GetBaseObject()->SummonCreature(e.action.summonCreature.creature, e.target.x, e.target.y, e.target.z, e.target.o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration))
+ if (Creature* summon = summoner->SummonCreature(e.action.summonCreature.creature, e.target.x, e.target.y, e.target.z, e.target.o, (TempSummonType)e.action.summonCreature.type, e.action.summonCreature.duration))
if (unit && e.action.summonCreature.attackInvoker)
summon->AI()->AttackStart(unit);
break;
}
case SMART_ACTION_SUMMON_GO:
{
- if (!GetBaseObject())
+ WorldObject* summoner = GetBaseObjectOrUnit(unit);
+ if (!summoner)
break;
ObjectList* targets = GetTargets(e, unit);
@@ -1306,7 +1313,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
Position pos = (*itr)->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);
- GetBaseObject()->SummonGameObject(e.action.summonGO.entry, pos, rot, e.action.summonGO.despawnTime);
+ summoner->SummonGameObject(e.action.summonGO.entry, pos, rot, e.action.summonGO.despawnTime);
}
delete targets;
@@ -1316,7 +1323,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break;
G3D::Quat rot = G3D::Matrix3::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);
+ summoner->SummonGameObject(e.action.summonGO.entry, Position(e.target.x, e.target.y, e.target.z, e.target.o), rot, e.action.summonGO.despawnTime);
break;
}
case SMART_ACTION_KILL_UNIT:
@@ -2465,6 +2472,30 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
delete targets;
break;
}
+ case SMART_ACTION_SCENE_PLAY:
+ {
+ ObjectList* targets = GetTargets(e, unit);
+ if (!targets)
+ break;
+
+ for (WorldObject* target : *targets)
+ if (Player* playerTarget = target->ToPlayer())
+ playerTarget->GetSceneMgr().PlayScene(e.action.scene.sceneId);
+
+ break;
+ }
+ case SMART_ACTION_SCENE_CANCEL:
+ {
+ ObjectList* targets = GetTargets(e, unit);
+ if (!targets)
+ break;
+
+ for (WorldObject* target : *targets)
+ if (Player* playerTarget = target->ToPlayer())
+ playerTarget->GetSceneMgr().CancelSceneBySceneId(e.action.scene.sceneId);
+
+ break;
+ }
default:
TC_LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry " SI64FMTD " SourceType %u, Event %u, Unhandled Action type %u", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
break;
@@ -2474,16 +2505,16 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
SmartScriptHolder& linked = SmartAIMgr::FindLinkedEvent(mEvents, e.link);
if (linked)
- ProcessEvent(linked, unit, var0, var1, bvar, spell, gob);
+ ProcessEvent(linked, unit, var0, var1, bvar, spell, gob, varString);
else
TC_LOG_DEBUG("sql.sql", "SmartScript::ProcessAction: Entry " SI64FMTD " SourceType %u, Event %u, Link Event %u not found or invalid, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.link);
}
}
-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, const SpellInfo* spell, GameObject* gob, std::string const& varString)
{
if (sConditionMgr->IsObjectMeetingSmartEventConditions(e.entryOrGuid, e.event_id, e.source_type, unit, GetBaseObject()))
- ProcessAction(e, unit, var0, var1, bvar, spell, gob);
+ ProcessAction(e, unit, var0, var1, bvar, spell, gob, varString);
RecalcTimer(e, min, max);
}
@@ -2910,7 +2941,7 @@ ObjectList* SmartScript::GetWorldObjectsInDist(float dist)
return targets;
}
-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, const SpellInfo* spell, GameObject* gob, std::string const& varString)
{
if (!e.active && e.GetEventType() != SMART_EVENT_LINK)
return;
@@ -3448,6 +3479,21 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
if (GetCounterId(e.event.counter.id) != 0 && GetCounterValue(e.event.counter.id) == e.event.counter.value)
ProcessTimedAction(e, e.event.counter.cooldownMin, e.event.counter.cooldownMax);
break;
+ case SMART_EVENT_SCENE_START:
+ case SMART_EVENT_SCENE_CANCEL:
+ case SMART_EVENT_SCENE_COMPLETE:
+ {
+ ProcessAction(e, unit);
+ break;
+ }
+ case SMART_EVENT_SCENE_TRIGGER:
+ {
+ if (e.event.param_string != varString)
+ return;
+
+ ProcessAction(e, unit, var0, 0, false, nullptr, nullptr, varString);
+ break;
+ }
default:
TC_LOG_ERROR("sql.sql", "SmartScript::ProcessEvent: Unhandled Event type %u", e.GetEventType());
break;
@@ -3633,7 +3679,7 @@ void SmartScript::OnUpdate(uint32 const diff)
}
}
-void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at)
+void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene)
{
if (e.empty())
{
@@ -3641,6 +3687,8 @@ void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEn
TC_LOG_DEBUG("scripts.ai", "SmartScript: EventMap for Entry %u is empty but is using SmartScript.", obj->GetEntry());
if (at)
TC_LOG_DEBUG("scripts.ai", "SmartScript: EventMap for AreaTrigger %u is empty but is using SmartScript.", at->ID);
+ if (scene)
+ TC_LOG_DEBUG("scripts.ai", "SmartScript: EventMap for SceneId %u is empty but is using SmartScript.", scene->SceneId);
return;
}
for (SmartAIEventList::iterator i = e.begin(); i != e.end(); ++i)
@@ -3667,6 +3715,8 @@ void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEn
TC_LOG_ERROR("sql.sql", "SmartScript: Entry %u has events but no events added to list because of instance flags.", obj->GetEntry());
if (mEvents.empty() && at)
TC_LOG_ERROR("sql.sql", "SmartScript: AreaTrigger %u has events but no events added to list because of instance flags. NOTE: triggers can not handle any instance flags.", at->ID);
+ if (mEvents.empty() && scene)
+ TC_LOG_ERROR("sql.sql", "SmartScript: SceneId %u has events but no events added to list because of instance flags. NOTE: scenes can not handle any instance flags.", scene->SceneId);
}
void SmartScript::GetScript()
@@ -3677,23 +3727,28 @@ void SmartScript::GetScript()
e = sSmartScriptMgr->GetScript(-((int32)me->GetSpawnId()), mScriptType);
if (e.empty())
e = sSmartScriptMgr->GetScript((int32)me->GetEntry(), mScriptType);
- FillScript(e, me, nullptr);
+ FillScript(e, me, nullptr, nullptr);
}
else if (go)
{
e = sSmartScriptMgr->GetScript(-((int32)go->GetSpawnId()), mScriptType);
if (e.empty())
e = sSmartScriptMgr->GetScript((int32)go->GetEntry(), mScriptType);
- FillScript(e, go, nullptr);
+ FillScript(e, go, nullptr, nullptr);
}
else if (trigger)
{
e = sSmartScriptMgr->GetScript((int32)trigger->ID, mScriptType);
- FillScript(e, nullptr, trigger);
+ FillScript(e, nullptr, trigger, nullptr);
+ }
+ else if (sceneTemplate)
+ {
+ e = sSmartScriptMgr->GetScript(sceneTemplate->SceneId, mScriptType);
+ FillScript(e, nullptr, nullptr, sceneTemplate);
}
}
-void SmartScript::OnInitialize(WorldObject* obj, AreaTriggerEntry const* at)
+void SmartScript::OnInitialize(WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene)
{
if (obj)//handle object based scripts
{
@@ -3713,12 +3768,19 @@ void SmartScript::OnInitialize(WorldObject* obj, AreaTriggerEntry const* at)
TC_LOG_ERROR("misc", "SmartScript::OnInitialize: Unhandled TypeID !WARNING!");
return;
}
- } else if (at)
+ }
+ else if (at)
{
mScriptType = SMART_SCRIPT_TYPE_AREATRIGGER;
trigger = at;
TC_LOG_DEBUG("scripts.ai", "SmartScript::OnInitialize: source is AreaTrigger %u", trigger->ID);
}
+ else if (scene)
+ {
+ mScriptType = SMART_SCRIPT_TYPE_SCENE;
+ sceneTemplate = scene;
+ TC_LOG_DEBUG("scripts.ai", "SmartScript::OnInitialize: source is Scene with id %u", scene->SceneId);
+ }
else
{
TC_LOG_ERROR("misc", "SmartScript::OnInitialize: !WARNING! Initialized objects are NULL.");
diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h
index 56a9ed67589..b3294736e3f 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.h
+++ b/src/server/game/AI/SmartScripts/SmartScript.h
@@ -28,24 +28,26 @@
#include "SmartScriptMgr.h"
//#include "SmartAI.h"
+class Player;
+
class TC_GAME_API SmartScript
{
public:
SmartScript();
~SmartScript();
- void OnInitialize(WorldObject* obj, AreaTriggerEntry const* at = nullptr);
+ void OnInitialize(WorldObject* obj, AreaTriggerEntry const* at = nullptr, SceneTemplate const* scene = nullptr);
void GetScript();
- void FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at);
+ void FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene);
- 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, const SpellInfo* spell = nullptr, GameObject* gob = nullptr, std::string const& varString = "");
+ void ProcessEvent(SmartScriptHolder& e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = nullptr, GameObject* gob = nullptr, std::string const& varString = "");
bool CheckTimer(SmartScriptHolder const& e) const;
void RecalcTimer(SmartScriptHolder& e, uint32 min, uint32 max);
void UpdateTimer(SmartScriptHolder& e, uint32 const diff);
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, const SpellInfo* spell = nullptr, GameObject* gob = nullptr, std::string const& varString = "");
+ void ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = nullptr, GameObject* gob = nullptr, std::string const& varString = "");
ObjectList* GetTargets(SmartScriptHolder const& e, Unit* invoker = nullptr);
ObjectList* GetWorldObjectsInDist(float dist);
void InstallTemplate(SmartScriptHolder const& e);
@@ -62,6 +64,15 @@ class TC_GAME_API SmartScript
obj = go;
return obj;
}
+ WorldObject* GetBaseObjectOrUnit(Unit* unit)
+ {
+ WorldObject* summoner = GetBaseObject();
+
+ if (!summoner && unit)
+ return unit;
+
+ return summoner;
+ }
static bool IsUnit(WorldObject* obj)
{
@@ -274,6 +285,7 @@ class TC_GAME_API SmartScript
GameObject* go;
ObjectGuid goOrigGUID;
AreaTriggerEntry const* trigger;
+ SceneTemplate const* sceneTemplate;
SmartScriptType mScriptType;
uint32 mEventPhase;
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index c99d1131dbf..c3ba1d4ef0e 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -190,6 +190,15 @@ void SmartAIMgr::LoadSmartAIFromDB()
}
break;
}
+ case SMART_SCRIPT_TYPE_SCENE:
+ {
+ if (!sObjectMgr->GetSceneTemplate((uint32)temp.entryOrGuid))
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Scene id (%u) does not exist, skipped loading.", uint32(temp.entryOrGuid));
+ continue;
+ }
+ break;
+ }
case SMART_SCRIPT_TYPE_TIMED_ACTIONLIST:
break;//nothing to check, really
default:
@@ -232,23 +241,24 @@ void SmartAIMgr::LoadSmartAIFromDB()
temp.event.raw.param2 = fields[9].GetUInt32();
temp.event.raw.param3 = fields[10].GetUInt32();
temp.event.raw.param4 = fields[11].GetUInt32();
-
- temp.action.type = (SMART_ACTION)fields[12].GetUInt8();
- temp.action.raw.param1 = fields[13].GetUInt32();
- temp.action.raw.param2 = fields[14].GetUInt32();
- temp.action.raw.param3 = fields[15].GetUInt32();
- temp.action.raw.param4 = fields[16].GetUInt32();
- temp.action.raw.param5 = fields[17].GetUInt32();
- temp.action.raw.param6 = fields[18].GetUInt32();
-
- temp.target.type = (SMARTAI_TARGETS)fields[19].GetUInt8();
- temp.target.raw.param1 = fields[20].GetUInt32();
- temp.target.raw.param2 = fields[21].GetUInt32();
- temp.target.raw.param3 = fields[22].GetUInt32();
- temp.target.x = fields[23].GetFloat();
- temp.target.y = fields[24].GetFloat();
- temp.target.z = fields[25].GetFloat();
- temp.target.o = fields[26].GetFloat();
+ temp.event.param_string = fields[12].GetString();
+
+ temp.action.type = (SMART_ACTION)fields[13].GetUInt8();
+ temp.action.raw.param1 = fields[14].GetUInt32();
+ temp.action.raw.param2 = fields[15].GetUInt32();
+ temp.action.raw.param3 = fields[16].GetUInt32();
+ temp.action.raw.param4 = fields[17].GetUInt32();
+ temp.action.raw.param5 = fields[18].GetUInt32();
+ temp.action.raw.param6 = fields[19].GetUInt32();
+
+ temp.target.type = (SMARTAI_TARGETS)fields[20].GetUInt8();
+ temp.target.raw.param1 = fields[21].GetUInt32();
+ temp.target.raw.param2 = fields[22].GetUInt32();
+ temp.target.raw.param3 = fields[23].GetUInt32();
+ temp.target.x = fields[24].GetFloat();
+ temp.target.y = fields[25].GetFloat();
+ temp.target.z = fields[26].GetFloat();
+ temp.target.o = fields[27].GetFloat();
//check target
if (!IsTargetValid(temp))
@@ -754,6 +764,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_EVENT_JUST_CREATED:
case SMART_EVENT_FOLLOW_COMPLETED:
case SMART_EVENT_ON_SPELLCLICK:
+ case SMART_EVENT_SCENE_START:
+ case SMART_EVENT_SCENE_CANCEL:
+ case SMART_EVENT_SCENE_COMPLETE:
+ case SMART_EVENT_SCENE_TRIGGER:
break;
default:
TC_LOG_ERROR("sql.sql", "SmartAIMgr: Not handled event_type(%u), Entry " SI64FMTD " SourceType %u Event %u Action %u, skipped.", e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
@@ -1217,6 +1231,26 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
}
break;
}
+ case SMART_ACTION_SCENE_PLAY:
+ {
+ if (!sObjectMgr->GetSceneTemplate(e.action.scene.sceneId))
+ {
+ TC_LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_SCENE_PLAY uses sceneId %u but scene don't exist, skipped", e.action.scene.sceneId);
+ return false;
+ }
+
+ break;
+ }
+ case SMART_ACTION_SCENE_CANCEL:
+ {
+ if (!sObjectMgr->GetSceneTemplate(e.action.scene.sceneId))
+ {
+ TC_LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_SCENE_CANCEL uses sceneId %u but scene don't exist, skipped", e.action.scene.sceneId);
+ return false;
+ }
+
+ break;
+ }
case SMART_ACTION_START_CLOSEST_WAYPOINT:
case SMART_ACTION_FOLLOW:
case SMART_ACTION_SET_ORIENTATION:
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index d9c679e73e1..550cc496eaa 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -179,8 +179,12 @@ enum SMART_EVENT
SMART_EVENT_DISTANCE_CREATURE = 75, // guid, entry, distance, repeat
SMART_EVENT_DISTANCE_GAMEOBJECT = 76, // guid, entry, distance, repeat
SMART_EVENT_COUNTER_SET = 77, // id, value, cooldownMin, cooldownMax
+ SMART_EVENT_SCENE_START = 78, // none
+ SMART_EVENT_SCENE_TRIGGER = 79, // param_string : triggerName
+ SMART_EVENT_SCENE_CANCEL = 80, // none
+ SMART_EVENT_SCENE_COMPLETE = 81, // none
- SMART_EVENT_END = 78
+ SMART_EVENT_END = 82
};
struct SmartEvent
@@ -423,12 +427,19 @@ struct SmartEvent
struct
{
+ uint32 sceneId;
+ } scene;
+
+ struct
+ {
uint32 param1;
uint32 param2;
uint32 param3;
uint32 param4;
} raw;
};
+
+ std::string param_string;
};
enum SMART_SCRIPT_RESPAWN_CONDITION
@@ -558,9 +569,12 @@ enum SMART_ACTION
SMART_ACTION_RANDOM_SOUND = 115, // soundId1, soundId2, soundId3, soundId4, soundId5, onlySelf
SMART_ACTION_SET_CORPSE_DELAY = 116, // timer
SMART_ACTION_DISABLE_EVADE = 117, // 0/1 (1 = disabled, 0 = enabled)
+ // 118 - 127 : 3.3.5 reserved
SMART_ACTION_PLAY_ANIMKIT = 128, // id, type (0 = oneShot, 1 = aiAnim, 2 = meleeAnim, 3 = movementAnim)
+ SMART_ACTION_SCENE_PLAY = 129, // sceneId
+ SMART_ACTION_SCENE_CANCEL = 130, // sceneId
- SMART_ACTION_END = 129
+ SMART_ACTION_END = 131
};
struct SmartAction
@@ -1081,6 +1095,11 @@ struct SmartAction
uint32 type;
} animKit;
+ struct
+ {
+ uint32 sceneId;
+ } scene;
+
//! Note for any new future actions
//! All parameters must have type uint32
@@ -1257,7 +1276,8 @@ enum SmartScriptType
SMART_SCRIPT_TYPE_TRANSPORT = 7, //
SMART_SCRIPT_TYPE_INSTANCE = 8, //
SMART_SCRIPT_TYPE_TIMED_ACTIONLIST = 9, //
- SMART_SCRIPT_TYPE_MAX = 10
+ SMART_SCRIPT_TYPE_SCENE = 10, //done
+ SMART_SCRIPT_TYPE_MAX = 11
};
enum SmartAITypeMaskId
@@ -1271,7 +1291,8 @@ enum SmartAITypeMaskId
SMART_SCRIPT_TYPE_MASK_SPELL = 64,
SMART_SCRIPT_TYPE_MASK_TRANSPORT = 128,
SMART_SCRIPT_TYPE_MASK_INSTANCE = 256,
- SMART_SCRIPT_TYPE_MASK_TIMED_ACTIONLIST = 512
+ SMART_SCRIPT_TYPE_MASK_TIMED_ACTIONLIST = 512,
+ SMART_SCRIPT_TYPE_MASK_SCENE = 1024
};
const uint32 SmartAITypeMask[SMART_SCRIPT_TYPE_MAX][2] =
@@ -1285,7 +1306,8 @@ const uint32 SmartAITypeMask[SMART_SCRIPT_TYPE_MAX][2] =
{SMART_SCRIPT_TYPE_SPELL, SMART_SCRIPT_TYPE_MASK_SPELL },
{SMART_SCRIPT_TYPE_TRANSPORT, SMART_SCRIPT_TYPE_MASK_TRANSPORT },
{SMART_SCRIPT_TYPE_INSTANCE, SMART_SCRIPT_TYPE_MASK_INSTANCE },
- {SMART_SCRIPT_TYPE_TIMED_ACTIONLIST, SMART_SCRIPT_TYPE_MASK_TIMED_ACTIONLIST }
+ {SMART_SCRIPT_TYPE_TIMED_ACTIONLIST, SMART_SCRIPT_TYPE_MASK_TIMED_ACTIONLIST },
+ {SMART_SCRIPT_TYPE_SCENE, SMART_SCRIPT_TYPE_MASK_SCENE }
};
const uint32 SmartAIEventMask[SMART_EVENT_END][2] =
@@ -1367,7 +1389,11 @@ const uint32 SmartAIEventMask[SMART_EVENT_END][2] =
{SMART_EVENT_FRIENDLY_HEALTH_PCT, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_DISTANCE_CREATURE, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_DISTANCE_GAMEOBJECT, SMART_SCRIPT_TYPE_MASK_CREATURE },
- {SMART_EVENT_COUNTER_SET, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }
+ {SMART_EVENT_COUNTER_SET, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
+ {SMART_EVENT_SCENE_START, SMART_SCRIPT_TYPE_MASK_SCENE },
+ {SMART_EVENT_SCENE_TRIGGER, SMART_SCRIPT_TYPE_MASK_SCENE },
+ {SMART_EVENT_SCENE_CANCEL, SMART_SCRIPT_TYPE_MASK_SCENE },
+ {SMART_EVENT_SCENE_COMPLETE, SMART_SCRIPT_TYPE_MASK_SCENE }
};
enum SmartEventFlags
diff --git a/src/server/game/Entities/Player/SceneMgr.cpp b/src/server/game/Entities/Player/SceneMgr.cpp
index 0b8ac7f1f7c..d92f531cdea 100644
--- a/src/server/game/Entities/Player/SceneMgr.cpp
+++ b/src/server/game/Entities/Player/SceneMgr.cpp
@@ -157,6 +157,18 @@ void SceneMgr::AddInstanceIdToSceneMap(uint32 sceneInstanceID, SceneTemplate con
_scenesByInstance[sceneInstanceID] = sceneTemplate;
}
+void SceneMgr::CancelSceneBySceneId(uint32 sceneId)
+{
+ std::vector<uint32> instancesIds;
+
+ for (auto const& itr : _scenesByInstance)
+ if (itr.second->SceneId == sceneId)
+ instancesIds.push_back(itr.first);
+
+ for (uint32 sceneInstanceID : instancesIds)
+ CancelScene(sceneInstanceID);
+}
+
void SceneMgr::CancelSceneByPackageId(uint32 sceneScriptPackageId)
{
std::vector<uint32> instancesIds;
diff --git a/src/server/game/Entities/Player/SceneMgr.h b/src/server/game/Entities/Player/SceneMgr.h
index d21312d6d3a..a87ea603bdd 100644
--- a/src/server/game/Entities/Player/SceneMgr.h
+++ b/src/server/game/Entities/Player/SceneMgr.h
@@ -52,6 +52,7 @@ public:
bool HasScene(uint32 sceneInstanceID, uint32 sceneScriptPackageId = 0) const;
void AddInstanceIdToSceneMap(uint32 sceneInstanceID, SceneTemplate const* sceneTemplate);
+ void CancelSceneBySceneId(uint32 sceneId);
void CancelSceneByPackageId(uint32 sceneScriptPackageId);
void RemoveSceneInstanceId(uint32 sceneInstanceID);
void RemoveAurasDueToSceneId(uint32 sceneId);