diff options
Diffstat (limited to 'src/server/game')
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..."); |
