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 isMainGroupMGB = false;
Raid* raid = GetStoredRaid();
if (isMainGroupMGB && (GetClass() != Class::Bard)) {
BotGroupSay(
@@ -9718,7 +9717,7 @@ bool Bot::BotHasEnoughMana(uint16 spell_id) {
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) {
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; }
uint32 BotGetSpellType(int spellslot) { return AIBot_spells[spellslot].type; }
uint16 BotGetSpellPriority(int spellslot) { return AIBot_spells[spellslot].priority; }
std::vector<BotSpells_Struct_wIndex> BotGetSpellsByType(uint16 spellType);
float GetProcChances(float ProcBonus, uint16 hand) override;
int GetHandToHandDamage(void) override;
bool TryFinishingBlow(Mob *defender, int64 &damage) override;
@@ -466,6 +467,7 @@ public:
void SetGroupSpellTargetList(std::vector<Mob*> spellTargetList) { _groupSpellTargetList = spellTargetList; }
Raid* GetStoredRaid() { return _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 DoResistCheck(Mob* target, uint16 spell_id, int32 resist_limit);
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 GetBestBotSpellForStunByTargetType(Bot* botCaster, SpellTargetType targetType, uint16 spellType, bool AE = false, Mob* tar = nullptr);
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 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 GetBestBotSpellForRez(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_enforced;
std::unordered_map<uint16, std::vector<BotSpells_Struct_wIndex>> AIBot_spells_by_type;
std::vector<BotTimer_Struct> bot_timers;
std::vector<BotBlockedBuffs_Struct> bot_blocked_buffs;
@@ -1099,7 +1102,7 @@ private:
bool _commandedSpell;
bool _pullingSpell;
std::vector<Mob*> _spellTargetList; // TODO bot rewrite - implement this and raid
std::vector<Mob*> _spellTargetList;
std::vector<Mob*> _groupSpellTargetList;
Raid* _storedRaid;
+18
View File
@@ -81,6 +81,24 @@ struct BotSpells_Struct {
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 {
uint32 timer_id;
uint32 timer_value;
+35 -32
View File
@@ -896,7 +896,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffect(Bot* botCaster, uint16 spell
}
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--) {
if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) {
@@ -911,7 +911,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffect(Bot* botCaster, uint16 spell
) {
BotSpell botSpell;
botSpell.SpellId = botSpellList[i].spellid;
botSpell.SpellIndex = i;
botSpell.SpellIndex = botSpellList[i].index;
botSpell.ManaCost = botSpellList[i].manacost;
result.push_back(botSpell);
@@ -934,7 +934,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster,
}
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--) {
if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) {
@@ -953,7 +953,7 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster,
) {
BotSpell botSpell;
botSpell.SpellId = botSpellList[i].spellid;
botSpell.SpellIndex = i;
botSpell.SpellIndex = botSpellList[i].index;
botSpell.ManaCost = botSpellList[i].manacost;
result.push_back(botSpell);
}
@@ -975,7 +975,7 @@ std::list<BotSpell> Bot::GetBotSpellsBySpellType(Bot* botCaster, uint16 spellTyp
}
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--) {
if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) {
@@ -989,7 +989,7 @@ std::list<BotSpell> Bot::GetBotSpellsBySpellType(Bot* botCaster, uint16 spellTyp
) {
BotSpell botSpell;
botSpell.SpellId = botSpellList[i].spellid;
botSpell.SpellIndex = i;
botSpell.SpellIndex = botSpellList[i].index;
botSpell.ManaCost = botSpellList[i].manacost;
result.push_back(botSpell);
@@ -1004,7 +1004,7 @@ std::vector<BotSpell_wPriority> Bot::GetPrioritizedBotSpellsBySpellType(Bot* bot
std::vector<BotSpell_wPriority> result;
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--) {
if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) {
@@ -1062,7 +1062,7 @@ std::vector<BotSpell_wPriority> Bot::GetPrioritizedBotSpellsBySpellType(Bot* bot
) {
BotSpell_wPriority botSpell;
botSpell.SpellId = botSpellList[i].spellid;
botSpell.SpellIndex = i;
botSpell.SpellIndex = botSpellList[i].index;
botSpell.ManaCost = botSpellList[i].manacost;
botSpell.Priority = botSpellList[i].priority;
@@ -1089,7 +1089,7 @@ BotSpell Bot::GetFirstBotSpellBySpellType(Bot* botCaster, uint16 spellType) {
result.ManaCost = 0;
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--) {
if (!IsValidSpellAndLoS(botSpellList[i].spellid, botCaster->HasLoS())) {
@@ -1102,7 +1102,7 @@ BotSpell Bot::GetFirstBotSpellBySpellType(Bot* botCaster, uint16 spellType) {
botCaster->IsValidSpellTypeBySpellID(spellType, botSpellList[i].spellid)
) {
result.SpellId = botSpellList[i].spellid;
result.SpellIndex = i;
result.SpellIndex = botSpellList[i].index;
result.ManaCost = botSpellList[i].manacost;
break;
@@ -1197,7 +1197,7 @@ BotSpell Bot::GetBestBotSpellForPercentageHeal(Bot *botCaster, Mob* tar, uint16
result.ManaCost = 0;
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--) {
if (!IsValidSpell(botSpellList[i].spellid)) {
continue;
@@ -1210,7 +1210,7 @@ BotSpell Bot::GetBestBotSpellForPercentageHeal(Bot *botCaster, Mob* tar, uint16
botCaster->CastChecks(botSpellList[i].spellid, tar, spellType)
) {
result.SpellId = botSpellList[i].spellid;
result.SpellIndex = i;
result.SpellIndex = botSpellList[i].index;
result.ManaCost = botSpellList[i].manacost;
break;
@@ -1906,7 +1906,7 @@ BotSpell Bot::GetBestBotWizardNukeSpellByTargetResists(Bot* botCaster, Mob* targ
return result;
}
BotSpell Bot::GetDebuffBotSpell(Bot* botCaster, Mob *tar) {
BotSpell Bot::GetDebuffBotSpell(Bot* botCaster, Mob *tar, uint16 spellType) {
BotSpell result;
result.SpellId = 0;
@@ -1917,7 +1917,7 @@ BotSpell Bot::GetDebuffBotSpell(Bot* botCaster, Mob *tar) {
return result;
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--) {
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)
&& botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) {
result.SpellId = botSpellList[i].spellid;
result.SpellIndex = i;
result.SpellIndex = botSpellList[i].index;
result.ManaCost = botSpellList[i].manacost;
break;
@@ -1940,7 +1940,7 @@ BotSpell Bot::GetDebuffBotSpell(Bot* botCaster, Mob *tar) {
return result;
}
BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar) {
BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar, uint16 spellType) {
BotSpell result;
result.SpellId = 0;
@@ -1963,7 +1963,7 @@ BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar) {
bool needsDiseaseResistDebuff = (tar->GetDR() + level_mod) > 100;
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--) {
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)
&& botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) {
result.SpellId = botSpellList[i].spellid;
result.SpellIndex = i;
result.SpellIndex = botSpellList[i].index;
result.ManaCost = botSpellList[i].manacost;
break;
@@ -2165,6 +2165,8 @@ bool Bot::AI_AddBotSpells(uint32 bot_spell_id) {
npc_spells_id = bot_spell_id;
AIBot_spells.clear();
AIBot_spells_enforced.clear();
AIBot_spells_by_type.clear();
if (!bot_spell_id) {
AIautocastspell_timer->Disable();
return false;
@@ -2455,6 +2457,7 @@ bool Bot::AI_AddBotSpells(uint32 bot_spell_id) {
AIautocastspell_timer->Disable();
} else {
AIautocastspell_timer->Trigger();
AssignBotSpellsToTypes(AIBot_spells, AIBot_spells_by_type); // Assign AIBot_spells to AIBot_spells_by_type with an index
}
return true;
}
@@ -2630,20 +2633,20 @@ void Bot::AddSpellToBotEnforceList(
HasAISpell = true;
BotSpells_Struct t;
t.priority = iPriority;
t.spellid = iSpellID;
t.type = iType;
t.manacost = iManaCost;
t.recast_delay = iRecastDelay;
t.time_cancast = 0;
t.resist_adjust = iResistAdjust;
t.minlevel = min_level;
t.maxlevel = maxlevel;
t.min_hp = min_hp;
t.max_hp = max_hp;
t.bucket_name = bucket_name;
t.bucket_value = bucket_value;
t.bucket_comparison = bucket_comparison;
t.priority = iPriority;
t.spellid = iSpellID;
t.type = iType;
t.manacost = iManaCost;
t.recast_delay = iRecastDelay;
t.time_cancast = 0;
t.resist_adjust = iResistAdjust;
t.minlevel = min_level;
t.maxlevel = maxlevel;
t.min_hp = min_hp;
t.max_hp = max_hp;
t.bucket_name = bucket_name;
t.bucket_value = bucket_value;
t.bucket_comparison = bucket_comparison;
AIBot_spells_enforced.push_back(t);
}