aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
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/server/game
parentdd64a3cd36d7c8db67f4075c5a8c1eb01898d1ed (diff)
Core/Scenes: Implemented scene system
Closes #17858 Closes #17976
Diffstat (limited to 'src/server/game')
-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
23 files changed, 529 insertions, 18 deletions
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...");