diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 8c9dc0a4e..3f6476ba9 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1322,7 +1322,7 @@ struct CombatDamage_Struct /* 11 */ float force; /* 15 */ float meleepush_xy; // see above notes in Action_Struct /* 19 */ float meleepush_z; -/* 23 */ +/* 23 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage }; /* diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 783156a48..4ee6d4ec0 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -658,9 +658,10 @@ namespace RoF OUT(type); OUT(spellid); OUT(damage); - OUT(force) + OUT(force); OUT(meleepush_xy); - OUT(meleepush_z) + OUT(meleepush_z); + OUT(special); FINISH_ENCODE(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index dbf233f44..7319dc98b 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -729,9 +729,10 @@ namespace RoF2 OUT(type); OUT(spellid); OUT(damage); - OUT(force) + OUT(force); OUT(meleepush_xy); - OUT(meleepush_z) + OUT(meleepush_z); + OUT(special); FINISH_ENCODE(); } diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index bc49fe88f..22748af8d 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1487,7 +1487,8 @@ struct CombatDamage_Struct /* 13 */ float force; // cd cc cc 3d /* 17 */ float meleepush_xy; // see above notes in Action_Struct /* 21 */ float meleepush_z; -/* 25 */ uint8 unknown25[5]; // was [9] +/* 25 */ uint8 unknown25; // was [9] +/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage /* 30 */ }; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index eb7c6edfb..adbfbb7fa 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -1517,7 +1517,8 @@ struct CombatDamage_Struct /* 13 */ float force; // cd cc cc 3d /* 17 */ float meleepush_xy; // see above notes in Action_Struct /* 21 */ float meleepush_z; -/* 25 */ uint8 unknown25[5]; // was [9] +/* 25 */ uint8 unknown25; // was [9] +/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage /* 30 */ }; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 1910a96e4..bbd5acd45 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -446,9 +446,10 @@ namespace SoD OUT(type); OUT(spellid); OUT(damage); - OUT(force) + OUT(force); OUT(meleepush_xy); - OUT(meleepush_z) + OUT(meleepush_z); + OUT(special); FINISH_ENCODE(); } diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 816bff323..4e537221c 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1275,7 +1275,8 @@ struct CombatDamage_Struct /* 11 */ float force; // cd cc cc 3d /* 15 */ float meleepush_xy; // see above notes in Action_Struct /* 19 */ float meleepush_z; -/* 23 */ uint8 unknown23[5]; // was [9] +/* 23 */ uint8 unknown23; // was [9] +/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage /* 28 */ }; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 421903970..cb725f6a7 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -426,9 +426,9 @@ namespace SoF OUT(type); OUT(spellid); OUT(damage); - OUT(force) + OUT(force); OUT(meleepush_xy); - OUT(meleepush_z) + OUT(meleepush_z); FINISH_ENCODE(); } diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 49ad7ba3e..d15f20999 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -1253,7 +1253,7 @@ struct CombatDamage_Struct /* 11 */ float force; // cd cc cc 3d /* 15 */ float meleepush_xy; // see above notes in Action_Struct /* 19 */ float meleepush_z; -/* 23 */ uint8 unknown23[5]; // was [9] +/* 23 */ uint8 unknown23[5]; // was [9] this appears unrelated to the stuff the other clients do here? /* 28 */ }; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index ec25aba61..42544f3b9 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -299,6 +299,23 @@ namespace Titanium dest->FastQueuePacket(&in, ack_req); } + ENCODE(OP_Damage) + { + ENCODE_LENGTH_EXACT(CombatDamage_Struct); + SETUP_DIRECT_ENCODE(CombatDamage_Struct, structs::CombatDamage_Struct); + + OUT(target); + OUT(source); + OUT(type); + OUT(spellid); + OUT(damage); + OUT(force); + OUT(meleepush_xy); + OUT(meleepush_z); + + FINISH_ENCODE(); + } + ENCODE(OP_DeleteCharge) { ENCODE_FORWARD(OP_MoveItem); } ENCODE(OP_DeleteItem) diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index 3d8dfbf79..477adf140 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -6,6 +6,7 @@ E(OP_BazaarSearch) E(OP_BecomeTrader) E(OP_ChannelMessage) E(OP_CharInventory) +E(OP_Damage) E(OP_DeleteCharge) E(OP_DeleteItem) E(OP_DeleteSpawn) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 1a786d94a..0e88a2a09 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -581,9 +581,10 @@ namespace UF OUT(type); OUT(spellid); OUT(damage); - OUT(force) + OUT(force); OUT(meleepush_xy); - OUT(meleepush_z) + OUT(meleepush_z); + OUT(special); FINISH_ENCODE(); } diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 882158492..046eb5138 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -1333,7 +1333,8 @@ struct CombatDamage_Struct /* 11 */ float force; // cd cc cc 3d /* 15 */ float meleepush_xy; // see above notes in Action_Struct /* 19 */ float meleepush_z; -/* 23 */ uint8 unknown23[5]; // was [9] +/* 23 */ uint8 unknown23; // was [9] +/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage /* 28 */ }; diff --git a/zone/attack.cpp b/zone/attack.cpp index 868c5ff03..aa17c2355 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1168,7 +1168,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate //note: throughout this method, setting `damage` to a negative is a way to //stop the attack calculations // IsFromSpell added to allow spell effects to use Attack. (Mainly for the Rampage AA right now.) -bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) +bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, int special) { if (!other) { SetTarget(nullptr); @@ -1373,7 +1373,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b SpellFinished(aabonuses.SkillAttackProc[2], other, 10, 0, -1, spells[aabonuses.SkillAttackProc[2]].ResistDiff); } - other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); + other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, true, -1, false, special); if (IsDead()) return false; @@ -1401,7 +1401,7 @@ void Mob::Heal() SendHPUpdate(); } -void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic) +void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { if(dead || IsCorpse()) return; @@ -1425,7 +1425,7 @@ void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes att damage = -5; //do a majority of the work... - CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); + CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic, special); if (damage > 0) { @@ -1719,7 +1719,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att return true; } -bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) +bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, int special) { int damage = 0; @@ -1931,7 +1931,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool damage = -5; if(GetHP() > 0 && !other->HasDied()) { - other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, false); // Not avoidable client already had thier chance to Avoid + other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, true, -1, false, special); // Not avoidable client already had thier chance to Avoid } else return false; @@ -1966,7 +1966,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool return false; } -void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic) { +void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { if(spell_id==0) spell_id = SPELL_UNKNOWN; @@ -2001,7 +2001,7 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack } //do a majority of the work... - CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); + CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic, special); if(damage > 0) { //see if we are gunna start fleeing @@ -3465,7 +3465,7 @@ bool Mob::CheckDoubleAttack() return zone->random.Int(1, 500) <= chance; } -void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, const SkillUseTypes skill_used, bool &avoidable, const int8 buffslot, const bool iBuffTic) { +void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, const SkillUseTypes skill_used, bool &avoidable, const int8 buffslot, const bool iBuffTic, int special) { // This method is called with skill_used=ABJURE for Damage Shield damage. bool FromDamageShield = (skill_used == SkillAbjuration); @@ -3705,6 +3705,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons a->type = SkillDamageTypes[skill_used]; // was 0x1c a->damage = damage; a->spellid = spell_id; + a->special = special; a->meleepush_xy = attacker->GetHeading() * 2.0f; if (RuleB(Combat, MeleePush) && damage > 0 && !IsRooted() && (IsClient() || zone->random.Roll(RuleI(Combat, MeleePushChance)))) { @@ -5109,7 +5110,7 @@ bool Client::CheckDualWield() return zone->random.Int(1, 375) <= chance; } -void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts) +void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int special) { if (!target) return; @@ -5117,23 +5118,23 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts) if (RuleB(Combat, UseLiveCombatRounds)) { // A "quad" on live really is just a successful dual wield where both double attack // The mobs that could triple lost the ability to when the triple attack skill was added in - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, MainPrimary, false, false, false, opts, special); if (CanThisClassDoubleAttack() && CheckDoubleAttack()) - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, MainPrimary, false, false, false, opts, special); return; } if (IsNPC()) { int16 n_atk = CastToNPC()->GetNumberOfAttacks(); if (n_atk <= 1) { - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, MainPrimary, false, false, false, opts, special); } else { for (int i = 0; i < n_atk; ++i) { - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, MainPrimary, false, false, false, opts, special); } } } else { - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, MainPrimary, false, false, false, opts, special); } // we use this random value in three comparisons with different @@ -5144,21 +5145,21 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts) // check double attack, this is NOT the same rules that clients use... && RandRoll < (GetLevel() + NPCDualAttackModifier)) { - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, MainPrimary, false, false, false, opts, special); // lets see if we can do a triple attack with the main hand // pets are excluded from triple and quads... if ((GetSpecialAbility(SPECATK_TRIPLE) || GetSpecialAbility(SPECATK_QUAD)) && !IsPet() && RandRoll < (GetLevel() + NPCTripleAttackModifier)) { - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, MainPrimary, false, false, false, opts, special); // now lets check the quad attack if (GetSpecialAbility(SPECATK_QUAD) && RandRoll < (GetLevel() + NPCQuadAttackModifier)) { - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, MainPrimary, false, false, false, opts, special); } } } } -void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts) +void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int special) { if (!target) return; @@ -5168,9 +5169,9 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts) (RuleB(Combat, UseLiveCombatRounds) && GetSpecialAbility(SPECATK_QUAD))) || GetEquipment(MaterialSecondary) != 0) { if (CheckDualWield()) { - Attack(target, MainSecondary, false, false, false, opts); + Attack(target, MainSecondary, false, false, false, opts, special); if (CanThisClassDoubleAttack() && GetLevel() > 35 && CheckDoubleAttack()) - Attack(target, MainSecondary, false, false, false, opts); + Attack(target, MainSecondary, false, false, false, opts, special); } } } diff --git a/zone/beacon.h b/zone/beacon.h index f7845e91d..a35f6a1ed 100644 --- a/zone/beacon.h +++ b/zone/beacon.h @@ -35,9 +35,9 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; } + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, - ExtraAttackOptions *opts = nullptr) { return false; } + ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; } diff --git a/zone/bot.cpp b/zone/bot.cpp index 052f84973..5e9717c82 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -4632,7 +4632,7 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att return true; } -void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic) { +void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { if(spell_id == 0) spell_id = SPELL_UNKNOWN; @@ -4651,7 +4651,7 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_ entity_list.MessageClose(this, true, 300, MT_Spells, "%s beams a smile at %s", GetCleanName(), from->GetCleanName() ); } - CommonDamage(from, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); + CommonDamage(from, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic, special); if(GetHP() < 0) { if(IsCasting()) InterruptSpell(); @@ -4678,7 +4678,7 @@ void Bot::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic); } -bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { +bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, int special) { if (!other) { SetTarget(nullptr); Log.Out(Logs::General, Logs::Error, "A null Mob object was passed to Bot::Attack for evaluation!"); diff --git a/zone/bot.h b/zone/bot.h index c78abdd8f..aa77c5f59 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -137,9 +137,9 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false); + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, - ExtraAttackOptions *opts = nullptr); + ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } virtual Raid* GetRaid() { return entity_list.GetRaidByMob(this); } diff --git a/zone/client.h b/zone/client.h index 54452f373..4b72ee94e 100644 --- a/zone/client.h +++ b/zone/client.h @@ -215,9 +215,9 @@ public: //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false); + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, - ExtraAttackOptions *opts = nullptr); + ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } virtual Raid* GetRaid() { return entity_list.GetRaidByClient(this); } diff --git a/zone/corpse.h b/zone/corpse.h index 562173e80..a9916f4fd 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -48,8 +48,8 @@ class Corpse : public Mob { /* Corpse: General */ virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; } - virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) { return false; } + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } + virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; } diff --git a/zone/encounter.h b/zone/encounter.h index a2977d7e0..e341fc7ae 100644 --- a/zone/encounter.h +++ b/zone/encounter.h @@ -35,9 +35,9 @@ public: //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; } + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, - ExtraAttackOptions *opts = nullptr) { + ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } virtual bool HasRaid() { return false; } diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 0247b376a..149d8c392 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -545,7 +545,7 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption if (h && h->entity_on_hatelist && h->entity_on_hatelist != caster) { if (caster->CombatRange(h->entity_on_hatelist)) { ++hit_count; - caster->ProcessAttackRounds(h->entity_on_hatelist, opts); + caster->ProcessAttackRounds(h->entity_on_hatelist, opts, 1); } } } diff --git a/zone/merc.cpp b/zone/merc.cpp index 936dfcc68..68907fb5b 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -4445,7 +4445,7 @@ void Merc::DoClassAttacks(Mob *target) { classattack_timer.Start(reuse / HasteModifier); } -bool Merc::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) +bool Merc::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, int special) { if (!other) { SetTarget(nullptr); @@ -4456,7 +4456,7 @@ bool Merc::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, boo return NPC::Attack(other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts); } -void Merc::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic) +void Merc::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { if(IsDead() || IsCorpse()) return; @@ -4464,7 +4464,7 @@ void Merc::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attac if(spell_id==0) spell_id = SPELL_UNKNOWN; - NPC::Damage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); + NPC::Damage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic, special); //Not needed since we're using NPC damage. //CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); diff --git a/zone/merc.h b/zone/merc.h index 9c683ed52..4f52d7367 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -61,9 +61,9 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false); + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, - bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr); + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return false; } virtual bool HasGroup() { return (GetGroup() ? true : false); } virtual Raid* GetRaid() { return 0; } @@ -397,4 +397,4 @@ private: Timer check_target_timer; }; -#endif // MERC_H \ No newline at end of file +#endif // MERC_H diff --git a/zone/mob.h b/zone/mob.h index 20df1ec41..43745351f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -145,7 +145,7 @@ public: uint16 GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg); // 13 = Primary (default), 14 = secondary virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, - bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) = 0; + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) = 0; int MonkSpecialAttack(Mob* other, uint8 skill_used); virtual void TryBackstab(Mob *other,int ReuseTime = 10); void TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand = MainPrimary, int damage = 0); @@ -167,16 +167,16 @@ public: void CommonBreakInvisible(); bool HasDied(); virtual bool CheckDualWield(); - void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); - void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); + void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0); + void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool CheckDoubleAttack(); // inline process for places where we need to do them outside of the AI_Process - void ProcessAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr) + void ProcessAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0) { if (target) { - DoMainHandAttackRounds(target, opts); + DoMainHandAttackRounds(target, opts, special); if (CanThisClassDualWield()) - DoOffHandAttackRounds(target, opts); + DoOffHandAttackRounds(target, opts, special); } return; } @@ -348,7 +348,7 @@ public: bool AffectedBySpellExcludingSlot(int slot, int effect); virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) = 0; virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, - bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) = 0; + bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) = 0; inline virtual void SetHP(int32 hp) { if (hp >= max_hp) cur_hp = max_hp; else cur_hp = hp;} bool ChangeHP(Mob* other, int32 amount, uint16 spell_id = 0, int8 buffslot = -1, bool iBuffTic = false); inline void SetOOCRegen(int32 newoocregen) {oocregen = newoocregen;} @@ -991,7 +991,7 @@ public: bool CheckAATimer(int timer); protected: - void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); + void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, int special = 0); static uint16 GetProcID(uint16 spell_id, uint8 effect_index); float _GetMovementSpeed(int mod) const; int _GetWalkSpeed() const; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 9a483fddd..4be97897a 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1978,14 +1978,14 @@ bool Mob::Rampage(ExtraAttackOptions *opts) if (m_target == GetTarget()) continue; if (CombatRange(m_target)) { - ProcessAttackRounds(m_target, opts); + ProcessAttackRounds(m_target, opts, 2); index_hit++; } } } if (RuleB(Combat, RampageHitsTarget) && index_hit < rampage_targets) - ProcessAttackRounds(GetTarget(), opts); + ProcessAttackRounds(GetTarget(), opts, 2); return true; } @@ -2004,7 +2004,7 @@ void Mob::AreaRampage(ExtraAttackOptions *opts) index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts); if(index_hit == 0) - ProcessAttackRounds(GetTarget(), opts); + ProcessAttackRounds(GetTarget(), opts, 1); } uint32 Mob::GetLevelCon(uint8 mylevel, uint8 iOtherLevel) { diff --git a/zone/npc.h b/zone/npc.h index 7274cccd1..32afd0afd 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -104,9 +104,9 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false); + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, - bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr); + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; }