From dec4648cf88a2b0bd9f278793515c55a4c58c2a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=9A=E7=BE=8E?= <2370337237@qq.com> Date: Mon, 22 Sep 2025 14:32:42 +0800 Subject: [PATCH] =?UTF-8?q?[=E5=A4=A7=E7=A7=98=E5=A2=83]=201=E3=80=81?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B7=B7=E5=90=88=E8=84=9A=E6=9C=AC=E5=8C=85?= =?UTF-8?q?=E8=A3=85=E5=99=A8=202=E3=80=81=E6=B7=BB=E5=8A=A0=E7=94=9F?= =?UTF-8?q?=E7=89=A9=E5=B1=9E=E6=80=A7=E8=AE=BE=E7=BD=AE=E6=96=B9=E6=B3=95?= =?UTF-8?q?=203=E3=80=81=E7=A6=81=E7=94=A8=E7=94=9F=E7=89=A9=E6=8E=89?= =?UTF-8?q?=E8=90=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/MythicPlusWrapperInstance.cpp | 222 ++++++++++++++++ .../src/MythicPlusWrapperInstance.h | 60 +++++ .../mod-mythic-plus/src/Mythic_Keystone.cpp | 233 +++++++++++++++-- modules/mod-mythic-plus/src/Mythic_Script.h | 75 ++++-- modules/mod-mythic-plus/src/loader.cpp | 4 +- .../instance_wailing_caverns_mythic.cpp | 236 ------------------ .../wailing_caverns/wailing_caverns_mythic.h | 51 ---- modules/mod_SMAddon/src/mod_SMAddon.cpp | 2 +- 8 files changed, 549 insertions(+), 334 deletions(-) create mode 100644 modules/mod-mythic-plus/src/MythicPlusWrapperInstance.cpp create mode 100644 modules/mod-mythic-plus/src/MythicPlusWrapperInstance.h delete mode 100644 modules/mod-mythic-plus/src/wailing_caverns/instance_wailing_caverns_mythic.cpp delete mode 100644 modules/mod-mythic-plus/src/wailing_caverns/wailing_caverns_mythic.h diff --git a/modules/mod-mythic-plus/src/MythicPlusWrapperInstance.cpp b/modules/mod-mythic-plus/src/MythicPlusWrapperInstance.cpp new file mode 100644 index 0000000..1a8bc5d --- /dev/null +++ b/modules/mod-mythic-plus/src/MythicPlusWrapperInstance.cpp @@ -0,0 +1,222 @@ +// modules/mod-mythic-plus/src/MythicPlusWrapperInstance.cpp +#include "MythicPlusWrapperInstance.h" +#include "Map.h" +#include "Player.h" +#include "Item.h" +#include "WorldDatabase.h" +#include "ScriptMgr.h" + +MythicPlusWrapperInstanceScript::MythicPlusWrapperInstanceScript(Map* map, uint32 mapId) + : InstanceScript(map), _mapId(mapId), _originalScript(nullptr), _countdownTimer(0) +{ + // 创建原始副本脚本实例 + _originalScript = CreateOriginalInstanceScript(map, mapId); + + // 初始化大秘境数据 + _mythicPlusData.clear(); + _allCreatureGUIDs.clear(); +} + +MythicPlusWrapperInstanceScript::~MythicPlusWrapperInstanceScript() +{ + delete _originalScript; +} + +void MythicPlusWrapperInstanceScript::Initialize() +{ + // 先让原始脚本初始化 + if (_originalScript) + _originalScript->Initialize(); + + // 初始化大秘境数据 + _mythicPlusData.clear(); + _allCreatureGUIDs.clear(); +} + +void MythicPlusWrapperInstanceScript::OnCreatureCreate(Creature* creature) +{ + // 先让原始脚本处理 + if (_originalScript) + _originalScript->OnCreatureCreate(creature); + + // 然后存储用于大秘境 + _allCreatureGUIDs.push_back(creature->GetGUID()); +} + +void MythicPlusWrapperInstanceScript::OnGameObjectCreate(GameObject* go) +{ + // 先让原始脚本处理 + if (_originalScript) + _originalScript->OnGameObjectCreate(go); + + // 处理大秘境特有的GameObject + HandleMythicPlusGameObjects(go); +} + +void MythicPlusWrapperInstanceScript::SetData(uint32 type, uint32 data) +{ + // 处理大秘境特有数据 + if (IsMythicPlusDataType(type)) + { + HandleMythicPlusSetData(type, data); + return; + } + + // 委托给原始脚本 + if (_originalScript) + _originalScript->SetData(type, data); +} + +uint32 MythicPlusWrapperInstanceScript::GetData(uint32 type) const +{ + // 处理大秘境特有数据 + if (IsMythicPlusDataType(type)) + { + auto itr = _mythicPlusData.find(type); + return itr != _mythicPlusData.end() ? itr->second : 0; + } + + // 委托给原始脚本 + if (_originalScript) + return _originalScript->GetData(type); + + return 0; +} + +void MythicPlusWrapperInstanceScript::DoAction(int32 actionId) +{ + // 处理大秘境特有动作 + if (actionId == ACTION_START_MYTHIC_COUNTDOWN) + { + StartMythicPlusCountdown(); + return; + } + + // 委托给原始脚本 + if (_originalScript) + _originalScript->DoAction(actionId); +} + +void MythicPlusWrapperInstanceScript::Update(uint32 diff) +{ + // 先更新原始脚本 + if (_originalScript) + _originalScript->Update(diff); + + // 然后更新大秘境调度器 + _scheduler.Update(diff); +} + +// 私有方法实现 +InstanceScript* MythicPlusWrapperInstanceScript::CreateOriginalInstanceScript(Map* map, uint32 mapId) +{ + // 获取实例模板 + InstanceTemplate const* instanceTemplate = sObjectMgr->GetInstanceTemplate(mapId); + if (instanceTemplate && instanceTemplate->ScriptId) + { + // 直接使用模板中的脚本ID创建脚本 + auto tempScript = ScriptRegistry::GetScriptById(instanceTemplate->ScriptId); + if (tempScript) + { + return tempScript->GetInstanceScript(map->ToInstanceMap()); + } + } + return nullptr; +} + +bool MythicPlusWrapperInstanceScript::IsMythicPlusDataType(uint32 type) const +{ + return type >= DATA_KEYSTONE_VALIDATED && type <= DATA_MYTHIC_CHALLENGE_ACTIVE; +} + +void MythicPlusWrapperInstanceScript::HandleMythicPlusSetData(uint32 type, uint32 data) +{ + _mythicPlusData[type] = data; + + if (type == DATA_KEYSTONE_VALIDATED && data == DONE) + { + // 显示空气墙 + if (GameObject* wall = instance->GetGameObject(_invisibleWallGUID)) + wall->SetPhaseMask(1, true); + + // 禁用能量之泉 + if (GameObject* well = instance->GetGameObject(_energyWellGUID)) + well->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE); + } + + if (data == DONE) + SaveToDB(); +} + +void MythicPlusWrapperInstanceScript::HandleMythicPlusGameObjects(GameObject* go) +{ + switch (go->GetEntry()) + { + case 410004: // GO_INVISIBLE_WALL + _invisibleWallGUID = go->GetGUID(); + go->SetPhaseMask(2, true); // 初始隐藏 + break; + case 410000: // GO_ENERGY_WELL + _energyWellGUID = go->GetGUID(); + break; + } +} + +void MythicPlusWrapperInstanceScript::StartMythicPlusCountdown() +{ + // 应用大秘境属性 + ApplyMythicPlusScalingToExistingCreatures(); + + // 开始倒计时 + _countdownTimer = 10; + DoUpdateWorldState(20100, 1); // WORLD_STATE_MYTHIC_COUNTDOWN_SHOW + DoUpdateWorldState(20101, _countdownTimer); // WORLD_STATE_MYTHIC_COUNTDOWN_TIME + + _scheduler.Schedule(1s, [this](TaskContext context) + { + --_countdownTimer; + DoUpdateWorldState(20101, _countdownTimer); + + if (_countdownTimer > 0) + { + context.Repeat(); + } + else + { + // 倒计时结束 + DoUpdateWorldState(20100, 0); + if (GameObject* wall = instance->GetGameObject(_invisibleWallGUID)) + wall->SetPhaseMask(2, true); + + SetData(DATA_MYTHIC_CHALLENGE_ACTIVE, DONE); + } + }); +} + +void MythicPlusWrapperInstanceScript::ApplyMythicPlusScalingToExistingCreatures() +{ + Map::PlayerList const& players = instance->GetPlayers(); + if (players.IsEmpty()) + return; + + Player* player = players.begin()->GetSource(); + Item* keystone = player->GetItemByEntry(999001); + if (!keystone) + return; + + uint8 keystoneLevel = MythicPlusCreatureManager::GetKeystoneLevel(keystone); + std::vector affixes = MythicPlusCreatureManager::GetKeystoneAffixes(keystone); + uint32 dungeonId = keystone->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID); + + for (const ObjectGuid& guid : _allCreatureGUIDs) + { + if (Creature* creature = instance->GetCreature(guid)) + { + if (creature->IsAlive()) + { + MythicPlusCreatureManager::ApplyMythicPlusScaling(creature, keystoneLevel, dungeonId); + MythicPlusCreatureManager::ApplyAffixEffects(creature, affixes); + } + } + } +} diff --git a/modules/mod-mythic-plus/src/MythicPlusWrapperInstance.h b/modules/mod-mythic-plus/src/MythicPlusWrapperInstance.h new file mode 100644 index 0000000..aae35fa --- /dev/null +++ b/modules/mod-mythic-plus/src/MythicPlusWrapperInstance.h @@ -0,0 +1,60 @@ +// modules/mod-mythic-plus/src/MythicPlusWrapperInstance.h +#ifndef _MYTHIC_PLUS_WRAPPER_INSTANCE_H +#define _MYTHIC_PLUS_WRAPPER_INSTANCE_H + +#include "InstanceScript.h" +#include "TaskScheduler.h" +#include "Mythic_Script.h" + +// 通用大秘境数据类型 +enum MythicPlusDataTypes +{ + DATA_KEYSTONE_VALIDATED = 1000, + DATA_MYTHIC_COUNTDOWN_TIMER = 1001, + DATA_MYTHIC_COUNTDOWN_ACTIVE = 1002, + DATA_MYTHIC_CHALLENGE_ACTIVE = 1003, +}; + +enum MythicPlusActions +{ + ACTION_START_MYTHIC_COUNTDOWN = 1000, +}; + +class MythicPlusWrapperInstanceScript : public InstanceScript +{ +public: + MythicPlusWrapperInstanceScript(Map* map, uint32 mapId); + ~MythicPlusWrapperInstanceScript(); + + void Initialize() override; + void OnCreatureCreate(Creature* creature) override; + void OnGameObjectCreate(GameObject* go) override; + void SetData(uint32 type, uint32 data) override; + uint32 GetData(uint32 type) const override; + void DoAction(int32 actionId) override; + void Update(uint32 diff) override; + +private: + InstanceScript* _originalScript; + uint32 _mapId; + + // 大秘境特有数据 + std::unordered_map _mythicPlusData; + std::vector _allCreatureGUIDs; + TaskScheduler _scheduler; + uint32 _countdownTimer; + + // 大秘境特有的GameObject GUIDs + ObjectGuid _invisibleWallGUID; + ObjectGuid _energyWellGUID; + + // 私有方法 + InstanceScript* CreateOriginalInstanceScript(Map* map, uint32 mapId); + bool IsMythicPlusDataType(uint32 type) const; + void HandleMythicPlusSetData(uint32 type, uint32 data); + void HandleMythicPlusGameObjects(GameObject* go); + void StartMythicPlusCountdown(); + void ApplyMythicPlusScalingToExistingCreatures(); +}; + +#endif diff --git a/modules/mod-mythic-plus/src/Mythic_Keystone.cpp b/modules/mod-mythic-plus/src/Mythic_Keystone.cpp index 82f7019..9e38903 100644 --- a/modules/mod-mythic-plus/src/Mythic_Keystone.cpp +++ b/modules/mod-mythic-plus/src/Mythic_Keystone.cpp @@ -7,16 +7,20 @@ #include "Chat.h" #include "PlayerScript.h" #include "InstanceScript.h" -#include #include #include #include "ObjectGuid.h" #include "SharedDefines.h" -#include #include #include "World.h" #include "Config.h" #include "ScriptMgr.h" +#include + +#include +#include +#include +#include // 实现单例 MythicPlusCacheManager* MythicPlusCacheManager::_instance = nullptr; @@ -41,28 +45,31 @@ void MythicPlusCacheManager::LoadConfigs() _affixRotations.clear(); // 词缀轮换配置数据结构 _enabledDungeonIds.clear(); // 清空启用的副本列表缓存 - // 加载副本配置 - QueryResult dungeonResult = WorldDatabase.Query("SELECT 副本ID, 副本名称, 地图ID, 基础时间限制, 最低等级, 最高等级, 启用状态 FROM acore_custom.大秘境副本配置"); + // 加载副本配置 - 包含属性调整字段 + QueryResult dungeonResult = WorldDatabase.Query("SELECT 副本ID, 副本名称, 地图ID, 基础时间限制, 最低等级, 最高等级, 启用状态, 每层生命倍数, 每层伤害倍数, 基础生命倍数, 基础伤害倍数 FROM acore_custom.大秘境副本配置"); if (dungeonResult) { do { Field* fields = dungeonResult->Fetch(); uint32 dungeonId = fields[0].Get(); - - bool enabled = fields[6].Get(); //是否启用 + bool enabled = fields[6].Get(); MythicDungeonConfig& config = _dungeonConfigs[dungeonId]; config.dungeonId = dungeonId; config.dungeonName = fields[1].Get(); - config.mapId = fields[2].Get(); // 新增 + config.mapId = fields[2].Get(); config.baseTimeLimit = fields[3].Get(); - config.minLevel = fields[4].Get(); // 新增 - config.maxLevel = fields[5].Get(); // 新增 - + config.minLevel = fields[4].Get(); + config.maxLevel = fields[5].Get(); config.enabled = enabled; - // 如果启用,添加到缓存列表 + // 新增:加载属性调整配置 + config.healthMultiplierPerLevel = fields[7].Get(); + config.damageMultiplierPerLevel = fields[8].Get(); + config.baseHealthMultiplier = fields[9].Get(); + config.baseDamageMultiplier = fields[10].Get(); + if (enabled) { _enabledDungeonIds.push_back(dungeonId); @@ -152,6 +159,17 @@ MythicAffixRotation const* MythicPlusCacheManager::GetCurrentWeekAffixRotation() return GetAffixRotation(currentWeek); } +// 获取大秘境配置地图 +MythicDungeonConfig const* MythicPlusCacheManager::GetDungeonConfigByMapId(uint32 mapId) const +{ + for (auto const& pair : _dungeonConfigs) + { + if (pair.second.mapId == mapId && pair.second.enabled) + return &pair.second; + } + return nullptr; +} + // 随机选择大秘境 static uint32 GetRandomMythicPlusDungeon() { @@ -176,7 +194,7 @@ static std::string GetDungeonName(uint32 dungeonId) static uint8 CalculateNewKeystoneLevel(uint8 completedLevel, bool inTime, uint32 dungeonId) { - // 从缓存获取副本配置 + // 从缓存获取副本配置 MythicDungeonConfig const* config = sMythicPlusCache->GetDungeonConfig(dungeonId); uint8 maxLevel = config ? config->maxLevel : 15; // 如果配置不存在,使用默认值15 @@ -188,7 +206,7 @@ static uint8 CalculateNewKeystoneLevel(uint8 completedLevel, bool inTime, uint32 else { // 超时完成,钥匙等级-1 - return std::max(completedLevel - 1, 2); // 最低2级 + return std::max(completedLevel - 1, 2); // 最低2级 } } @@ -598,7 +616,7 @@ void MythicPlusKeystoneManager::UpgradeKeystone(Player* player, Item* keystone, { uint64 keystoneGUID = keystone->GetGUID().GetCounter(); - // 从物品属性获取当前副本ID + // 从物品属性获取当前副本ID uint32 currentDungeonId = keystone->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID); // 计算新等级(军团再临机制) @@ -678,18 +696,18 @@ private: { uint64 keystoneGUID = keystone->GetGUID().GetCounter(); - // 首先获取钥石等级 + // 首先获取钥石等级 QueryResult levelResult = CharacterDatabase.Query( "SELECT 钥石等级 FROM 角色大秘境钥石 WHERE 物品GUID = {}", keystoneGUID); if (levelResult) { uint8 keystoneLevel = levelResult->Fetch()[0].Get(); - // 根据钥石等级计算应有的词缀 + // 根据钥石等级计算应有的词缀 uint32 affix1 = 0, affix2 = 0, affix3 = 0, affix4 = 0; MythicPlusKeystoneManager::CalculateAffixesForLevel(keystoneLevel, affix1, affix2, affix3, affix4); - // 只更新应有的词缀 + // 只更新应有的词缀 CharacterDatabase.Execute("UPDATE 角色大秘境钥石 SET 词缀1 = {}, 词缀2 = {}, 词缀3 = {}, 词缀4 = {} WHERE 物品GUID = {}", affix1, affix2, affix3, affix4, keystoneGUID); } } @@ -715,6 +733,25 @@ class MythicPlusGlobalScript : public GlobalScript public: MythicPlusGlobalScript() : GlobalScript("MythicPlusGlobalScript") {} + // 控制掉落检查 + bool OnAllowedForPlayerLootCheck(Player const* player, ObjectGuid source) override + { + if (!player || !player->GetMap()) + return false; + + // 检查是否在大秘境模式中 + if (InstanceScript* instance = player->GetInstanceScript()) + { + if (instance->GetData(DATA_MYTHIC_CHALLENGE_ACTIVE) == DONE) + { + // 大秘境激活时禁用生物掉落 - 返回 true 表示阻止掉落 + return true; + } + } + + return false; // 让其他脚本处理 + } + void OnAfterUpdateEncounterState(Map* map, EncounterCreditType type, uint32 creditEntry, Unit* source, Difficulty difficulty_fixed, DungeonEncounterList const* encounters, uint32 dungeonCompleted, bool updated) override { LOG_INFO("server.loading", "我的脚本::遭遇状态更新后 - 地图ID={}, 击杀目标ID={}, 完成副本ID={}, 是否更新={}", map->GetId(), creditEntry, dungeonCompleted, updated); @@ -926,12 +963,170 @@ public: } + void OnBeforeCreateInstanceScript(InstanceMap* instanceMap, InstanceScript** instanceData, bool load, std::string data, uint32 completedEncounterMask) override + { + uint32 mapId = instanceMap->GetId(); + + // 检查是否是大秘境启用的副本 + if (IsMythicPlusEnabledMap(mapId)) + { + // 创建混合脚本包装器 + *instanceData = new MythicPlusWrapperInstanceScript(instanceMap, mapId); + } + } +private: + bool IsMythicPlusEnabledMap(uint32 mapId) const + { + // 从配置表检查 + MythicDungeonConfig const* config = sMythicPlusCache->GetDungeonConfigByMapId(mapId); + return config != nullptr; + } }; + + +// 生物属性管理器实现 +float MythicPlusCreatureManager::CalculateHealthMultiplier(uint8 level, uint32 dungeonId) +{ + MythicDungeonConfig const* config = sMythicPlusCache->GetDungeonConfig(dungeonId); + if (!config) + return 1.0f + (level * 0.08f); // 默认8%递增 + + return config->baseHealthMultiplier + (level * config->healthMultiplierPerLevel); +} + +float MythicPlusCreatureManager::CalculateDamageMultiplier(uint8 level, uint32 dungeonId) +{ + MythicDungeonConfig const* config = sMythicPlusCache->GetDungeonConfig(dungeonId); + if (!config) + return 1.0f + (level * 0.08f); // 默认8%递增 + + return config->baseDamageMultiplier + (level * config->damageMultiplierPerLevel); +} + +void MythicPlusCreatureManager::ApplyMythicPlusScaling(Creature* creature, uint8 keystoneLevel, uint32 dungeonId) +{ + if (!creature || keystoneLevel == 0) + return; + + float healthMultiplier = CalculateHealthMultiplier(keystoneLevel, dungeonId); + float damageMultiplier = CalculateDamageMultiplier(keystoneLevel, dungeonId); + + // 应用生命值调整 + uint32 newMaxHealth = creature->GetCreateHealth() * healthMultiplier; + creature->SetMaxHealth(newMaxHealth); + creature->SetHealth(newMaxHealth); + + // 应用伤害调整(使用你的更好方式) + creature->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, (damageMultiplier - 1.0f) * 100.0f, true); + + LOG_INFO("mythic.plus", "Applied scaling to creature {} - Level: {}, Health: {}, Damage: {}%", + creature->GetEntry(), keystoneLevel, newMaxHealth, damageMultiplier * 100.0f); +} + +// 应用词缀光环 +void MythicPlusCreatureManager::ApplyAffixEffects(Creature* creature, std::vector const& affixes) +{ + for (uint32 affixSpellId : affixes) + { + if (affixSpellId != 0) + { + creature->AddAura(affixSpellId, creature); + } + } +} + +bool MythicPlusCreatureManager::IsMythicPlusActive(Map* map) +{ + if (!map || !map->IsDungeon()) + return false; + + if (InstanceMap* instanceMap = map->ToInstanceMap()) + { + if (InstanceScript* instance = instanceMap->GetInstanceScript()) + { + return instance->GetData(DATA_MYTHIC_CHALLENGE_ACTIVE) == DONE; + } + } + return false; +} + +// 获取当前大秘境等级 +uint8 MythicPlusCreatureManager::GetCurrentKeystoneLevel(Map* map) +{ + if (!map) + return 2; + + Map::PlayerList const& players = map->GetPlayers(); + for (auto const& playerRef : players) + { + if (Player* player = playerRef.GetSource()) + { + Item* keystone = player->GetItemByEntry(999001); + if (keystone) + { + uint64 keystoneGUID = keystone->GetGUID().GetCounter(); + QueryResult result = CharacterDatabase.Query( + "SELECT 钥石等级 FROM 角色大秘境钥石 WHERE 物品GUID = {}", keystoneGUID); + if (result) + return result->Fetch()[0].Get(); + } + } + } + return 2; +} + +uint8 MythicPlusCreatureManager::GetKeystoneLevel(Item* keystone) +{ + if (!keystone) return 2; + + uint64 keystoneGUID = keystone->GetGUID().GetCounter(); + QueryResult result = CharacterDatabase.Query( + "SELECT 钥石等级 FROM 角色大秘境钥石 WHERE 物品GUID = {}", keystoneGUID); + + if (result) + { + return result->Fetch()[0].Get(); + } + return 2; +} + + +std::vector MythicPlusCreatureManager::GetKeystoneAffixes(Item* keystone) +{ + std::vector affixes; + if (!keystone) return affixes; + + uint64 keystoneGUID = keystone->GetGUID().GetCounter(); + QueryResult result = CharacterDatabase.Query( + "SELECT 词缀1, 词缀2, 词缀3, 词缀4 FROM 角色大秘境钥石 WHERE 物品GUID = {}", keystoneGUID); + + if (result) + { + Field* fields = result->Fetch(); + for (int i = 0; i < 4; ++i) + { + uint32 affixSpellId = fields[i].Get(); + if (affixSpellId != 0) + { + //// 从词缀配置获取法术ID ,不需要因为 affixSpellId 已经是法术ID了 + //MythicAffixConfig const* affixConfig = sMythicPlusCache->GetAffixConfig(affixSpellId); + //if (affixConfig && affixConfig->spellId != 0) + //{ + // affixes.push_back(affixConfig->spellId); + //} + + affixes.push_back(affixSpellId); + } + } + } + return affixes; +} + void AddSC_MythicPlusKeystone() { new MythicPlusPlayerScript(); new MythicPlusGlobalScript(); - new MythicPlusWorldScript(); // 周重置钥石逻辑 - new Mod_MythicPlusAllMapScript(); + new MythicPlusWorldScript(); // 周重置钥石逻辑 + new Mod_MythicPlusAllMapScript(); // 全局拦截脚本 } diff --git a/modules/mod-mythic-plus/src/Mythic_Script.h b/modules/mod-mythic-plus/src/Mythic_Script.h index d965854..4958197 100644 --- a/modules/mod-mythic-plus/src/Mythic_Script.h +++ b/modules/mod-mythic-plus/src/Mythic_Script.h @@ -1,23 +1,28 @@ // modules\mod-mythic-plus\src\Mythic_Script.h -#ifndef _MOD_MYTHIC_SCRIPT_H_ +#ifndef _MOD_MYTHIC_SCRIPT_H_ #define _MOD_MYTHIC_SCRIPT_H_ #pragma once -#include "Player.h" -#include "Item.h" -#include "PlayerScript.h" -#include "InstanceScript.h" +#include "Player.h" +#include "Item.h" +#include "PlayerScript.h" +#include "InstanceScript.h" // 副本配置数据结构 struct MythicDungeonConfig { uint32 dungeonId; std::string dungeonName; - uint32 mapId; // 新增:地图ID - uint32 baseTimeLimit; // 基础时间限制(秒) - uint8 minLevel; // 新增:最低等级 - uint8 maxLevel; // 新增:最高等级 - bool enabled; // 是否启用 + uint32 mapId; // 新增:地图ID + uint32 baseTimeLimit; // 基础时间限制(秒) + uint8 minLevel; // 新增:最低等级 + uint8 maxLevel; // 新增:最高等级 + bool enabled; // 是否启用 + + float healthMultiplierPerLevel; // 每层生命值倍数 + float damageMultiplierPerLevel; // 每层伤害倍数 + float baseHealthMultiplier; // 基础生命值倍数 + float baseDamageMultiplier; // 基础伤害倍数 }; // 词缀配置数据结构 @@ -26,9 +31,9 @@ struct MythicAffixConfig uint32 affixId; std::string affixName; std::string affixDescription; - uint32 spellId; // 法术ID - uint8 enableLevel; // 启用等级 - uint8 affixType; // 词缀类型 + uint32 spellId; // 法术ID + uint8 enableLevel; // 启用等级 + uint8 affixType; // 词缀类型 }; // 词缀轮换配置数据结构 @@ -36,7 +41,7 @@ struct MythicAffixRotation { uint32 week; // 周次 uint32 affix1; // 词缀1 - uint32 affix2; // 词缀2 + uint32 affix2; // 词缀2 uint32 affix3; // 词缀3 uint32 affix4; // 词缀4 }; @@ -53,18 +58,21 @@ public: // 获取副本配置 MythicDungeonConfig const* GetDungeonConfig(uint32 dungeonId) const; - // 获取词缀配置 + // 获取词缀配置 MythicAffixConfig const* GetAffixConfig(uint32 affixId) const; - // 获取词缀轮换配置 + // 获取词缀轮换配置 MythicAffixRotation const* GetAffixRotation(uint32 week) const; - // 获取当前周的词缀轮换 + // 获取当前周的词缀轮换 MythicAffixRotation const* GetCurrentWeekAffixRotation() const; - // 获取启用的副本列表 + // 获取启用的副本列表 std::vector const& GetEnabledDungeonIds() const { return _enabledDungeonIds; } + // 获取大秘境配置地图 + MythicDungeonConfig const* GetDungeonConfigByMapId(uint32 mapId) const; + private: MythicPlusCacheManager() = default; ~MythicPlusCacheManager() = default; @@ -80,7 +88,7 @@ private: #define sMythicPlusCache MythicPlusCacheManager::instance() -// 钥匙处理器类声明 +// 钥匙处理器类声明 class MythicPlusKeystoneHandler { public: @@ -97,21 +105,21 @@ public: private: static std::vector ParsePacketData(std::string const& data); - + static void StartMythicPlusChallenge(Player* player, uint32 dungeonId, uint8 level); - + }; -// 钥匙管理器类声明 +// 钥匙管理器类声明 class MythicPlusKeystoneManager { public: static Item* CreateAndGiveKeystone(Player* player, uint32 dungeonId, uint8 level); - // 在副本完成后生成或升级钥石 + // 在副本完成后生成或升级钥石 static void HandleDungeonCompletion(Player* player, uint32 dungeonId, uint8 completedLevel, bool inTime, uint32 completionTime); - // 创建初始钥石 + // 创建初始钥石 static Item* CreateInitialKeystone(Player* player, uint32 dungeonId, uint8 level); // 根据钥石等级计算词缀 @@ -133,8 +141,25 @@ private: }; +// 生物属性管理器类声明 +class MythicPlusCreatureManager +{ +public: + static void ApplyMythicPlusScaling(Creature* creature, uint8 keystoneLevel, uint32 dungeonId); + static void ApplyAffixEffects(Creature* creature, std::vector const& affixes); + static bool IsMythicPlusActive(Map* map); + static uint8 GetCurrentKeystoneLevel(Map* map); + + static uint8 GetKeystoneLevel(Item* keystone); + static std::vector GetKeystoneAffixes(Item* keystone); + +private: + static float CalculateHealthMultiplier(uint8 level, uint32 dungeonId); + static float CalculateDamageMultiplier(uint8 level, uint32 dungeonId); +}; + void GO_KeystonePedestalScripts(); void AddSC_MythicPlusKeystone(); -#endif +#endif diff --git a/modules/mod-mythic-plus/src/loader.cpp b/modules/mod-mythic-plus/src/loader.cpp index 4db60bc..5248ee3 100644 --- a/modules/mod-mythic-plus/src/loader.cpp +++ b/modules/mod-mythic-plus/src/loader.cpp @@ -2,11 +2,11 @@ void GO_KeystonePedestalScripts(); void AddSC_MythicPlusKeystone(); -void AddMythicPlusWailingCavernsScripts(); +//void AddMythicPlusWailingCavernsScripts(); void Addmod_mythic_plusScripts() { GO_KeystonePedestalScripts(); AddSC_MythicPlusKeystone(); - AddMythicPlusWailingCavernsScripts(); + //AddMythicPlusWailingCavernsScripts(); } diff --git a/modules/mod-mythic-plus/src/wailing_caverns/instance_wailing_caverns_mythic.cpp b/modules/mod-mythic-plus/src/wailing_caverns/instance_wailing_caverns_mythic.cpp deleted file mode 100644 index 45b7fc5..0000000 --- a/modules/mod-mythic-plus/src/wailing_caverns/instance_wailing_caverns_mythic.cpp +++ /dev/null @@ -1,236 +0,0 @@ -///* -// * 完全复制哀嚎洞穴副本脚本文件 -// * 添加部分自定义数据以支撑大秘境功能 -// */ -// -// // modules\mod-mythic-plus\src\wailing_caverns\instance_wailing_caverns_mythic.cpp -// -//#include "InstanceMapScript.h" -//#include "InstanceScript.h" -//#include "wailing_caverns_mythic.h" -//#include -//#include -// -//class instance_wailing_caverns_mythic : public InstanceMapScript -//{ -//public: -// instance_wailing_caverns_mythic() : InstanceMapScript("instance_wailing_caverns_mythic", MAP_WAILING_CAVERNS) {} -// -// InstanceScript* GetInstanceScript(InstanceMap* map) const override -// { -// return new instance_wailing_caverns_InstanceMapScript(map); -// } -// -// struct instance_wailing_caverns_InstanceMapScript : public InstanceScript -// { -// instance_wailing_caverns_InstanceMapScript(Map* map) : InstanceScript(map), _countdownTimer(0) { } -// -// void Initialize() override -// { -// memset(&_encounters, 0, sizeof(_encounters)); -// } -// -// void OnCreatureCreate(Creature* creature) override -// { -// if (creature->GetEntry() == NPC_DISCIPLE_OF_NARALEX) -// DiscipleOfNaralexGUID = creature->GetGUID(); -// else if (creature->GetEntry() == NPC_LORD_SERPENTIS) -// SerpentisGUID = creature->GetGUID(); -// -// // 存储所有生物GUID -// allCreatureGUIDs.push_back(creature->GetGUID()); -// } -// -// void OnGameObjectCreate(GameObject* go) override -// { -// switch (go->GetEntry()) -// { -// case GO_INVISIBLE_WALL: -// invisibleWallGUID = go->GetGUID(); -// // 初始状态:设置到不可见相位 -// go->SetPhaseMask(2, true); // 相位2,玩家看不到 -// break; -// case GO_ENERGY_WELL: -// energyWellGUID = go->GetGUID(); -// break; -// } -// } -// -// void SetData(uint32 type, uint32 data) override -// { -// switch (type) -// { -// case TYPE_LORD_COBRAHN: -// case TYPE_LORD_PYTHAS: -// case TYPE_LADY_ANACONDRA: -// case TYPE_LORD_SERPENTIS: -// case TYPE_MUTANUS: -// _encounters[type] = data; -// break; -// -// case DATA_KEYSTONE_VALIDATED: -// _encounters[5] = data; // 确保数据被存储 -// if (data == DONE) -// { -// if (GameObject* wall = instance->GetGameObject(invisibleWallGUID)) -// // 恢复到玩家可见的相位 -// wall->SetPhaseMask(1, true); // 相位1,玩家可见 -// -// // 禁用能量之泉 -// if (GameObject* well = instance->GetGameObject(energyWellGUID)) -// well->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE); -// } -// break; -// -// case DATA_MYTHIC_CHALLENGE_ACTIVE: // 添加这个case -// _encounters[8] = data; -// break; -// } -// -// if (data == DONE) -// SaveToDB(); -// -// if (type == TYPE_LORD_COBRAHN && _encounters[TYPE_LORD_SERPENTIS] != DONE) -// { -// if (Creature* serpentis = instance->GetCreature(SerpentisGUID)) -// serpentis->AI()->Talk(SAY_SERPENTIS); -// } -// -// if (type != TYPE_MUTANUS && _encounters[TYPE_LORD_COBRAHN] == DONE && _encounters[TYPE_LORD_PYTHAS] == DONE && -// _encounters[TYPE_LADY_ANACONDRA] == DONE && _encounters[TYPE_LORD_SERPENTIS] == DONE) -// { -// if (Creature* disciple = instance->GetCreature(DiscipleOfNaralexGUID)) -// disciple->AI()->Talk(SAY_DISCIPLE); -// } -// } -// -// uint32 GetData(uint32 type) const override -// { -// switch (type) -// { -// case TYPE_LORD_COBRAHN: -// case TYPE_LORD_PYTHAS: -// case TYPE_LADY_ANACONDRA: -// case TYPE_LORD_SERPENTIS: -// return _encounters[type]; -// case DATA_KEYSTONE_VALIDATED: -// return _encounters[5]; // 添加这个case -// case DATA_MYTHIC_CHALLENGE_ACTIVE: // 添加这个case -// return _encounters[8]; -// default: -// break; -// } -// return 0; -// } -// -// void ReadSaveDataMore(std::istringstream& data) override -// { -// data >> _encounters[0]; -// data >> _encounters[1]; -// data >> _encounters[2]; -// data >> _encounters[3]; -// data >> _encounters[4]; -// } -// -// void WriteSaveDataMore(std::ostringstream& data) override -// { -// data << _encounters[0] << ' ' -// << _encounters[1] << ' ' -// << _encounters[2] << ' ' -// << _encounters[3] << ' ' -// << _encounters[4] << ' '; -// } -// -// void DoAction(int32 actionId) override -// { -// if (actionId == ACTION_START_MYTHIC_COUNTDOWN) -// { -// // 先应用大秘境副本中的生物属性 -// ApplyMythicPlusScalingToExistingCreatures(); -// -// // 开始10秒倒计时 -// _countdownTimer = 10; -// DoUpdateWorldState(WORLD_STATE_MYTHIC_COUNTDOWN_SHOW, 1); -// DoUpdateWorldState(WORLD_STATE_MYTHIC_COUNTDOWN_TIME, _countdownTimer); -// -// scheduler.Schedule(1s, GROUP_MYTHIC_COUNTDOWN, [this](TaskContext context) -// { -// --_countdownTimer; -// DoUpdateWorldState(WORLD_STATE_MYTHIC_COUNTDOWN_TIME, _countdownTimer); -// -// if (_countdownTimer > 0) -// { -// context.Repeat(); -// } -// else -// { -// // 倒计时结束,移除空气墙 -// DoUpdateWorldState(WORLD_STATE_MYTHIC_COUNTDOWN_SHOW, 0); -// if (GameObject* wall = instance->GetGameObject(invisibleWallGUID)) -// wall->SetPhaseMask(2, true); // 隐藏空气墙 -// -// // 开始大秘境挑战 -// SetData(DATA_MYTHIC_CHALLENGE_ACTIVE, DONE); -// } -// }); -// } -// } -// -// void Update(uint32 diff) override -// { -// scheduler.Update(diff); -// } -// -// private: -// uint32 _encounters[MAX_ENCOUNTERS]; -// ObjectGuid DiscipleOfNaralexGUID; // 任务NPC 穆约 -// ObjectGuid SerpentisGUID; -// ObjectGuid invisibleWallGUID; -// ObjectGuid energyWellGUID; -// uint32 _countdownTimer; // 倒计时变量 -// TaskScheduler scheduler; // 调度器 -// std::vector allCreatureGUIDs; // 存储所有生物GUID -// -// // 对现有生物应用大秘境属性 -// void ApplyMythicPlusScalingToExistingCreatures() -// { -// // 获取副本中的玩家来获取钥石信息 -// Map::PlayerList const& players = instance->GetPlayers(); -// if (players.IsEmpty()) // 修正:使用 empty() 而不是 IsEmpty() -// return; -// -// Player* player = players.begin()->GetSource(); -// Item* keystone = player->GetItemByEntry(999001); -// if (!keystone) -// return; -// -// uint8 keystoneLevel = MythicPlusCreatureManager::GetKeystoneLevel(keystone); -// std::vector affixes = MythicPlusCreatureManager::GetKeystoneAffixes(keystone); -// uint32 dungeonId = keystone->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID); -// -// // 遍历所有存储的生物GUID -// -// for (const ObjectGuid& guid : allCreatureGUIDs) -// { -// if (guid == DiscipleOfNaralexGUID) -// continue; -// -// if (Creature* creature = instance->GetCreature(guid)) -// { -// if (creature->IsAlive()) // 确保生物还活着 -// { -// MythicPlusCreatureManager::ApplyMythicPlusScaling(creature, keystoneLevel, dungeonId); -// MythicPlusCreatureManager::ApplyAffixEffects(creature, affixes); -// } -// } -// -// } -// -// } -// }; -//}; -// -//void AddMythicPlusWailingCavernsScripts() -//{ -// new instance_wailing_caverns_mythic(); -//} diff --git a/modules/mod-mythic-plus/src/wailing_caverns/wailing_caverns_mythic.h b/modules/mod-mythic-plus/src/wailing_caverns/wailing_caverns_mythic.h deleted file mode 100644 index 8d19e97..0000000 --- a/modules/mod-mythic-plus/src/wailing_caverns/wailing_caverns_mythic.h +++ /dev/null @@ -1,51 +0,0 @@ -//// modules\mod-mythic-plus\src\wailing_caverns\wailing_caverns_mythic.h -//#ifndef _MOD_MYTHIC_WAILING_CAVERNS_H -//#define _MOD_MYTHIC_WAILING_CAVERNS_H -// -//#define DataHeader "WMP" // WMP = Wailing Caverns Mythic Plus -// -//enum DataTypes -//{ -// TYPE_LORD_COBRAHN = 0, -// TYPE_LORD_PYTHAS = 1, -// TYPE_LADY_ANACONDRA = 2, -// TYPE_LORD_SERPENTIS = 3, -// TYPE_MUTANUS = 4, -// DATA_KEYSTONE_VALIDATED = 5, // 新增 -// -// -// DATA_MYTHIC_COUNTDOWN_TIMER = 6, // 倒计时状态 -// DATA_MYTHIC_COUNTDOWN_ACTIVE = 7, // 倒计时是否激活 -// DATA_MYTHIC_CHALLENGE_ACTIVE = 8, // 新增 -// -// MAX_ENCOUNTERS = 9, // 更新数量 -// -// NPC_DISCIPLE_OF_NARALEX = 3678, -// NPC_LORD_SERPENTIS = 3673, -// -// SAY_DISCIPLE = 0, -// SAY_SERPENTIS = 0, -// GO_INVISIBLE_WALL = 410004, // 墙体ID -// GO_ENERGY_WELL = 410000, // 能量之泉ID -//}; -// -//// 添加动作定义 -//enum Actions -//{ -// ACTION_START_MYTHIC_COUNTDOWN = 1, -//}; -// -//// 添加世界状态定义 -//enum WorldStates -//{ -// WORLD_STATE_MYTHIC_COUNTDOWN_SHOW = 20100, -// WORLD_STATE_MYTHIC_COUNTDOWN_TIME = 20101, -//}; -// -//// 添加调度器组定义 -//enum SchedulerGroups -//{ -// GROUP_MYTHIC_COUNTDOWN = 1, -//}; -// -//#endif diff --git a/modules/mod_SMAddon/src/mod_SMAddon.cpp b/modules/mod_SMAddon/src/mod_SMAddon.cpp index 1bde13c..be609f1 100644 --- a/modules/mod_SMAddon/src/mod_SMAddon.cpp +++ b/modules/mod_SMAddon/src/mod_SMAddon.cpp @@ -15,7 +15,7 @@ #include #include #include -#include "wailing_caverns_mythic.h" +#include "MythicPlusWrapperInstance.h" // 根据guidLow在背包中查找物品