增加 VIP 战斗能量最大值百分比功能

This commit is contained in:
尚美 2025-09-03 11:35:28 +08:00
parent a042c11907
commit e5652aa41c
2 changed files with 194 additions and 7 deletions

View File

@ -4,6 +4,7 @@
#include "ScriptedGossip.h"
#include "DatabaseEnv.h"
#include "Player.h"
#include "Chat.h"
#include "VIP.h"
#include "mod_Requirement/Requirement.h"
@ -30,7 +31,7 @@ void VIP::Load()
// 6 7 8 9 10 11 12 13
"符印强化增加成功百分比,移除宝石增加成功百分比,升级后奖励模板ID,图标,名称,泡点奖励模板ID,菜单文本,拾取范围,"
// 14 15 16 17 18
"图标宽度,图标高度,图标X轴,图标Y轴,灵力更新速度,物品升星增加成功百分比,物品升星增幅,锻造属性提升百分比 from acore_custom.__会员",
"图标宽度,图标高度,图标X轴,图标Y轴,灵力更新速度,物品升星增加成功百分比,物品升星增幅,锻造属性提升百分比,战斗能量上限提升 from acore_custom.__会员",
"__会员-------------------",
// 过滤函数:无过滤
[](Field* fields) -> bool {
@ -65,6 +66,7 @@ void VIP::Load()
VIPTemp.itemStarUpgradeBoost = fields[20].Get<float>(); // 物品升星增幅
VIPTemp.itemForgeAttributeBoostRate = fields[21].Get<uint32>(); // VIP在锻造时提高获得更好属性的概率
VIPTemp.powerBoostPercent = fields[22].Get<uint32>(); // 资源加成百分比 - 新增
return VIPTemp;
}
@ -216,7 +218,7 @@ float VIP::GetLootRate(Player* player)
auto playerData = g_CustomPlayerDataManager.GetOrCreatePlayerData(playerGuid);
if (playerData)
{
uint32 len = VIPVec.size(); //定义int类型的len变量 等于 VIPVec.总大小 VIPVec是表 __会员 的总条数
uint32 len = VIPVec.size(); //定义int类型的len变量 等于 VIPVec.总大小 VIPVec是表 __会员 的总条数
for (size_t i = 0; i < len; i++) //设置for循环 小于总数量 +1循环 直到最后一条
if (playerData->vipLevel == VIPVec[i].vipLv) //如果 玩家VIP等级 等于 _会员表列[当前条目]的VIP等级
return VIPVec[i].lootRate; //返回 _会员表列[当前条目] 的 lootRate 掉落倍率
@ -232,7 +234,7 @@ float VIP::Getlootrange(Player* player)
if (!playerData)
return 0;
uint32 len = VIPVec.size(); //定义int类型的len变量 等于 VIPVec.总大小 VIPVec是表 __会员 的总条数
uint32 len = VIPVec.size(); //定义int类型的len变量 等于 VIPVec.总大小 VIPVec是表 __会员 的总条数
for (size_t i = 0; i < len; i++) //设置for循环 小于总数量 +1循环 直到最后一条
if (playerData->vipLevel == VIPVec[i].vipLv) //如果 玩家VIP等级 等于 _会员表列[当前条目]的VIP等级
return VIPVec[i].lootrange; //返回 _会员表列[当前条目] 的 lootrange 拾取范围
@ -247,13 +249,31 @@ uint32 VIP::GetSPowerUPSpeed(Player* player)
if (!playerData)
return 0;
uint32 len = VIPVec.size();
uint32 len = VIPVec.size();
for (size_t i = 0; i < len; i++)
if (playerData->vipLevel == VIPVec[i].vipLv)
return VIPVec[i].SPowerUPSpeed;
return 5000;
}
// 获取VIP战斗能量加成百分比
uint32 VIP::GetPowerBoost(Player* player)
{
uint64 playerGuid = player->GetGUID().GetCounter();
auto playerData = g_CustomPlayerDataManager.GetOrCreatePlayerData(playerGuid);
if (!playerData)
return 0;
for (const auto& vipTemplate : VIPVec)
{
if (vipTemplate.vipLv == playerData->vipLevel)
{
return vipTemplate.powerBoostPercent;
}
}
return 0;
}
void VIP::Up(Player* player)
{
uint64 playerGuid = player->GetGUID().GetCounter();
@ -416,9 +436,9 @@ void VIP::AddGossip(Player* player, Object* obj)
GetVIP(player, VipName1, VipIcon1);
// 获取下一级VIP信息
std::string VipName2 = "";
std::string VipName2 = "";
std::string VipIcon2 = "";
GetNextVIP(player, VipName2, VipIcon2);
GetNextVIP(player, VipName2, VipIcon2);
// 使用GetMaxVIPLevel()获取最大VIP等级
uint32 maxLevel = GetMaxVIPLevel();
@ -461,7 +481,7 @@ public:
if (!result)
{
playerData->vipLevel = 0;
}
}
else
{
Field* fields = result->Fetch();
@ -472,7 +492,170 @@ public:
}
}
};
// VIP战斗能量加成脚本钩子
class VIPPowerBoostPlayer : public PlayerScript
{
public:
VIPPowerBoostPlayer() : PlayerScript("VIPPowerBoostPlayer") {}
// 当玩家的最大能量值更新后触发的钩子函数
// player: 当前玩家对象
// power: 能量类型(法力值、怒气、能量、符文能量等)
// value: 计算后的最大能量值(可以被修改)
void OnPlayerAfterUpdateMaxPower(Player* player, Powers& power, float& value) override
{
// 获取玩家当前的VIP能量加成百分比
uint32 boostPercent = sVIP->GetPowerBoost(player);
if (boostPercent > 0)
{
// 检查当前更新的能量类型是否是该职业的主要资源类型
if (ShouldApplyBoost(player, power))
{
// 记录加成前的原始值,用于向玩家显示变化
float originalValue = value;
// 应用VIP加成新值 = 原值 × (100 + 加成百分比) ÷ 100
// 例如原值100加成20%,则新值 = 100 × (100 + 20) ÷ 100 = 120
value = value * (100 + boostPercent) / 100;
// 向玩家发送能量变化的消息通知
SendPowerChangeMessage(player, power, originalValue, value, boostPercent);
}
}
}
private:
// 判断是否应该对指定的能量类型应用VIP加成
// 处理德鲁伊的多种资源类型
bool ShouldApplyBoost(Player* player, Powers power)
{
// 德鲁伊特殊处理:对所有可能使用的资源类型都应用加成
if (player->getClass() == CLASS_DRUID)
{
// 德鲁伊的三种主要资源类型都应该获得VIP加成
return (power == POWER_MANA || // 人形态/枭兽形态/树形态
power == POWER_ENERGY || // 猫形态
power == POWER_RAGE); // 熊形态
}
// 其他职业按照标准逻辑判断
return IsMainPowerType(player, power);
}
// 判断指定的能量类型是否是该职业的主要资源类型
// player: 玩家对象
// power: 要检查的能量类型
// 返回值: true表示是主要资源类型false表示不是
bool IsMainPowerType(Player* player, Powers power)
{
switch (player->getClass())
{
case CLASS_WARRIOR:
return power == POWER_RAGE;
case CLASS_ROGUE:
return power == POWER_ENERGY;
case CLASS_DEATH_KNIGHT:
return power == POWER_RUNIC_POWER;
case CLASS_PALADIN:
case CLASS_HUNTER:
case CLASS_PRIEST:
case CLASS_SHAMAN:
case CLASS_MAGE:
case CLASS_WARLOCK:
case CLASS_DRUID: // 德鲁伊在这里默认返回法力值
default:
return power == POWER_MANA;
}
}
// 向玩家发送能量变化的消息通知
// player: 玩家对象
// power: 能量类型
// oldValue: 变化前的值
// newValue: 变化后的值
// boostPercent: VIP加成百分比
void SendPowerChangeMessage(Player* player, Powers power, float oldValue, float newValue, uint32 boostPercent)
{
auto playerData = g_CustomPlayerDataManager.GetOrCreatePlayerData(player->GetGUID().GetCounter());
if (!playerData)
return;
// 获取能量类型的中文名称
std::string powerName = GetPowerTypeName(power);
std::string VIPName =sVIP->GetVIPName(playerData->vipLevel);
// 对于怒气和符文能量显示值需要除以10
uint32 displayOldValue = static_cast<uint32>(oldValue);
uint32 displayNewValue = static_cast<uint32>(newValue);
if (power == POWER_RAGE || power == POWER_RUNIC_POWER)
{
displayOldValue /= 10;
displayNewValue /= 10;
}
std::ostringstream message;
message << "|cff00ff00[VIP【" << VIPName << "】]|r " << powerName << "上限提升!"
<< "\n原值: |cffffffff" << displayOldValue << "|r"
<< "\n加成: |cffffff00+" << boostPercent << "%|r"
<< "\n新值: |cff00ff00" << displayNewValue << "|r";
// 发送消息到玩家聊天窗口
ChatHandler(player->GetSession()).SendSysMessage(message.str().c_str());
}
// 根据能量类型返回对应的中文名称
// power: 能量类型枚举值
// 返回值: 能量类型的中文名称字符串
std::string GetPowerTypeName(Powers power)
{
switch (power)
{
case POWER_MANA: // 法力值
return "法力值";
case POWER_RAGE: // 怒气
return "怒气";
case POWER_ENERGY: // 能量
return "能量";
case POWER_RUNIC_POWER: // 符文能量
return "符文能量";
default: // 未知类型
return "战斗资源";
}
}
};
// 处理德鲁伊形态变化的脚本钩子类
// 这个类继承自UnitScript用于监听单位包括玩家的形态变化事件
class VIPPowerBoostUnit : public UnitScript
{
public:
VIPPowerBoostUnit() : UnitScript("VIPPowerBoostUnit") {}
// 当单位(玩家)变换形态时触发的钩子函数
// unit: 变换形态的单位对象
// form: 新的形态ID
void OnUnitSetShapeshiftForm(Unit* unit, uint8 form) override
{
if (Player* player = unit->ToPlayer())
{
// 获取玩家当前的主要能量类型(形态变化后可能已经改变)
Powers powerType = player->getPowerType();
// 手动触发该能量类型的最大值重新计算
// 这会触发OnPlayerAfterUpdateMaxPower钩子从而重新应用VIP加成
player->UpdateMaxPower(powerType);
}
}
};
void AddSC_VIP_LOGIN()
{
new VIPLogin();
new VIPPowerBoostPlayer(); // 新增VIP能量加成脚本PlayerScript
new VIPPowerBoostUnit(); // 新增VIP形态变化处理脚本UnitScript
}

View File

@ -56,6 +56,7 @@ struct VIPTemplate
float itemStarUpgradeBoost; // 物品升星增幅
uint32 itemForgeAttributeBoostRate; // VIP在锻造时提高获得更好属性的概率
uint32 powerBoostPercent; // 资源加成百分比 - 新增字段
};
extern std::vector<VIPTemplate> VIPVec; // 全局VIP模板数据容器
@ -111,6 +112,9 @@ public:
*/
uint32 GetSPowerUPSpeed(Player* player);
// 获取VIP资源加成百分比
uint32 GetPowerBoost(Player* player);
/**
* @brief VIP等级
* @param player