Add rules (Bots, AICastSpellTypeDelay, Bots, AICastSpellTypeHeldDelay) to prevent spamming of failed spell type AI casts

This commit is contained in:
nytmyr
2025-01-31 15:30:25 -06:00
parent 09bbe87268
commit c5aa1ea06f
5 changed files with 30 additions and 0 deletions
+2
View File
@@ -898,6 +898,8 @@ RULE_STRING(Bots, ZonesWithSpawnLimits, "", "Comma-delimited list of zones where
RULE_STRING(Bots, ZoneSpawnLimits, "", "Comma-delimited list of spawn limits for zones.")
RULE_STRING(Bots, ZonesWithForcedSpawnLimits, "", "Comma-delimited list of zones where bot spawn limits are forced. This will take priority over any other type of spawn limits.")
RULE_STRING(Bots, ZoneForcedSpawnLimits, "", "Comma-delimited list of forced spawn limits for zones.")
RULE_INT(Bots, AICastSpellTypeDelay, 100, "Delay in milliseconds between AI cast attempts for each spell type. Default 100ms")
RULE_INT(Bots, AICastSpellTypeHeldDelay, 2500, "Delay in milliseconds between AI cast attempts for each spell type that is held or disabled. Default 2500ms (2.5s)")
RULE_CATEGORY_END()
RULE_CATEGORY(Chat)
+4
View File
@@ -9434,6 +9434,9 @@ bool Bot::PrecastChecks(Mob* tar, uint16 spell_type) {
LogBotSpellChecksDetail("{} says, 'Running [{}] PreChecks on [{}].'", GetCleanName(), GetSpellTypeNameByID(spell_type), tar->GetCleanName());
if (GetUltimateSpellHold(spell_type, tar)) {
if (!IsCommandedSpell()) {
SetSpellTypeAITimer(spell_type, RuleI(Bots, AICastSpellTypeHeldDelay));
}
LogBotSpellChecksDetail("{} says, 'Cancelling cast of [{}] on [{}] due to GetUltimateSpellHold.'", GetCleanName(), GetSpellTypeNameByID(spell_type), tar->GetCleanName());
return false;
}
@@ -10521,6 +10524,7 @@ void Bot::LoadDefaultBotSettings() {
t.ae_or_group_target_count = GetDefaultSpellTypeAEOrGroupTargetCount(i, bot_stance);
t.announce_cast = GetDefaultSpellTypeAnnounceCast(i, bot_stance);
t.recast_timer.Start();
t.ai_delay.Start();
m_bot_spell_settings.push_back(t);
+2
View File
@@ -637,6 +637,8 @@ public:
inline void SetSpellMaxThreshold(uint16 spell_type, uint8 threshold_value) { m_bot_spell_settings[spell_type].max_threshold = threshold_value; }
inline bool SpellTypeRecastCheck(uint16 spellType) { return !m_bot_spell_settings[spellType].recast_timer.GetRemainingTime(); }
void SetSpellTypeRecastTimer(uint16 spell_type, uint32 recast_time) { m_bot_spell_settings[spell_type].recast_timer.Start(recast_time); }
inline bool SpellTypeAIDelayCheck(uint16 spellType) { return !m_bot_spell_settings[spellType].ai_delay.GetRemainingTime(); }
void SetSpellTypeAITimer(uint16 spell_type, uint32 recast_time) { m_bot_spell_settings[spell_type].ai_delay.Start(recast_time); }
uint16 GetDefaultSpellDelay(uint16 spell_type, uint8 stance = Stance::Balanced);
uint8 GetDefaultSpellMinThreshold(uint16 spell_type, uint8 stance = Stance::Balanced);
uint8 GetDefaultSpellMaxThreshold(uint16 spell_type, uint8 stance = Stance::Balanced);
+1
View File
@@ -131,6 +131,7 @@ struct BotSpellSettings {
uint16 ae_or_group_target_count; // require target count to cast an AE or Group spell type
uint16 announce_cast; // announce when casting a certain spell type
Timer recast_timer; // recast timer based off delay
Timer ai_delay; // spell timer based off delay
};
struct BotSpellTypeOrder {
+21
View File
@@ -663,6 +663,7 @@ bool Bot::AI_PursueCastCheck() {
for (auto& current_cast : cast_order) {
if (current_cast.priority == 0) {
SetSpellTypeAITimer(current_cast.spellType, RuleI(Bots, AICastSpellTypeHeldDelay));
LogBotSpellChecksDetail("{} says, '[{}] is priority 0, skipping.'", GetCleanName(), GetSpellTypeNameByID(current_cast.spellType));
continue;
}
@@ -679,12 +680,18 @@ bool Bot::AI_PursueCastCheck() {
continue;
}
if (!SpellTypeAIDelayCheck(current_cast.spellType)) {
continue;
}
result = AttemptAICastSpell(current_cast.spellType, nullptr);
if (!result && IsBotSpellTypeBeneficial(current_cast.spellType)) {
result = AttemptCloseBeneficialSpells(current_cast.spellType);
}
SetSpellTypeAITimer(current_cast.spellType, RuleI(Bots, AICastSpellTypeDelay));
if (result) {
break;
}
@@ -731,6 +738,7 @@ bool Bot::AI_IdleCastCheck() {
for (auto& current_cast : cast_order) {
if (current_cast.priority == 0) {
SetSpellTypeAITimer(current_cast.spellType, RuleI(Bots, AICastSpellTypeHeldDelay));
LogBotSpellChecksDetail("{} says, '[{}] is priority 0, skipping.'", GetCleanName(), GetSpellTypeNameByID(current_cast.spellType));
continue;
}
@@ -755,6 +763,10 @@ bool Bot::AI_IdleCastCheck() {
continue;
}
if (!SpellTypeAIDelayCheck(current_cast.spellType)) {
continue;
}
result = AttemptAICastSpell(current_cast.spellType, nullptr);
if (result) {
@@ -763,6 +775,8 @@ bool Bot::AI_IdleCastCheck() {
result = AttemptCloseBeneficialSpells(current_cast.spellType);
SetSpellTypeAITimer(current_cast.spellType, RuleI(Bots, AICastSpellTypeDelay));
if (result) {
break;
}
@@ -799,6 +813,7 @@ bool Bot::AI_EngagedCastCheck() {
for (auto& current_cast : cast_order) {
if (current_cast.priority == 0) {
SetSpellTypeAITimer(current_cast.spellType, RuleI(Bots, AICastSpellTypeHeldDelay));
LogBotSpellChecksDetail("{} says, '[{}] is priority 0, skipping.'", GetCleanName(), GetSpellTypeNameByID(current_cast.spellType));
continue;
}
@@ -815,8 +830,14 @@ bool Bot::AI_EngagedCastCheck() {
continue;
}
if (!SpellTypeAIDelayCheck(current_cast.spellType)) {
continue;
}
result = AttemptAICastSpell(current_cast.spellType, nullptr);
SetSpellTypeAITimer(current_cast.spellType, RuleI(Bots, AICastSpellTypeDelay));
if (!result && IsBotSpellTypeBeneficial(current_cast.spellType)) {
result = AttemptCloseBeneficialSpells(current_cast.spellType);
}