diff options
author | Traesh <traesh@farahlon.com> | 2016-09-25 16:13:12 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-09-25 16:13:12 +0200 |
commit | d4887311e39527e036419ebd966f399fdbdae67a (patch) | |
tree | 7a87b65e493e3b0660790b02b151107fc4ab66b4 /src | |
parent | dd64a3cd36d7c8db67f4075c5a8c1eb01898d1ed (diff) |
Core/Scenes: Implemented scene system
Closes #17858
Closes #17976
Diffstat (limited to 'src')
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. |