[Rule] Add rule for bard aggro cap (#3909)

BardAggroCap - Default 40

Allows adjustment of per song bard aggro cap.
This commit is contained in:
Fryguy 2024-01-08 23:29:24 -05:00 committed by GitHub
parent 98928aee74
commit 8f34bd998f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 52 deletions

View File

@ -625,6 +625,7 @@ RULE_REAL(Aggro, PetAttackRange, 40000.0, "Maximum squared range /pet attack wor
RULE_BOOL(Aggro, NPCAggroMaxDistanceEnabled, true, "If enabled, NPC's will drop aggro beyond 600 units or what is defined at the zone level") RULE_BOOL(Aggro, NPCAggroMaxDistanceEnabled, true, "If enabled, NPC's will drop aggro beyond 600 units or what is defined at the zone level")
RULE_BOOL(Aggro, AggroPlayerPets, false, "If enabled, NPCs will aggro player pets") RULE_BOOL(Aggro, AggroPlayerPets, false, "If enabled, NPCs will aggro player pets")
RULE_BOOL(Aggro, UndeadAlwaysAggro, true, "should undead always aggro?") RULE_BOOL(Aggro, UndeadAlwaysAggro, true, "should undead always aggro?")
RULE_INT(Aggro, BardAggroCap, 40, "per song bard aggro cap.")
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(TaskSystem) RULE_CATEGORY(TaskSystem)

View File

@ -1181,47 +1181,52 @@ bool Mob::CheckLosFN(glm::vec3 posWatcher, float sizeWatcher, glm::vec3 posTarge
} }
//offensive spell aggro //offensive spell aggro
int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc) int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool is_proc)
{ {
if (IsNoDetrimentalSpellAggroSpell(spell_id)) if (IsNoDetrimentalSpellAggroSpell(spell_id)) {
return 0; return 0;
}
int32 AggroAmount = 0; int32 aggro_amount = 0;
int32 nonModifiedAggro = 0; int32 non_modified_aggro = 0;
uint16 slevel = GetLevel(); uint16 mob_level = GetLevel();
bool dispel = false; bool dispel = false;
bool on_hatelist = target ? target->CheckAggro(this) : false; bool on_hatelist = target ? target->CheckAggro(this) : false;
int proc_cap = RuleI(Aggro, MaxScalingProcAggro); int proc_cap = RuleI(Aggro, MaxScalingProcAggro);
int64 hate_cap = isproc && proc_cap != -1 ? proc_cap : 1200; int64 hate_cap = is_proc && proc_cap != -1 ? proc_cap : 1200;
int64 target_hp = target ? target->GetMaxHP() : 18000; // default to max int64 target_hp = target ? target->GetMaxHP() : 18000; // default to max
int64 default_aggro = 25; int64 default_aggro = 25;
if (target_hp >= 18000) // max if (target_hp >= 18000) { // max
default_aggro = hate_cap; default_aggro = hate_cap;
else if (target_hp >= 390) // min, 390 is the first number with int division that is 26 } else if (target_hp >= 390) { // min, 390 is the first number with int division that is 26
default_aggro = target_hp / 15; default_aggro = target_hp / 15;
}
for (int o = 0; o < EFFECT_COUNT; o++) { for (int o = 0; o < EFFECT_COUNT; o++) {
switch (spells[spell_id].effect_id[o]) { switch (spells[spell_id].effect_id[o]) {
case SE_CurrentHPOnce: case SE_CurrentHPOnce:
case SE_CurrentHP: { case SE_CurrentHP: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], slevel, spell_id); int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if(val < 0) if(val < 0) {
AggroAmount -= val; aggro_amount -= val;
}
break; break;
} }
case SE_MovementSpeed: { case SE_MovementSpeed: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], slevel, spell_id); int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 0) if (val < 0) {
AggroAmount += default_aggro; aggro_amount += default_aggro;
}
break; break;
} }
case SE_AttackSpeed: case SE_AttackSpeed:
case SE_AttackSpeed2: case SE_AttackSpeed2:
case SE_AttackSpeed3: { case SE_AttackSpeed3: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], slevel, spell_id); int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 100) if (val < 100) {
AggroAmount += default_aggro; aggro_amount += default_aggro;
}
break; break;
} }
case SE_Stun: case SE_Stun:
@ -1230,16 +1235,17 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc)
case SE_Charm: case SE_Charm:
case SE_Fear: case SE_Fear:
case SE_Fearstun: case SE_Fearstun:
AggroAmount += default_aggro; aggro_amount += default_aggro;
break; break;
case SE_Root: case SE_Root:
AggroAmount += 10; aggro_amount += 10;
break; break;
case SE_ACv2: case SE_ACv2:
case SE_ArmorClass: { case SE_ArmorClass: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], slevel, spell_id); int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 0) if (val < 0) {
AggroAmount += default_aggro; aggro_amount += default_aggro;
}
break; break;
} }
case SE_ATK: case SE_ATK:
@ -1255,31 +1261,34 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc)
case SE_INT: case SE_INT:
case SE_WIS: case SE_WIS:
case SE_CHA: { case SE_CHA: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], slevel, spell_id); int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 0) if (val < 0) {
AggroAmount += 10; aggro_amount += 10;
}
break; break;
} }
case SE_ResistAll: { case SE_ResistAll: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], slevel, spell_id); int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 0) if (val < 0) {
AggroAmount += 50; aggro_amount += 50;
}
break; break;
} }
case SE_AllStats: { case SE_AllStats: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], slevel, spell_id); int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 0) if (val < 0) {
AggroAmount += 70; aggro_amount += 70;
}
break; break;
} }
case SE_BardAEDot: case SE_BardAEDot:
AggroAmount += 10; aggro_amount += 10;
break; break;
case SE_SpinTarget: case SE_SpinTarget:
case SE_Amnesia: case SE_Amnesia:
case SE_Silence: case SE_Silence:
case SE_Destroy: case SE_Destroy:
AggroAmount += default_aggro; aggro_amount += default_aggro;
break; break;
// unsure -- leave them this for now // unsure -- leave them this for now
case SE_Harmony: case SE_Harmony:
@ -1301,7 +1310,7 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc)
case SE_DamageShield: case SE_DamageShield:
case SE_SpellDamageShield: case SE_SpellDamageShield:
case SE_ReverseDS: { case SE_ReverseDS: {
AggroAmount += slevel * 2; aggro_amount += mob_level * 2;
break; break;
} }
// unsure -- leave them this for now // unsure -- leave them this for now
@ -1309,9 +1318,10 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc)
case SE_ManaRegen_v2: case SE_ManaRegen_v2:
case SE_ManaPool: case SE_ManaPool:
case SE_CurrentEndurance: { case SE_CurrentEndurance: {
int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], slevel, spell_id); int64 val = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
if (val < 0) if (val < 0) {
AggroAmount -= val * 2; aggro_amount -= val * 2;
}
break; break;
} }
case SE_CancelMagic: case SE_CancelMagic:
@ -1321,37 +1331,41 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc)
break; break;
case SE_ReduceHate: case SE_ReduceHate:
case SE_InstantHate: case SE_InstantHate:
nonModifiedAggro = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], slevel, spell_id); non_modified_aggro = CalcSpellEffectValue_formula(spells[spell_id].formula[o], spells[spell_id].base_value[o], spells[spell_id].max_value[o], mob_level, spell_id);
break; break;
} }
} }
if (IsBardSong(spell_id) && AggroAmount > 40) if (IsBardSong(spell_id) && aggro_amount > RuleI(Aggro, BardAggroCap)) {
AggroAmount = 40; // bard songs seem to cap to 40 for most of their spells? aggro_amount = RuleI(Aggro, BardAggroCap);
}
if (dispel && target && target->GetHateAmount(this) < 100) if (dispel && target && target->GetHateAmount(this) < 100) {
AggroAmount += 50; aggro_amount += 50;
}
if (spells[spell_id].hate_added != 0) // overrides the hate (ex. tash), can be negative. if (spells[spell_id].hate_added != 0) { // overrides the hate (ex. tash), can be negative.
AggroAmount = spells[spell_id].hate_added; aggro_amount = spells[spell_id].hate_added;
}
if (GetOwner() && IsPet() && AggroAmount > 0) if (GetOwner() && IsPet() && aggro_amount > 0) {
AggroAmount = AggroAmount * RuleI(Aggro, PetSpellAggroMod) / 100; aggro_amount = aggro_amount * RuleI(Aggro, PetSpellAggroMod) / 100;
}
// hate focus ignored on first action for some reason // hate focus ignored on first action for some reason
if (!on_hatelist && AggroAmount > 0) { if (!on_hatelist && aggro_amount > 0) {
int HateMod = RuleI(Aggro, SpellAggroMod); int HateMod = RuleI(Aggro, SpellAggroMod);
HateMod += GetFocusEffect(focusSpellHateMod, spell_id); HateMod += GetFocusEffect(focusSpellHateMod, spell_id);
aggro_amount = (aggro_amount * HateMod) / 100;
AggroAmount = (AggroAmount * HateMod) / 100;
} }
// initial aggro gets a bonus 100 besides for dispel or hate override // initial aggro gets a bonus 100 besides for dispel or hate override
// We add this 100 in AddToHateList so we need to account for the oddities here // We add this 100 in AddToHateList so we need to account for the oddities here
if (dispel && spells[spell_id].hate_added > 0 && !on_hatelist) if (dispel && spells[spell_id].hate_added > 0 && !on_hatelist) {
AggroAmount -= 100; aggro_amount -= 100;
}
return AggroAmount + spells[spell_id].bonus_hate + nonModifiedAggro; return aggro_amount + spells[spell_id].bonus_hate + non_modified_aggro;
} }
//healing and buffing aggro //healing and buffing aggro