Implement AIBot_spells_by_type to reduce looping when searching for spells

This commit is contained in:
nytmyr
2024-12-22 22:38:52 -06:00
parent 998f34842b
commit 83d41f00d2
4 changed files with 103 additions and 37 deletions
+44 -2
View File
@@ -6061,7 +6061,6 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spe
bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool& stopLogic) { bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool& stopLogic) {
bool isMainGroupMGB = false; bool isMainGroupMGB = false;
Raid* raid = GetStoredRaid();
if (isMainGroupMGB && (GetClass() != Class::Bard)) { if (isMainGroupMGB && (GetClass() != Class::Bard)) {
BotGroupSay( BotGroupSay(
@@ -9718,7 +9717,7 @@ bool Bot::BotHasEnoughMana(uint16 spell_id) {
return true; return true;
} }
bool Bot::IsTargetAlreadyReceivingSpell(Mob* tar, uint16 spell_id) { //TODO bot rewrite - add raid and spell targets bool Bot::IsTargetAlreadyReceivingSpell(Mob* tar, uint16 spell_id) {
if (!tar || !spell_id) { if (!tar || !spell_id) {
return true; return true;
} }
@@ -11971,3 +11970,46 @@ void Bot::CleanBotBlockedBuffs()
} }
} }
} }
std::vector<BotSpells_Struct_wIndex> Bot::BotGetSpellsByType(uint16 spellType) {
if (!AIBot_spells_by_type[spellType].empty()) {
return AIBot_spells_by_type[spellType];
}
else {
spellType = GetParentSpellType(spellType);
return AIBot_spells_by_type[spellType];
}
}
void Bot::AssignBotSpellsToTypes(std::vector<BotSpells_Struct>& AIBot_spells, std::unordered_map<uint16, std::vector<BotSpells_Struct_wIndex>>& AIBot_spells_by_type) {
AIBot_spells_by_type.clear();
for (size_t i = 0; i < AIBot_spells.size(); ++i) {
const auto& spell = AIBot_spells[i];
if (spell.spellid <= 0) {
continue;
}
BotSpells_Struct_wIndex spellWithIndex{
static_cast<uint32>(i),
spell.type,
spell.spellid,
spell.manacost,
spell.time_cancast,
spell.recast_delay,
spell.priority,
spell.resist_adjust,
spell.minlevel,
spell.maxlevel,
spell.min_hp,
spell.max_hp,
spell.bucket_name,
spell.bucket_value,
spell.bucket_comparison
};
AIBot_spells_by_type[spell.type].emplace_back(spellWithIndex);
}
}
+6 -3
View File
@@ -236,6 +236,7 @@ public:
uint16 BotGetSpells(int spellslot) { return AIBot_spells[spellslot].spellid; } uint16 BotGetSpells(int spellslot) { return AIBot_spells[spellslot].spellid; }
uint32 BotGetSpellType(int spellslot) { return AIBot_spells[spellslot].type; } uint32 BotGetSpellType(int spellslot) { return AIBot_spells[spellslot].type; }
uint16 BotGetSpellPriority(int spellslot) { return AIBot_spells[spellslot].priority; } uint16 BotGetSpellPriority(int spellslot) { return AIBot_spells[spellslot].priority; }
std::vector<BotSpells_Struct_wIndex> BotGetSpellsByType(uint16 spellType);
float GetProcChances(float ProcBonus, uint16 hand) override; float GetProcChances(float ProcBonus, uint16 hand) override;
int GetHandToHandDamage(void) override; int GetHandToHandDamage(void) override;
bool TryFinishingBlow(Mob *defender, int64 &damage) override; bool TryFinishingBlow(Mob *defender, int64 &damage) override;
@@ -466,6 +467,7 @@ public:
void SetGroupSpellTargetList(std::vector<Mob*> spellTargetList) { _groupSpellTargetList = spellTargetList; } void SetGroupSpellTargetList(std::vector<Mob*> spellTargetList) { _groupSpellTargetList = spellTargetList; }
Raid* GetStoredRaid() { return _storedRaid; } Raid* GetStoredRaid() { return _storedRaid; }
void SetStoredRaid(Raid* storedRaid) { _storedRaid = storedRaid; } void SetStoredRaid(Raid* storedRaid) { _storedRaid = storedRaid; }
void AssignBotSpellsToTypes(std::vector<BotSpells_Struct>& AIBot_spells, std::unordered_map<uint16, std::vector<BotSpells_Struct_wIndex>>& AIBot_spells_by_type);
bool IsTargetAlreadyReceivingSpell(Mob* tar, uint16 spell_id); bool IsTargetAlreadyReceivingSpell(Mob* tar, uint16 spell_id);
bool DoResistCheck(Mob* target, uint16 spell_id, int32 resist_limit); bool DoResistCheck(Mob* target, uint16 spell_id, int32 resist_limit);
bool DoResistCheckBySpellType(Mob* tar, uint16 spell_id, uint16 spellType); bool DoResistCheckBySpellType(Mob* tar, uint16 spell_id, uint16 spellType);
@@ -622,9 +624,9 @@ public:
static BotSpell GetBestBotSpellForNukeByTargetType(Bot* botCaster, SpellTargetType targetType, uint16 spellType, bool AE = false, Mob* tar = nullptr); static BotSpell GetBestBotSpellForNukeByTargetType(Bot* botCaster, SpellTargetType targetType, uint16 spellType, bool AE = false, Mob* tar = nullptr);
static BotSpell GetBestBotSpellForStunByTargetType(Bot* botCaster, SpellTargetType targetType, uint16 spellType, bool AE = false, Mob* tar = nullptr); static BotSpell GetBestBotSpellForStunByTargetType(Bot* botCaster, SpellTargetType targetType, uint16 spellType, bool AE = false, Mob* tar = nullptr);
static BotSpell GetBestBotWizardNukeSpellByTargetResists(Bot* botCaster, Mob* target, uint16 spellType); static BotSpell GetBestBotWizardNukeSpellByTargetResists(Bot* botCaster, Mob* target, uint16 spellType);
static BotSpell GetDebuffBotSpell(Bot* botCaster, Mob* target); static BotSpell GetDebuffBotSpell(Bot* botCaster, Mob* target, uint16 spellType);
static BotSpell GetBestBotSpellForCure(Bot* botCaster, Mob* target, uint16 spellType); static BotSpell GetBestBotSpellForCure(Bot* botCaster, Mob* target, uint16 spellType);
static BotSpell GetBestBotSpellForResistDebuff(Bot* botCaster, Mob* target); static BotSpell GetBestBotSpellForResistDebuff(Bot* botCaster, Mob* target, uint16 spellType);
static BotSpell GetBestBotSpellForNukeByBodyType(Bot* botCaster, uint8 bodyType, uint16 spellType, bool AE = false, Mob* tar = nullptr); static BotSpell GetBestBotSpellForNukeByBodyType(Bot* botCaster, uint8 bodyType, uint16 spellType, bool AE = false, Mob* tar = nullptr);
static BotSpell GetBestBotSpellForRez(Bot* botCaster, Mob* target, uint16 spellType); static BotSpell GetBestBotSpellForRez(Bot* botCaster, Mob* target, uint16 spellType);
static BotSpell GetBestBotSpellForCharm(Bot* botCaster, Mob* target, uint16 spellType); static BotSpell GetBestBotSpellForCharm(Bot* botCaster, Mob* target, uint16 spellType);
@@ -1020,6 +1022,7 @@ protected:
std::vector<BotSpells_Struct> AIBot_spells; std::vector<BotSpells_Struct> AIBot_spells;
std::vector<BotSpells_Struct> AIBot_spells_enforced; std::vector<BotSpells_Struct> AIBot_spells_enforced;
std::unordered_map<uint16, std::vector<BotSpells_Struct_wIndex>> AIBot_spells_by_type;
std::vector<BotTimer_Struct> bot_timers; std::vector<BotTimer_Struct> bot_timers;
std::vector<BotBlockedBuffs_Struct> bot_blocked_buffs; std::vector<BotBlockedBuffs_Struct> bot_blocked_buffs;
@@ -1099,7 +1102,7 @@ private:
bool _commandedSpell; bool _commandedSpell;
bool _pullingSpell; bool _pullingSpell;
std::vector<Mob*> _spellTargetList; // TODO bot rewrite - implement this and raid std::vector<Mob*> _spellTargetList;
std::vector<Mob*> _groupSpellTargetList; std::vector<Mob*> _groupSpellTargetList;
Raid* _storedRaid; Raid* _storedRaid;
+18
View File
@@ -81,6 +81,24 @@ struct BotSpells_Struct {
uint8 bucket_comparison; uint8 bucket_comparison;
}; };
struct BotSpells_Struct_wIndex {
uint32 index; //index of AIBot_spells
uint32 type; // 0 = never, must be one (and only one) of the defined values
int16 spellid; // <= 0 = no spell
int16 manacost; // -1 = use spdat, -2 = no cast time
uint32 time_cancast; // when we can cast this spell next
int32 recast_delay;
int16 priority;
int16 resist_adjust;
uint8 minlevel;
uint8 maxlevel;
int16 min_hp; // >0 won't cast if HP is below
int16 max_hp; // >0 won't cast if HP is above
std::string bucket_name;
std::string bucket_value;
uint8 bucket_comparison;
};
struct BotTimer_Struct { struct BotTimer_Struct {
uint32 timer_id; uint32 timer_id;
uint32 timer_value; uint32 timer_value;
+21 -18
View File
@@ -896,7 +896,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffect(Bot* botCaster, uint16 spell
} }
if (botCaster->AI_HasSpells()) { if (botCaster->AI_HasSpells()) {
std::vector<BotSpells_Struct> botSpellList = botCaster->AIBot_spells; std::vector<BotSpells_Struct_wIndex> botSpellList = botCaster->BotGetSpellsByType(spellType);
for (int i = botSpellList.size() - 1; i >= 0; i--) { for (int i = botSpellList.size() - 1; i >= 0; i--) {
if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) { if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) {
@@ -911,7 +911,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffect(Bot* botCaster, uint16 spell
) { ) {
BotSpell botSpell; BotSpell botSpell;
botSpell.SpellId = botSpellList[i].spellid; botSpell.SpellId = botSpellList[i].spellid;
botSpell.SpellIndex = i; botSpell.SpellIndex = botSpellList[i].index;
botSpell.ManaCost = botSpellList[i].manacost; botSpell.ManaCost = botSpellList[i].manacost;
result.push_back(botSpell); result.push_back(botSpell);
@@ -934,7 +934,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster,
} }
if (botCaster->AI_HasSpells()) { if (botCaster->AI_HasSpells()) {
std::vector<BotSpells_Struct> botSpellList = botCaster->AIBot_spells; std::vector<BotSpells_Struct_wIndex> botSpellList = botCaster->BotGetSpellsByType(spellType);
for (int i = botSpellList.size() - 1; i >= 0; i--) { for (int i = botSpellList.size() - 1; i >= 0; i--) {
if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) { if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) {
@@ -953,7 +953,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster,
) { ) {
BotSpell botSpell; BotSpell botSpell;
botSpell.SpellId = botSpellList[i].spellid; botSpell.SpellId = botSpellList[i].spellid;
botSpell.SpellIndex = i; botSpell.SpellIndex = botSpellList[i].index;
botSpell.ManaCost = botSpellList[i].manacost; botSpell.ManaCost = botSpellList[i].manacost;
result.push_back(botSpell); result.push_back(botSpell);
} }
@@ -975,7 +975,7 @@ std::list<BotSpell> Bot::GetBotSpellsBySpellType(Bot* botCaster, uint16 spellTyp
} }
if (botCaster->AI_HasSpells()) { if (botCaster->AI_HasSpells()) {
std::vector<BotSpells_Struct> botSpellList = botCaster->AIBot_spells; std::vector<BotSpells_Struct_wIndex> botSpellList = botCaster->BotGetSpellsByType(spellType);
for (int i = botSpellList.size() - 1; i >= 0; i--) { for (int i = botSpellList.size() - 1; i >= 0; i--) {
if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) { if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) {
@@ -989,7 +989,7 @@ std::list<BotSpell> Bot::GetBotSpellsBySpellType(Bot* botCaster, uint16 spellTyp
) { ) {
BotSpell botSpell; BotSpell botSpell;
botSpell.SpellId = botSpellList[i].spellid; botSpell.SpellId = botSpellList[i].spellid;
botSpell.SpellIndex = i; botSpell.SpellIndex = botSpellList[i].index;
botSpell.ManaCost = botSpellList[i].manacost; botSpell.ManaCost = botSpellList[i].manacost;
result.push_back(botSpell); result.push_back(botSpell);
@@ -1004,7 +1004,7 @@ std::vector<BotSpell_wPriority> Bot::GetPrioritizedBotSpellsBySpellType(Bot* bot
std::vector<BotSpell_wPriority> result; std::vector<BotSpell_wPriority> result;
if (botCaster && botCaster->AI_HasSpells()) { if (botCaster && botCaster->AI_HasSpells()) {
std::vector<BotSpells_Struct> botSpellList = botCaster->AIBot_spells; std::vector<BotSpells_Struct_wIndex> botSpellList = botCaster->BotGetSpellsByType(spellType);
for (int i = botSpellList.size() - 1; i >= 0; i--) { for (int i = botSpellList.size() - 1; i >= 0; i--) {
if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) { if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) {
@@ -1062,7 +1062,7 @@ std::vector<BotSpell_wPriority> Bot::GetPrioritizedBotSpellsBySpellType(Bot* bot
) { ) {
BotSpell_wPriority botSpell; BotSpell_wPriority botSpell;
botSpell.SpellId = botSpellList[i].spellid; botSpell.SpellId = botSpellList[i].spellid;
botSpell.SpellIndex = i; botSpell.SpellIndex = botSpellList[i].index;
botSpell.ManaCost = botSpellList[i].manacost; botSpell.ManaCost = botSpellList[i].manacost;
botSpell.Priority = botSpellList[i].priority; botSpell.Priority = botSpellList[i].priority;
@@ -1089,7 +1089,7 @@ BotSpell Bot::GetFirstBotSpellBySpellType(Bot* botCaster, uint16 spellType) {
result.ManaCost = 0; result.ManaCost = 0;
if (botCaster && botCaster->AI_HasSpells()) { if (botCaster && botCaster->AI_HasSpells()) {
std::vector<BotSpells_Struct> botSpellList = botCaster->AIBot_spells; std::vector<BotSpells_Struct_wIndex> botSpellList = botCaster->BotGetSpellsByType(spellType);
for (int i = botSpellList.size() - 1; i >= 0; i--) { for (int i = botSpellList.size() - 1; i >= 0; i--) {
if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) { if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) {
@@ -1102,7 +1102,7 @@ BotSpell Bot::GetFirstBotSpellBySpellType(Bot* botCaster, uint16 spellType) {
botCaster->IsValidSpellTypeBySpellID(spellType, botSpellList[i].spellid) botCaster->IsValidSpellTypeBySpellID(spellType, botSpellList[i].spellid)
) { ) {
result.SpellId = botSpellList[i].spellid; result.SpellId = botSpellList[i].spellid;
result.SpellIndex = i; result.SpellIndex = botSpellList[i].index;
result.ManaCost = botSpellList[i].manacost; result.ManaCost = botSpellList[i].manacost;
break; break;
@@ -1197,7 +1197,7 @@ BotSpell Bot::GetBestBotSpellForPercentageHeal(Bot *botCaster, Mob* tar, uint16
result.ManaCost = 0; result.ManaCost = 0;
if (botCaster && botCaster->AI_HasSpells()) { if (botCaster && botCaster->AI_HasSpells()) {
std::vector<BotSpells_Struct> botSpellList = botCaster->AIBot_spells; std::vector<BotSpells_Struct_wIndex> botSpellList = botCaster->BotGetSpellsByType(spellType);
for (int i = botSpellList.size() - 1; i >= 0; i--) { for (int i = botSpellList.size() - 1; i >= 0; i--) {
if (!IsValidSpell(botSpellList[i].spellid)) { if (!IsValidSpell(botSpellList[i].spellid)) {
continue; continue;
@@ -1210,7 +1210,7 @@ BotSpell Bot::GetBestBotSpellForPercentageHeal(Bot *botCaster, Mob* tar, uint16
botCaster->CastChecks(botSpellList[i].spellid, tar, spellType) botCaster->CastChecks(botSpellList[i].spellid, tar, spellType)
) { ) {
result.SpellId = botSpellList[i].spellid; result.SpellId = botSpellList[i].spellid;
result.SpellIndex = i; result.SpellIndex = botSpellList[i].index;
result.ManaCost = botSpellList[i].manacost; result.ManaCost = botSpellList[i].manacost;
break; break;
@@ -1906,7 +1906,7 @@ BotSpell Bot::GetBestBotWizardNukeSpellByTargetResists(Bot* botCaster, Mob* targ
return result; return result;
} }
BotSpell Bot::GetDebuffBotSpell(Bot* botCaster, Mob *tar) { BotSpell Bot::GetDebuffBotSpell(Bot* botCaster, Mob *tar, uint16 spellType) {
BotSpell result; BotSpell result;
result.SpellId = 0; result.SpellId = 0;
@@ -1917,7 +1917,7 @@ BotSpell Bot::GetDebuffBotSpell(Bot* botCaster, Mob *tar) {
return result; return result;
if (botCaster->AI_HasSpells()) { if (botCaster->AI_HasSpells()) {
std::vector<BotSpells_Struct> botSpellList = botCaster->AIBot_spells; std::vector<BotSpells_Struct_wIndex> botSpellList = botCaster->BotGetSpellsByType(spellType);
for (int i = botSpellList.size() - 1; i >= 0; i--) { for (int i = botSpellList.size() - 1; i >= 0; i--) {
if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) { if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) {
@@ -1929,7 +1929,7 @@ BotSpell Bot::GetDebuffBotSpell(Bot* botCaster, Mob *tar) {
&& tar->CanBuffStack(botSpellList[i].spellid, botCaster->GetLevel(), true) >= 0) && tar->CanBuffStack(botSpellList[i].spellid, botCaster->GetLevel(), true) >= 0)
&& botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) { && botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) {
result.SpellId = botSpellList[i].spellid; result.SpellId = botSpellList[i].spellid;
result.SpellIndex = i; result.SpellIndex = botSpellList[i].index;
result.ManaCost = botSpellList[i].manacost; result.ManaCost = botSpellList[i].manacost;
break; break;
@@ -1940,7 +1940,7 @@ BotSpell Bot::GetDebuffBotSpell(Bot* botCaster, Mob *tar) {
return result; return result;
} }
BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar) { BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar, uint16 spellType) {
BotSpell result; BotSpell result;
result.SpellId = 0; result.SpellId = 0;
@@ -1963,7 +1963,7 @@ BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar) {
bool needsDiseaseResistDebuff = (tar->GetDR() + level_mod) > 100; bool needsDiseaseResistDebuff = (tar->GetDR() + level_mod) > 100;
if (botCaster->AI_HasSpells()) { if (botCaster->AI_HasSpells()) {
std::vector<BotSpells_Struct> botSpellList = botCaster->AIBot_spells; std::vector<BotSpells_Struct_wIndex> botSpellList = botCaster->BotGetSpellsByType(spellType);
for (int i = botSpellList.size() - 1; i >= 0; i--) { for (int i = botSpellList.size() - 1; i >= 0; i--) {
if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) { if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) {
@@ -1980,7 +1980,7 @@ BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar) {
&& tar->CanBuffStack(botSpellList[i].spellid, botCaster->GetLevel(), true) >= 0) && tar->CanBuffStack(botSpellList[i].spellid, botCaster->GetLevel(), true) >= 0)
&& botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) { && botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) {
result.SpellId = botSpellList[i].spellid; result.SpellId = botSpellList[i].spellid;
result.SpellIndex = i; result.SpellIndex = botSpellList[i].index;
result.ManaCost = botSpellList[i].manacost; result.ManaCost = botSpellList[i].manacost;
break; break;
@@ -2165,6 +2165,8 @@ bool Bot::AI_AddBotSpells(uint32 bot_spell_id) {
npc_spells_id = bot_spell_id; npc_spells_id = bot_spell_id;
AIBot_spells.clear(); AIBot_spells.clear();
AIBot_spells_enforced.clear(); AIBot_spells_enforced.clear();
AIBot_spells_by_type.clear();
if (!bot_spell_id) { if (!bot_spell_id) {
AIautocastspell_timer->Disable(); AIautocastspell_timer->Disable();
return false; return false;
@@ -2455,6 +2457,7 @@ bool Bot::AI_AddBotSpells(uint32 bot_spell_id) {
AIautocastspell_timer->Disable(); AIautocastspell_timer->Disable();
} else { } else {
AIautocastspell_timer->Trigger(); AIautocastspell_timer->Trigger();
AssignBotSpellsToTypes(AIBot_spells, AIBot_spells_by_type); // Assign AIBot_spells to AIBot_spells_by_type with an index
} }
return true; return true;
} }