[大秘境]

1、添加混合脚本包装器
2、添加生物属性设置方法
3、禁用生物掉落
This commit is contained in:
尚美 2025-09-22 14:32:42 +08:00
parent a332823676
commit dec4648cf8
8 changed files with 549 additions and 334 deletions

View File

@ -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<InstanceMapScript>::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<uint32> 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);
}
}
}
}

View File

@ -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<uint32, uint32> _mythicPlusData;
std::vector<ObjectGuid> _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

View File

@ -7,16 +7,20 @@
#include "Chat.h"
#include "PlayerScript.h"
#include "InstanceScript.h"
#include <GCAddon.h>
#include <sstream>
#include <vector>
#include "ObjectGuid.h"
#include "SharedDefines.h"
#include <Mythic_Script.h>
#include <GameTime.h>
#include "World.h"
#include "Config.h"
#include "ScriptMgr.h"
#include <GridNotifiers.h>
#include <Mythic_Script.h>
#include <GCAddon.h>
#include <wailing_caverns_mythic.h>
#include <MythicPlusWrapperInstance.h>
// 实现单例
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<uint32>();
bool enabled = fields[6].Get<bool>(); //是否启用
bool enabled = fields[6].Get<bool>();
MythicDungeonConfig& config = _dungeonConfigs[dungeonId];
config.dungeonId = dungeonId;
config.dungeonName = fields[1].Get<std::string>();
config.mapId = fields[2].Get<uint32>(); // 新增
config.mapId = fields[2].Get<uint32>();
config.baseTimeLimit = fields[3].Get<uint32>();
config.minLevel = fields[4].Get<uint8>(); // 新增
config.maxLevel = fields[5].Get<uint8>(); // 新增
config.minLevel = fields[4].Get<uint8>();
config.maxLevel = fields[5].Get<uint8>();
config.enabled = enabled;
// 如果启用,添加到缓存列表
// 新增:加载属性调整配置
config.healthMultiplierPerLevel = fields[7].Get<float>();
config.damageMultiplierPerLevel = fields[8].Get<float>();
config.baseHealthMultiplier = fields[9].Get<float>();
config.baseDamageMultiplier = fields[10].Get<float>();
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<uint8>(completedLevel - 1, 2); // 最低2级
return std::max<uint8>(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<uint8>();
// 根据钥石等级计算应有的词缀
// 根据钥石等级计算应有的词缀
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<uint32> 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<uint8>();
}
}
}
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<uint8>();
}
return 2;
}
std::vector<uint32> MythicPlusCreatureManager::GetKeystoneAffixes(Item* keystone)
{
std::vector<uint32> 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<uint32>();
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(); // 全局拦截脚本
}

View File

@ -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<uint32> 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<std::string> 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<uint32> const& affixes);
static bool IsMythicPlusActive(Map* map);
static uint8 GetCurrentKeystoneLevel(Map* map);
static uint8 GetKeystoneLevel(Item* keystone);
static std::vector<uint32> 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

View File

@ -2,11 +2,11 @@
void GO_KeystonePedestalScripts();
void AddSC_MythicPlusKeystone();
void AddMythicPlusWailingCavernsScripts();
//void AddMythicPlusWailingCavernsScripts();
void Addmod_mythic_plusScripts()
{
GO_KeystonePedestalScripts();
AddSC_MythicPlusKeystone();
AddMythicPlusWailingCavernsScripts();
//AddMythicPlusWailingCavernsScripts();
}

View File

@ -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 <Mythic_Script.h>
//#include <GCAddon.h>
//
//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<ObjectGuid> 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<uint32> 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();
//}

View File

@ -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

View File

@ -15,7 +15,7 @@
#include <CustomPlayerDataManager.h>
#include <mod_CustomItemData.h>
#include <Mythic_Script.h>
#include "wailing_caverns_mythic.h"
#include "MythicPlusWrapperInstance.h"
// 根据guidLow在背包中查找物品