优化[大秘境]

1、使用缓存查询大秘境信息
2、增加词缀4
3、读取词缀ID,而不是读取词缀名称发送数据
4、调整钥石属性顺序,以免发送空数据到客户端导致的无法实时显示信息
5、根据钥石等级计算词缀
6、修改地图判断匹配 DUNGEON_DIFFICULTY_EPIC 史诗
7、增加记录玩家本周信息数据
This commit is contained in:
尚美 2025-09-20 11:12:41 +08:00
parent b715ec6f1a
commit 4324b13b6a
4 changed files with 283 additions and 102 deletions

View File

@ -39,6 +39,7 @@ void MythicPlusCacheManager::LoadConfigs()
_dungeonConfigs.clear(); // 副本配置数据结构
_affixConfigs.clear(); // 词缀配置数据结构
_affixRotations.clear(); // 词缀轮换配置数据结构
_enabledDungeonIds.clear(); // 清空启用的副本列表缓存
// 加载副本配置
QueryResult dungeonResult = WorldDatabase.Query("SELECT 副本ID, 副本名称, 地图ID, 基础时间限制, 最低等级, 最高等级, 启用状态 FROM acore_custom.大秘境副本配置");
@ -49,6 +50,8 @@ void MythicPlusCacheManager::LoadConfigs()
Field* fields = dungeonResult->Fetch();
uint32 dungeonId = fields[0].Get<uint32>();
bool enabled = fields[6].Get<bool>(); //是否启用
MythicDungeonConfig& config = _dungeonConfigs[dungeonId];
config.dungeonId = dungeonId;
config.dungeonName = fields[1].Get<std::string>();
@ -56,7 +59,14 @@ void MythicPlusCacheManager::LoadConfigs()
config.baseTimeLimit = fields[3].Get<uint32>();
config.minLevel = fields[4].Get<uint8>(); // 新增
config.maxLevel = fields[5].Get<uint8>(); // 新增
config.enabled = fields[6].Get<bool>();
config.enabled = enabled;
// 如果启用,添加到缓存列表
if (enabled)
{
_enabledDungeonIds.push_back(dungeonId);
}
} while (dungeonResult->NextRow());
}
@ -82,7 +92,7 @@ void MythicPlusCacheManager::LoadConfigs()
}
// 加载词缀轮换配置
QueryResult affixResult = WorldDatabase.Query("SELECT 周次, 词缀1, 词缀2, 词缀3 FROM acore_custom.大秘境词缀轮换");
QueryResult affixResult = WorldDatabase.Query("SELECT 周次, 词缀1, 词缀2, 词缀3, 词缀4 FROM acore_custom.大秘境词缀轮换");
if (affixResult)
{
do
@ -95,6 +105,7 @@ void MythicPlusCacheManager::LoadConfigs()
rotation.affix1 = fields[1].Get<uint32>();
rotation.affix2 = fields[2].Get<uint32>();
rotation.affix3 = fields[3].Get<uint32>();
rotation.affix4 = fields[4].Get<uint32>();
} while (affixResult->NextRow());
}
@ -141,48 +152,43 @@ MythicAffixRotation const* MythicPlusCacheManager::GetCurrentWeekAffixRotation()
return GetAffixRotation(currentWeek);
}
// 随机选择大秘境
static uint32 GetRandomMythicPlusDungeon()
{
// 从配置表中随机选择一个启用的副本
QueryResult result = WorldDatabase.Query("SELECT 副本ID FROM acore_custom.大秘境副本配置 WHERE 启用状态 = 1");
if (!result)
// 从缓存获取启用的副本列表
std::vector<uint32> const& enabledDungeons = sMythicPlusCache->GetEnabledDungeonIds();
if (enabledDungeons.empty())
return 1; // 默认副本ID
std::vector<uint32> dungeonIds;
do
{
Field* fields = result->Fetch();
dungeonIds.push_back(fields[0].Get<uint32>());
} while (result->NextRow());
if (dungeonIds.empty())
return 1;
return dungeonIds[urand(0, dungeonIds.size() - 1)];
// 使用 urand 随机选择一个副本
return enabledDungeons[urand(0, enabledDungeons.size() - 1)];
}
static std::string GetDungeonName(uint32 dungeonId)
{
QueryResult result = WorldDatabase.Query("SELECT 副本名称 FROM acore_custom.大秘境副本配置 WHERE 副本ID = {}", dungeonId);
if (result)
{
Field* fields = result->Fetch();
return fields[0].Get<std::string>();
}
// 使用缓存而不是直接查询数据库
MythicDungeonConfig const* config = sMythicPlusCache->GetDungeonConfig(dungeonId);
if (config)
return config->dungeonName;
return "未知副本";
}
static uint8 CalculateNewKeystoneLevel(uint8 completedLevel, bool inTime)
static uint8 CalculateNewKeystoneLevel(uint8 completedLevel, bool inTime, uint32 dungeonId)
{
// 从缓存获取副本配置
MythicDungeonConfig const* config = sMythicPlusCache->GetDungeonConfig(dungeonId);
uint8 maxLevel = config ? config->maxLevel : 15; // 如果配置不存在使用默认值15
if (inTime)
{
// 按时完成,钥匙等级+1
return std::min<uint8>(completedLevel + 1, 15); // 最高15级
return std::min<uint8>(completedLevel + 1, maxLevel);
}
else
{
// 超时完成,钥匙等级-1
return std::max<uint8>(completedLevel - 1, 2); // 最低2级
return std::max<uint8>(completedLevel - 1, 2); // 最低2级
}
}
@ -242,10 +248,7 @@ void MythicPlusKeystoneHandler::HandleKeystoneActivation(Player* player, std::st
std::string MythicPlusKeystoneHandler::GetKeystoneInfo(Player* player, uint64 keystoneGUID)
{
// 从 Characters 库查询钥石数据
QueryResult result = CharacterDatabase.Query(
"SELECT 副本ID, 钥石等级, 词缀1, 词缀2, 词缀3 FROM 角色大秘境钥石 WHERE 物品GUID = {}",
keystoneGUID
);
QueryResult result = CharacterDatabase.Query("SELECT 副本ID, 钥石等级, 词缀1, 词缀2, 词缀3, 词缀4 FROM 角色大秘境钥石 WHERE 物品GUID = {}", keystoneGUID);
if (!result)
return "";
@ -256,16 +259,14 @@ std::string MythicPlusKeystoneHandler::GetKeystoneInfo(Player* player, uint64 ke
uint32 affix1 = fields[2].Get<uint32>();
uint32 affix2 = fields[3].Get<uint32>();
uint32 affix3 = fields[4].Get<uint32>();
uint32 affix4 = fields[5].Get<uint32>();
// 获取词缀名称,过滤掉空的词缀
std::string affixName1 = GetAffixName(affix1);
std::string affixName2 = GetAffixName(affix2);
std::string affixName3 = GetAffixName(affix3);
std::vector<std::string> activeAffixes;
if (!affixName1.empty()) activeAffixes.push_back(affixName1);
if (!affixName2.empty()) activeAffixes.push_back(affixName2);
if (!affixName3.empty()) activeAffixes.push_back(affixName3);
// 直接使用词缀数值过滤掉值为0的词缀
std::vector<uint32> activeAffixes;
if (affix1 != 0) activeAffixes.push_back(affix1);
if (affix2 != 0) activeAffixes.push_back(affix2);
if (affix3 != 0) activeAffixes.push_back(affix3);
if (affix4 != 0) activeAffixes.push_back(affix4);
// 构造词缀字符串,如果没有词缀则显示"无词缀"
std::string affixesStr;
@ -279,7 +280,7 @@ std::string MythicPlusKeystoneHandler::GetKeystoneInfo(Player* player, uint64 ke
for (size_t i = 0; i < activeAffixes.size(); ++i)
{
if (i > 0) affixesStr += ", ";
affixesStr += activeAffixes[i];
affixesStr += std::to_string(activeAffixes[i]);
}
}
@ -289,7 +290,7 @@ std::string MythicPlusKeystoneHandler::GetKeystoneInfo(Player* player, uint64 ke
return "";
// 构造返回给客户端的数据:钥石名称|等级|时间限制|词缀1名称|词缀2名称|词缀3名称
return fmt::format("钥石:{}|史诗等级{}|持续时间:{}|{}",
return fmt::format("{}|{}|{}|{}|",
dungeonConfig->dungeonName,
level,
dungeonConfig->baseTimeLimit / 60,
@ -343,31 +344,40 @@ void MythicPlusKeystoneHandler::StartMythicPlusChallenge(Player* player, uint32
ChatHandler(player->GetSession()).PSendSysMessage("开始大秘境挑战 - 副本ID: {}, 等级: {}", dungeonId, level);
}
// 设置钥石属性
void MythicPlusKeystoneHandler::SetKeystoneProperties(Item* keystone, uint32 dungeonId, uint8 level)
{
if (!keystone)
{
LOG_ERROR("mythic.plus", "SetKeystoneProperties: keystone is null");
return;
}
// 使用RandomProperty字段存储副本ID
keystone->SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, dungeonId);
// 获取当前周的词缀
MythicAffixRotation const* currentAffixes = sMythicPlusCache->GetCurrentWeekAffixRotation();
uint32 affix1 = 0, affix2 = 0, affix3 = 0;
if (currentAffixes)
{
affix1 = currentAffixes->affix1;
affix2 = currentAffixes->affix2;
affix3 = currentAffixes->affix3;
}
uint32 affix1 = 0, affix2 = 0, affix3 = 0, affix4 = 0;
MythicPlusKeystoneManager::CalculateAffixesForLevel(level, affix1, affix2, affix3, affix4); // 计算词缀
// 在 Characters 库中存储钥石数据
// 存储钥石数据
uint64 itemGuid = keystone->GetGUID().GetCounter();
uint32 playerGuid = keystone->GetOwnerGUID().GetCounter();
CharacterDatabase.Execute(
"INSERT INTO 角色大秘境钥石 (物品GUID, 角色GUID, 副本ID, 钥石等级, 词缀1, 词缀2, 词缀3) "
"VALUES ({}, {}, {}, {}, {}, {}, {})",
itemGuid, playerGuid, dungeonId, level, affix1, affix2, affix3
);
try
{
CharacterDatabase.Execute(
"INSERT INTO 角色大秘境钥石 (物品GUID, 角色GUID, 副本ID, 钥石等级, 词缀1, 词缀2, 词缀3, 词缀4) "
"VALUES ({}, {}, {}, {}, {}, {}, {}, {})",
itemGuid, playerGuid, dungeonId, level, affix1, affix2, affix3, affix4
);
}
catch (...)
{
LOG_ERROR("mythic.plus", "Failed to insert keystone data for player {}", playerGuid);
}
}
// 获取当前周词缀
@ -377,8 +387,7 @@ std::vector<uint32> MythicPlusKeystoneHandler::GetCurrentWeekAffixes()
uint32 currentWeek = GetCurrentMythicPlusWeek();
QueryResult result = WorldDatabase.Query(
"SELECT 词缀1, 词缀2, 词缀3 FROM acore_custom.大秘境词缀轮换 WHERE 周次 = {}",
currentWeek);
"SELECT 词缀1, 词缀2, 词缀3, 词缀4 FROM acore_custom.大秘境词缀轮换 WHERE 周次 = {}", currentWeek);
if (result)
{
@ -386,15 +395,14 @@ std::vector<uint32> MythicPlusKeystoneHandler::GetCurrentWeekAffixes()
return {
fields[0].Get<uint32>(),
fields[1].Get<uint32>(),
fields[2].Get<uint32>()
fields[2].Get<uint32>(),
fields[4].Get<uint32>() // 添加第4个词缀
};
}
// 默认词缀
return { 1, 2, 3 };
return { 1, 2, 3, 4 };
}
////////////// 钥匙管理器类 ////////////
Item* MythicPlusKeystoneManager::CreateAndGiveKeystone(Player* player, uint32 dungeonId, uint8 level)
{
@ -403,10 +411,6 @@ Item* MythicPlusKeystoneManager::CreateAndGiveKeystone(Player* player, uint32 du
if (!keystone)
return nullptr;
// 设置钥匙属性
MythicPlusKeystoneHandler::SetKeystoneProperties(keystone, dungeonId, level);
// 添加到玩家背包
ItemPosCountVec dest;
InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 999001, 1);
if (msg == EQUIP_ERR_OK)
@ -414,18 +418,16 @@ Item* MythicPlusKeystoneManager::CreateAndGiveKeystone(Player* player, uint32 du
Item* storedItem = player->StoreNewItem(dest, 999001, true);
if (storedItem)
{
// 发送获得物品通知
// 在存储的物品上设置属性
MythicPlusKeystoneHandler::SetKeystoneProperties(storedItem, dungeonId, level);
player->SendNewItem(storedItem, 1, true, false);
// 发送钥匙数据给客户端
// 现在可以安全地获取钥石信息
std::string keystoneData = MythicPlusKeystoneHandler::GetKeystoneInfo(player, storedItem->GetGUID().GetCounter());
sGCAddon->SendPacketTo(player, "SM_S_KEYSTONE_CREATED", keystoneData); // 新创建钥石时
sGCAddon->SendPacketTo(player, "SM_S_KEYSTONE_CREATED", keystoneData);
return storedItem;
}
}
delete keystone;
return nullptr;
}
@ -458,12 +460,6 @@ Item* MythicPlusKeystoneManager::CreateInitialKeystone(Player* player, uint32 du
return nullptr;
}
// 创建钥石物品
Item* keystone = Item::CreateItem(999001, 1, player);
if (!keystone)
return nullptr;
// 添加到玩家背包
ItemPosCountVec dest;
InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 999001, 1);
if (msg == EQUIP_ERR_OK)
@ -471,26 +467,56 @@ Item* MythicPlusKeystoneManager::CreateInitialKeystone(Player* player, uint32 du
Item* storedItem = player->StoreNewItem(dest, 999001, true);
if (storedItem)
{
// 设置钥石属性
MythicPlusKeystoneHandler::SetKeystoneProperties(storedItem, dungeonId, level);
// 发送获得物品通知
player->SendNewItem(storedItem, 1, true, false);
// 发送钥石数据给客户端
std::string keystoneData = MythicPlusKeystoneHandler::GetKeystoneInfo(player, storedItem->GetGUID().GetCounter());
sGCAddon->SendPacketTo(player, "SM_S_KEYSTONE_INITIAL", keystoneData); // 获得初始钥石时
ChatHandler(player->GetSession()).PSendSysMessage("恭喜获得大秘境钥石!副本:{}, 等级:{}", GetDungeonName(dungeonId), level);
player->GetSession()->GetQueryProcessor().AddCallback(
CharacterDatabase.AsyncQuery("SELECT 1").WithCallback([player, storedItem](QueryResult result) {
std::string keystoneData = MythicPlusKeystoneHandler::GetKeystoneInfo(player, storedItem->GetGUID().GetCounter());
sGCAddon->SendPacketTo(player, "SM_S_KEYSTONE_INITIAL", keystoneData);
})
);
return storedItem;
}
}
delete keystone;
return nullptr;
}
// 根据钥石等级计算词缀
void MythicPlusKeystoneManager::CalculateAffixesForLevel(uint8 level, uint32& affix1, uint32& affix2, uint32& affix3, uint32& affix4)
{
affix1 = affix2 = affix3 = affix4 = 0;
MythicAffixRotation const* currentAffixes = sMythicPlusCache->GetCurrentWeekAffixRotation();
if (!currentAffixes) return;
// 根据钥石等级确定词缀数量
if (level >= 2) {
MythicAffixConfig const* affixConfig1 = sMythicPlusCache->GetAffixConfig(currentAffixes->affix1);
if (affixConfig1 && affixConfig1->enableLevel <= level)
affix1 = affixConfig1->spellId;
}
if (level >= 4) {
MythicAffixConfig const* affixConfig2 = sMythicPlusCache->GetAffixConfig(currentAffixes->affix2);
if (affixConfig2 && affixConfig2->enableLevel <= level)
affix2 = affixConfig2->spellId;
}
if (level >= 7) {
MythicAffixConfig const* affixConfig3 = sMythicPlusCache->GetAffixConfig(currentAffixes->affix3);
if (affixConfig3 && affixConfig3->enableLevel <= level)
affix3 = affixConfig3->spellId;
}
if (level >= 10) {
MythicAffixConfig const* affixConfig4 = sMythicPlusCache->GetAffixConfig(currentAffixes->affix4);
if (affixConfig4 && affixConfig4->enableLevel <= level)
affix4 = affixConfig4->spellId;
}
}
bool MythicPlusKeystoneHandler::ValidateKeystoneForInsertion(Player* player, uint32 itemId, std::string& errorMsg, std::string& keystoneInfo)
{
// 1. 基础验证
@ -572,25 +598,38 @@ void MythicPlusKeystoneManager::UpgradeKeystone(Player* player, Item* keystone,
{
uint64 keystoneGUID = keystone->GetGUID().GetCounter();
// 从物品属性获取当前副本ID
uint32 currentDungeonId = keystone->GetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID);
// 计算新等级(军团再临机制)
uint8 newLevel = CalculateNewKeystoneLevel(completedLevel, inTime);
uint8 newLevel = CalculateNewKeystoneLevel(completedLevel, inTime, currentDungeonId);
// 随机新副本
uint32 newDungeonId = GetRandomMythicPlusDungeon();
// 更新数据库
// 重新计算词缀
MythicAffixRotation const* currentAffixes = sMythicPlusCache->GetCurrentWeekAffixRotation();
uint32 affix1 = 0, affix2 = 0, affix3 = 0, affix4 = 0;
MythicPlusKeystoneManager::CalculateAffixesForLevel(newLevel, affix1, affix2, affix3, affix4); // 计算词缀
// 更新数据库,包含词缀
CharacterDatabase.Execute(
"UPDATE 角色大秘境钥石 SET 副本ID = {}, 钥石等级 = {}, 上次更新 = NOW() WHERE 物品GUID = {}",
newDungeonId, newLevel, keystoneGUID);
"UPDATE 角色大秘境钥石 SET 副本ID = {}, 钥石等级 = {}, 词缀1 = {}, 词缀2 = {}, 词缀3 = {}, 词缀4 = {}, 上次更新 = NOW() WHERE 物品GUID = {}",
newDungeonId, newLevel, affix1, affix2, affix3, affix4, keystoneGUID);
// 更新物品属性
keystone->SetInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID, newDungeonId);
// 发送更新数据给客户端
std::string keystoneData = MythicPlusKeystoneHandler::GetKeystoneInfo(player, keystoneGUID);
sGCAddon->SendPacketTo(player, "SM_S_KEYSTONE_UPGRADED", keystoneData); // 钥石升级时
// 使用异步回调确保数据库更新完成后再发送数据包
player->GetSession()->GetQueryProcessor().AddCallback(
CharacterDatabase.AsyncQuery("SELECT 1").WithCallback([player, keystoneGUID, newDungeonId, newLevel](QueryResult result) {
std::string keystoneData = MythicPlusKeystoneHandler::GetKeystoneInfo(player, keystoneGUID);
sGCAddon->SendPacketTo(player, "SM_S_KEYSTONE_UPGRADED", keystoneData);
ChatHandler(player->GetSession()).PSendSysMessage("钥石已更新!新副本:{}, 等级:{}", GetDungeonName(newDungeonId), newLevel);
ChatHandler(player->GetSession()).PSendSysMessage("钥石已更新!新副本:{}, 等级:{}",
GetDungeonName(newDungeonId), newLevel);
})
);
}
// 在 MythicPlusKeystone.cpp 中添加玩家脚本
@ -643,7 +682,7 @@ private:
MythicAffixRotation const* currentAffixes = sMythicPlusCache->GetCurrentWeekAffixRotation();
if (currentAffixes)
{
CharacterDatabase.Execute("UPDATE 角色大秘境钥石 SET 词缀1 = {}, 词缀2 = {}, 词缀3 = {} WHERE 物品GUID = {}", currentAffixes->affix1, currentAffixes->affix2, currentAffixes->affix3, keystoneGUID);
CharacterDatabase.Execute("UPDATE 角色大秘境钥石 SET 词缀1 = {}, 词缀2 = {}, 词缀3 = {}, 词缀4 = {} WHERE 物品GUID = {}", currentAffixes->affix1, currentAffixes->affix2, currentAffixes->affix3, currentAffixes->affix4, keystoneGUID);
// 发送更新后的钥石数据
std::string keystoneData = MythicPlusKeystoneHandler::GetKeystoneInfo(player, keystoneGUID);
@ -713,15 +752,21 @@ private:
return result != nullptr;
}
// 新增:检查是否符合获得初始钥石的条件
// 检查是否符合获得初始钥石的条件
bool IsEligibleForInitialKeystone(Player* player, Map* map)
{
// 1. 玩家没有钥石
if (player->GetItemByEntry(999001))
return false;
// 2. 是普通难度副本
if (map->GetDifficulty() != DUNGEON_DIFFICULTY_NORMAL)
// 2. 检查本周是否已经获得过首次钥石
if (HasWeeklyKeystoneReward(player))
return false;
Difficulty nandu = map->GetDifficulty();
// 3. 必须是史诗难度副本
if (nandu != DUNGEON_DIFFICULTY_EPIC)
return false;
// 3. 玩家等级足够比如80级
@ -735,7 +780,7 @@ private:
return result != nullptr;
}
// 新增:为普通副本完成给予初始钥石
// 为普通副本完成给予初始钥石
void GiveInitialKeystoneForNormalDungeon(Player* player, Map* map)
{
// 获取随机大秘境副本ID不一定是当前副本
@ -746,6 +791,9 @@ private:
if (keystone)
{
// 记录本周已获得首次钥石
SetWeeklyKeystoneReward(player);
ChatHandler(player->GetSession()).PSendSysMessage("恭喜完成副本!你获得了第一个大秘境钥石:{} (等级2)", GetDungeonName(dungeonId));
}
}
@ -784,11 +832,102 @@ private:
// 暂时返回默认值,后续需要完善
return 1800; // 30分钟
}
// 在 MythicPlusGlobalScript 类中添加这个私有方法
bool HasWeeklyKeystoneReward(Player* player)
{
uint32 playerGuid = player->GetGUID().GetCounter();
// 获取当前周重置时间
Seconds currentWeekReset = sWorld->GetNextWeeklyQuestsResetTime();
// 查询玩家本周是否已经获得过首次钥石
QueryResult result = CharacterDatabase.Query(
"SELECT 1 FROM 角色大秘境周进度 WHERE 角色GUID = {} AND 周重置时间 = {} AND 已获得首次钥石 = 1",
playerGuid, currentWeekReset.count()
);
return result != nullptr;
}
// 记录玩家本周已获得首次钥石
void SetWeeklyKeystoneReward(Player* player)
{
uint32 playerGuid = player->GetGUID().GetCounter();
Seconds currentWeekReset = sWorld->GetNextWeeklyQuestsResetTime(); // 返回下一次周重置的时间戳
CharacterDatabase.Execute(
"INSERT INTO 角色大秘境周进度 (角色GUID, 周重置时间, 已获得首次钥石, 首次史诗本完成时间) "
"VALUES ({}, {}, 1, NOW()) "
"ON DUPLICATE KEY UPDATE 已获得首次钥石 = 1, 首次史诗本完成时间 = NOW()",
playerGuid, currentWeekReset.count()
);
}
};
// 周重置钥石逻辑
class MythicPlusWorldScript : public WorldScript
{
private:
static Seconds _lastCheckedWeeklyReset;
public:
MythicPlusWorldScript() : WorldScript("MythicPlusWorldScript") {}
void OnUpdate(uint32 diff) override
{
// 每小时检查一次周重置
static uint32 weeklyCheckTimer = 0;
weeklyCheckTimer += diff;
if (weeklyCheckTimer >= 3600000) // 1小时
{
CheckWeeklyReset();
weeklyCheckTimer = 0;
}
}
private:
void CheckWeeklyReset()
{
Seconds currentWeeklyReset = sWorld->GetNextWeeklyQuestsResetTime(); // 返回下一次周重置的时间戳
if (_lastCheckedWeeklyReset != currentWeeklyReset)
{
// 清理过期的周进度数据
CharacterDatabase.Execute("DELETE FROM 角色大秘境周进度 WHERE 周重置时间 < {}",
currentWeeklyReset.count());
_lastCheckedWeeklyReset = currentWeeklyReset;
}
}
};
// 静态变量定义
Seconds MythicPlusWorldScript::_lastCheckedWeeklyReset = Seconds(0);
// 地图脚本实现
class Mod_MythicPlusAllMapScript : public AllMapScript
{
public:
Mod_MythicPlusAllMapScript() : AllMapScript("Mod_MythicPlusAllMapScript") {}
// 处理玩家进入地图事件
void OnPlayerEnterAll(Map* map, Player* player) override
{
if (!map || !player) return;
Difficulty nandu = map->GetDifficulty();
ChatHandler(player->GetSession()).PSendSysMessage("进入了地图:{} 难度:{}", map->GetMapName(), nandu);
}
};
void AddSC_MythicPlusKeystone()
{
new MythicPlusPlayerScript();
new MythicPlusGlobalScript();
new MythicPlusWorldScript(); // 周重置钥石逻辑
new Mod_MythicPlusAllMapScript();
}

