优化[属性调整_生物]性能

1、移除CreautreModVec,使用三级哈希表利用FindTemplate快速查询
2、增加 OnModCustomRespawn 自定义钩子,处理生物刷新时的属性应用
This commit is contained in:
尚美 2025-08-13 23:33:11 +08:00
parent b96a351035
commit 1ad0565da2
3 changed files with 341 additions and 253 deletions

View File

@ -831,18 +831,12 @@ public:
mod_CustomCreature* customCreature = mod_CustomCreature::GetForCreature(creature);
if (customCreature)
{
for (auto itr = CreautreModVec.begin(); itr != CreautreModVec.end(); itr++)
{
if (itr->Entry == creature->GetEntry())
{
// 使用自定义生物类的变量来调整伤害
if (customCreature->C_MeleeDmg > 0)
damage = customCreature->C_MeleeDmg; // 直接设置伤害值为 C_MeleeDmg 的值
else if (customCreature->C_MeleeDmg < 0)
damage *= (-customCreature->C_MeleeDmg); // 将伤害乘以 -C_MeleeDmg 的绝对值
}
}
// 使用优化后的快速查找,无需遍历
// 直接使用已经存储在customCreature中的数据
if (customCreature->C_MeleeDmg > 0)
damage = customCreature->C_MeleeDmg; // 直接设置伤害值
else if (customCreature->C_MeleeDmg < 0)
damage *= (-customCreature->C_MeleeDmg); // 将伤害乘以绝对值
}
}
else if (attacker->GetTypeId() == TYPEID_PLAYER) //对于玩家的伤害修改
@ -1114,20 +1108,20 @@ public:
int32 amountToModify = static_cast<int32>(remainingDamage) - static_cast<int32>(originalDamage);
dmgInfo.ModifyDamage(amountToModify);
// 如果减伤后伤害有变化,记录变化的值
LOG_ERROR("server.loading", "{}{}{}{},减伤后伤害:{},生物的护甲:{}"
"生物的火焰抗性:{},生物的自然抗性:{},生物的冰霜抗性:{}"
"生物的暗影抗性:{},生物的奥术抗性:{}",
attackerType, //攻击单位类型 [玩家] [生物]
attacker->GetName(), //攻击单位名称
victimType, //被攻击单位类型 [玩家] [生物]
victim->GetName(), //被攻击单位名称
dmgInfo.GetDamage(), //伤害值
victim->GetArmor(), //单位护甲值
victim->GetResistance(SPELL_SCHOOL_FIRE), //火焰抗性
victim->GetResistance(SPELL_SCHOOL_NATURE), //自然抗性
victim->GetResistance(SPELL_SCHOOL_FROST), //冰霜抗性
victim->GetResistance(SPELL_SCHOOL_SHADOW), //暗影抗性
victim->GetResistance(SPELL_SCHOOL_ARCANE)); //奥术抗性
//LOG_ERROR("server.loading", "{}{}{}{},减伤后伤害:{},生物的护甲:{}"
// "生物的火焰抗性:{},生物的自然抗性:{},生物的冰霜抗性:{}"
// "生物的暗影抗性:{},生物的奥术抗性:{}",
// attackerType, //攻击单位类型 [玩家] [生物]
// attacker->GetName(), //攻击单位名称
// victimType, //被攻击单位类型 [玩家] [生物]
// victim->GetName(), //被攻击单位名称
// dmgInfo.GetDamage(), //伤害值
// victim->GetArmor(), //单位护甲值
// victim->GetResistance(SPELL_SCHOOL_FIRE), //火焰抗性
// victim->GetResistance(SPELL_SCHOOL_NATURE), //自然抗性
// victim->GetResistance(SPELL_SCHOOL_FROST), //冰霜抗性
// victim->GetResistance(SPELL_SCHOOL_SHADOW), //暗影抗性
// victim->GetResistance(SPELL_SCHOOL_ARCANE)); //奥术抗性
}
}
@ -1148,7 +1142,7 @@ public:
int32 amountToModify = static_cast<int32>(remainingDamage) - static_cast<int32>(originalDamage);
dmgInfo.ModifyDamage(amountToModify);
// 如果减伤后伤害有变化,记录变化的值
LOG_ERROR("server.loading", "{}{}{}{},减伤后伤害:{},玩家的护甲:{}", attackerType, attacker->GetName(), victimType, victim->GetName(), dmgInfo.GetDamage(), victim->GetArmor());
// LOG_ERROR("server.loading", "{}{}{}{},减伤后伤害:{},玩家的护甲:{}", attackerType, attacker->GetName(), victimType, victim->GetName(), dmgInfo.GetDamage(), victim->GetArmor());
}
}
}
@ -1192,15 +1186,9 @@ public:
mod_CustomCreature* customCreature = mod_CustomCreature::GetForCreature(creature);
if (customCreature)
{
for (auto itr = CreautreModVec.begin(); itr != CreautreModVec.end(); itr++)
{
uint32 testentry = creature->GetEntry();
if (testentry == itr->Entry)
{
if (customCreature->C_Armor > 0)
value = customCreature->C_Armor;
}
}
// 直接使用customCreature中已存储的护甲值无需查找
if (customCreature->C_Armor > 0)
value = customCreature->C_Armor;
}
}
}

