From 872abdc795434ee276c6798c0be97928dfb43164 Mon Sep 17 00:00:00 2001 From: nytmyr <53322305+nytmyr@users.noreply.github.com> Date: Thu, 12 Dec 2024 15:33:11 -0600 Subject: [PATCH] move bot backstab to mob --- zone/attack.cpp | 3 +- zone/bot.cpp | 28 +++++++++---- zone/bot.h | 3 -- zone/special_attacks.cpp | 85 ++++++++++++++++++++++++++++++---------- 4 files changed, 88 insertions(+), 31 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 4a2e03bbf..fa6e25e06 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -6461,8 +6461,9 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac } else { int ass = TryAssassinate(defender, hit.skill); - if (ass > 0) + if (ass > 0) { hit.damage_done = ass; + } } } else if (hit.skill == EQ::skills::SkillFrenzy && GetClass() == Class::Berserker && GetLevel() > 50) { diff --git a/zone/bot.cpp b/zone/bot.cpp index 56d8a39be..25253c183 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -5383,18 +5383,32 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { } if (skill_to_use == EQ::skills::SkillFrenzy) { - int AtkRounds = 3; + int AtkRounds = 1; + float HasteMod = (FrenzyReuseTime - 1) / (GetHaste() * 0.01f); + reuse = (FrenzyReuseTime * 1000); DoAnim(anim2HSlashing); - reuse = (FrenzyReuseTime * 1000); - did_attack = true; - while(AtkRounds > 0) { - if (GetTarget() && (AtkRounds == 1 || zone->random.Int(0, 100) < 75)) { - DoSpecialAttackDamage(GetTarget(), EQ::skills::SkillFrenzy, dmg, 0, dmg, reuse, true); - } + // bards can do riposte frenzy for some reason + if (!IsRiposte && GetClass() == Class::Berserker) { + int chance = GetLevel() * 2 + GetSkill(EQ::skills::SkillFrenzy); + if (zone->random.Roll0(450) < chance) + AtkRounds++; + if (zone->random.Roll0(450) < chance) + AtkRounds++; + } + while (AtkRounds > 0) { + if (GetTarget() != this) + + DoSpecialAttackDamage(GetTarget(), EQ::skills::SkillFrenzy, dmg, 0, dmg, HasteMod); AtkRounds--; } + + if (reuse > 0 && IsRiposte) { + reuse = 0; + } + + did_attack = true; } if (skill_to_use == EQ::skills::SkillKick) { diff --git a/zone/bot.h b/zone/bot.h index 287721ae9..457f7eebf 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -249,9 +249,6 @@ public: inline uint16 MaxSkill(EQ::skills::SkillType skillid) { return MaxSkill(skillid, GetClass(), GetLevel()); } int GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target = nullptr) override; void DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance = false); - void TryBackstab(Mob *other,int ReuseTime = 10) override; - void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10) override; - void RogueAssassinate(Mob* other) override; void DoClassAttacks(Mob *target, bool IsRiposte=false); void CalcBonuses() override; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 5e9c6f792..cd8b8ac91 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -709,54 +709,78 @@ int Mob::MonkSpecialAttack(Mob *other, uint8 unchecked_type) } void Mob::TryBackstab(Mob *other, int ReuseTime) { - if(!other) + if (!other) { return; + } bool bIsBehind = false; bool bCanFrontalBS = false; //make sure we have a proper weapon if we are a client. - if(IsClient()) { + if (IsClient()) { const EQ::ItemInstance *wpn = CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary); + if (!wpn || (wpn->GetItem()->ItemType != EQ::item::ItemType1HPiercing)){ MessageString(Chat::Red, BACKSTAB_WEAPON); return; } } + else if (IsBot()) { + const EQ::ItemInstance* inst = CastToBot()->GetBotItem(EQ::invslot::slotPrimary); + const EQ::ItemData* botpiercer = nullptr; + + if (inst) { + botpiercer = inst->GetItem(); + } + + if (!botpiercer || (botpiercer->ItemType != EQ::item::ItemType1HPiercing)) { + if (!CastToBot()->GetCombatRoundForAlerts()) { + CastToBot()->SetCombatRoundForAlerts(); + CastToBot()->BotGroupSay(this, "I can't backstab with this weapon!"); + } + + return; + } + } //Live AA - Triple Backstab int tripleChance = itembonuses.TripleBackstab + spellbonuses.TripleBackstab + aabonuses.TripleBackstab; - if (BehindMob(other, GetX(), GetY())) + if (BehindMob(other, GetX(), GetY())) { bIsBehind = true; - + } else { //Live AA - Seized Opportunity int FrontalBSChance = itembonuses.FrontalBackstabChance + spellbonuses.FrontalBackstabChance + aabonuses.FrontalBackstabChance; - if (FrontalBSChance && zone->random.Roll(FrontalBSChance)) + if (FrontalBSChance && zone->random.Roll(FrontalBSChance)) { bCanFrontalBS = true; + } } if (bIsBehind || bCanFrontalBS || (IsNPC() && CanFacestab())) { // Player is behind other OR can do Frontal Backstab - if (bCanFrontalBS && IsClient()) // I don't think there is any message ... - CastToClient()->Message(Chat::White,"Your fierce attack is executed with such grace, your target did not see it coming!"); + if (bCanFrontalBS && IsClient()) { // I don't think there is any message ... + CastToClient()->Message(Chat::White, "Your fierce attack is executed with such grace, your target did not see it coming!"); + } RogueBackstab(other,false,ReuseTime); + if (level >= RuleI(Combat, DoubleBackstabLevelRequirement)) { // TODO: 55-59 doesn't appear to match just checking double attack, 60+ does though - if(IsClient() && CastToClient()->CheckDoubleAttack()) - { - if(other->GetHP() > 0) - RogueBackstab(other,false,ReuseTime); + if(IsOfClientBot() && CastToClient()->CheckDoubleAttack()) { + if (other->GetHP() > 0) { + RogueBackstab(other, false, ReuseTime); + } - if (tripleChance && other->GetHP() > 0 && zone->random.Roll(tripleChance)) - RogueBackstab(other,false,ReuseTime); + if (tripleChance && other->GetHP() > 0 && zone->random.Roll(tripleChance)) { + RogueBackstab(other, false, ReuseTime); + } } } - if(IsClient()) + if (IsClient()) { CastToClient()->CheckIncreaseSkill(EQ::skills::SkillBackstab, other, 10); + } } //Live AA - Chaotic Backstab @@ -766,14 +790,20 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { //we can stab from any angle, we do min damage though. // chaotic backstab can't double etc Seized can, but that's because it's a chance to do normal BS // Live actually added SPA 473 which grants chance to double here when they revamped chaotic/seized + RogueBackstab(other, true, ReuseTime); - if(IsClient()) + + if (IsClient()) { CastToClient()->CheckIncreaseSkill(EQ::skills::SkillBackstab, other, 10); + } + m_specialattacks = eSpecialAttacks::None; int double_bs_front = aabonuses.Double_Backstab_Front + itembonuses.Double_Backstab_Front + spellbonuses.Double_Backstab_Front; - if (double_bs_front && other->GetHP() > 0 && zone->random.Roll(double_bs_front)) + + if (double_bs_front && other->GetHP() > 0 && zone->random.Roll(double_bs_front)) { RogueBackstab(other, false, ReuseTime); + } } else { //We do a single regular attack if we attack from the front without chaotic stab Attack(other, EQ::invslot::slotPrimary); @@ -790,10 +820,25 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) // make sure we can hit (bane, magical, etc) if (IsClient()) { - const EQ::ItemInstance *wpn = CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary); - if (!GetWeaponDamage(other, wpn)) + const EQ::ItemInstance* wpn = CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary); + + if (!GetWeaponDamage(other, wpn)) { return; - } else if (!GetWeaponDamage(other, (const EQ::ItemData*)nullptr)){ + } + } + else if (IsBot()) { + EQ::ItemInstance* botweaponInst = CastToBot()->GetBotItem(EQ::invslot::slotPrimary); + + if (botweaponInst) { + if (!GetWeaponDamage(other, botweaponInst)) { + return; + } + } + else if (!GetWeaponDamage(other, (const EQ::ItemData*)nullptr)) { + return; + } + } + else if (!GetWeaponDamage(other, (const EQ::ItemData*)nullptr)) { return; } @@ -2454,7 +2499,7 @@ int Mob::TryAssassinate(Mob *defender, EQ::skills::SkillType skillInUse) int chance = GetDEX(); if (skillInUse == EQ::skills::SkillBackstab) { chance = 100 * chance / (chance + 3500); - if (IsClient() || IsBot()) { + if (IsOfClientBot()) { chance += GetHeroicDEX(); } chance *= 10;