View File

@ -38,6 +38,7 @@ struct MythicAffixRotation
uint32 affix1; // 词缀1
uint32 affix2; // 词缀2
uint32 affix3; // 词缀3
uint32 affix4; // 词缀4
};
// 缓存管理器类声明
@ -61,6 +62,9 @@ public:
// 获取当前周的词缀轮换
MythicAffixRotation const* GetCurrentWeekAffixRotation() const;
// 获取启用的副本列表
std::vector<uint32> const& GetEnabledDungeonIds() const { return _enabledDungeonIds; }
private:
MythicPlusCacheManager() = default;
~MythicPlusCacheManager() = default;
@ -70,6 +74,8 @@ private:
std::unordered_map<uint32, MythicDungeonConfig> _dungeonConfigs;
std::unordered_map<uint32, MythicAffixConfig> _affixConfigs;
std::unordered_map<uint32, MythicAffixRotation> _affixRotations;
std::vector<uint32> _enabledDungeonIds; // 缓存启用的副本ID列表
};
#define sMythicPlusCache MythicPlusCacheManager::instance()
@ -108,6 +114,9 @@ public:
// 创建初始钥石
static Item* CreateInitialKeystone(Player* player, uint32 dungeonId, uint8 level);
// 根据钥石等级计算词缀
static void CalculateAffixesForLevel(uint8 level, uint32& affix1, uint32& affix2, uint32& affix3, uint32& affix4);
private:
static Item* FindPlayerKeystone(Player* player)
{

View File

@ -87,6 +87,7 @@
#include <mod_GhostScripts/src/mod-RandSpell/RandSpell.h>
#include "mod_Creature_MultiLifeMultiplier.h" //生物血量扩展
#include <MirrorClone.h>
#include <Mythic_Script.h>
using namespace Acore::ChatCommands;
@ -276,6 +277,8 @@ void DataLoader::LoadAll()
sCreatureMultiHealthMgr->LoadCreatureHealthData(); //生物血量扩展
sMirrorCloneConfigMgr->LoadMirrorConfigs();
sMythicPlusCache->Initialize();
}
class DataLoaderWorldScript : public WorldScript

