From d05dcb5d600c54291f478ebe1c8943bf84f1e2ea Mon Sep 17 00:00:00 2001 From: nytmyr <53322305+nytmyr@users.noreply.github.com> Date: Fri, 20 Dec 2024 21:21:14 -0600 Subject: [PATCH] raid optimizations --- common/ruletypes.h | 8 ++++---- zone/attack.cpp | 4 ++-- zone/bot.cpp | 27 +++++++++++++-------------- zone/bot.h | 8 ++++---- zone/bot_commands/cast.cpp | 4 ++-- zone/bot_commands/depart.cpp | 2 +- zone/botspellsai.cpp | 20 ++++++++++++-------- zone/mob.cpp | 28 ++++++++++++++++------------ zone/mob.h | 2 +- 9 files changed, 55 insertions(+), 48 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index bb7b56340..415b070e8 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -815,10 +815,10 @@ RULE_INT(Bots, PercentChanceToCastGroupCure, 75, "The chance for a bot to attemp RULE_INT(Bots, PercentChanceToCastHateRedux, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.") RULE_INT(Bots, PercentChanceToCastFear, 75, "The chance for a bot to attempt to cast the given spell type in combat. Default 75%.") RULE_INT(Bots, PercentChanceToCastOtherType, 90, "The chance for a bot to attempt to cast the remaining spell types in combat. Default 0-%.") -RULE_INT(Bots, MinDelayBetweenInCombatCastAttempts, 250, "The minimum delay in milliseconds between cast attempts while in-combat. This is rolled between the min and max. Default 250ms.") -RULE_INT(Bots, MaxDelayBetweenInCombatCastAttempts, 2000, "The maximum delay in milliseconds between cast attempts while in-combat. This is rolled between the min and max. Default 2000ms.") -RULE_INT(Bots, MinDelayBetweenOutCombatCastAttempts, 125, "The minimum delay in milliseconds between cast attempts while out-of-combat. This is rolled between the min and max. Default 125ms.") -RULE_INT(Bots, MaxDelayBetweenOutCombatCastAttempts, 500, "The maximum delay in milliseconds between cast attempts while out-of-combat. This is rolled between the min and max. Default 500ms.") +RULE_INT(Bots, MinDelayBetweenInCombatCastAttempts, 500, "The minimum delay in milliseconds between cast attempts while in-combat. This is rolled between the min and max. Default 500ms.") +RULE_INT(Bots, MaxDelayBetweenInCombatCastAttempts, 2000, "The maximum delay in milliseconds between cast attempts while in-combat. This is rolled between the min and max. Default 2500ms.") +RULE_INT(Bots, MinDelayBetweenOutCombatCastAttempts, 1000, "The minimum delay in milliseconds between cast attempts while out-of-combat. This is rolled between the min and max. Default 1000ms.") +RULE_INT(Bots, MaxDelayBetweenOutCombatCastAttempts, 2500, "The maximum delay in milliseconds between cast attempts while out-of-combat. This is rolled between the min and max. Default 2500ms.") RULE_INT(Bots, MezChance, 35, "35 Default. Chance for a bot to attempt to Mez a target after validating it is eligible.") RULE_INT(Bots, AEMezChance, 35, "35 Default. Chance for a bot to attempt to AE Mez targets after validating they are eligible.") RULE_INT(Bots, MezSuccessDelay, 3500, "3500 (3.5 sec) Default. Delay between successful Mez attempts.") diff --git a/zone/attack.cpp b/zone/attack.cpp index d1c862096..130d5e293 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2624,10 +2624,10 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy bool owner_in_group = false; if ( - give_exp->IsInGroupOrRaid(give_exp->GetUltimateOwner(), RuleB(Bots, SameRaidGroupForXP)) || + give_exp->IsInGroupOrRaid(give_exp->GetUltimateOwner(), nullptr, RuleB(Bots, SameRaidGroupForXP)) || give_exp->IsPet() && give_exp->GetOwner() && - give_exp->GetOwner()->IsInGroupOrRaid(give_exp->GetUltimateOwner(), RuleB(Bots, SameRaidGroupForXP)) + give_exp->GetOwner()->IsInGroupOrRaid(give_exp->GetUltimateOwner(), nullptr, RuleB(Bots, SameRaidGroupForXP)) ) { owner_in_group = true; } diff --git a/zone/bot.cpp b/zone/bot.cpp index 616468225..7ec75f3de 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2093,7 +2093,7 @@ void Bot::AI_Process() else { follow_mob = entity_list.GetMob(GetFollowID()); - if (!follow_mob || !IsInGroupOrRaid(follow_mob)) { + if (!follow_mob || !IsInGroupOrRaid(follow_mob, raid)) { follow_mob = leash_owner; } } @@ -2367,7 +2367,7 @@ void Bot::AI_Process() // AUTO DEFEND - if (TryAutoDefend(bot_owner, leash_distance) ) { + if (TryAutoDefend(bot_owner, leash_distance, raid) ) { return; } @@ -2466,7 +2466,7 @@ bool Bot::TryIdleChecks(float fm_distance) { // This is as close as I could get without modifying the aggro mechanics and making it an expensive process... // 'class Client' doesn't make use of hate_list -bool Bot::TryAutoDefend(Client* bot_owner, float leash_distance) { +bool Bot::TryAutoDefend(Client* bot_owner, float leash_distance, Raid* raid) { if (RuleB(Bots, AllowOwnerOptionAutoDefend) && bot_owner->GetBotOption(Client::booAutoDefend)) { @@ -2503,14 +2503,13 @@ bool Bot::TryAutoDefend(Client* bot_owner, float leash_distance) { bool assisteeFound = false; if (IsRaidGrouped()) { - Raid* r = entity_list.GetRaidByBot(this); - if (r) { - for (const auto& m : r->members) { + if (raid) { + for (const auto& m : raid->members) { if ( m.member && m.member->IsClient() && m.member->GetAggroCount() && - r->IsAssister(m.member_name) + raid->IsAssister(m.member_name) ) { temp_xhaters = m.member->GetXTargetAutoMgr(); @@ -2554,7 +2553,7 @@ bool Bot::TryAutoDefend(Client* bot_owner, float leash_distance) { if (bot_owner->GetAssistee()) { Client* c = entity_list.GetClientByCharID(bot_owner->GetAssistee()); - if (bot_owner->IsInGroupOrRaid(c) && c->GetAggroCount()) { + if (bot_owner->IsInGroupOrRaid(c, raid) && c->GetAggroCount()) { tempHaters = bot_owner->GetXTargetAutoMgr(); if (tempHaters && !tempHaters->empty()) { @@ -7222,7 +7221,7 @@ bool Bot::AttemptCloseBeneficialSpells(uint16 spellType, Raid* raid, std::vector } } - result = AttemptAICastSpell(spellType, tar); + result = AttemptAICastSpell(spellType, tar, raid); if (!result) { if (tar->HasPet() && (!m->GetPet()->IsFamiliar() || RuleB(Bots, AllowBuffingHealingFamiliars))) { @@ -7236,7 +7235,7 @@ bool Bot::AttemptCloseBeneficialSpells(uint16 spellType, Raid* raid, std::vector continue; } - result = AttemptAICastSpell(spellType, tar); + result = AttemptAICastSpell(spellType, tar, raid); } } @@ -10810,7 +10809,7 @@ std::list Bot::GetSpellTypesPrioritized(uint8 priorityType) { return castOrder; } -bool Bot::AttemptAICastSpell(uint16 spellType, Mob* tar) { +bool Bot::AttemptAICastSpell(uint16 spellType, Mob* tar, Raid* raid) { bool result = false; if (!tar) { @@ -10834,12 +10833,12 @@ bool Bot::AttemptAICastSpell(uint16 spellType, Mob* tar) { tar = this; } - if (!PrecastChecks(tar, spellType) || !AICastSpell(tar, GetChanceToCastBySpellType(spellType), spellType)) { + if (!PrecastChecks(tar, spellType) || !AICastSpell(tar, GetChanceToCastBySpellType(spellType), spellType, raid)) { return result; } } else { - if (!PrecastChecks(tar, spellType) || !AICastSpell(tar, GetChanceToCastBySpellType(spellType), spellType)) { + if (!PrecastChecks(tar, spellType) || !AICastSpell(tar, GetChanceToCastBySpellType(spellType), spellType, raid)) { return result; } } @@ -10995,7 +10994,7 @@ bool Bot::AttemptForcedCastSpell(Mob* tar, uint16 spell_id) { !RuleB(Bots, EnableBotTGB) && IsGroupSpell(forcedSpellID) && !IsTGBCompatibleSpell(forcedSpellID) && - !IsInGroupOrRaid(tar, true) + !IsInGroupOrRaid(tar, nullptr, true) ) { LogTestDebug("{} failed TGB for {} [#{}].", GetCleanName(), spell.name, forcedSpellID); //deleteme return false; diff --git a/zone/bot.h b/zone/bot.h index 4920e808d..eb7a9ae6c 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -397,8 +397,8 @@ public: void AI_Bot_Event_SpellCastFinished(bool iCastSucceeded, uint16 slot); // AI Methods - bool AICastSpell(Mob* tar, uint8 iChance, uint16 spellType, uint16 subTargetType = UINT16_MAX, uint16 subType = UINT16_MAX); - bool AttemptAICastSpell(uint16 spellType, Mob* tar = nullptr); + bool AICastSpell(Mob* tar, uint8 iChance, uint16 spellType, Raid* raid = nullptr, uint16 subTargetType = UINT16_MAX, uint16 subType = UINT16_MAX); + bool AttemptAICastSpell(uint16 spellType, Mob* tar = nullptr, Raid* raid = nullptr); bool AttemptAACastSpell(Mob* tar, uint16 spell_id, AA::Rank* rank); bool AttemptForcedCastSpell(Mob* tar, uint16 spell_id); bool AttemptCloseBeneficialSpells(uint16 spellType, Raid* raid, std::vector targetList); @@ -597,7 +597,7 @@ public: static std::list GetBotSpellsForSpellEffect(Bot* botCaster, uint16 spellType, int spellEffect); static std::list GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, uint16 spellType, int spellEffect, SpellTargetType targetType); static std::list GetBotSpellsBySpellType(Bot* botCaster, uint16 spellType); - static std::list GetPrioritizedBotSpellsBySpellType(Bot* botCaster, uint16 spellType, Mob* tar, bool AE = false, uint16 subTargetType = UINT16_MAX, uint16 subType = UINT16_MAX); + static std::list GetPrioritizedBotSpellsBySpellType(Bot* botCaster, uint16 spellType, Mob* tar, bool AE = false, Raid* raid = nullptr, uint16 subTargetType = UINT16_MAX, uint16 subType = UINT16_MAX); static BotSpell GetFirstBotSpellBySpellType(Bot* botCaster, uint16 spellType); static BotSpell GetBestBotSpellForVeryFastHeal(Bot* botCaster, Mob* tar, uint16 spellType = BotSpellTypes::RegularHeal); @@ -990,7 +990,7 @@ public: bool TryFacingTarget(Mob* tar); bool TryPursueTarget(float leash_distance, glm::vec3& Goal); bool TryMeditate(); - bool TryAutoDefend(Client* bot_owner, float leash_distance); + bool TryAutoDefend(Client* bot_owner, float leash_distance, Raid* raid = nullptr); bool TryIdleChecks(float fm_distance); bool TryNonCombatMovementChecks(Client* bot_owner, const Mob* follow_mob, glm::vec3& Goal); bool TryBardMovementCasts(); diff --git a/zone/bot_commands/cast.cpp b/zone/bot_commands/cast.cpp index d02c9f2a9..b62162e75 100644 --- a/zone/bot_commands/cast.cpp +++ b/zone/bot_commands/cast.cpp @@ -506,7 +506,7 @@ void bot_command_cast(Client* c, const Seperator* sep) if ( IsBotSpellTypeBeneficial(spellType) && !RuleB(Bots, CrossRaidBuffingAndHealing) && - !bot_iter->IsInGroupOrRaid(newTar, true) + !bot_iter->IsInGroupOrRaid(newTar, nullptr, true) ) { continue; } @@ -588,7 +588,7 @@ void bot_command_cast(Client* c, const Seperator* sep) LogTestDebug("{}: {} says, 'Attempting {} [{}-{}] on [{}]'", __LINE__, bot_iter->GetCleanName(), c->GetSpellTypeNameByID(spellType), (subType != UINT16_MAX ? c->GetSubTypeNameByID(subType) : "Standard"), (subTargetType != UINT16_MAX ? c->GetSubTypeNameByID(subTargetType) : "Standard"), (newTar ? newTar->GetCleanName() : "NOBODY")); //deleteme bot_iter->SetCommandedSpell(true); - if (bot_iter->AICastSpell(newTar, 100, spellType, subTargetType, subType)) { + if (bot_iter->AICastSpell(newTar, 100, spellType, nullptr, subTargetType, subType)) { if (!firstFound) { firstFound = bot_iter; } diff --git a/zone/bot_commands/depart.cpp b/zone/bot_commands/depart.cpp index e7c50156a..6fb4fdb29 100644 --- a/zone/bot_commands/depart.cpp +++ b/zone/bot_commands/depart.cpp @@ -164,7 +164,7 @@ void bot_command_depart(Client* c, const Seperator* sep) std::map> listZones; for (auto bot_iter : sbl) { - if (!bot_iter->IsInGroupOrRaid(tar, !single)) { + if (!bot_iter->IsInGroupOrRaid(tar, nullptr, !single)) { continue; } diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 2df5bfedc..c637f2c89 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -21,7 +21,7 @@ #include "../common/repositories/bot_spells_entries_repository.h" #include "../common/repositories/npc_spells_repository.h" -bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 spellType, uint16 subTargetType, uint16 subType) { +bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 spellType, Raid* raid, uint16 subTargetType, uint16 subType) { if (!tar) { return false; } @@ -217,7 +217,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 spellType, uint16 subTarge break; } - std::list botSpellList = GetPrioritizedBotSpellsBySpellType(this, spellType, tar, (IsAEBotSpellType(spellType) || subTargetType == CommandedSubTypes::AETarget), subTargetType, subType); + std::list botSpellList = GetPrioritizedBotSpellsBySpellType(this, spellType, tar, (IsAEBotSpellType(spellType) || subTargetType == CommandedSubTypes::AETarget), raid, subTargetType, subType); for (const auto& s : botSpellList) { @@ -651,7 +651,7 @@ bool Bot::AI_PursueCastCheck() { continue; } - result = AttemptAICastSpell(currentCast.spellType); + result = AttemptAICastSpell(currentCast.spellType, nullptr, raid); if (!result && IsBotSpellTypeBeneficial(currentCast.spellType)) { result = AttemptCloseBeneficialSpells(currentCast.spellType, raid, v); @@ -725,7 +725,7 @@ bool Bot::AI_IdleCastCheck() { continue; } - result = AttemptAICastSpell(currentCast.spellType); + result = AttemptAICastSpell(currentCast.spellType, nullptr, raid); if (result) { break; @@ -784,7 +784,7 @@ bool Bot::AI_EngagedCastCheck() { continue; } - result = AttemptAICastSpell(currentCast.spellType); + result = AttemptAICastSpell(currentCast.spellType, nullptr, raid); if (!result && IsBotSpellTypeBeneficial(currentCast.spellType)) { result = AttemptCloseBeneficialSpells(currentCast.spellType, raid, v); @@ -1007,9 +1007,13 @@ std::list Bot::GetBotSpellsBySpellType(Bot* botCaster, uint16 spellTyp return result; } -std::list Bot::GetPrioritizedBotSpellsBySpellType(Bot* botCaster, uint16 spellType, Mob* tar, bool AE, uint16 subTargetType, uint16 subType) { +std::list Bot::GetPrioritizedBotSpellsBySpellType(Bot* botCaster, uint16 spellType, Mob* tar, bool AE, Raid* raid, uint16 subTargetType, uint16 subType) { std::list result; + if (!raid) { + raid = botCaster->GetRaid(); + } + if (botCaster && botCaster->AI_HasSpells()) { std::vector botSpellList = botCaster->AIBot_spells; @@ -1050,7 +1054,7 @@ std::list Bot::GetPrioritizedBotSpellsBySpellType(Bot* botCa !RuleB(Bots, EnableBotTGB) && IsGroupSpell(botSpellList[i].spellid) && !IsTGBCompatibleSpell(botSpellList[i].spellid) && - !botCaster->IsInGroupOrRaid(tar, true) + !botCaster->IsInGroupOrRaid(tar, raid, true) ) { continue; } @@ -2009,7 +2013,7 @@ BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar) { return result; } -BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob* tar, uint16 spellType) { +BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob* tar, uint16 spellType) { //TODO bot rewrite - add raid nd target list? BotSpell_wPriority result; result.SpellId = 0; diff --git a/zone/mob.cpp b/zone/mob.cpp index 321ea6af2..1814414e8 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -9897,7 +9897,7 @@ void Mob::ClearDataBucketCache() } } -bool Mob::IsInGroupOrRaid(Mob *other, bool sameRaidGroup) { +bool Mob::IsInGroupOrRaid(Mob *other, Raid* raid, bool sameRaidGroup) { if (!other || !IsOfClientBotMerc() || !other->IsOfClientBotMerc()) { return false; } @@ -9906,29 +9906,33 @@ bool Mob::IsInGroupOrRaid(Mob *other, bool sameRaidGroup) { return true; } - auto* r = GetRaid(); - auto* rO = other->GetRaid(); + if (IsRaidGrouped() && !raid) { + raid = GetRaid(); - if (r) { - if (!rO || r != rO) { + if (!raid) { return false; } + } - auto rG = r->GetGroup(GetCleanName()); - auto rOG = rO->GetGroup(other->GetCleanName()); + if (raid) { + if (!other->IsRaidGrouped()) { + return false; + } + auto rGroup = raid->GetGroup(GetCleanName()); + auto rOGroup = raid->GetGroup(other->GetCleanName()); - if (rG == RAID_GROUPLESS || rOG == RAID_GROUPLESS || (sameRaidGroup && rG != rOG)) { + if (rGroup == RAID_GROUPLESS || rOGroup == RAID_GROUPLESS || (sameRaidGroup && rGroup != rOGroup)) { return false; } return true; } else { - auto* g = GetGroup(); - auto* gO = other->GetGroup(); + auto* group = GetGroup(); + auto* groupOther = other->GetGroup(); - if (g) { - if (!gO || g != gO) { + if (group) { + if (!groupOther || group != groupOther) { return false; } diff --git a/zone/mob.h b/zone/mob.h index e38e13337..90dbd7b0f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -779,7 +779,7 @@ public: virtual bool HasGroup() = 0; virtual Raid* GetRaid() = 0; virtual Group* GetGroup() = 0; - bool IsInGroupOrRaid(Mob* other, bool sameRaidGroup = false); + bool IsInGroupOrRaid(Mob* other, Raid* raid = nullptr, bool sameRaidGroup = false); //Faction virtual inline int32 GetPrimaryFaction() const { return 0; }