From b83373491e4f90117bc0b2608d0c4ab9519d5bd5 Mon Sep 17 00:00:00 2001 From: Fryguy Date: Sun, 7 Jan 2024 12:13:17 -0500 Subject: [PATCH] [Rules] PC Push and NPCtoNPC Push (#3879) * [Rules] PC Push and NPCtoNPC Push Added knobs to increase/decrease push for players/clients by percentage. Added toggle to enable or disable (disabled by default) NPCtoNPC push (2013 patch) * Requested Changes * Fix build errors --- common/ruletypes.h | 3 +++ zone/attack.cpp | 33 +++++++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 93992327e..3b92b6aa5 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -516,6 +516,9 @@ RULE_BOOL(Combat, OneProcPerWeapon, true, "If enabled, One proc per weapon per r RULE_BOOL(Combat, ProjectileDmgOnImpact, true, "If enabled, projectiles (i.e. arrows) will hit on impact, instead of instantly") RULE_BOOL(Combat, MeleePush, true, "Enable melee push") RULE_INT(Combat, MeleePushChance, 50, "NPC chance the target will be pushed. Made up, 100 actually isn't that bad") +RULE_REAL(Combat, MeleePushForceClientPercent, 0.00, "Percent to add or remove from push for players") +RULE_REAL(Combat, MeleePushForcePetPercent, 0.00, "Percent to add or remove from push for pets") +RULE_BOOL(Combat, NPCtoNPCPush, false, "Disabled prevents NPC to NPC pushing per the 2013+ patch.") RULE_BOOL(Combat, UseLiveCombatRounds, true, "Turn this false if you don't want to worry about fixing up combat rounds for NPCs") RULE_INT(Combat, NPCAssistCap, 5, "Maximum number of NPC that will assist another NPC at once") RULE_INT(Combat, NPCAssistCapTimer, 6000, "Time a NPC will take to clear assist aggro cap space (milliseconds)") diff --git a/zone/attack.cpp b/zone/attack.cpp index 04f86cc13..e2f9017b9 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4187,8 +4187,9 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons } //send an HP update if we are hurt - if (GetHP() < GetMaxHP()) + if (GetHP() < GetMaxHP()) { SendHPUpdate(); // the OP_Damage actually updates the client in these cases, so we skip the HP update for them + } } //end `if damage was done` //send damage packet... @@ -4196,32 +4197,48 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons auto outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer; a->target = GetID(); - if (attacker == nullptr) + + if (!attacker) { a->source = 0; - else if (attacker->IsClient() && attacker->CastToClient()->GMHideMe()) + } else if (attacker->IsClient() && attacker->CastToClient()->GMHideMe()) { a->source = 0; - else + } else { a->source = attacker->GetID(); + } + a->type = (EQ::ValueWithin(skill_used, EQ::skills::Skill1HBlunt, EQ::skills::Skill2HPiercing)) ? SkillDamageTypes[skill_used] : SkillDamageTypes[EQ::skills::SkillHandtoHand]; // was 0x1c a->damage = damage; a->spellid = spell_id; - if (special == eSpecialAttacks::AERampage) + + if (special == eSpecialAttacks::AERampage) { a->special = 1; - else if (special == eSpecialAttacks::Rampage) + } else if (special == eSpecialAttacks::Rampage) { a->special = 2; - else + } else { a->special = 0; + } + a->hit_heading = attacker ? attacker->GetHeading() : 0.0f; if (RuleB(Combat, MeleePush) && damage > 0 && !IsRooted() && (IsClient() || zone->random.Roll(RuleI(Combat, MeleePushChance)))) { a->force = EQ::skills::GetSkillMeleePushForce(skill_used); + + if (RuleR(Combat, MeleePushForceClientPercent) && IsClient()) { + a->force += a->force * RuleR(Combat, MeleePushForceClientPercent); + } + + if (RuleR(Combat, MeleePushForcePetPercent) && IsPet()) { + a->force += a->force * RuleR(Combat, MeleePushForcePetPercent); + } + if (IsNPC()) { - if (attacker && attacker->IsNPC()) { + if (!RuleB(Combat, NPCtoNPCPush) && attacker && attacker->IsNPC()) { a->force = 0.0f; // 2013 change that disabled NPC vs NPC push } else { a->force *= 0.10f; // force against NPCs is divided by 10 I guess? ex bash is 0.3, parsed 0.03 against an NPC } + if (ForcedMovement == 0 && a->force != 0.0f && position_update_melee_push_timer.Check()) { m_Delta.x += a->force * g_Math.FastSin(a->hit_heading); m_Delta.y += a->force * g_Math.FastCos(a->hit_heading);