diff --git a/zone/attack.cpp b/zone/attack.cpp index e2f9017b9..090ead500 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2119,6 +2119,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool } RemoveFromHateList(other); + RemoveFromRampageList(other); LogCombat("I am not allowed to attack [{}]", other->GetName()); return false; } diff --git a/zone/bot.cpp b/zone/bot.cpp index 8cb7760b7..fb3fda203 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2783,10 +2783,12 @@ bool Bot::IsValidTarget(Client* bot_owner, Client* leash_owner, float lo_distanc // Normally, we wouldn't want to do this without class checks..but, too many issues can arise if we let enchanter animation pets run rampant if (HasPet()) { GetPet()->RemoveFromHateList(tar); + GetPet()->RemoveFromRampageList(tar); GetPet()->SetTarget(nullptr); } RemoveFromHateList(tar); + RemoveFromRampageList(tar); SetTarget(nullptr); SetAttackFlag(false); diff --git a/zone/entity.cpp b/zone/entity.cpp index cabe9d31c..0689d6ac7 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1491,18 +1491,21 @@ void EntityList::RemoveFromTargets(Mob *mob, bool RemoveFromXTargets) Mob *m = it->second; ++it; - if (!m) + if (!m) { continue; + } if (RemoveFromXTargets && mob) { - if (m->IsClient() && (mob->CheckAggro(m) || mob->IsOnFeignMemory(m))) + if (m->IsClient() && (mob->CheckAggro(m) || mob->IsOnFeignMemory(m))) { m->CastToClient()->RemoveXTarget(mob, false); // FadingMemories calls this function passing the client. - else if (mob->IsClient() && (m->CheckAggro(mob) || m->IsOnFeignMemory(mob))) + } else if (mob->IsClient() && (m->CheckAggro(mob) || m->IsOnFeignMemory(mob))) { mob->CastToClient()->RemoveXTarget(m, false); + } } m->RemoveFromHateList(mob); + m->RemoveFromRampageList(mob); } } @@ -1515,20 +1518,24 @@ void EntityList::RemoveFromTargetsFadingMemories(Mob *spell_target, bool RemoveF continue; } - if (max_level && mob->GetLevel() > max_level) + if (max_level && mob->GetLevel() > max_level) { continue; + } - if (mob->GetSpecialAbility(IMMUNE_FADING_MEMORIES)) + if (mob->GetSpecialAbility(IMMUNE_FADING_MEMORIES)) { continue; + } if (RemoveFromXTargets && spell_target) { - if (mob->IsClient() && (spell_target->CheckAggro(mob) || spell_target->IsOnFeignMemory(mob))) + if (mob->IsClient() && (spell_target->CheckAggro(mob) || spell_target->IsOnFeignMemory(mob))) { mob->CastToClient()->RemoveXTarget(spell_target, false); - else if (spell_target->IsClient() && (mob->CheckAggro(spell_target) || mob->IsOnFeignMemory(spell_target))) + } else if (spell_target->IsClient() && (mob->CheckAggro(spell_target) || mob->IsOnFeignMemory(spell_target))) { spell_target->CastToClient()->RemoveXTarget(mob, false); + } } mob->RemoveFromHateList(spell_target); + mob->RemoveFromRampageList(spell_target); } } @@ -3188,8 +3195,10 @@ void EntityList::RemoveFromHateLists(Mob *mob, bool settoone) if (it->second->CheckAggro(mob)) { if (!settoone) { it->second->RemoveFromHateList(mob); - if (mob->IsClient()) + it->second->RemoveFromRampageList(mob); + if (mob->IsClient()) { mob->CastToClient()->RemoveXTarget(it->second, false); // gotta do book keeping + } } else { it->second->SetHateAmountOnEnt(mob, 1); } @@ -3548,8 +3557,11 @@ void EntityList::ClearAggro(Mob* targ) if (c) { c->RemoveXTarget(it->second, false); } + it->second->RemoveFromHateList(targ); + it->second->RemoveFromRampageList(targ, true); } + if (c && it->second->IsOnFeignMemory(c)) { it->second->RemoveFromFeignMemory(c); //just in case we feigned c->RemoveXTarget(it->second, false); @@ -3573,6 +3585,7 @@ void EntityList::ClearWaterAggro(Mob* targ) c->RemoveXTarget(it->second, false); } it->second->RemoveFromHateList(targ); + it->second->RemoveFromRampageList(targ); } if (c && it->second->IsOnFeignMemory(c)) { it->second->RemoveFromFeignMemory(c); //just in case we feigned @@ -3618,6 +3631,11 @@ void EntityList::ClearFeignAggro(Mob *targ) } it->second->RemoveFromHateList(targ); + + if (it->second->GetSpecialAbility(SPECATK_RAMPAGE)) { + it->second->RemoveFromRampageList(targ, true); + } + if (targ->IsClient()) { if (it->second->GetLevel() >= 35 && zone->random.Roll(60)) { it->second->AddFeignMemory(targ); diff --git a/zone/mob.h b/zone/mob.h index e5ce8f513..78dcd97c2 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1137,6 +1137,7 @@ public: bool Rampage(ExtraAttackOptions *opts); bool AddRampage(Mob*); void ClearRampage(); + void RemoveFromRampageList(Mob* mob, bool remove_feigned = false); void SetBottomRampageList(); void SetTopRampageList(); void AreaRampage(ExtraAttackOptions *opts); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 5440cef28..ad9c927f3 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -778,6 +778,7 @@ void Client::AI_Process() if (GetTarget()->IsCorpse()) { RemoveFromHateList(this); + RemoveFromRampageList(this); return; } @@ -1089,6 +1090,7 @@ void Mob::AI_Process() { if (target->IsCorpse()) { RemoveFromHateList(this); + RemoveFromRampageList(this); return; } @@ -2062,6 +2064,32 @@ void Mob::ClearRampage() RampageArray.clear(); } +void Mob::RemoveFromRampageList(Mob* mob, bool remove_feigned) +{ + if (!mob) { + return; + } + + if ( + IsNPC() && + GetSpecialAbility(SPECATK_RAMPAGE) && + ( + remove_feigned || + mob->IsNPC() || + ( + mob->IsClient() && + !mob->CastToClient()->GetFeigned() + ) + ) + ) { + for (int i = 0; i < RampageArray.size(); i++) { + if (mob->GetID() == RampageArray[i]) { + RampageArray[i] = 0; + } + } + } +} + bool Mob::Rampage(ExtraAttackOptions *opts) { int index_hit = 0; @@ -2083,8 +2111,16 @@ bool Mob::Rampage(ExtraAttackOptions *opts) // range is important Mob *m_target = entity_list.GetMob(RampageArray[i]); if (m_target) { - if (m_target == GetTarget()) + if (m_target == GetTarget()) { continue; + } + + if (m_target->IsCorpse()) { + LogAggroDetail("[{}] is on [{}]'s rampage list", m_target->GetCleanName(), GetCleanName()); + RemoveFromRampageList(m_target, true); + continue; + } + if (DistanceSquaredNoZ(GetPosition(), m_target->GetPosition()) <= NPC_RAMPAGE_RANGE2) { ProcessAttackRounds(m_target, opts); index_hit++; diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index e715ec14f..2b681434a 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -204,6 +204,7 @@ bool Perl_NPC_IsOnHatelist(NPC* self, Mob* mob) // @categories Hate and Aggro void Perl_NPC_RemoveFromHateList(NPC* self, Mob* mob) // @categories Hate and Aggro { self->RemoveFromHateList(mob); + self->RemoveFromRampageList(mob); } void Perl_NPC_SetNPCFactionID(NPC* self, int faction_id) // @categories Faction