优化[大秘境]
1、使用缓存查询大秘境信息 2、增加词缀4 3、读取词缀ID,而不是读取词缀名称发送数据 4、调整钥石属性顺序,以免发送空数据到客户端导致的无法实时显示信息 5、根据钥石等级计算词缀 6、修改地图判断匹配 DUNGEON_DIFFICULTY_EPIC 史诗 7、增加记录玩家本周信息数据
This commit is contained in:
parent
b715ec6f1a
commit
4324b13b6a
@ -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();
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user