【硬核模式】优化
1、增加”硬核模式类型“表设置多级难度 2、各种条件限制的设定和限制处理 3、插件的发包数据处理
This commit is contained in:
parent
d766592c5b
commit
22f07eab1d
@ -14,7 +14,8 @@ HardcoreDatabase* HardcoreDatabase::instance()
|
||||
|
||||
bool HardcoreDatabase::LoadHardcoreData(uint32 playerGuid, HardcoreData& data)
|
||||
{
|
||||
std::string query = Acore::StringFormat("SELECT 角色编号, 状态, UNIX_TIMESTAMP(启用时间), UNIX_TIMESTAMP(死亡时间), 最终等级, 死亡原因, 击杀者编号 FROM 角色硬核模式 WHERE 角色编号 = {}", playerGuid);
|
||||
std::string query = Acore::StringFormat("SELECT 角色编号, 状态, 难度类型编号, 启用时间, 死亡时间, 最终等级, 死亡原因, 击杀者编号,奖励已领取 FROM 角色硬核模式 WHERE 角色编号 = {}", playerGuid);
|
||||
|
||||
QueryResult result = CharacterDatabase.Query(query);
|
||||
|
||||
if (!result)
|
||||
@ -23,32 +24,33 @@ bool HardcoreDatabase::LoadHardcoreData(uint32 playerGuid, HardcoreData& data)
|
||||
Field* fields = result->Fetch();
|
||||
data.guid = fields[0].Get<uint32>();
|
||||
data.status = static_cast<HardcoreStatus>(fields[1].Get<uint8>());
|
||||
data.enableTime = fields[2].Get<uint32>();
|
||||
data.deathTime = fields[3].Get<uint32>();
|
||||
data.finalLevel = fields[4].Get<uint8>();
|
||||
data.deathCause = fields[5].Get<std::string>();
|
||||
data.killerGuid = fields[6].Get<uint32>();
|
||||
data.difficultyTypeId = fields[2].Get<uint32>();
|
||||
data.enableTime = fields[3].Get<uint32>();
|
||||
data.deathTime = fields[4].Get<uint32>();
|
||||
data.finalLevel = fields[5].Get<uint8>();
|
||||
data.deathCause = fields[6].Get<std::string>();
|
||||
data.killerGuid = fields[7].Get<uint32>();
|
||||
data.rewardReceived = fields[8].Get<bool>(); // 奖励领取状态
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HardcoreDatabase::SaveHardcoreData(const HardcoreData& data)
|
||||
{
|
||||
std::string enableTimeStr = data.enableTime > 0 ? Acore::StringFormat("FROM_UNIXTIME({})", data.enableTime) : "NULL";
|
||||
std::string deathTimeStr = data.deathTime > 0 ? Acore::StringFormat("FROM_UNIXTIME({})", data.deathTime) : "NULL";
|
||||
|
||||
std::string escapedCause = data.deathCause;
|
||||
CharacterDatabase.EscapeString(escapedCause);
|
||||
|
||||
std::string query = Acore::StringFormat(
|
||||
"REPLACE INTO 角色硬核模式 (角色编号, 状态, 启用时间, 死亡时间, 最终等级, 死亡原因, 击杀者编号) VALUES ({}, {}, {}, {}, {}, '{}', {})",
|
||||
"REPLACE INTO 角色硬核模式 (角色编号, 状态, 难度类型编号, 启用时间, 死亡时间, 最终等级, 死亡原因, 击杀者编号) VALUES ({}, {}, {}, {}, {}, {}, '{}', {})",
|
||||
data.guid,
|
||||
static_cast<uint8>(data.status),
|
||||
enableTimeStr,
|
||||
deathTimeStr,
|
||||
data.difficultyTypeId,
|
||||
data.enableTime,
|
||||
data.deathTime,
|
||||
data.finalLevel,
|
||||
escapedCause,
|
||||
data.killerGuid
|
||||
data.killerGuid,
|
||||
data.rewardReceived ? 1 : 0 // 新增:保存奖励领取状态
|
||||
);
|
||||
|
||||
CharacterDatabase.Execute(query);
|
||||
|
||||
@ -9,20 +9,22 @@
|
||||
// 前向声明,避免循环包含
|
||||
enum HardcoreStatus : uint8
|
||||
{
|
||||
HC_STATUS_DISABLED = 0,
|
||||
HC_STATUS_ENABLED = 1,
|
||||
HC_STATUS_DEAD = 2
|
||||
HC_STATUS_NORMAL = 0, // 未启用硬核模式 - 玩家处于正常游戏模式
|
||||
HC_STATUS_HARDCORE= 1, // 已启用硬核模式 - 玩家处于硬核模式,死亡将是永久的
|
||||
HC_STATUS_DEAD = 2 // 硬核模式中已死亡 - 玩家在硬核模式中死亡,无法复活
|
||||
};
|
||||
|
||||
struct HardcoreData
|
||||
{
|
||||
uint32 guid;
|
||||
HardcoreStatus status;
|
||||
HardcoreStatus status; // 生存状态(正常/硬核/死亡)
|
||||
uint32 difficultyTypeId; // 难度类型ID(对应"硬核模式类型"表)
|
||||
time_t enableTime;
|
||||
time_t deathTime;
|
||||
uint8 finalLevel;
|
||||
std::string deathCause;
|
||||
uint32 killerGuid;
|
||||
bool rewardReceived = false; // 是否已获得奖励
|
||||
};
|
||||
|
||||
class HardcoreDatabase
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -10,6 +10,23 @@
|
||||
#include "ChatCommand.h"
|
||||
#include "Optional.h"
|
||||
|
||||
struct HardcoreModeType
|
||||
{
|
||||
uint32 id;
|
||||
std::string name;
|
||||
std::string subtitle; // 子标题
|
||||
std::string description; // 描述文本
|
||||
std::string backtexture; // 背景纹理
|
||||
std::string HardcoreLogo; // 难度标志图
|
||||
std::string RewBoxTexture; // 奖励宝箱纹理
|
||||
bool permanentDeath;
|
||||
float expModifier;
|
||||
uint32 groupRestrictions; // 组队限制
|
||||
bool questRestrictions;
|
||||
bool auctionRestrictions;
|
||||
uint32 RewID; // 奖励ID 关联【_模板_奖励】表
|
||||
};
|
||||
|
||||
class HardcoreMode
|
||||
{
|
||||
public:
|
||||
@ -18,7 +35,7 @@ public:
|
||||
bool IsHardcorePlayer(Player* player);
|
||||
HardcoreStatus GetHardcoreStatus(Player* player);
|
||||
HardcoreStatus GetHardcoreStatusByGuid(uint32 guid);
|
||||
void EnableHardcoreMode(Player* player);
|
||||
void EnableHardcoreMode(Player* player, uint32 difficultyTypeId);
|
||||
void EnableHardcoreModeForOfflineCharacter(uint32 guid);
|
||||
void DisableHardcoreModeForOfflineCharacter(uint32 guid);
|
||||
void SetPlayerDead(Player* player, const std::string& cause, Unit* killer = nullptr);
|
||||
@ -26,14 +43,42 @@ public:
|
||||
bool CanGroupWith(Player* player, Player* target);
|
||||
void LoadHardcoreData(Player* player);
|
||||
void SaveHardcoreData(const HardcoreData& data);
|
||||
void SetPlayerDifficultyType(Player* player, uint32 difficultyTypeId); // 当玩家选择特定难度时,需要将难度类型ID存储到玩家的硬核数据中
|
||||
|
||||
// 新增:替代操作码的方法
|
||||
const HardcoreModeType* GetModeTypeById(uint32 difficultyTypeId); // 获取难度类型信息
|
||||
std::string GetPlayerModeName(Player* player); // 获取模式名称的方法
|
||||
|
||||
bool IsValidDifficultyType(uint32 difficultyTypeId); // 验证该难度类型是否在"硬核模式类型"表中存在,防止无效的难度ID被设置
|
||||
uint32 GetPlayerDifficultyType(Player* player); // 获取玩家硬核模式类型
|
||||
void ToggleHardcoreModeForCharacter(WorldSession* session, const std::string& characterName, bool enable);
|
||||
void SendHardcoreStatusToClient(WorldSession* session);
|
||||
|
||||
// 加载硬核模式类型
|
||||
void LoadHardcoreModeTypes();
|
||||
std::string GetHardcoreModeTypesData();
|
||||
|
||||
// 解除玩家限制状态
|
||||
void RemoveHardcoreRestrictions(Player* player);
|
||||
|
||||
// 检查限制的方法
|
||||
bool ShouldApplyGroupRestriction(Player* player);
|
||||
bool ShouldApplyQuestRestriction(Player* player);
|
||||
bool ShouldApplyAuctionRestriction(Player* player);
|
||||
float GetExpModifier(Player* player);
|
||||
bool CanGroupWithPlayer(Player* inviter, Player* invitee);
|
||||
uint32 GetGroupRestrictionType(Player* player); // 获取玩家的组队限制类型
|
||||
|
||||
// 奖励发放
|
||||
void GiveHardcoreReward(Player* player);
|
||||
bool HasReceivedHardcoreReward(Player* player);
|
||||
void MarkHardcoreRewardAsGiven(Player* player);
|
||||
|
||||
private:
|
||||
std::unordered_map<uint32, HardcoreData> _hardcoreData;
|
||||
std::mutex _dataMutex;
|
||||
|
||||
std::vector<HardcoreModeType> _hardcoreModeTypes;
|
||||
std::mutex _typesMutex;
|
||||
};
|
||||
|
||||
#define sHardcoreMode HardcoreMode::instance()
|
||||
@ -43,11 +88,37 @@ class HardcorePlayerScript : public PlayerScript
|
||||
public:
|
||||
HardcorePlayerScript() : PlayerScript("HardcorePlayerScript") { }
|
||||
|
||||
void OnPlayerFirstLogin(Player* player) override; // 当角色创建时调用
|
||||
void OnPlayerLogin(Player* player) override;
|
||||
void OnPlayerLogout(Player* player) override;
|
||||
bool OnPlayerCanResurrect(Player* player) override;
|
||||
void OnPlayerJustDied(Player* player) override;
|
||||
void OnPlayerReleasedGhost(Player* player) override;
|
||||
void OnPlayerUpdate(Player* player, uint32 p_time) override;
|
||||
|
||||
bool OnPlayerCanGroupInvite(Player* player, std::string& membername) override; // 限制组队行为
|
||||
bool OnPlayerCanGroupAccept(Player* player, Group* group) override; // 限制接受组队行为
|
||||
bool OnPlayerCanPlaceAuctionBid(Player* /*player*/, AuctionEntry* /*auction*/)override; // 拍卖行交易
|
||||
bool OnPlayerBeforeQuestComplete(Player* player, uint32 quest_id) override;
|
||||
void OnPlayerGiveXP(Player* /*player*/, uint32& /*amount*/, Unit* /*victim*/, uint8 /*xpSource*/) override; // 玩家获得经验时调用
|
||||
void OnPlayerLevelChanged(Player* /*player*/, uint8 /*oldlevel*/) override; // 玩家等级发生变化后调用
|
||||
|
||||
void CheckGroupLevelRestrictions(Player* player); // 检查组队限制
|
||||
|
||||
|
||||
// 限制玩家状态
|
||||
void ApplyHardcoreRestrictions(Player* player);
|
||||
|
||||
|
||||
|
||||
// 启动5秒定时器
|
||||
void StartHardcoreReminder(Player* player);
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
std::unordered_set<uint32> _reminderPlayers; // 需要提醒的玩家GUID
|
||||
std::unordered_map<uint32, uint64> _reminderStartTime; // 记录每个玩家的提醒开始时间
|
||||
std::unordered_map<uint32, uint32> _reminderCount; // 玩家GUID -> 提醒计数
|
||||
};
|
||||
|
||||
class HardcoreWorldScript : public WorldScript
|
||||
@ -78,11 +149,16 @@ public:
|
||||
private:
|
||||
static bool HandleHardcoreEnableCommand(ChatHandler* handler);
|
||||
static bool HandleHardcoreStatusCommand(ChatHandler* handler, Optional<Acore::ChatCommands::PlayerIdentifier> target);
|
||||
static bool HandleHardcoreDisableCommand(ChatHandler* handler, Acore::ChatCommands::PlayerIdentifier target);
|
||||
static bool HandleHardcoreReviveCommand(ChatHandler* handler, Acore::ChatCommands::PlayerIdentifier target);
|
||||
static bool HandleHardcoreDisableCommand(ChatHandler* handler, Optional<Acore::ChatCommands::PlayerIdentifier> target);
|
||||
static bool HandleHardcoreReviveCommand(ChatHandler* handler, Optional<Acore::ChatCommands::PlayerIdentifier> target);
|
||||
|
||||
// 新增:替代操作码的命令
|
||||
static bool HandleHardcoreToggleCommand(ChatHandler* handler, Optional<std::string> characterName);
|
||||
|
||||
// 移除硬核模式
|
||||
static bool HandleHardcoreDelCommand(ChatHandler* handler, Optional<std::string> characterName);
|
||||
|
||||
|
||||
static bool HandleHardcoreListCommand(ChatHandler* handler);
|
||||
};
|
||||
|
||||
|
||||
@ -88,6 +88,7 @@
|
||||
#include "mod_Creature_MultiLifeMultiplier.h" //生物血量扩展
|
||||
#include <MirrorClone.h>
|
||||
#include <Mythic_Script.h>
|
||||
#include <HardcoreMode.h>
|
||||
|
||||
using namespace Acore::ChatCommands;
|
||||
|
||||
@ -279,6 +280,8 @@ void DataLoader::LoadAll()
|
||||
sMirrorCloneConfigMgr->LoadMirrorConfigs();
|
||||
|
||||
sMythicPlusCache->Initialize();
|
||||
|
||||
sHardcoreMode->LoadHardcoreModeTypes(); // 硬核模式
|
||||
}
|
||||
|
||||
class DataLoaderWorldScript : public WorldScript
|
||||
|
||||
@ -18,6 +18,9 @@
|
||||
#include "MythicPlusWrapperInstance.h"
|
||||
#include <MapMgr.h>
|
||||
#include <GridNotifiers.h>
|
||||
#include <HardcoreMode.h>
|
||||
#include <Reward.h>
|
||||
#include <CommonFunc.h>
|
||||
|
||||
void ResetInstanceCreaturesAndObjects(Player* player, InstanceMap* instanceMap)
|
||||
{
|
||||
@ -881,6 +884,57 @@ bool ModSMAddon::OnRecv(Player* player, std::string msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 查看当前难度奖励信息
|
||||
else if (sGCAddon->IsOpcode(opcode, "SM_C_VIRWHARDCORE_REWINFO"))
|
||||
{
|
||||
std::string RewIDStr = sGCAddon->SplitStr(msg, 1);
|
||||
uint32 RewID = std::stoul(RewIDStr);
|
||||
std::ostringstream oss;
|
||||
if (!sRew->IsExist(RewID))
|
||||
{
|
||||
LOG_ERROR("server.loading", "难度ID {} 不存在", RewID);
|
||||
oss << "|TInterface\\DialogFrame\\UI-Dialog-Icon-AlertNew:60:60:0:-10|t"
|
||||
<< "\n|cFFFF0606[警告]|r:\n难度ID [" << RewID << "] [不存在] \n";
|
||||
sCF->SendAcceptOrCancel(player, 9999, oss.str());
|
||||
return false;
|
||||
}
|
||||
std::string Reward = sRew->GetDescription(RewID, true);
|
||||
oss << "当前难度奖励\n\n" << Reward<< "\n";
|
||||
sCF->SendAcceptOrCancel(player, 9999, oss.str());
|
||||
}
|
||||
|
||||
// 选择硬核模式难度
|
||||
else if (sGCAddon->IsOpcode(opcode, "SM_C_SELECTHARDCOREMODE"))
|
||||
{
|
||||
std::string difficultyIdStr = sGCAddon->SplitStr(msg, 1);
|
||||
uint32 difficultyId = std::stoul(difficultyIdStr);
|
||||
|
||||
// 验证难度类型是否有效
|
||||
if (!sHardcoreMode->IsValidDifficultyType(difficultyId))
|
||||
{
|
||||
LOG_ERROR("server.loading", "Player {} selected invalid difficulty type {}", player->GetName(), difficultyId);
|
||||
return false;
|
||||
}
|
||||
|
||||
HardcoreStatus aaaa = sHardcoreMode->GetHardcoreStatus(player);
|
||||
// 检查玩家是否已经设置过难度
|
||||
if (aaaa != HC_STATUS_NORMAL)
|
||||
{
|
||||
LOG_WARN("server.loading", "Player {} attempted to change difficulty but already has hardcore mode set", player->GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 解除所有限制
|
||||
sHardcoreMode->RemoveHardcoreRestrictions(player);
|
||||
|
||||
// 设置玩家的硬核模式和难度类型
|
||||
sHardcoreMode->EnableHardcoreMode(player, difficultyId);
|
||||
|
||||
LOG_INFO("server.loading", "Player {} selected hardcore difficulty type {}", player->GetName(), difficultyId);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user