diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index e68924844..86a75a545 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -535,37 +535,20 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption if (!target || !caster) return 0; - int ret = 0; - std::list id_list; - auto iterator = list.begin(); - while (iterator != list.end()) - { - struct_HateList *h = (*iterator); - ++iterator; - if (h && h->entity_on_hatelist && h->entity_on_hatelist != caster) - { - if (caster->CombatRange(h->entity_on_hatelist)) - { - id_list.push_back(h->entity_on_hatelist->GetID()); - ++ret; + int hit_count = 0; + auto it = list.begin(); + while (it != list.end() && hit_count < count) { + struct_HateList *h = (*it); + 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); } } + ++it; } - std::list::iterator iter = id_list.begin(); - while (iter != id_list.end()) - { - Mob *cur = entity_list.GetMobID((*iter)); - if (cur) - { - for (int i = 0; i < count; ++i) { - caster->Attack(cur, MainPrimary, false, false, false, opts); - } - } - iter++; - } - - return ret; + return hit_count; } void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_center) diff --git a/zone/mob.h b/zone/mob.h index ec705faf7..02d6d3e55 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -170,6 +170,16 @@ public: void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); virtual bool CheckDoubleAttack(bool tripleAttack = false); // mob version doesn't use this flag + // inline process for places where we need to do them outside of the AI_Process + void ProcessAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr) + { + if (target) { + DoMainHandAttackRounds(target, opts); + if (CanThisClassDualWield()) + DoOffHandAttackRounds(target, opts); + } + return; + } //Appearance void SendLevelAppearance(); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index f4a511b7b..c8654849a 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1103,6 +1103,7 @@ void Mob::AI_Process() { if(attack_timer.Check()) { DoMainHandAttackRounds(target); + bool specialed = false; // NPCs can only do one of these a round if (GetSpecialAbility(SPECATK_FLURRY)) { int flurry_chance = GetSpecialAbilityParam(SPECATK_FLURRY, 0); flurry_chance = flurry_chance > 0 ? flurry_chance : RuleI(Combat, NPCFlurryChance); @@ -1134,6 +1135,7 @@ void Mob::AI_Process() { opts.crit_flat = cur; Flurry(&opts); + specialed = true; } } @@ -1154,7 +1156,7 @@ void Mob::AI_Process() { } } - if (GetSpecialAbility(SPECATK_RAMPAGE)) + if (GetSpecialAbility(SPECATK_RAMPAGE) && !specialed) { int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0); rampage_chance = rampage_chance > 0 ? rampage_chance : 20; @@ -1190,10 +1192,11 @@ void Mob::AI_Process() { opts.crit_flat = cur; } Rampage(&opts); + specialed = true; } } - if (GetSpecialAbility(SPECATK_AREA_RAMPAGE)) + if (GetSpecialAbility(SPECATK_AREA_RAMPAGE) && !specialed) { int rampage_chance = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 0); rampage_chance = rampage_chance > 0 ? rampage_chance : 20; @@ -1230,6 +1233,7 @@ void Mob::AI_Process() { } AreaRampage(&opts); + specialed = true; } } } @@ -1974,14 +1978,14 @@ bool Mob::Rampage(ExtraAttackOptions *opts) if (m_target == GetTarget()) continue; if (CombatRange(m_target)) { - Attack(m_target, MainPrimary, false, false, false, opts); + ProcessAttackRounds(m_target, opts); index_hit++; } } } if (RuleB(Combat, RampageHitsTarget) && index_hit < rampage_targets) - Attack(GetTarget(), MainPrimary, false, false, false, opts); + ProcessAttackRounds(GetTarget(), opts); return true; } @@ -1999,9 +2003,8 @@ void Mob::AreaRampage(ExtraAttackOptions *opts) rampage_targets = rampage_targets > 0 ? rampage_targets : 1; index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts); - if(index_hit == 0) { - Attack(GetTarget(), MainPrimary, false, false, false, opts); - } + if(index_hit == 0) + ProcessAttackRounds(GetTarget(), opts); } uint32 Mob::GetLevelCon(uint8 mylevel, uint8 iOtherLevel) {