aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTraesh <traesh@farahlon.com>2016-09-25 16:13:12 +0200
committerShauren <shauren.trinity@gmail.com>2016-09-25 16:13:12 +0200
commitd4887311e39527e036419ebd966f399fdbdae67a (patch)
tree7a87b65e493e3b0660790b02b151107fc4ab66b4 /src
parentdd64a3cd36d7c8db67f4075c5a8c1eb01898d1ed (diff)
Core/Scenes: Implemented scene system
Closes #17858 Closes #17976
Diffstat (limited to 'src')
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.cpp6
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.h4
-rw-r--r--src/server/game/Accounts/RBAC.h8
-rw-r--r--src/server/game/DataStores/DB2Metadata.h4
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp4
-rw-r--r--src/server/game/DataStores/DB2Stores.h2
-rw-r--r--src/server/game/DataStores/DB2Structure.h15
-rw-r--r--src/server/game/DataStores/DBCEnums.h9
-rw-r--r--src/server/game/Entities/Player/Player.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.h5
-rw-r--r--src/server/game/Entities/Player/SceneMgr.cpp209
-rw-r--r--src/server/game/Entities/Player/SceneMgr.h74
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp33
-rw-r--r--src/server/game/Globals/ObjectMgr.h22
-rw-r--r--src/server/game/Handlers/SceneHandler.cpp10
-rw-r--r--src/server/game/Miscellaneous/Language.h12
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp48
-rw-r--r--src/server/game/Scripting/ScriptMgr.h27
-rw-r--r--src/server/game/Server/Packets/ScenePackets.cpp17
-rw-r--r--src/server/game/Server/Packets/ScenePackets.h12
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp6
-rw-r--r--src/server/game/Spells/Auras/SpellAuraDefines.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp22
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h1
-rw-r--r--src/server/game/World/World.cpp3
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp45
-rw-r--r--src/server/scripts/Commands/cs_list.cpp25
-rw-r--r--src/server/scripts/Commands/cs_reload.cpp11
-rw-r--r--src/server/scripts/Commands/cs_scene.cpp139
-rw-r--r--src/server/scripts/Commands/cs_script_loader.cpp2
-rw-r--r--src/server/scripts/World/scene_scripts.cpp42
-rw-r--r--src/server/scripts/World/world_script_loader.cpp2
32 files changed, 759 insertions, 64 deletions
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp
index 5ecd9c17357..60197392569 100644
--- a/src/server/database/Database/Implementation/HotfixDatabase.cpp
+++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp
@@ -687,6 +687,12 @@ void HotfixDatabaseConnection::DoPrepareStatements()
PrepareStatement(HOTFIX_SEL_SCALING_STAT_DISTRIBUTION, "SELECT ID, ItemLevelCurveID, MinLevel, MaxLevel FROM scaling_stat_distribution"
" ORDER BY ID DESC", CONNECTION_SYNCH);
+ // SceneScript.db2
+ PrepareStatement(HOTFIX_SEL_SCENE_SCRIPT, "SELECT ID, Name, Script, PrevScriptId, NextScriptId FROM scene_script ORDER BY ID DESC", CONNECTION_SYNCH);
+
+ // SceneScriptPackage.db2
+ PrepareStatement(HOTFIX_SEL_SCENE_SCRIPT_PACKAGE, "SELECT ID, Name FROM scene_script_package ORDER BY ID DESC", CONNECTION_SYNCH);
+
// SkillLine.db2
PrepareStatement(HOTFIX_SEL_SKILL_LINE, "SELECT ID, DisplayName, Description, AlternateVerb, SpellIconID, Flags, CategoryID, CanLink, "
"ParentSkillLineID FROM skill_line ORDER BY ID DESC", CONNECTION_SYNCH);
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h
index 57c1512eca5..eafc14e07e3 100644
--- a/src/server/database/Database/Implementation/HotfixDatabase.h
+++ b/src/server/database/Database/Implementation/HotfixDatabase.h
@@ -372,6 +372,10 @@ enum HotfixDatabaseStatements
HOTFIX_SEL_SCALING_STAT_DISTRIBUTION,
+ HOTFIX_SEL_SCENE_SCRIPT,
+
+ HOTFIX_SEL_SCENE_SCRIPT_PACKAGE,
+
HOTFIX_SEL_SKILL_LINE,
HOTFIX_SEL_SKILL_LINE_LOCALE,
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index ddefe9959ea..ff169981de1 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -748,7 +748,13 @@ enum RBACPermissions
RBAC_PERM_COMMAND_NEARGRAVEYARD = 841,
RBAC_PERM_COMMAND_RELOAD_CHARACTER_TEMPLATE = 842,
RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING = 843,
- RBAC_PERM_COMMAND_DEBUG_SEND_PLAYSCENE = 844,
+ RBAC_PERM_COMMAND_SCENE = 844,
+ RBAC_PERM_COMMAND_SCENE_DEBUG = 845,
+ RBAC_PERM_COMMAND_SCENE_PLAY = 846,
+ RBAC_PERM_COMMAND_SCENE_PLAY_PACKAGE = 847,
+ RBAC_PERM_COMMAND_SCENE_CANCEL = 848,
+ RBAC_PERM_COMMAND_LIST_SCENES = 849,
+ RBAC_PERM_COMMAND_RELOAD_SCENE_TEMPLATE = 850,
// custom permissions 1000+
RBAC_PERM_MAX
diff --git a/src/server/game/DataStores/DB2Metadata.h b/src/server/game/DataStores/DB2Metadata.h
index c08a41293bd..54a380dadeb 100644
--- a/src/server/game/DataStores/DB2Metadata.h
+++ b/src/server/game/DataStores/DB2Metadata.h
@@ -4402,7 +4402,7 @@ struct SceneScriptMeta
{
static DB2Meta const* Instance()
{
- static char const* types = "sshh";
+ static char const* types = "SShh";
static uint8 const arraySizes[4] = { 1, 1, 1, 1 };
static DB2Meta instance(-1, 4, 0xE564690A, types, arraySizes);
return &instance;
@@ -4413,7 +4413,7 @@ struct SceneScriptPackageMeta
{
static DB2Meta const* Instance()
{
- static char const* types = "s";
+ static char const* types = "S";
static uint8 const arraySizes[1] = { 1 };
static DB2Meta instance(-1, 1, 0x67818447, types, arraySizes);
return &instance;
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index 661c2418da6..31f4d0e4438 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -170,6 +170,8 @@ DB2Storage<QuestXPEntry> sQuestXPStore("QuestXP.db2", Que
DB2Storage<RandPropPointsEntry> sRandPropPointsStore("RandPropPoints.db2", RandPropPointsMeta::Instance(), HOTFIX_SEL_RAND_PROP_POINTS);
DB2Storage<RulesetItemUpgradeEntry> sRulesetItemUpgradeStore("RulesetItemUpgrade.db2", RulesetItemUpgradeMeta::Instance(), HOTFIX_SEL_RULESET_ITEM_UPGRADE);
DB2Storage<ScalingStatDistributionEntry> sScalingStatDistributionStore("ScalingStatDistribution.db2", ScalingStatDistributionMeta::Instance(), HOTFIX_SEL_SCALING_STAT_DISTRIBUTION);
+DB2Storage<SceneScriptEntry> sSceneScriptStore("SceneScript.db2", SceneScriptMeta::Instance(), HOTFIX_SEL_SCENE_SCRIPT);
+DB2Storage<SceneScriptPackageEntry> sSceneScriptPackageStore("SceneScriptPackage.db2", SceneScriptPackageMeta::Instance(), HOTFIX_SEL_SCENE_SCRIPT_PACKAGE);
DB2Storage<SkillLineEntry> sSkillLineStore("SkillLine.db2", SkillLineMeta::Instance(), HOTFIX_SEL_SKILL_LINE);
DB2Storage<SkillLineAbilityEntry> sSkillLineAbilityStore("SkillLineAbility.db2", SkillLineAbilityMeta::Instance(), HOTFIX_SEL_SKILL_LINE_ABILITY);
DB2Storage<SkillRaceClassInfoEntry> sSkillRaceClassInfoStore("SkillRaceClassInfo.db2", SkillRaceClassInfoMeta::Instance(), HOTFIX_SEL_SKILL_RACE_CLASS_INFO);
@@ -449,6 +451,8 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale)
LOAD_DB2(sRandPropPointsStore);
LOAD_DB2(sRulesetItemUpgradeStore);
LOAD_DB2(sScalingStatDistributionStore);
+ LOAD_DB2(sSceneScriptStore);
+ LOAD_DB2(sSceneScriptPackageStore);
LOAD_DB2(sSkillLineStore);
LOAD_DB2(sSkillLineAbilityStore);
LOAD_DB2(sSkillRaceClassInfoStore);
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index 74120768731..d13faa13c56 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -137,6 +137,8 @@ TC_GAME_API extern DB2Storage<QuestXPEntry> sQuestXPStor
TC_GAME_API extern DB2Storage<RandPropPointsEntry> sRandPropPointsStore;
TC_GAME_API extern DB2Storage<ScalingStatDistributionEntry> sScalingStatDistributionStore;
TC_GAME_API extern DB2Storage<SkillLineEntry> sSkillLineStore;
+TC_GAME_API extern DB2Storage<SceneScriptEntry> sSceneScriptStore;
+TC_GAME_API extern DB2Storage<SceneScriptPackageEntry> sSceneScriptPackageStore;
TC_GAME_API extern DB2Storage<SkillLineAbilityEntry> sSkillLineAbilityStore;
TC_GAME_API extern DB2Storage<SkillRaceClassInfoEntry> sSkillRaceClassInfoStore;
TC_GAME_API extern DB2Storage<SoundKitEntry> sSoundKitStore;
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
index 7be7706101a..e9c02124ba0 100644
--- a/src/server/game/DataStores/DB2Structure.h
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -2049,6 +2049,21 @@ struct ScalingStatDistributionEntry
uint32 MaxLevel;
};
+struct SceneScriptEntry
+{
+ uint32 ID;
+ char const* Name;
+ char const* Script;
+ uint16 PrevScriptId;
+ uint16 NextScriptId;
+};
+
+struct SceneScriptPackageEntry
+{
+ uint32 ID;
+ char const* Name;
+};
+
struct SkillLineEntry
{
uint32 ID;
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index c38661301b3..0aa0c05e3a8 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -891,4 +891,13 @@ enum CurrencyTypes
CURRENCY_TYPE_ARTIFACT_KNOWLEDGE = 1171,
};
+enum SceneFlags
+{
+ SCENEFLAG_UNK1 = 0x01,
+ SCENEFLAG_UNK2 = 0x02,
+ SCENEFLAG_NOT_CANCELABLE = 0x04,
+ SCENEFLAG_UNK8 = 0x08,
+ SCENEFLAG_UNK16 = 0x10, // 16, most common value
+};
+
#endif
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 202a36b4375..5f7032bb5ce 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -113,7 +113,7 @@ static uint32 copseReclaimDelay[MAX_DEATH_COUNT] = { 30, 60, 120 };
uint64 const MAX_MONEY_AMOUNT = 9999999999ULL;
-Player::Player(WorldSession* session) : Unit(true)
+Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this)
{
m_speakTime = 0;
m_speakCount = 0;
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index b51fdfccd47..f53b55a4caa 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -32,6 +32,7 @@
#include "WorldSession.h"
#include "PlayerTaxi.h"
#include "TradeData.h"
+#include "SceneMgr.h"
struct CreatureTemplate;
struct Mail;
@@ -2476,6 +2477,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool IsAdvancedCombatLoggingEnabled() const { return _advancedCombatLoggingEnabled; }
void SetAdvancedCombatLogging(bool enabled) { _advancedCombatLoggingEnabled = enabled; }
+ SceneMgr& GetSceneMgr() { return m_sceneMgr; }
+
protected:
// Gamemaster whisper whitelist
GuidList WhisperList;
@@ -2824,6 +2827,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint32 manaBeforeDuel;
WorldLocation _corpseLocation;
+
+ SceneMgr m_sceneMgr;
};
TC_GAME_API void AddItemsSetItem(Player* player, Item* item);
diff --git a/src/server/game/Entities/Player/SceneMgr.cpp b/src/server/game/Entities/Player/SceneMgr.cpp
new file mode 100644
index 00000000000..9679ae892c6
--- /dev/null
+++ b/src/server/game/Entities/Player/SceneMgr.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "SceneMgr.h"
+#include "Chat.h"
+#include "Language.h"
+#include "ObjectMgr.h"
+#include "Player.h"
+#include "ScenePackets.h"
+#include "ScriptMgr.h"
+#include "SpellAuraEffects.h"
+
+SceneMgr::SceneMgr(Player* player) : _player(player)
+{
+ _standaloneSceneInstanceID = 0;
+ _isDebuggingScenes = false;
+}
+
+uint32 SceneMgr::PlayScene(uint32 sceneId, Position const* position /*= nullptr*/)
+{
+ SceneTemplate const* sceneTemplate = sObjectMgr->GetSceneTemplate(sceneId);
+ return PlaySceneByTemplate(sceneTemplate, position);
+}
+
+uint32 SceneMgr::PlaySceneByTemplate(SceneTemplate const* sceneTemplate, Position const* position /*= nullptr*/)
+{
+ if (!sceneTemplate)
+ return 0;
+
+ SceneScriptPackageEntry const* entry = sSceneScriptPackageStore.LookupEntry(sceneTemplate->ScenePackageId);
+ if (!entry)
+ return 0;
+
+ // By default, take player position
+ if (!position)
+ position = GetPlayer();
+
+ uint32 sceneInstanceID = GetNewStandaloneSceneInstanceID();
+
+ if (_isDebuggingScenes)
+ ChatHandler(GetPlayer()->GetSession()).PSendSysMessage(LANG_COMMAND_SCENE_DEBUG_PLAY, sceneInstanceID, sceneTemplate->ScenePackageId, sceneTemplate->PlaybackFlags);
+
+ WorldPackets::Scenes::PlayScene playScene;
+ playScene.SceneID = sceneTemplate->SceneId;
+ playScene.PlaybackFlags = sceneTemplate->PlaybackFlags;
+ playScene.SceneInstanceID = sceneInstanceID;
+ playScene.SceneScriptPackageID = sceneTemplate->ScenePackageId;
+ playScene.Location = *position;
+ playScene.TransportGUID = GetPlayer()->GetTransGUID();
+
+ GetPlayer()->GetSession()->SendPacket(playScene.Write(), true);
+
+ AddInstanceIdToSceneMap(sceneInstanceID, sceneTemplate);
+
+ sScriptMgr->OnSceneStart(GetPlayer(), sceneInstanceID, sceneTemplate);
+
+ return sceneInstanceID;
+}
+
+uint32 SceneMgr::PlaySceneByPackageId(uint32 sceneScriptPackageId, uint32 playbackflags /*= SCENEFLAG_UNK16*/, Position const* position /*= nullptr*/)
+{
+ SceneTemplate sceneTemplate;
+ sceneTemplate.SceneId = 0;
+ sceneTemplate.ScenePackageId = sceneScriptPackageId;
+ sceneTemplate.PlaybackFlags = playbackflags;
+ sceneTemplate.ScriptId = 0;
+
+ return PlaySceneByTemplate(&sceneTemplate, position);
+}
+
+void SceneMgr::CancelScene(uint32 sceneInstanceID, bool removeFromMap /*= true*/)
+{
+ if (removeFromMap)
+ RemoveSceneInstanceId(sceneInstanceID);
+
+ WorldPackets::Scenes::CancelScene cancelScene;
+ cancelScene.SceneInstanceID = sceneInstanceID;
+ GetPlayer()->GetSession()->SendPacket(cancelScene.Write(), true);
+}
+
+void SceneMgr::OnSceneTrigger(uint32 sceneInstanceID, std::string const& triggerName)
+{
+ if (!HasScene(sceneInstanceID))
+ return;
+
+ if (_isDebuggingScenes)
+ ChatHandler(GetPlayer()->GetSession()).PSendSysMessage(LANG_COMMAND_SCENE_DEBUG_TRIGGER, sceneInstanceID, triggerName.c_str());
+
+ SceneTemplate const* sceneTemplate = GetSceneTemplateFromInstanceId(sceneInstanceID);
+ sScriptMgr->OnSceneTrigger(GetPlayer(), sceneInstanceID, sceneTemplate, triggerName);
+}
+
+void SceneMgr::OnSceneCancel(uint32 sceneInstanceID)
+{
+ if (!HasScene(sceneInstanceID))
+ return;
+
+ if (_isDebuggingScenes)
+ ChatHandler(GetPlayer()->GetSession()).PSendSysMessage(LANG_COMMAND_SCENE_DEBUG_CANCEL, sceneInstanceID);
+
+ SceneTemplate const* sceneTemplate = GetSceneTemplateFromInstanceId(sceneInstanceID);
+
+ // Must be done before removing aura
+ RemoveSceneInstanceId(sceneInstanceID);
+
+ if (sceneTemplate->SceneId != 0)
+ RemoveAurasDueToSceneId(sceneTemplate->SceneId);
+
+ sScriptMgr->OnSceneCancel(GetPlayer(), sceneInstanceID, sceneTemplate);
+}
+
+void SceneMgr::OnSceneComplete(uint32 sceneInstanceID)
+{
+ if (!HasScene(sceneInstanceID))
+ return;
+
+ if (_isDebuggingScenes)
+ ChatHandler(GetPlayer()->GetSession()).PSendSysMessage(LANG_COMMAND_SCENE_DEBUG_COMPLETE, sceneInstanceID);
+
+ SceneTemplate const* sceneTemplate = GetSceneTemplateFromInstanceId(sceneInstanceID);
+
+ // Must be done before removing aura
+ RemoveSceneInstanceId(sceneInstanceID);
+
+ if (sceneTemplate->SceneId != 0)
+ RemoveAurasDueToSceneId(sceneTemplate->SceneId);
+
+ sScriptMgr->OnSceneComplete(GetPlayer(), sceneInstanceID, sceneTemplate);
+}
+
+bool SceneMgr::HasScene(uint32 sceneInstanceID, uint32 sceneScriptPackageId /*= 0*/) const
+{
+ auto itr = _scenesByInstance.find(sceneInstanceID);
+
+ if (itr != _scenesByInstance.end())
+ return !sceneScriptPackageId || sceneScriptPackageId == itr->second->ScenePackageId;
+
+ return false;
+}
+
+void SceneMgr::AddInstanceIdToSceneMap(uint32 sceneInstanceID, SceneTemplate const* sceneTemplate)
+{
+ _scenesByInstance[sceneInstanceID] = sceneTemplate;
+}
+
+void SceneMgr::CancelSceneByPackageId(uint32 sceneScriptPackageId)
+{
+ std::vector<uint32> instancesIds;
+
+ for (auto itr : _scenesByInstance)
+ if (itr.second->ScenePackageId == sceneScriptPackageId)
+ instancesIds.push_back(itr.first);
+
+ for (uint32 sceneInstanceID : instancesIds)
+ CancelScene(sceneInstanceID);
+}
+
+void SceneMgr::RemoveSceneInstanceId(uint32 sceneInstanceID)
+{
+ _scenesByInstance.erase(sceneInstanceID);
+}
+
+void SceneMgr::RemoveAurasDueToSceneId(uint32 sceneId)
+{
+ Player::AuraEffectList const& scenePlayAuras = GetPlayer()->GetAuraEffectsByType(SPELL_AURA_PLAY_SCENE);
+ for (AuraEffect* scenePlayAura : scenePlayAuras)
+ {
+ if (uint32(scenePlayAura->GetMiscValue()) == sceneId)
+ {
+ GetPlayer()->RemoveAura(scenePlayAura->GetBase());
+ break;
+ }
+ }
+}
+
+SceneTemplate const* SceneMgr::GetSceneTemplateFromInstanceId(uint32 sceneInstanceID)
+{
+ auto itr = _scenesByInstance.find(sceneInstanceID);
+
+ if (itr != _scenesByInstance.end())
+ return itr->second;
+
+ return nullptr;
+}
+
+uint32 SceneMgr::GetActiveSceneCount(uint32 sceneScriptPackageId /*= 0*/)
+{
+ uint32 activeSceneCount = 0;
+
+ for (auto itr : _scenesByInstance)
+ if (!sceneScriptPackageId || itr.second->ScenePackageId == sceneScriptPackageId)
+ ++activeSceneCount;
+
+ return activeSceneCount;
+}
diff --git a/src/server/game/Entities/Player/SceneMgr.h b/src/server/game/Entities/Player/SceneMgr.h
new file mode 100644
index 00000000000..8315a811321
--- /dev/null
+++ b/src/server/game/Entities/Player/SceneMgr.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SceneMgr_h__
+#define SceneMgr_h__
+
+#include "Common.h"
+
+class Player;
+struct Position;
+struct SceneTemplate;
+
+typedef std::map<uint32, SceneTemplate const*> SceneTemplateByInstance;
+
+class TC_GAME_API SceneMgr
+{
+public:
+ SceneMgr(Player* player);
+
+ Player* GetPlayer() const { return _player; }
+
+ uint32 PlayScene(uint32 sceneId, Position const* position = nullptr);
+ uint32 PlaySceneByTemplate(SceneTemplate const* sceneTemplate, Position const* position = nullptr);
+ uint32 PlaySceneByPackageId(uint32 sceneScriptPackageId, uint32 playbackflags = SCENEFLAG_UNK16, Position const* position = nullptr);
+ void CancelScene(uint32 sceneInstanceID, bool removeFromMap = true);
+
+ void OnSceneTrigger(uint32 sceneInstanceID, std::string const& triggerName);
+ void OnSceneCancel(uint32 sceneInstanceID);
+ void OnSceneComplete(uint32 sceneInstanceID);
+
+ void RecreateScene(uint32 sceneScriptPackageId, uint32 playbackflags = SCENEFLAG_UNK16, Position const* position = nullptr)
+ {
+ CancelSceneByPackageId(sceneScriptPackageId);
+ PlaySceneByPackageId(sceneScriptPackageId, playbackflags, position);
+ }
+
+ bool HasScene(uint32 sceneInstanceID, uint32 sceneScriptPackageId = 0) const;
+
+ void AddInstanceIdToSceneMap(uint32 sceneInstanceID, SceneTemplate const* sceneTemplate);
+ void CancelSceneByPackageId(uint32 sceneScriptPackageId);
+ void RemoveSceneInstanceId(uint32 sceneInstanceID);
+ void RemoveAurasDueToSceneId(uint32 sceneId);
+
+ SceneTemplate const* GetSceneTemplateFromInstanceId(uint32 sceneInstanceID);
+ uint32 GetActiveSceneCount(uint32 sceneScriptPackageId = 0);
+ SceneTemplateByInstance const& GetSceneTemplateByInstanceMap() const { return _scenesByInstance; }
+
+ uint32 GetNewStandaloneSceneInstanceID() { return ++_standaloneSceneInstanceID; }
+
+ void ToggleDebugSceneMode() { _isDebuggingScenes = !_isDebuggingScenes; }
+ bool IsInDebugSceneMode() const { return _isDebuggingScenes; }
+
+private:
+ Player* _player;
+ SceneTemplateByInstance _scenesByInstance;
+ uint32 _standaloneSceneInstanceID;
+ bool _isDebuggingScenes;
+};
+
+#endif // SceneMgr_h__
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index ec1492d7d4f..b05576e223f 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -8764,6 +8764,8 @@ void ObjectMgr::LoadScriptNames()
"UNION "
"SELECT DISTINCT(ScriptName) FROM outdoorpvp_template WHERE ScriptName <> '' "
"UNION "
+ "SELECT DISTINCT(ScriptName) FROM scene_template WHERE ScriptName <> '' "
+ "UNION "
"SELECT DISTINCT(script) FROM instance_template WHERE script <> ''");
if (!result)
@@ -9601,3 +9603,34 @@ void ObjectMgr::LoadCreatureQuestItems()
TC_LOG_INFO("server.loading", ">> Loaded %u creature quest items in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+
+void ObjectMgr::LoadSceneTemplates()
+{
+ uint32 oldMSTime = getMSTime();
+ _sceneTemplateStore.clear();
+
+ QueryResult templates = WorldDatabase.Query("SELECT SceneId, Flags, ScriptPackageID, ScriptName FROM scene_template");
+
+ if (!templates)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 scene templates. DB table `scene_template` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = templates->Fetch();
+
+ uint32 sceneId = fields[0].GetUInt32();
+ SceneTemplate& sceneTemplate = _sceneTemplateStore[sceneId];
+ sceneTemplate.SceneId = sceneId;
+ sceneTemplate.PlaybackFlags = fields[1].GetUInt32();
+ sceneTemplate.ScenePackageId = fields[2].GetUInt32();
+ sceneTemplate.ScriptId = sObjectMgr->GetScriptId(fields[3].GetCString());
+
+ } while (templates->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u scene templates in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
+}
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 01b1b87ca68..383ee438335 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -624,6 +624,16 @@ struct CharacterTemplate
typedef std::unordered_map<uint32, CharacterTemplate> CharacterTemplateContainer;
+struct SceneTemplate
+{
+ uint32 SceneId;
+ uint32 PlaybackFlags;
+ uint32 ScenePackageId;
+ uint32 ScriptId;
+};
+
+typedef std::unordered_map<uint32, SceneTemplate> SceneTemplateContainer;
+
enum SkillRangeType
{
SKILL_RANGE_LANGUAGE, // 300..300
@@ -1069,6 +1079,8 @@ class TC_GAME_API ObjectMgr
void LoadTerrainWorldMaps();
void LoadAreaPhases();
+ void LoadSceneTemplates();
+
std::string GeneratePetName(uint32 entry);
uint32 GetBaseXP(uint8 level);
uint32 GetXPForLevel(uint8 level) const;
@@ -1403,6 +1415,15 @@ class TC_GAME_API ObjectMgr
return nullptr;
}
+ SceneTemplate const* GetSceneTemplate(uint32 sceneId) const
+ {
+ auto itr = _sceneTemplateStore.find(sceneId);
+ if (itr != _sceneTemplateStore.end())
+ return &itr->second;
+
+ return nullptr;
+ }
+
private:
// first free id for selected id type
uint32 _auctionId;
@@ -1556,6 +1577,7 @@ class TC_GAME_API ObjectMgr
RealmNameContainer _realmNameStore;
CharacterTemplateContainer _characterTemplateStore;
+ SceneTemplateContainer _sceneTemplateStore;
enum CreatureLinkedRespawnType
{
diff --git a/src/server/game/Handlers/SceneHandler.cpp b/src/server/game/Handlers/SceneHandler.cpp
index a8e08c9841f..fa9b708d51c 100644
--- a/src/server/game/Handlers/SceneHandler.cpp
+++ b/src/server/game/Handlers/SceneHandler.cpp
@@ -18,19 +18,25 @@
#include "Common.h"
#include "ScenePackets.h"
#include "WorldSession.h"
+#include "Player.h"
void WorldSession::HandleSceneTriggerEvent(WorldPackets::Scenes::SceneTriggerEvent& sceneTriggerEvent)
{
- TC_LOG_DEBUG("scenes", "HandleSceneTriggerEvent: SceneInstanceID: %u Event: %s", sceneTriggerEvent.SceneInstanceID, sceneTriggerEvent._Event.c_str());
+ TC_LOG_DEBUG("scenes", "HandleSceneTriggerEvent: SceneInstanceID: %u Event: %s", sceneTriggerEvent.SceneInstanceID, sceneTriggerEvent.Event.c_str());
+
+ GetPlayer()->GetSceneMgr().OnSceneTrigger(sceneTriggerEvent.SceneInstanceID, sceneTriggerEvent.Event);
}
void WorldSession::HandleScenePlaybackComplete(WorldPackets::Scenes::ScenePlaybackComplete& scenePlaybackComplete)
{
-
TC_LOG_DEBUG("scenes", "HandleScenePlaybackComplete: SceneInstanceID: %u", scenePlaybackComplete.SceneInstanceID);
+
+ GetPlayer()->GetSceneMgr().OnSceneComplete(scenePlaybackComplete.SceneInstanceID);
}
void WorldSession::HandleScenePlaybackCanceled(WorldPackets::Scenes::ScenePlaybackCanceled& scenePlaybackCanceled)
{
TC_LOG_DEBUG("scenes", "HandleScenePlaybackCanceled: SceneInstanceID: %u", scenePlaybackCanceled.SceneInstanceID);
+
+ GetPlayer()->GetSceneMgr().OnSceneCancel(scenePlaybackCanceled.SceneInstanceID);
}
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index 5b1a0272879..b675d83a9f1 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -1132,7 +1132,17 @@ enum TrinityStrings
LANG_COMMAND_MUTEHISTORY_EMPTY = 5060,
LANG_COMMAND_MUTEHISTORY_OUTPUT = 5061,
- // Room for more Trinity strings 5062-9999
+ // Scene debugs commands
+ LANG_COMMAND_SCENE_DEBUG_ON = 5062,
+ LANG_COMMAND_SCENE_DEBUG_OFF = 5063,
+ LANG_COMMAND_SCENE_DEBUG_PLAY = 5064,
+ LANG_COMMAND_SCENE_DEBUG_TRIGGER = 5065,
+ LANG_COMMAND_SCENE_DEBUG_CANCEL = 5066,
+ LANG_COMMAND_SCENE_DEBUG_COMPLETE = 5067,
+ LANG_DEBUG_SCENE_OBJECT_LIST = 5068,
+ LANG_DEBUG_SCENE_OBJECT_DETAIL = 5069,
+
+ // Room for more Trinity strings 5070-9999
// Level requirement notifications
LANG_SAY_REQ = 6604,
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index d228e161b69..17a71ed8ff8 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -96,6 +96,10 @@ template<>
struct is_script_database_bound<AchievementCriteriaScript>
: std::true_type { };
+template<>
+struct is_script_database_bound<SceneScript>
+ : std::true_type { };
+
enum Spells
{
SPELL_HOTSWAP_VISUAL_SPELL_EFFECT = 40162 // 59084
@@ -2296,6 +2300,43 @@ void ScriptMgr::ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& dama
FOREACH_SCRIPT(PlayerScript)->ModifySpellDamageTaken(target, attacker, damage);
}
+// Scene
+void ScriptMgr::OnSceneStart(Player* player, uint32 sceneInstanceID, SceneTemplate const* sceneTemplate)
+{
+ ASSERT(player);
+ ASSERT(sceneTemplate);
+
+ GET_SCRIPT(SceneScript, sceneTemplate->ScriptId, tmpscript);
+ tmpscript->OnSceneStart(player, sceneInstanceID, sceneTemplate);
+}
+
+void ScriptMgr::OnSceneTrigger(Player* player, uint32 sceneInstanceID, SceneTemplate const* sceneTemplate, std::string const& triggerName)
+{
+ ASSERT(player);
+ ASSERT(sceneTemplate);
+
+ GET_SCRIPT(SceneScript, sceneTemplate->ScriptId, tmpscript);
+ tmpscript->OnSceneTriggerEvent(player, sceneInstanceID, sceneTemplate, triggerName);
+}
+
+void ScriptMgr::OnSceneCancel(Player* player, uint32 sceneInstanceID, SceneTemplate const* sceneTemplate)
+{
+ ASSERT(player);
+ ASSERT(sceneTemplate);
+
+ GET_SCRIPT(SceneScript, sceneTemplate->ScriptId, tmpscript);
+ tmpscript->OnSceneCancel(player, sceneInstanceID, sceneTemplate);
+}
+
+void ScriptMgr::OnSceneComplete(Player* player, uint32 sceneInstanceID, SceneTemplate const* sceneTemplate)
+{
+ ASSERT(player);
+ ASSERT(sceneTemplate);
+
+ GET_SCRIPT(SceneScript, sceneTemplate->ScriptId, tmpscript);
+ tmpscript->OnSceneComplete(player, sceneInstanceID, sceneTemplate);
+}
+
SpellScriptLoader::SpellScriptLoader(const char* name)
: ScriptObject(name)
{
@@ -2450,6 +2491,12 @@ AccountScript::AccountScript(const char* name)
ScriptRegistry<AccountScript>::Instance()->AddScript(this);
}
+SceneScript::SceneScript(const char* name)
+ : ScriptObject(name)
+{
+ ScriptRegistry<SceneScript>::Instance()->AddScript(this);
+}
+
GuildScript::GuildScript(const char* name)
: ScriptObject(name)
{
@@ -2489,3 +2536,4 @@ template class TC_GAME_API ScriptRegistry<GuildScript>;
template class TC_GAME_API ScriptRegistry<GroupScript>;
template class TC_GAME_API ScriptRegistry<UnitScript>;
template class TC_GAME_API ScriptRegistry<AccountScript>;
+template class TC_GAME_API ScriptRegistry<SceneScript>;
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index a8458af987b..22d8426796e 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -69,6 +69,7 @@ struct Condition;
struct ItemTemplate;
struct MapEntry;
struct OutdoorPvPData;
+struct SceneTemplate;
#define VISIBLE_RANGE 166.0f //MAX visible range (size of grid)
@@ -831,6 +832,26 @@ class TC_GAME_API GroupScript : public ScriptObject
virtual void OnDisband(Group* /*group*/) { }
};
+class TC_GAME_API SceneScript : public ScriptObject
+{
+ protected:
+
+ SceneScript(const char* name);
+
+ public:
+ // Called when a player start a scene
+ virtual void OnSceneStart(Player* /*player*/, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) { }
+
+ // Called when a player receive trigger from scene
+ virtual void OnSceneTriggerEvent(Player* /*player*/, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/, std::string const& /*triggerName*/) { }
+
+ // Called when a scene is canceled
+ virtual void OnSceneCancel(Player* /*player*/, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) { }
+
+ // Called when a scene is completed
+ virtual void OnSceneComplete(Player* /*player*/, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) { }
+};
+
// Manages registration, loading, and execution of scripts.
class TC_GAME_API ScriptMgr
{
@@ -1107,6 +1128,12 @@ class TC_GAME_API ScriptMgr
void ModifyMeleeDamage(Unit* target, Unit* attacker, uint32& damage);
void ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage);
+ public: /* SceneScript */
+ void OnSceneStart(Player* player, uint32 sceneInstanceID, SceneTemplate const* sceneTemplate);
+ void OnSceneTrigger(Player* player, uint32 sceneInstanceID, SceneTemplate const* sceneTemplate, std::string const& triggerName);
+ void OnSceneCancel(Player* player, uint32 sceneInstanceID, SceneTemplate const* sceneTemplate);
+ void OnSceneComplete(Player* player, uint32 sceneInstanceID, SceneTemplate const* sceneTemplate);
+
private:
uint32 _scriptCount;
diff --git a/src/server/game/Server/Packets/ScenePackets.cpp b/src/server/game/Server/Packets/ScenePackets.cpp
index d5297f69930..d203a8bed1d 100644
--- a/src/server/game/Server/Packets/ScenePackets.cpp
+++ b/src/server/game/Server/Packets/ScenePackets.cpp
@@ -19,21 +19,28 @@
WorldPacket const* WorldPackets::Scenes::PlayScene::Write()
{
- _worldPacket << SceneID;
- _worldPacket << PlaybackFlags;
- _worldPacket << SceneInstanceID;
- _worldPacket << SceneScriptPackageID;
+ _worldPacket << int32(SceneID);
+ _worldPacket << int32(PlaybackFlags);
+ _worldPacket << int32(SceneInstanceID);
+ _worldPacket << int32(SceneScriptPackageID);
_worldPacket << TransportGUID;
_worldPacket << Location.PositionXYZOStream();
return &_worldPacket;
}
+WorldPacket const* WorldPackets::Scenes::CancelScene::Write()
+{
+ _worldPacket << int32(SceneInstanceID);
+
+ return &_worldPacket;
+}
+
void WorldPackets::Scenes::SceneTriggerEvent::Read()
{
uint32 len = _worldPacket.ReadBits(6);
_worldPacket >> SceneInstanceID;
- _Event = _worldPacket.ReadString(len);
+ Event = _worldPacket.ReadString(len);
}
void WorldPackets::Scenes::ScenePlaybackComplete::Read()
diff --git a/src/server/game/Server/Packets/ScenePackets.h b/src/server/game/Server/Packets/ScenePackets.h
index df6a1f0957e..7d64e3fabc1 100644
--- a/src/server/game/Server/Packets/ScenePackets.h
+++ b/src/server/game/Server/Packets/ScenePackets.h
@@ -40,6 +40,16 @@ namespace WorldPackets
Position Location;
};
+ class TC_GAME_API CancelScene final : public ServerPacket
+ {
+ public:
+ CancelScene() : ServerPacket(SMSG_CANCEL_SCENE, 4) { }
+
+ WorldPacket const* Write() override;
+
+ int32 SceneInstanceID = 0;
+ };
+
class SceneTriggerEvent final : public ClientPacket
{
public:
@@ -48,7 +58,7 @@ namespace WorldPackets
void Read() override;
uint32 SceneInstanceID = 0;
- std::string _Event;
+ std::string Event;
};
class ScenePlaybackComplete final : public ClientPacket
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 2444db82b45..d6647db388c 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -691,9 +691,9 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_SAVE_ENABLED_ADDONS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SAVE_EQUIPMENT_SET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetSave);
DEFINE_HANDLER(CMSG_SAVE_GUILD_EMBLEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSaveGuildEmblem);
- DEFINE_HANDLER(CMSG_SCENE_PLAYBACK_CANCELED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleScenePlaybackCanceled);
- DEFINE_HANDLER(CMSG_SCENE_PLAYBACK_COMPLETE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleScenePlaybackComplete);
- DEFINE_HANDLER(CMSG_SCENE_TRIGGER_EVENT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleSceneTriggerEvent);
+ DEFINE_HANDLER(CMSG_SCENE_PLAYBACK_CANCELED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleScenePlaybackCanceled);
+ DEFINE_HANDLER(CMSG_SCENE_PLAYBACK_COMPLETE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleScenePlaybackComplete);
+ DEFINE_HANDLER(CMSG_SCENE_TRIGGER_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSceneTriggerEvent);
DEFINE_HANDLER(CMSG_SELF_RES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSelfResOpcode);
DEFINE_HANDLER(CMSG_SELL_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSellItemOpcode);
DEFINE_HANDLER(CMSG_SELL_WOW_TOKEN_CONFIRM, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h
index 3007acdc281..0627847b463 100644
--- a/src/server/game/Spells/Auras/SpellAuraDefines.h
+++ b/src/server/game/Spells/Auras/SpellAuraDefines.h
@@ -487,7 +487,7 @@ enum AuraType
SPELL_AURA_SCALE_PLAYER_LEVEL = 427, // NYI
SPELL_AURA_428 = 428,
SPELL_AURA_429 = 429,
- SPELL_AURA_430 = 430,
+ SPELL_AURA_PLAY_SCENE = 430,
SPELL_AURA_431 = 431,
SPELL_AURA_432 = 432,
SPELL_AURA_433 = 433,
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index b0a6862f8d6..26618e63680 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -489,7 +489,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNULL, //427 SPELL_AURA_SCALE_PLAYER_LEVEL
&AuraEffect::HandleNULL, //428
&AuraEffect::HandleNULL, //429
- &AuraEffect::HandleNULL, //430
+ &AuraEffect::HandlePlayScene, //430 SPELL_AURA_PLAY_SCENE
&AuraEffect::HandleNULL, //431
&AuraEffect::HandleNULL, //432
&AuraEffect::HandleNULL, //433
@@ -6711,3 +6711,23 @@ void AuraEffect::HandleAllowUsingGameobjectsWhileMounted(AuraApplication const*
else if (!aurApp->GetTarget()->HasAuraType(SPELL_AURA_ALLOW_USING_GAMEOBJECTS_WHILE_MOUNTED))
aurApp->GetTarget()->RemoveFlag(PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_CAN_USE_OBJECTS_MOUNTED);
}
+
+void AuraEffect::HandlePlayScene(AuraApplication const* aurApp, uint8 mode, bool apply) const
+{
+ if (!(mode & AURA_EFFECT_HANDLE_REAL))
+ return;
+
+ Player* player = aurApp->GetTarget()->ToPlayer();
+ if (!player)
+ return;
+
+ uint32 sceneId = GetMiscValue();
+
+ if (apply)
+ player->GetSceneMgr().PlayScene(sceneId);
+ else
+ {
+ SceneTemplate const* sceneTemplate = sObjectMgr->GetSceneTemplate(sceneId);
+ player->GetSceneMgr().CancelSceneByPackageId(sceneTemplate->ScenePackageId);
+ }
+}
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index 5ecf741d967..03f3de465b3 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -309,6 +309,7 @@ class TC_GAME_API AuraEffect
void HandleShowConfirmationPrompt(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleOverridePetSpecs(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAllowUsingGameobjectsWhileMounted(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandlePlayScene(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// aura effect periodic tick handlers
void HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const;
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 6772638526b..75b6a3e0931 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1828,6 +1828,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Pet Name Parts...");
sObjectMgr->LoadPetNames();
+ TC_LOG_INFO("server.loading", "Loading Scenes Templates...");
+ sObjectMgr->LoadSceneTemplates();
+
CharacterDatabaseCleaner::CleanDatabase();
TC_LOG_INFO("server.loading", "Loading the max pet number...");
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index 84f86492750..abb5250ac59 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -37,7 +37,6 @@ EndScriptData */
#include "MapManager.h"
#include "MovementPackets.h"
#include "SpellPackets.h"
-#include "ScenePackets.h"
#include <fstream>
#include <limits>
@@ -68,7 +67,6 @@ public:
{ "sellerror", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_SELLERROR, false, &HandleDebugSendSellErrorCommand, "" },
{ "setphaseshift", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_SETPHASESHIFT, false, &HandleDebugSendSetPhaseShiftCommand, "" },
{ "spellfail", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_SPELLFAIL, false, &HandleDebugSendSpellFailCommand, "" },
- { "playscene", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_PLAYSCENE, false, &HandleDebugSendPlaySceneCommand, "" },
};
static std::vector<ChatCommand> debugCommandTable =
{
@@ -1482,49 +1480,6 @@ public:
return true;
}
- static bool HandleDebugSendPlaySceneCommand(ChatHandler* handler, char const* args)
- {
- if (!*args)
- return false;
-
- int32 sceneID = 0;
- int32 playbackFlags = 0;
- int32 sceneInstanceID = 0;
- int32 sceneScriptPackageID = 0;
-
- char* a = strtok((char*)args, " ");
- char* b = strtok(NULL, " ");
- char* c = strtok(NULL, " ");
- char* d = strtok(NULL, " ");
-
- if (!a || !b || !c || !d)
- return false;
-
- if (a)
- sceneID = atoi(a);
- if (b)
- playbackFlags = atoi(b);
- if (c)
- sceneInstanceID = atoi(c);
- if (d)
- sceneScriptPackageID = atoi(d);
-
- Player* me = handler->GetSession()->GetPlayer();
-
- WorldPackets::Scenes::PlayScene packet;
- packet.SceneID = sceneID;
- packet.PlaybackFlags = playbackFlags;
- packet.SceneInstanceID = sceneInstanceID;
- packet.SceneScriptPackageID = sceneScriptPackageID;
- packet.TransportGUID = me->GetTransGUID();
- packet.Location = me->GetPosition();
- handler->GetSession()->SendPacket(packet.Write(), true);
-
- TC_LOG_DEBUG("network", "Sent SMSG_PLAY_SCENE to %s, SceneID: %d, PlaybackFlags: %d, SceneInstanceID: %d, SceneScriptPackageID: %d", me->GetName().c_str(), sceneID, playbackFlags, sceneInstanceID, sceneScriptPackageID);
-
- return true;
- }
-
static bool HandleDebugRaidResetCommand(ChatHandler* /*handler*/, char const* args)
{
char* map_str = args ? strtok((char*)args, " ") : nullptr;
diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp
index b66fc95c407..775b1b3943f 100644
--- a/src/server/scripts/Commands/cs_list.cpp
+++ b/src/server/scripts/Commands/cs_list.cpp
@@ -45,6 +45,7 @@ public:
{ "object", rbac::RBAC_PERM_COMMAND_LIST_OBJECT, true, &HandleListObjectCommand, "" },
{ "auras", rbac::RBAC_PERM_COMMAND_LIST_AURAS, false, &HandleListAurasCommand, "" },
{ "mail", rbac::RBAC_PERM_COMMAND_LIST_MAIL, true, &HandleListMailCommand, "" },
+ { "scenes", rbac::RBAC_PERM_COMMAND_LIST_SCENES, false, &HandleListScenesCommand, "" },
};
static std::vector<ChatCommand> commandTable =
{
@@ -576,6 +577,30 @@ public:
handler->PSendSysMessage(LANG_LIST_MAIL_NOT_FOUND);
return true;
}
+
+ static bool HandleListScenesCommand(ChatHandler* handler, char const* /*args*/)
+ {
+ Player* target = handler->getSelectedPlayer();
+
+ if (!target)
+ target = handler->GetSession()->GetPlayer();
+
+ if (!target)
+ {
+ handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+
+ SceneTemplateByInstance const& instanceByPackageMap = target->GetSceneMgr().GetSceneTemplateByInstanceMap();
+
+ handler->PSendSysMessage(LANG_DEBUG_SCENE_OBJECT_LIST, target->GetSceneMgr().GetActiveSceneCount());
+
+ for (auto instanceByPackage : instanceByPackageMap)
+ handler->PSendSysMessage(LANG_DEBUG_SCENE_OBJECT_DETAIL, instanceByPackage.second->ScenePackageId, instanceByPackage.first);
+
+ return true;
+ }
};
void AddSC_list_commandscript()
diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp
index 4b185e7d6c5..ee59c6117e5 100644
--- a/src/server/scripts/Commands/cs_reload.cpp
+++ b/src/server/scripts/Commands/cs_reload.cpp
@@ -128,6 +128,7 @@ public:
{ "reputation_reward_rate", rbac::RBAC_PERM_COMMAND_RELOAD_REPUTATION_REWARD_RATE, true, &HandleReloadReputationRewardRateCommand, "" },
{ "reputation_spillover_template", rbac::RBAC_PERM_COMMAND_RELOAD_SPILLOVER_TEMPLATE, true, &HandleReloadReputationRewardRateCommand, "" },
{ "skill_discovery_template", rbac::RBAC_PERM_COMMAND_RELOAD_SKILL_DISCOVERY_TEMPLATE, true, &HandleReloadSkillDiscoveryTemplateCommand, "" },
+ { "scene_template", rbac::RBAC_PERM_COMMAND_RELOAD_SCENE_TEMPLATE, true, &HandleReloadSceneTemplateCommand, "" },
{ "skill_extra_item_template", rbac::RBAC_PERM_COMMAND_RELOAD_SKILL_EXTRA_ITEM_TEMPLATE, true, &HandleReloadSkillExtraItemTemplateCommand, "" },
{ "skill_fishing_base_level", rbac::RBAC_PERM_COMMAND_RELOAD_SKILL_FISHING_BASE_LEVEL, true, &HandleReloadSkillFishingBaseLevelCommand, "" },
{ "skinning_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_SKINNING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesSkinningCommand, "" },
@@ -1118,7 +1119,6 @@ public:
return true;
}
-
static bool HandleReloadPhaseDefinitionsCommand(ChatHandler* handler, const char* /*args*/)
{
TC_LOG_INFO("misc", "Reloading terrain_phase_info table...");
@@ -1127,6 +1127,15 @@ public:
return true;
}
+
+ static bool HandleReloadSceneTemplateCommand(ChatHandler* handler, const char* /*args*/)
+ {
+ TC_LOG_INFO("misc", "Reloading scene_template table...");
+ sObjectMgr->LoadSceneTemplates();
+ handler->SendGlobalGMSysMessage("Scenes templates reloaded. New scriptname need a reboot.");
+ return true;
+ }
+
static bool HandleReloadRBACCommand(ChatHandler* handler, const char* /*args*/)
{
TC_LOG_INFO("misc", "Reloading RBAC tables...");
diff --git a/src/server/scripts/Commands/cs_scene.cpp b/src/server/scripts/Commands/cs_scene.cpp
new file mode 100644
index 00000000000..557dff607c4
--- /dev/null
+++ b/src/server/scripts/Commands/cs_scene.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "Chat.h"
+#include "Language.h"
+#include "Player.h"
+#include "ObjectMgr.h"
+
+class scene_commandscript : public CommandScript
+{
+public:
+ scene_commandscript() : CommandScript("scene_commandscript") { }
+
+ std::vector<ChatCommand> GetCommands() const override
+ {
+ static std::vector<ChatCommand> sceneCommandTable =
+ {
+ { "debug", rbac::RBAC_PERM_COMMAND_SCENE_DEBUG, false, &HandleDebugSceneCommand, "" },
+ { "play", rbac::RBAC_PERM_COMMAND_SCENE_PLAY, false, &HandlePlaySceneCommand, "" },
+ { "playpackage", rbac::RBAC_PERM_COMMAND_SCENE_PLAY_PACKAGE, false, &HandlePlayScenePackageCommand, "" },
+ { "cancel", rbac::RBAC_PERM_COMMAND_SCENE_CANCEL, false, &HandleCancelSceneCommand, "" }
+ };
+ static std::vector<ChatCommand> commandTable =
+ {
+ { "scene", rbac::RBAC_PERM_COMMAND_SCENE, true, NULL, "", sceneCommandTable }
+ };
+ return commandTable;
+ }
+
+ static bool HandleDebugSceneCommand(ChatHandler* handler, char const* /*args*/)
+ {
+ if (Player* player = handler->GetSession()->GetPlayer())
+ {
+ player->GetSceneMgr().ToggleDebugSceneMode();
+ handler->PSendSysMessage(player->GetSceneMgr().IsInDebugSceneMode() ? LANG_COMMAND_SCENE_DEBUG_ON : LANG_COMMAND_SCENE_DEBUG_OFF);
+ }
+
+ return true;
+ }
+
+ static bool HandlePlaySceneCommand(ChatHandler* handler, char const* args)
+ {
+ if (!*args)
+ return false;
+
+ char const* sceneIdStr = strtok((char*)args, " ");
+
+ if (!sceneIdStr)
+ return false;
+
+ uint32 sceneId = atoi(sceneIdStr);
+ Player* target = handler->getSelectedPlayerOrSelf();
+
+ if (!target)
+ {
+ handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+
+ if (!sObjectMgr->GetSceneTemplate(sceneId))
+ return false;
+
+ target->GetSceneMgr().PlayScene(sceneId);
+ return true;
+ }
+
+ static bool HandlePlayScenePackageCommand(ChatHandler* handler, char const* args)
+ {
+ if (!*args)
+ return false;
+
+ char const* scenePackageIdStr = strtok((char*)args, " ");
+ char const* flagsStr = strtok(NULL, "");
+
+ if (!scenePackageIdStr)
+ return false;
+
+ uint32 scenePackageId = atoi(scenePackageIdStr);
+ uint32 flags = flagsStr ? atoi(flagsStr) : SCENEFLAG_UNK16;
+ Player* target = handler->getSelectedPlayerOrSelf();
+
+ if (!target)
+ {
+ handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+
+ if (!sSceneScriptPackageStore.HasRecord(scenePackageId))
+ return false;
+
+ target->GetSceneMgr().PlaySceneByPackageId(scenePackageId, flags);
+ return true;
+ }
+
+ static bool HandleCancelSceneCommand(ChatHandler* handler, char const* args)
+ {
+ if (!*args)
+ return false;
+
+ Player* target = handler->getSelectedPlayerOrSelf();
+
+ if (!target)
+ {
+ handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+
+ uint32 id = atoi((char*)args);
+
+ if (!sSceneScriptPackageStore.HasRecord(id))
+ return false;
+
+ target->GetSceneMgr().CancelSceneByPackageId(id);
+ return true;
+ }
+};
+
+void AddSC_scene_commandscript()
+{
+ new scene_commandscript();
+}
diff --git a/src/server/scripts/Commands/cs_script_loader.cpp b/src/server/scripts/Commands/cs_script_loader.cpp
index 4e59ad13e95..6ff338eb82e 100644
--- a/src/server/scripts/Commands/cs_script_loader.cpp
+++ b/src/server/scripts/Commands/cs_script_loader.cpp
@@ -51,6 +51,7 @@ void AddSC_quest_commandscript();
void AddSC_rbac_commandscript();
void AddSC_reload_commandscript();
void AddSC_reset_commandscript();
+void AddSC_scene_commandscript();
void AddSC_send_commandscript();
void AddSC_server_commandscript();
void AddSC_tele_commandscript();
@@ -97,6 +98,7 @@ void AddCommandsScripts()
AddSC_rbac_commandscript();
AddSC_reload_commandscript();
AddSC_reset_commandscript();
+ AddSC_scene_commandscript();
AddSC_send_commandscript();
AddSC_server_commandscript();
AddSC_tele_commandscript();
diff --git a/src/server/scripts/World/scene_scripts.cpp b/src/server/scripts/World/scene_scripts.cpp
new file mode 100644
index 00000000000..860c97e60ea
--- /dev/null
+++ b/src/server/scripts/World/scene_scripts.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "Player.h"
+
+enum SceneSpells
+{
+ SPELL_DEATHWING_SIMULATOR = 201184
+};
+
+class scene_deathwing_simulator : public SceneScript
+{
+ public:
+ scene_deathwing_simulator() : SceneScript("scene_deathwing_simulator") { }
+
+ // Called when a player receive trigger from scene
+ void OnSceneTriggerEvent(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/, std::string const& triggerName) override
+ {
+ if (triggerName == "BURN PLAYER")
+ player->CastSpell(player, SPELL_DEATHWING_SIMULATOR, true); // Deathwing Simulator Burn player
+ }
+};
+
+void AddSC_scene_scripts()
+{
+ new scene_deathwing_simulator();
+}
diff --git a/src/server/scripts/World/world_script_loader.cpp b/src/server/scripts/World/world_script_loader.cpp
index bc007ab8100..2d5b5efebf2 100644
--- a/src/server/scripts/World/world_script_loader.cpp
+++ b/src/server/scripts/World/world_script_loader.cpp
@@ -30,6 +30,7 @@ void AddSC_npc_innkeeper();
void AddSC_npcs_special();
void AddSC_achievement_scripts();
void AddSC_action_ip_logger();
+void AddSC_scene_scripts();
// player
void AddSC_chat_log();
void AddSC_duel_reset();
@@ -49,6 +50,7 @@ void AddWorldScripts()
AddSC_npcs_special();
AddSC_achievement_scripts();
AddSC_chat_log(); // location: scripts\World\chat_log.cpp
+ AddSC_scene_scripts();
// FIXME: This should be moved in a script validation hook.
// To avoid duplicate code, we check once /*ONLY*/ if logging is permitted or not.