优化[属性调整_生物]性能
1、移除CreautreModVec,使用三级哈希表利用FindTemplate快速查询 2、增加 OnModCustomRespawn 自定义钩子,处理生物刷新时的属性应用
This commit is contained in:
parent
b96a351035
commit
1ad0565da2
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user