diff options
author | Traesh <traesh@farahlon.com> | 2017-03-17 21:21:35 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2017-03-17 21:21:35 +0100 |
commit | 01ded93a4218869068cd0d9160d4d79c38496d46 (patch) | |
tree | 8c15c35f933f60ec809bec820d39900fe5988a08 | |
parent | 77d1080ff5516b11d579277e1267c21ea4f24bfe (diff) |
Core/AI: enable SmartScripts on Scenes + add scene related actions/events
Closes #19194
-rw-r--r-- | sql/updates/world/master/2017_03_17_02_world.sql | 1 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/WorldDatabase.cpp | 2 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartAI.cpp | 35 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.cpp | 98 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.h | 24 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.cpp | 68 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.h | 38 | ||||
-rw-r--r-- | src/server/game/Entities/Player/SceneMgr.cpp | 12 | ||||
-rw-r--r-- | src/server/game/Entities/Player/SceneMgr.h | 1 |
9 files changed, 231 insertions, 48 deletions
diff --git a/sql/updates/world/master/2017_03_17_02_world.sql b/sql/updates/world/master/2017_03_17_02_world.sql new file mode 100644 index 00000000000..6cf7d5e7702 --- /dev/null +++ b/sql/updates/world/master/2017_03_17_02_world.sql @@ -0,0 +1 @@ +ALTER TABLE `smart_scripts` ADD COLUMN `event_param_string` VARCHAR(255) DEFAULT '' NOT NULL AFTER `event_param4`; 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); |