mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 10:31:29 +00:00
[Bug Fix] NPC Faction War prevention. (#3595)
* [Bug] NPC Faction War prevention. This should assist with prevention of NPC Faction waring. I have been using this code on my server for over 5 years with no coredumps or any noted bugs. This was brought up as users have reported a few events where they can trigger NPC's to fight each other. * Correct a few entries to line up with updated code. * Re-add missing RestTimer functionality
This commit is contained in:
parent
c0fe0f11f7
commit
f7780b0247
@ -42,27 +42,26 @@ HateList::~HateList()
|
||||
{
|
||||
}
|
||||
|
||||
void HateList::WipeHateList()
|
||||
{
|
||||
void HateList::WipeHateList(bool npc_only) {
|
||||
auto iterator = list.begin();
|
||||
while (iterator != list.end()) {
|
||||
Mob *m = (*iterator)->entity_on_hatelist;
|
||||
if (m && (m->IsClient() || (m->IsPet() && m->GetOwner()->IsClient())) && npc_only) {
|
||||
iterator++;
|
||||
} else {
|
||||
if (m) {
|
||||
if (parse->HasQuestSub(hate_owner->GetNPCTypeID(), EVENT_HATE_LIST)) {
|
||||
parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), m, "0", 0);
|
||||
}
|
||||
|
||||
while (iterator != list.end())
|
||||
{
|
||||
Mob* m = (*iterator)->entity_on_hatelist;
|
||||
if (m)
|
||||
{
|
||||
if (parse->HasQuestSub(hate_owner->GetNPCTypeID(), EVENT_HATE_LIST)) {
|
||||
parse->EventNPC(EVENT_HATE_LIST, hate_owner->CastToNPC(), m, "0", 0);
|
||||
}
|
||||
|
||||
if (m->IsClient()) {
|
||||
m->CastToClient()->DecrementAggroCount();
|
||||
m->CastToClient()->RemoveXTarget(hate_owner, true);
|
||||
if (m->IsClient()) {
|
||||
m->CastToClient()->DecrementAggroCount();
|
||||
m->CastToClient()->RemoveXTarget(hate_owner, true);
|
||||
}
|
||||
delete (*iterator);
|
||||
iterator = list.erase(iterator);
|
||||
}
|
||||
}
|
||||
delete (*iterator);
|
||||
iterator = list.erase(iterator);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -88,7 +88,7 @@ public:
|
||||
void SetHateAmountOnEnt(Mob *other, int64 in_hate, uint64 in_damage);
|
||||
void SetHateOwner(Mob *new_hate_owner) { hate_owner = new_hate_owner; }
|
||||
void SpellCast(Mob *caster, uint32 spell_id, float range, Mob *ae_center = nullptr);
|
||||
void WipeHateList();
|
||||
void WipeHateList(bool npc_only = false);
|
||||
void RemoveStaleEntries(int time_ms, float dist);
|
||||
|
||||
|
||||
|
||||
18
zone/mob.cpp
18
zone/mob.cpp
@ -4888,16 +4888,14 @@ bool Mob::RemoveFromHateList(Mob* mob)
|
||||
return bFound;
|
||||
}
|
||||
|
||||
void Mob::WipeHateList()
|
||||
{
|
||||
if(IsEngaged())
|
||||
{
|
||||
hate_list.WipeHateList();
|
||||
AI_Event_NoLongerEngaged();
|
||||
}
|
||||
else
|
||||
{
|
||||
hate_list.WipeHateList();
|
||||
void Mob::WipeHateList(bool npc_only) {
|
||||
if (IsEngaged()) {
|
||||
hate_list.WipeHateList(npc_only);
|
||||
if (hate_list.IsHateListEmpty()) {
|
||||
AI_Event_NoLongerEngaged();
|
||||
}
|
||||
} else {
|
||||
hate_list.WipeHateList(npc_only);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -767,7 +767,7 @@ public:
|
||||
void SetAssistAggro(bool value) { AssistAggro = value; if (PrimaryAggro) AssistAggro = false; }
|
||||
bool HateSummon();
|
||||
void FaceTarget(Mob* mob_to_face = 0);
|
||||
void WipeHateList();
|
||||
void WipeHateList(bool npc_only = false);
|
||||
void AddFeignMemory(Mob* attacker);
|
||||
void RemoveFromFeignMemory(Mob* attacker);
|
||||
void ClearFeignMemory();
|
||||
|
||||
@ -1062,6 +1062,10 @@ void Mob::AI_Process() {
|
||||
SetTarget(hate_list.GetClosestEntOnHateList(this));
|
||||
else {
|
||||
if (AI_target_check_timer->Check()) {
|
||||
if (IsNPC() && (!IsPet() || (HasOwner() && GetOwner()->IsNPC())) && !CastToNPC()->WillAggroNPCs()) {
|
||||
WipeHateList(true); // wipe NPCs from hate list to prevent faction war
|
||||
}
|
||||
|
||||
if (IsFocused()) {
|
||||
if (!target) {
|
||||
SetTarget(hate_list.GetEntWithMostHateOnList(this));
|
||||
|
||||
@ -3885,11 +3885,12 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
|
||||
|
||||
if (IsDetrimentalSpell(buff.spellid)) {
|
||||
if (caster->IsClient()) {
|
||||
if (!caster->CastToClient()->GetFeigned())
|
||||
if (!caster->CastToClient()->GetFeigned()) {
|
||||
AddToHateList(caster, -effect_value);
|
||||
} else if (!IsClient()) // Allow NPC's to generate hate if casted on other
|
||||
// NPC's.
|
||||
}
|
||||
} else if (!IsClient()) { // Allow NPC's to generate hate if casted on other NPC's
|
||||
AddToHateList(caster, -effect_value);
|
||||
}
|
||||
}
|
||||
|
||||
effect_value = caster->GetActDoTDamage(buff.spellid, effect_value, this);
|
||||
@ -3990,6 +3991,12 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
|
||||
case SE_Charm: {
|
||||
if (!caster || !PassCharismaCheck(caster, buff.spellid)) {
|
||||
BuffFadeByEffect(SE_Charm);
|
||||
|
||||
// Remove from hate list of any NPC's hate list and remove all NPCs this hate list
|
||||
if (IsNPC()) {
|
||||
entity_list.RemoveFromHateLists(this);
|
||||
WipeHateList(true);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@ -4244,41 +4244,39 @@ bool Mob::SpellOnTarget(
|
||||
spelltar->DamageShield(this, true);
|
||||
}
|
||||
|
||||
if (
|
||||
spelltar->IsAIControlled() &&
|
||||
IsDetrimentalSpell(spell_id) &&
|
||||
!IsHarmonySpell(spell_id)
|
||||
) {
|
||||
auto aggro_amount = CheckAggroAmount(spell_id, spelltar, isproc);
|
||||
LogSpells("Spell [{}] cast on [{}] generated [{}] hate", spell_id,
|
||||
spelltar->GetName(), aggro_amount);
|
||||
if (aggro_amount > 0) {
|
||||
spelltar->AddToHateList(this, aggro_amount);
|
||||
} else {
|
||||
int64 newhate = spelltar->GetHateAmount(this) + aggro_amount;
|
||||
spelltar->SetHateAmountOnEnt(this, std::max(newhate, static_cast<int64>(1)));
|
||||
}
|
||||
} else if (IsBeneficialSpell(spell_id) && !IsSummonPCSpell(spell_id)) {
|
||||
if (this != spelltar && IsClient()){
|
||||
if (spelltar->IsClient()) {
|
||||
CastToClient()->UpdateRestTimer(spelltar->CastToClient()->GetRestTimer());
|
||||
} else if (spelltar->IsPet()) {
|
||||
auto* owner = spelltar->GetOwner();
|
||||
if (owner && owner != this && owner->IsClient()) {
|
||||
CastToClient()->UpdateRestTimer(owner->CastToClient()->GetRestTimer());
|
||||
if (!(spelltar->IsNPC() && IsNPC() && !(IsPet() && GetOwner()->IsClient()))) {
|
||||
if (spelltar->IsAIControlled() && IsDetrimentalSpell(spell_id) && !IsHarmonySpell(spell_id)) {
|
||||
auto aggro_amount = CheckAggroAmount(spell_id, spelltar, isproc);
|
||||
LogSpellsDetail("Spell {} cast on {} generated {} hate", spell_id,
|
||||
spelltar->GetName(), aggro_amount);
|
||||
if (aggro_amount > 0) {
|
||||
spelltar->AddToHateList(this, aggro_amount);
|
||||
} else {
|
||||
int64 newhate = spelltar->GetHateAmount(this) + aggro_amount;
|
||||
spelltar->SetHateAmountOnEnt(this, std::max(newhate, static_cast<int64>(1)));
|
||||
}
|
||||
} else if (IsBeneficialSpell(spell_id) && !IsSummonPCSpell(spell_id)) {
|
||||
if (this != spelltar && IsClient()){
|
||||
if (spelltar->IsClient()) {
|
||||
CastToClient()->UpdateRestTimer(spelltar->CastToClient()->GetRestTimer());
|
||||
} else if (spelltar->IsPet()) {
|
||||
auto* owner = spelltar->GetOwner();
|
||||
if (owner && owner != this && owner->IsClient()) {
|
||||
CastToClient()->UpdateRestTimer(owner->CastToClient()->GetRestTimer());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entity_list.AddHealAggro(
|
||||
spelltar,
|
||||
this,
|
||||
CheckHealAggroAmount(
|
||||
spell_id,
|
||||
entity_list.AddHealAggro(
|
||||
spelltar,
|
||||
(spelltar->GetMaxHP() - spelltar->GetHP())
|
||||
)
|
||||
);
|
||||
this,
|
||||
CheckHealAggroAmount(
|
||||
spell_id,
|
||||
spelltar,
|
||||
(spelltar->GetMaxHP() - spelltar->GetHP())
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// make sure spelltar is high enough level for the buff
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user