View File

@ -2,6 +2,7 @@
#include "PlayerScript.h"
#include <Chat.h>
#include <SpellMgr.h>
#include "Group.h"
#include "mod_SMAddon.h"
#include <GCAddon.h>
@ -52,7 +53,7 @@ std::string ModSMAddon::GetSpellLink(uint32 spellID)
bool ModSMAddon::OnRecv(Player* player, std::string msg)
{
if (!player)
if (!player)
return false;
if (msg.empty())
@ -64,7 +65,7 @@ bool ModSMAddon::OnRecv(Player* player, std::string msg)
stripLineInvisibleChars(msg);
std::string opcode = sGCAddon->SplitStr(msg, 0);
std::string opcode = sGCAddon->SplitStr(msg, 0);
// 物品升星_验证
if (sGCAddon->IsOpcode(opcode, "SM_C_CONFIRM_STARTITEM"))
@ -724,7 +725,36 @@ bool ModSMAddon::OnRecv(Player* player, std::string msg)
}
/////////////////////// 大秘境 ///////////////////////
// 插入了大秘境钥匙
// 切换史诗难度
else if (sGCAddon->IsOpcode(opcode, "SM_C_MYTHIC_DIFFICULTY"))
{
std::string difficultyType = sGCAddon->SplitStr(msg, 1);
if (difficultyType == "EPIC")
{
// 手动设置史诗难度
if (Group* group = player->GetGroup())
{
if (group->IsLeader(player->GetGUID()))
{
// 添加重置操作
group->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false, player);
group->SetDungeonDifficulty(DUNGEON_DIFFICULTY_EPIC);
}
}
else
{
// 添加重置操作
Player::ResetInstances(player->GetGUID(), INSTANCE_RESET_CHANGE_DIFFICULTY, false);
player->SetDungeonDifficulty(DUNGEON_DIFFICULTY_EPIC);
}
player->SendDungeonDifficulty(player->GetGroup() != nullptr);
//ChatHandler(player->GetSession()).SendNotification("已切换到史诗难度");
}
}
// 插入了大秘境钥匙
else if (sGCAddon->IsOpcode(opcode, "SM_C_KEYINSERTCOMMAND"))
{
std::string itemIdStr = sGCAddon->SplitStr(msg, 1);
@ -745,7 +775,7 @@ bool ModSMAddon::OnRecv(Player* player, std::string msg)
}
return false;
return false;
}