mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 05:21:29 +00:00
[Rule] Over Taunt Hate (#3900)
* [Rule] Over taunt hate rule Rule to add additional hate when taunt succeeds. This can help tune snap aggro on taunt classes. Only works when taunt succeeds and not already top hate. * Requested Adjustments * Add default +1 on rule * Revert back to 0 default on rule with +1 on the standard formula * formatting fix
This commit is contained in:
parent
3e958c575b
commit
dfb06db17b
@ -515,6 +515,7 @@ RULE_REAL(Combat, AvgDefProcsPerMinute, 2.0, "Average defense procs per minute")
|
||||
RULE_REAL(Combat, DefProcPerMinAgiContrib, 0.075, "How much agility contributes to defensive proc rate")
|
||||
RULE_INT(Combat, NPCFlurryChance, 20, "Chance for NPC to flurry")
|
||||
RULE_BOOL(Combat, TauntOverLevel, 1, "Allows you to taunt NPC's over warriors level")
|
||||
RULE_INT(Combat, TauntOverAggro, 0, "+ amount over hate_top it will add before any bonus hate.")
|
||||
RULE_REAL(Combat, TauntSkillFalloff, 0.33, "For every taunt skill point that's not maxed you lose this percentage chance to taunt")
|
||||
RULE_BOOL(Combat, EXPFromDmgShield, false, "Determine if damage from a damage shield counts for experience gain")
|
||||
RULE_INT(Combat, QuiverHasteCap, 1000, "Quiver haste cap 1000 on live for a while, currently 700 on live")
|
||||
|
||||
@ -1147,7 +1147,7 @@ public:
|
||||
void StartEnrage();
|
||||
void ProcessEnrage();
|
||||
bool IsEnraged();
|
||||
void Taunt(NPC *who, bool always_succeed, int chance_bonus = 0, bool FromSpell = false, int32 bonus_hate = 0);
|
||||
void Taunt(NPC *who, bool always_succeed, int chance_bonus = 0, bool from_spell = false, int32 bonus_hate = 0);
|
||||
|
||||
virtual void AI_Init();
|
||||
virtual void AI_Start(uint32 iMoveDelay = 0);
|
||||
|
||||
@ -2128,19 +2128,15 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell, int32 bonus_hate)
|
||||
void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool from_spell, int32 bonus_hate)
|
||||
{
|
||||
if (who == nullptr)
|
||||
if (!who || DivineAura() || (!from_spell && !CombatRange(who))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DivineAura())
|
||||
return;
|
||||
|
||||
if (!FromSpell && !CombatRange(who))
|
||||
return;
|
||||
|
||||
if (!always_succeed && IsClient())
|
||||
if (!always_succeed && IsClient()) {
|
||||
CastToClient()->CheckIncreaseSkill(EQ::skills::SkillTaunt, who, 10);
|
||||
}
|
||||
|
||||
Mob *hate_top = who->GetHateMost();
|
||||
|
||||
@ -2148,57 +2144,63 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell,
|
||||
bool success = false;
|
||||
|
||||
// Support for how taunt worked pre 2000 on LIVE - Can not taunt NPC over your level.
|
||||
if ((RuleB(Combat, TauntOverLevel) == false) && (level_difference < 0) ||
|
||||
who->GetSpecialAbility(IMMUNE_TAUNT)) {
|
||||
if (
|
||||
!RuleB(Combat, TauntOverLevel) &&
|
||||
level_difference < 0 ||
|
||||
who->GetSpecialAbility(IMMUNE_TAUNT)
|
||||
) {
|
||||
MessageString(Chat::SpellFailure, FAILED_TAUNT);
|
||||
return;
|
||||
}
|
||||
|
||||
// All values used based on live parses after taunt was updated in 2006.
|
||||
if ((hate_top && hate_top->GetHPRatio() >= 20) || hate_top == nullptr || chance_bonus) {
|
||||
if (
|
||||
(hate_top && hate_top->GetHPRatio() >= 20) ||
|
||||
!hate_top ||
|
||||
chance_bonus
|
||||
) {
|
||||
// SE_Taunt this is flat chance
|
||||
if (chance_bonus) {
|
||||
success = zone->random.Roll(chance_bonus);
|
||||
} else {
|
||||
float tauntchance = 50.0f;
|
||||
|
||||
if (always_succeed)
|
||||
tauntchance = 101.0f;
|
||||
|
||||
else {
|
||||
float taunt_chance = 50.0f;
|
||||
|
||||
if (always_succeed) {
|
||||
taunt_chance = 101.0f;
|
||||
} else {
|
||||
if (level_difference < 0) {
|
||||
tauntchance += static_cast<float>(level_difference) * 3.0f;
|
||||
if (tauntchance < 20)
|
||||
tauntchance = 20.0f;
|
||||
}
|
||||
|
||||
else {
|
||||
tauntchance += static_cast<float>(level_difference) * 5.0f;
|
||||
if (tauntchance > 65)
|
||||
tauntchance = 65.0f;
|
||||
taunt_chance += static_cast<float>(level_difference) * 3.0f;
|
||||
if (taunt_chance < 20) {
|
||||
taunt_chance = 20.0f;
|
||||
}
|
||||
} else {
|
||||
taunt_chance += static_cast<float>(level_difference) * 5.0f;
|
||||
if (taunt_chance > 65) {
|
||||
taunt_chance = 65.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TauntSkillFalloff rate is not based on any real data. Default of 33% gives a reasonable
|
||||
// result.
|
||||
if (IsClient() && !always_succeed)
|
||||
tauntchance -= (RuleR(Combat, TauntSkillFalloff) *
|
||||
if (IsClient() && !always_succeed) {
|
||||
taunt_chance -= (RuleR(Combat, TauntSkillFalloff) *
|
||||
(CastToClient()->MaxSkill(EQ::skills::SkillTaunt) -
|
||||
GetSkill(EQ::skills::SkillTaunt)));
|
||||
}
|
||||
|
||||
if (tauntchance < 1)
|
||||
tauntchance = 1.0f;
|
||||
if (taunt_chance < 1) {
|
||||
taunt_chance = 1.0f;
|
||||
}
|
||||
|
||||
tauntchance /= 100.0f;
|
||||
|
||||
success = tauntchance > zone->random.Real(0, 1);
|
||||
taunt_chance /= 100.0f;
|
||||
success = taunt_chance > zone->random.Real(0, 1);
|
||||
|
||||
LogHate(
|
||||
"Taunter mob {} target npc {} tauntchance [{}] success [{}] hate_top [{}]",
|
||||
"Taunter mob {} target npc {} taunt_chance [{}] success [{}] hate_top [{}]",
|
||||
GetMobDescription(),
|
||||
who->GetMobDescription(),
|
||||
tauntchance,
|
||||
taunt_chance,
|
||||
success ? "true" : "false",
|
||||
hate_top ? hate_top->GetMobDescription() : "not found"
|
||||
);
|
||||
@ -2206,27 +2208,34 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell,
|
||||
|
||||
if (success) {
|
||||
if (hate_top && hate_top != this) {
|
||||
int64 newhate = (who->GetNPCHate(hate_top) - who->GetNPCHate(this)) + 1 + bonus_hate;
|
||||
int64 new_hate = (
|
||||
(who->GetNPCHate(hate_top) - who->GetNPCHate(this)) +
|
||||
bonus_hate +
|
||||
RuleI(Combat, TauntOverAggro) +
|
||||
1
|
||||
);
|
||||
|
||||
LogHate(
|
||||
"Taunter mob {} target npc {} newhate [{}] hated_top {} hate_of_top [{}] this_hate [{}] bonus_hate [{}]",
|
||||
"Not Top Hate - Taunter [{}] Target [{}] Hated Top [{}] Hate Top Amt [{}] This Character Amt [{}] Bonus_Hate Amt [{}] TauntOverAggro Amt [{}] - Total [{}]",
|
||||
GetMobDescription(),
|
||||
who->GetMobDescription(),
|
||||
newhate,
|
||||
hate_top->GetMobDescription(),
|
||||
who->GetNPCHate(hate_top),
|
||||
who->GetNPCHate(this),
|
||||
bonus_hate
|
||||
bonus_hate,
|
||||
RuleI(Combat, TauntOverAggro),
|
||||
new_hate
|
||||
);
|
||||
|
||||
who->CastToNPC()->AddToHateList(this, newhate);
|
||||
who->CastToNPC()->AddToHateList(this, new_hate);
|
||||
success = true;
|
||||
} else {
|
||||
who->CastToNPC()->AddToHateList(this, 12);
|
||||
}
|
||||
|
||||
if (who->CanTalk())
|
||||
if (who->CanTalk()) {
|
||||
who->SayString(SUCCESSFUL_TAUNT, GetCleanName());
|
||||
}
|
||||
} else {
|
||||
MessageString(Chat::SpellFailure, FAILED_TAUNT);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user