diff --git a/zone/bot.cpp b/zone/bot.cpp index 0cd7e7272..4d9214c71 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -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 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& AIBot_spells, std::unordered_map>& 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(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); + } +} diff --git a/zone/bot.h b/zone/bot.h index 7edb42517..d2488671b 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -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 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 spellTargetList) { _groupSpellTargetList = spellTargetList; } Raid* GetStoredRaid() { return _storedRaid; } void SetStoredRaid(Raid* storedRaid) { _storedRaid = storedRaid; } + void AssignBotSpellsToTypes(std::vector& AIBot_spells, std::unordered_map>& 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 AIBot_spells; std::vector AIBot_spells_enforced; + std::unordered_map> AIBot_spells_by_type; std::vector bot_timers; std::vector bot_blocked_buffs; @@ -1099,7 +1102,7 @@ private: bool _commandedSpell; bool _pullingSpell; - std::vector _spellTargetList; // TODO bot rewrite - implement this and raid + std::vector _spellTargetList; std::vector _groupSpellTargetList; Raid* _storedRaid; diff --git a/zone/bot_structs.h b/zone/bot_structs.h index 9a05a70e4..22d33957e 100644 --- a/zone/bot_structs.h +++ b/zone/bot_structs.h @@ -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; diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 2f68593ff..5f3c3d784 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -896,7 +896,7 @@ std::list Bot::GetBotSpellsForSpellEffect(Bot* botCaster, uint16 spell } if (botCaster->AI_HasSpells()) { - std::vector botSpellList = botCaster->AIBot_spells; + std::vector 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 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 Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, } if (botCaster->AI_HasSpells()) { - std::vector botSpellList = botCaster->AIBot_spells; + std::vector 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 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 Bot::GetBotSpellsBySpellType(Bot* botCaster, uint16 spellTyp } if (botCaster->AI_HasSpells()) { - std::vector botSpellList = botCaster->AIBot_spells; + std::vector 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 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 Bot::GetPrioritizedBotSpellsBySpellType(Bot* bot std::vector result; if (botCaster && botCaster->AI_HasSpells()) { - std::vector botSpellList = botCaster->AIBot_spells; + std::vector 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 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 botSpellList = botCaster->AIBot_spells; + std::vector 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 botSpellList = botCaster->AIBot_spells; + std::vector 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 botSpellList = botCaster->AIBot_spells; + std::vector 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 botSpellList = botCaster->AIBot_spells; + std::vector 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); }