View File

@ -18,76 +18,99 @@
#include "mod_Scripts/CustomScripts.h"
#include <CustomPlayerDataManager.h>
std::vector<CreautreModTemplate> CreautreModVec;
void CreatureMod::Load()
{
uint32 oldMSTime = getMSTime();
CreautreModVec.clear();
QueryResult result = WorldDatabase.Query(
// 清理旧数据
_modTemplates.clear();
_modIndex.clear();
// 0 1 2 3 4 5 6 7
QueryResult result = WorldDatabase.Query(
"SELECT 生物ID,等级,生命值,物理伤害值或倍率,法术伤害值或倍率,治疗效果倍率,减伤百分比,抗性值,"
// 8 9 10 11 12 13 14 15 16 17 18 19
"击杀奖励模板ID,击杀奖励几率,击杀是否全服提示,护甲值,攻击间隔,离开原位置重置距离,击杀奖励法宝值,掉落ID1,掉落ID2,掉落ID3,掉落ID4,掉落ID5,"
// 20 21 22 23 24 25 26 27
"队伍击杀奖励模板ID,队伍击杀奖励几率,击杀奖励自定义等级值,击杀召唤物体ID,副本挑战等级,是否加载原掉落,随机技能组模板ID,难度 FROM acore_custom._属性调整_生物");
if (result)
{
// 预分配内存
_modTemplates.reserve(result->GetRowCount());
do
{
Field* fields = result->Fetch();
CreautreModTemplate Temp;
Temp.Entry = fields[0].Get<uint32>();
Temp.Level = fields[1].Get<uint8>();
Temp.Health = fields[2].Get<uint32>();
Temp.MeleeDmg = fields[3].Get<float>();
Temp.SpellDmgMod = fields[4].Get<float>();
Temp.HealMod = fields[5].Get<float>();
Temp.ReduceDmgPct = fields[6].Get<float>();
Temp.Resistance = fields[7].Get<uint32>(); // 抗性
Temp.KillRewId = fields[8].Get<uint32>();
Temp.KillRewChance = fields[9].Get<float>();
Temp.KillAnnounce = fields[10].Get<bool>();
Temp.Armor = fields[11].Get<int32>();
Temp.AttackTime = fields[12].Get<uint32>();
Temp.ResetDistance = fields[13].Get<float>();
Temp.AddTalismanValue = fields[14].Get<int32>();
CreautreModTemplate temp;
// 填充数据(保持原有逻辑)
temp.Entry = fields[0].Get<uint32>();
temp.Level = fields[1].Get<uint8>();
temp.Health = fields[2].Get<uint32>();
temp.MeleeDmg = fields[3].Get<float>();
temp.SpellDmgMod = fields[4].Get<float>();
temp.HealMod = fields[5].Get<float>();
temp.ReduceDmgPct = fields[6].Get<float>();
temp.Resistance = fields[7].Get<uint32>();
temp.KillRewId = fields[8].Get<uint32>();
temp.KillRewChance = fields[9].Get<float>();
temp.KillAnnounce = fields[10].Get<bool>();
temp.Armor = fields[11].Get<int32>();
temp.AttackTime = fields[12].Get<uint32>();
temp.ResetDistance = fields[13].Get<float>();
temp.AddTalismanValue = fields[14].Get<int32>();
for (size_t i = 0; i < MAX_CUSTOM_LOOT_COUNT; i++)
Temp.LootId[i] = fields[15 + i].Get<uint32>();
temp.LootId[i] = fields[15 + i].Get<uint32>();
temp.KillGroupRewId = fields[20].Get<uint32>();
temp.KillGroupRewChance = fields[21].Get<float>();
temp.AddRankValue = fields[22].Get<int32>();
temp.KillRewGameObject = fields[23].Get<int32>();
temp.ChallengeLv = fields[24].Get<uint32>();
temp.SrcLoot = fields[25].Get<bool>();
temp.RandSpellGroupId = fields[26].Get<uint32>();
temp.Diff = fields[27].Get<uint32>();
// 存储到向量中
_modTemplates.push_back(temp);
// 构建三级索引 - O(1)查找
_modIndex[temp.Entry][temp.ChallengeLv][temp.Diff] = &_modTemplates.back();
Temp.KillGroupRewId = fields[20].Get<uint32>();
Temp.KillGroupRewChance = fields[21].Get<float>();
Temp.AddRankValue = fields[22].Get<int32>();
Temp.KillRewGameObject = fields[23].Get<int32>();
Temp.ChallengeLv = fields[24].Get<uint32>();
Temp.SrcLoot = fields[25].Get<bool>();
Temp.RandSpellGroupId = fields[26].Get<uint32>();
Temp.Diff = fields[27].Get<uint32>();
CreautreModVec.push_back(Temp);
} while (result->NextRow());
sLog->outMessage("server", LogLevel::LOG_LEVEL_INFO, ">> 读取自定义功能数据表【_属性调整_生物-----------】,共{}条数据读取加载,用时{}毫秒", CreautreModVec.size(), GetMSTimeDiffToNow(oldMSTime));
sLog->outMessage("server", LogLevel::LOG_LEVEL_INFO, ">> 读取自定义功能数据表【_属性调整_生物-----------】,共{}条数据读取加载,用时{}毫秒", _modTemplates.size(), GetMSTimeDiffToNow(oldMSTime));
}
}
// 快速查找函数 - O(1)复杂度
CreautreModTemplate* CreatureMod::FindTemplate(uint32 entry, uint32 challengeLv, uint32 diff)
{
auto entryIt = _modIndex.find(entry);
if (entryIt == _modIndex.end())
return nullptr;
auto challengeIt = entryIt->second.find(challengeLv);
if (challengeIt == entryIt->second.end())
return nullptr;
auto diffIt = challengeIt->second.find(diff);
if (diffIt == challengeIt->second.end())
return nullptr;
return diffIt->second;
}
void CreatureMod::SetMod(Creature* creature)
{
// 获取该creature的mod_CustomCreature实例
mod_CustomCreature* customCreature = mod_CustomCreature::GetForCreature(creature);
if (!customCreature)
return;
// 获取该creature所在map的GetCustomMapFromMap实例
//mod_CustomMap* customMap = mod_CustomMap::GetCustomMapFromMap(creature->GetMap());
//使用GetOrCreateCustomMap
mod_CustomMap* customMap = mod_CustomMap::GetOrCreateCustomMap(creature->GetMap());
if (!customMap) return; // 或者其他错误处理
if (creature->GetEntry() == 1964 || creature->IsGuardian() || creature->IsHunterPet() || creature->IsTotem() && creature->IsPet())
// 早期退出条件
if (creature->GetEntry() == 1964 || creature->IsGuardian() || creature->IsHunterPet() || creature->IsTotem() || creature->IsPet())
return;
// 如果该生物已经在 "_属性调整_地图"中有属性调整,就使用"_属性调整_地图"的属性调整
@ -99,47 +122,40 @@ void CreatureMod::SetMod(Creature* creature)
if (creature->IsCivilian())
return;
uint32 Entry = creature->GetEntry();
uint32 ChallengeLv = customMap->challengeLv;
uint32 Diff = creature->GetMap()->GetDifficulty();
uint32 entry = creature->GetEntry();
uint32 challengeLv = customMap->challengeLv;
uint32 diff = creature->GetMap()->GetDifficulty();
for (auto itr = CreautreModVec.begin(); itr != CreautreModVec.end(); itr++)
{
if (Entry == itr->Entry && ChallengeLv == itr->ChallengeLv && Diff == itr->Diff)
{
customCreature->C_Level = itr->Level;
customCreature->C_Health = itr->Health;
//customCreature->C_HpMod = 1;
customCreature->C_MeleeDmg = itr->MeleeDmg;
customCreature->C_SpellDmgMod = itr->SpellDmgMod;
customCreature->C_HealMod = itr->HealMod;
customCreature->C_ReduceDmgPct = itr->ReduceDmgPct;
// 使用O(1)查找替代O(n)遍历
CreautreModTemplate* modTemplate = FindTemplate(entry, challengeLv, diff);
if (!modTemplate)
return;
customCreature->C_Resistance = itr->Resistance; //原格式
//新修改 具体到类型
/*for (size_t i = 0; i < MAX_SPELL_SCHOOL; i++)
customCreature->C_Resistance[i] = itr->Resistance[i];*/
// 应用修改(保持原有逻辑)
customCreature->C_Level = modTemplate->Level;
customCreature->C_Health = modTemplate->Health;
customCreature->C_MeleeDmg = modTemplate->MeleeDmg;
customCreature->C_SpellDmgMod = modTemplate->SpellDmgMod;
customCreature->C_HealMod = modTemplate->HealMod;
customCreature->C_ReduceDmgPct = modTemplate->ReduceDmgPct;
customCreature->C_Resistance = modTemplate->Resistance;
customCreature->C_SrcLoot = modTemplate->SrcLoot;
customCreature->C_SrcLoot = itr->SrcLoot;
for (size_t i = 0; i < MAX_CUSTOM_LOOT_COUNT; i++)
customCreature->C_LootId[i] = modTemplate->LootId[i];
for (size_t i = 0; i < MAX_CUSTOM_LOOT_COUNT; i++)
customCreature->C_LootId[i] = itr->LootId[i];
customCreature->C_KillRewId = itr->KillRewId;
customCreature->C_KillRewChance = itr->KillRewChance;
customCreature->C_KillGroupRewId = itr->KillGroupRewId;
customCreature->C_KillGroupRewChance = itr->KillGroupRewChance;
customCreature->C_KillAnnounce = itr->KillAnnounce;
customCreature->C_Armor = itr->Armor;
customCreature->C_AttackTime = itr->AttackTime;
customCreature->C_ResetDistance = itr->ResetDistance;
customCreature->C_AddTalismanValue = itr->AddTalismanValue;
customCreature->C_AddAddRankValue = itr->AddRankValue;
customCreature->C_KillRewGameObject = itr->KillRewGameObject;
customCreature->RandSpellGroupId = itr->RandSpellGroupId;
break;
}
}
customCreature->C_KillRewId = modTemplate->KillRewId;
customCreature->C_KillRewChance = modTemplate->KillRewChance;
customCreature->C_KillGroupRewId = modTemplate->KillGroupRewId;
customCreature->C_KillGroupRewChance = modTemplate->KillGroupRewChance;
customCreature->C_KillAnnounce = modTemplate->KillAnnounce;
customCreature->C_Armor = modTemplate->Armor;
customCreature->C_AttackTime = modTemplate->AttackTime;
customCreature->C_ResetDistance = modTemplate->ResetDistance;
customCreature->C_AddTalismanValue = modTemplate->AddTalismanValue;
customCreature->C_AddAddRankValue = modTemplate->AddRankValue;
customCreature->C_KillRewGameObject = modTemplate->KillRewGameObject;
customCreature->RandSpellGroupId = modTemplate->RandSpellGroupId;
}
// ResetReactStateEvent 定义
@ -164,53 +180,40 @@ private:
void CreatureMod::CreatureReset(Creature* creature, uint32 diff)
{
// 首先判断生物是否为空,如果是,则直接返回
if (!creature || !creature->IsInWorld())
if (!creature || !creature->IsInWorld() || !creature->IsInCombat())
return;
//生物不在战斗中 直接返回
if (!creature->IsInCombat())
return;
// 检查附近是否有玩家(可选优化)
Unit* nearestPlayer = creature->SelectNearestTarget(200.0f, true); // 200码内只检查玩家
if (!nearestPlayer)
return; // 附近没有玩家,跳过处理
mod_CustomCreature* customCreature = mod_CustomCreature::GetForCreature(creature);
if (!customCreature || customCreature->C_ResetDistance <= 0) //跳过未设置距离的生物
if (!customCreature || customCreature->C_ResetDistance <= 0)
return;
customCreature->reset_timer += diff; // 重置时间
if (customCreature->reset_timer <= 3000) // 或者考虑更长时间间隔
// 增加更新间隔 - 从每帧检查改为每3秒检查一次
customCreature->reset_timer += diff;
if (customCreature->reset_timer <= 3000)
return;
customCreature->reset_timer = 0;
// 对于副本中的生物,可能需要额外的检查或处理
if (creature->GetMap()->IsDungeon()) {
// 检查是否应该应用不同的重置逻辑
// 可能需要更多的条件来决定是否执行重置,或者如何执行重置
// 例如,检查是否存在特殊机制阻止生物返回,或者生物是否有特殊标志位等
}
// 优化:先检查距离再检查玩家,避免不必要的玩家搜索
float distance = creature->GetHomePosition().GetExactDist2d(creature);
if (distance <= customCreature->C_ResetDistance)
return;
if (distance > customCreature->C_ResetDistance)
{
creature->HandleEmoteCommand(EMOTE_ONESHOT_COWER); // 逃跑表情
creature->Yell("你们跑得太远了!", LANG_UNIVERSAL); // 或者使用更合适的文本
creature->CombatStop(true);
creature->GetThreatMgr().ClearAllThreat();
creature->GetMotionMaster()->MoveTargetedHome();
creature->GetAI()->Reset();
// 只有距离超出时才检查附近玩家
Unit* nearestPlayer = creature->SelectNearestTarget(200.0f, true);
if (!nearestPlayer)
return;
// 设置生物为非攻击状态以防止它立即返回来
creature->SetReactState(REACT_PASSIVE);
// 计划在一段时间后重置生物的反应状态
creature->m_Events.AddEvent(new ResetReactStateEvent(creature), creature->m_Events.CalculateTime(3000)); // 5秒后重置
}
// 执行重置逻辑
creature->HandleEmoteCommand(EMOTE_ONESHOT_COWER);
creature->Yell("你们跑得太远了!", LANG_UNIVERSAL);
creature->CombatStop(true);
creature->GetThreatMgr().ClearAllThreat();
creature->GetMotionMaster()->MoveTargetedHome();
creature->GetAI()->Reset();
creature->SetReactState(REACT_PASSIVE);
creature->m_Events.AddEvent(new ResetReactStateEvent(creature),
creature->m_Events.CalculateTime(3000));
}
@ -221,128 +224,200 @@ public:
void OnPlayerCreatureKill(Player* killer, Creature* killed) override
{
// 确保单位是生物
if (!killed)
if (!killed || !killer)
return;
// 确保击杀者是玩家
if (!killer)
uint32 entry = killed->GetEntry();
uint32 diff = killed->GetMap()->GetDifficulty();
// 使用快速查找替代线性搜索
// 注意这里需要获取ChallengeLv可能需要从killed的map获取
mod_CustomMap* customMap = mod_CustomMap::GetOrCreateCustomMap(killed->GetMap());
if (!customMap)
return;
uint32 Diff = killed->GetMap()->GetDifficulty();
uint32 challengeLv = customMap->challengeLv;
CreautreModTemplate* modTemplate = sCreatureMod->FindTemplate(entry, challengeLv, diff);
if (!modTemplate)
return;
//防止除了 "_属性调整_生物" 以外的生物也会执行代码 造成性能浪费
for (auto itr = CreautreModVec.begin(); itr != CreautreModVec.end(); itr++)
mod_CustomCreature* customCreature = mod_CustomCreature::GetForCreature(killed);
if (!customCreature)
return;
// 处理击杀奖励(保持原有逻辑但优化性能)
ProcessKillRewards(killer, killed, customCreature, modTemplate);
}
private:
void ProcessKillRewards(Player* killer, Creature* killed,
mod_CustomCreature* customCreature,
CreautreModTemplate* modTemplate)
{
// 游戏对象召唤
if (customCreature->C_KillRewGameObject != 0)
killer->SummonGameObject(customCreature->C_KillRewGameObject,
killed->GetPositionX(), killed->GetPositionY(),
killed->GetPositionZ(), killed->GetOrientation(),
0, 0, 0, 0, 0);
// 个人击杀奖励
if (customCreature->C_KillRewId != 0 &&
frand(0, 100) <= customCreature->C_KillRewChance)
sRew->Rew(killer, customCreature->C_KillRewId);
// 队伍奖励处理 - 缓存队伍成员列表
Group* group = killer->GetGroup();
if (group && customCreature->C_KillGroupRewId != 0)
{
if (killed->GetEntry() == itr->Entry && /*ChallengeLv == itr->ChallengeLv &&*/ Diff == itr->Diff)
// 预先收集符合条件的队伍成员,避免重复遍历
std::vector<Player*> eligibleMembers;
eligibleMembers.reserve(group->GetMembersCount()); // 预分配内存
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
{
mod_CustomCreature* customCreature = mod_CustomCreature::GetForCreature(killed);
if (customCreature->C_KillRewGameObject != 0)
killer->SummonGameObject(customCreature->C_KillRewGameObject, killed->GetPositionX(), killed->GetPositionY(), killed->GetPositionZ(), killed->GetOrientation(), 0, 0, 0, 0, 0);
uint32 testentry = killed->GetEntry(); //调试用来查看生物ID
//击杀奖励
if (customCreature->C_KillRewId != 0 && frand(0, 100) <= customCreature->C_KillRewChance)
sRew->Rew(killer, customCreature->C_KillRewId);
//队伍击杀奖励
if (customCreature->C_KillGroupRewId != 0)
if (Group* group = killer->GetGroup())
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
if (Player* member = itr->GetSource())
if (member->IsInWorld() && member->GetGUID() != killer->GetGUID() && frand(0, 100) <= customCreature->C_KillGroupRewChance && member->IsSelfOrInSameMap(killer) && member->GetDistance(killer) <= 200.0f)
sRew->Rew(member, customCreature->C_KillGroupRewId);
CreatureTemplate const* ccc = killed->GetCreatureTemplate();
if (ccc->rank >= 2 && killed->GetMaxHealth() > 3000000)
if (Player* member = itr->GetSource())
{
std::string msg;
if (killer->GetGroup())
msg = sString->Format(sString->GetText(STR_GROUP_KILL_CREATURE), sCF->GetNameLink(killer).c_str(), killed->GetCreatureTemplate()->Name.c_str());
else
msg = sString->Format(sString->GetText(STR_KILL_CREATRE), sCF->GetNameLink(killer).c_str(), killed->GetCreatureTemplate()->Name.c_str());
sCustomWorldData->SendScreenMessage(msg.c_str());
}
//击杀广播
if (customCreature->C_KillAnnounce)
{
std::string msg;
if (killer->GetGroup())
msg = sString->Format(sString->GetText(CORE_STR_TYPES(STR_GROUP_KILL_CREATURE)), sCF->GetNameLink(killer).c_str(), killed->GetCreatureTemplate()->Name.c_str());
else
msg = sString->Format(sString->GetText(CORE_STR_TYPES(STR_KILL_CREATRE)), sCF->GetNameLink(killer).c_str(), killed->GetCreatureTemplate()->Name.c_str());
sCustomWorldData->SendScreenMessage(msg.c_str());
}
//自定义等级值 正数-击杀者 负数-整个队伍
if (customCreature->C_AddAddRankValue > 0)
sRank->Update(killer, customCreature->C_AddAddRankValue, true);
else if (customCreature->C_AddAddRankValue < 0)
{
if (Group* group = killer->GetGroup())
if (member->IsInWorld() && member->GetGUID() != killer->GetGUID() &&
member->IsSelfOrInSameMap(killer) && member->GetDistance(killer) <= 200.0f)
{
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
if (Player* member = itr->GetSource())
if (member->IsInWorld() && member->GetDistance(killer) <= 200.0f)
sRank->Update(member, abs(customCreature->C_AddAddRankValue), true);
eligibleMembers.push_back(member);
}
else
sRank->Update(killer, abs(customCreature->C_AddAddRankValue), true);
}
}
//法宝值 正数-击杀者 负数-整个队伍
if (customCreature->C_AddTalismanValue > 0)
// 统一处理符合条件的成员
for (Player* member : eligibleMembers)
{
if (frand(0, 100) <= customCreature->C_KillGroupRewChance)
sRew->Rew(member, customCreature->C_KillGroupRewId);
}
}
// 优化广播消息处理
ProcessKillAnnouncement(killer, killed, customCreature);
// 处理等级值和法宝值奖励
ProcessRankAndTalismanRewards(killer, killed, customCreature);
// 处理掉落
ProcessCustomLoot(killer, killed, customCreature);
}
void ProcessKillAnnouncement(Player* killer, Creature* killed, mod_CustomCreature* customCreature)
{
// 检查是否需要广播
CreatureTemplate const* cTemplate = killed->GetCreatureTemplate();
bool shouldAnnounce = (cTemplate->rank >= 2 && killed->GetMaxHealth() > 3000000) ||
customCreature->C_KillAnnounce;
if (!shouldAnnounce)
return;
// 缓存常用字符串,避免重复格式化
static std::string killerName;
static std::string creatureName;
killerName = sCF->GetNameLink(killer);
creatureName = killed->GetCreatureTemplate()->Name;
std::string msg;
if (killer->GetGroup())
msg = sString->Format(sString->GetText(STR_GROUP_KILL_CREATURE),
killerName.c_str(), creatureName.c_str());
else
msg = sString->Format(sString->GetText(STR_KILL_CREATRE),
killerName.c_str(), creatureName.c_str());
sCustomWorldData->SendScreenMessage(msg.c_str());
}
void ProcessRankAndTalismanRewards(Player* killer, Creature* killed, mod_CustomCreature* customCreature)
{
Group* group = killer->GetGroup();
// 处理等级值奖励
if (customCreature->C_AddAddRankValue != 0)
{
if (customCreature->C_AddAddRankValue > 0)
{
sRank->Update(killer, customCreature->C_AddAddRankValue, true);
}
else if (group)
{
// 负数表示队伍奖励,预先收集符合条件的成员
std::vector<Player*> nearbyMembers;
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
{
sTalisman->AddTalismanValue(killer, customCreature->C_AddTalismanValue, true);
if (killed->IsDungeonBoss())
if (Player* member = itr->GetSource())
{
sTalisman->SaveTalisManValue(killer, true);
}
}
else if (customCreature->C_AddTalismanValue < 0)
{
if (Group* group = killer->GetGroup())
{
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
if (Player* member = itr->GetSource())
if (member->IsInWorld() && member->GetDistance(killer) <= 200.0f)
{
sTalisman->AddTalismanValue(member, abs(customCreature->C_AddTalismanValue), true);
if (killed->IsDungeonBoss())
{
sTalisman->SaveTalisManValue(killer);
}
}
}
else
{
sTalisman->AddTalismanValue(killer, abs(customCreature->C_AddTalismanValue), true);
if (killed->IsDungeonBoss())
{
sTalisman->SaveTalisManValue(killer);
}
if (member->IsInWorld() && member->GetDistance(killer) <= 200.0f)
nearbyMembers.push_back(member);
}
}
// 是否加载原始掉落 不知道是不是这里造成的队伍中拾取袋子图标
if (!customCreature->C_SrcLoot)
killed->loot.clear(); //清除原始掉落
uint32 rewardValue = abs(customCreature->C_AddAddRankValue);
for (Player* member : nearbyMembers)
sRank->Update(member, rewardValue, true);
}
else
{
sRank->Update(killer, abs(customCreature->C_AddAddRankValue), true);
}
}
// 根据生物的C_LootId数组设置自定义掉落
for (size_t i = 0; i < MAX_CUSTOM_LOOT_COUNT; i++)
if (customCreature->C_LootId[i] > 0)
killed->loot.FillLoot(customCreature->C_LootId[i], LootTemplates_Creature, killer, false, false, killed->GetLootMode());
// 处理法宝值奖励(类似逻辑)
if (customCreature->C_AddTalismanValue != 0)
{
bool isDungeonBoss = killed->IsDungeonBoss();
if (customCreature->C_AddTalismanValue > 0)
{
sTalisman->AddTalismanValue(killer, customCreature->C_AddTalismanValue, true);
if (isDungeonBoss)
sTalisman->SaveTalisManValue(killer, true);
}
else if (group)
{
std::vector<Player*> nearbyMembers;
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
{
if (Player* member = itr->GetSource())
{
if (member->IsInWorld() && member->GetDistance(killer) <= 200.0f)
nearbyMembers.push_back(member);
}
}
uint32 talismanValue = abs(customCreature->C_AddTalismanValue);
for (Player* member : nearbyMembers)
{
sTalisman->AddTalismanValue(member, talismanValue, true);
if (isDungeonBoss)
sTalisman->SaveTalisManValue(member);
}
}
else
{
sTalisman->AddTalismanValue(killer, abs(customCreature->C_AddTalismanValue), true);
if (isDungeonBoss)
sTalisman->SaveTalisManValue(killer);
}
}
}
void ProcessCustomLoot(Player* killer, Creature* killed, mod_CustomCreature* customCreature)
{
// 处理原始掉落
if (!customCreature->C_SrcLoot)
killed->loot.clear();
// 批量处理自定义掉落
for (size_t i = 0; i < MAX_CUSTOM_LOOT_COUNT; i++)
{
if (customCreature->C_LootId[i] > 0)
{
killed->loot.FillLoot(customCreature->C_LootId[i], LootTemplates_Creature,
killer, false, false, killed->GetLootMode());
}
}
}
@ -450,6 +525,23 @@ public:
sCustomScript->CastRandSpell(creature, diff);//额外技能
}
//补丁用@尚美[模块] 20240316 当函数Respawn前调用
virtual void OnModCustomRespawn(Creature* creature)
{
if (!creature)
return;
// 应用属性修改
sCreatureMod->SetMod(creature);
// 获取customCreature并应用数据
mod_CustomCreature* customCreature = mod_CustomCreature::GetForCreature(creature);
if (customCreature)
{
CustomModModifyData(customCreature, creature);
}
}
// 添加生物销毁时的清理
void OnCreatureRemoveWorld(Creature* creature) override
{

View File

@ -28,7 +28,8 @@ struct CreautreModTemplate
uint32 RandSpellGroupId;
uint32 Diff;
};
extern std::vector<CreautreModTemplate> CreautreModVec;
// 新的索引结构 - 三级哈希表
typedef std::unordered_map<uint32, std::unordered_map<uint32, std::unordered_map<uint32, CreautreModTemplate*>>> CreatureModIndex;
class CreatureMod
{
@ -45,7 +46,14 @@ public:
// 生物重置
void CreatureReset(Creature* creature, uint32 diff);
// 快速查找函数
CreautreModTemplate* FindTemplate(uint32 entry, uint32 challengeLv, uint32 diff);
private:
CreatureModIndex _modIndex; // [Entry][ChallengeLv][Diff] -> Template*
std::vector<CreautreModTemplate> _modTemplates; // 存储实际数据
};
#define sCreatureMod CreatureMod::instance()