[Combat] Implemented rule for live like Riposte mechanics (#1927)

* Live like Riposte

* [Combat] Implemented rule for live like Riposte mechanics

bot fix
This commit is contained in:
KayenEQ 2022-01-15 19:37:47 -05:00 committed by GitHub
parent 91aa950304
commit 5f482a9b30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 25 additions and 11 deletions

View File

@ -508,7 +508,7 @@ RULE_INT(Combat, SneakPullAssistRange, 400, "Modified range of assist for sneak
RULE_BOOL(Combat, Classic2HBAnimation, false, "2HB will use the 2 hand piercing animation instead of the overhead slashing animation") RULE_BOOL(Combat, Classic2HBAnimation, false, "2HB will use the 2 hand piercing animation instead of the overhead slashing animation")
RULE_BOOL(Combat, ArcheryConsumesAmmo, true, "Set to false to disable Archery Ammo Consumption") RULE_BOOL(Combat, ArcheryConsumesAmmo, true, "Set to false to disable Archery Ammo Consumption")
RULE_BOOL(Combat, ThrowingConsumesAmmo, true, "Set to false to disable Throwing Ammo Consumption") RULE_BOOL(Combat, ThrowingConsumesAmmo, true, "Set to false to disable Throwing Ammo Consumption")
RULE_BOOL(Combat, ImmuneToEnrageFromRiposteSpellEffect, true, "Set to false to disable SPA 173 SE_RiposteChance from making those with the effect on them immune to enrage") RULE_BOOL(Combat, UseLiveRiposteMechanics, false, "Set to true to disable SPA 173 SE_RiposteChance from making those with the effect on them immune to enrage, can longer riposte from a riposte.")
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(NPC) RULE_CATEGORY(NPC)

View File

@ -433,9 +433,20 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit)
// riposte -- it may seem crazy, but if the attacker has SPA 173 on them, they are immune to Ripo // riposte -- it may seem crazy, but if the attacker has SPA 173 on them, they are immune to Ripo
bool ImmuneRipo = false; bool ImmuneRipo = false;
if (RuleB(Combat, ImmuneToEnrageFromRiposteSpellEffect)) { if (!RuleB(Combat, UseLiveRiposteMechanics)) {
ImmuneRipo = attacker->aabonuses.RiposteChance || attacker->spellbonuses.RiposteChance || attacker->itembonuses.RiposteChance || attacker->IsEnraged(); ImmuneRipo = attacker->aabonuses.RiposteChance || attacker->spellbonuses.RiposteChance || attacker->itembonuses.RiposteChance || attacker->IsEnraged();
} }
/*
Live Riposte Mechanics (~Kayen updated 1/22)
-Ripostes can not trigger another riposte. (Ie. Riposte from defender can't then trigger the attacker to riposte)
-Ripostes can not be 'avoided', only hit or miss.
-Attacker with SPA 173 is not immune to riposte. The defender can riposte against the attackers melee hits.
Legacy Riposte Mechanics
-Ripostes can trigger another riposte
-Attacker with SPA 173 is immune to riposte
-Attacker that is enraged is immune to riposte
*/
// Need to check if we have something in MainHand to actually attack with (or fists) // Need to check if we have something in MainHand to actually attack with (or fists)
if (hit.hand != EQ::invslot::slotRange && (CanThisClassRiposte() || IsEnraged()) && InFront && !ImmuneRipo) { if (hit.hand != EQ::invslot::slotRange && (CanThisClassRiposte() || IsEnraged()) && InFront && !ImmuneRipo) {
@ -1373,25 +1384,27 @@ int Client::DoDamageCaps(int base_damage)
// other is the defender, this is the attacker // other is the defender, this is the attacker
//SYNC WITH: tune.cpp, mob.h TuneDoAttack //SYNC WITH: tune.cpp, mob.h TuneDoAttack
void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts) void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, bool FromRiposte)
{ {
if (!other) if (!other)
return; return;
LogCombat("[{}]::DoAttack vs [{}] base [{}] min [{}] offense [{}] tohit [{}] skill [{}]", GetName(), LogCombat("[{}]::DoAttack vs [{}] base [{}] min [{}] offense [{}] tohit [{}] skill [{}]", GetName(),
other->GetName(), hit.base_damage, hit.min_damage, hit.offense, hit.tohit, hit.skill); other->GetName(), hit.base_damage, hit.min_damage, hit.offense, hit.tohit, hit.skill);
// check to see if we hit.. if (!RuleB(Combat, UseLiveRiposteMechanics)) {
if (other->AvoidDamage(this, hit)) { FromRiposte = false;
}
// check to see if we hit..
if (!FromRiposte && other->AvoidDamage(this, hit)) {
int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough;
if (strike_through && zone->random.Roll(strike_through)) { if (strike_through && zone->random.Roll(strike_through)) {
MessageString(Chat::StrikeThrough, MessageString(Chat::StrikeThrough,
STRIKETHROUGH_STRING); // You strike through your opponents defenses! STRIKETHROUGH_STRING); // You strike through your opponents defenses!
hit.damage_done = 1; // set to one, we will check this to continue hit.damage_done = 1; // set to one, we will check this to continue
} }
// I'm pretty sure you can riposte a riposte
if (hit.damage_done == DMG_RIPOSTED) { if (hit.damage_done == DMG_RIPOSTED) {
DoRiposte(other); DoRiposte(other);
//if (IsDead())
return; return;
} }
LogCombat("Avoided/strikethrough damage with code [{}]", hit.damage_done); LogCombat("Avoided/strikethrough damage with code [{}]", hit.damage_done);
@ -1574,7 +1587,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus); my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus);
DoAttack(other, my_hit, opts); DoAttack(other, my_hit, opts, bRiposte);
} }
else { else {
my_hit.damage_done = DMG_INVULNERABLE; my_hit.damage_done = DMG_INVULNERABLE;
@ -2166,7 +2179,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
my_hit.offense = offense(my_hit.skill); my_hit.offense = offense(my_hit.skill);
my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus); my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus);
DoAttack(other, my_hit, opts); DoAttack(other, my_hit, opts, bRiposte);
other->AddToHateList(this, hate); other->AddToHateList(this, hate);
@ -4822,6 +4835,7 @@ void Mob::DoRiposte(Mob *defender)
} }
defender->Attack(this, EQ::invslot::slotPrimary, true); defender->Attack(this, EQ::invslot::slotPrimary, true);
if (HasDied()) if (HasDied())
return; return;

View File

@ -4906,7 +4906,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus); my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus);
DoAttack(other, my_hit, opts); DoAttack(other, my_hit, opts, FromRiposte);
LogCombat("Final damage after all reductions: [{}]", my_hit.damage_done); LogCombat("Final damage after all reductions: [{}]", my_hit.damage_done);
} else { } else {

View File

@ -195,7 +195,7 @@ public:
// 13 = Primary (default), 14 = secondary // 13 = Primary (default), 14 = secondary
virtual bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, virtual bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) = 0; bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) = 0;
void DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr); void DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr, bool FromRiposte = false);
int MonkSpecialAttack(Mob* other, uint8 skill_used); int MonkSpecialAttack(Mob* other, uint8 skill_used);
virtual void TryBackstab(Mob *other,int ReuseTime = 10); virtual void TryBackstab(Mob *other,int ReuseTime = 10);
bool AvoidDamage(Mob *attacker, DamageHitInfo &hit); bool AvoidDamage(Mob *attacker, DamageHitInfo &hit);