From 85df09b3f2bd6399b564d982afb1041428f1e7e5 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sat, 23 Aug 2014 03:21:36 -0400 Subject: [PATCH] Implemented NPC special ability 40 'NPC_CHASE_DISTANCE' Param 0: Sets max distance you need to be away from an npc for it to chase you. Param 1: Sets min distance you need to be from npc for it to chase you. Usage: Ideally used with ranged attack npcs / casters who you DO NOT WANT to chase you unless you get too close or too far or out of sight. --- zone/aggro.cpp | 27 ++++++++++++++++++++++++++- zone/common.h | 3 ++- zone/mob.cpp | 2 ++ zone/mob.h | 7 ++++++- zone/special_attacks.cpp | 6 ++++++ 5 files changed, 42 insertions(+), 3 deletions(-) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index d55dab4fd..109720e47 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -873,7 +873,30 @@ bool Mob::CombatRange(Mob* other) if (size_mod > 10000) size_mod = size_mod / 7; - if (DistNoRoot(*other) <= size_mod) + float _DistNoRoot = DistNoRoot(*other); + + if (GetSpecialAbility(NPC_CHASE_DISTANCE)){ + + float max_dist = static_cast(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 0)); + float min_dist = static_cast(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 1)); + + if (max_dist == 1) + max_dist = 250.0f; //Default it to 250 if you forget to put a value + + max_dist = max_dist * max_dist; + + if (!min_dist) + min_dist = size_mod; //Default to melee range + else + min_dist = min_dist * min_dist; + + if (CheckLastLosState() && (_DistNoRoot >= min_dist && _DistNoRoot <= max_dist)) + SetPseudoRoot(true); + else + SetPseudoRoot(false); + } + + if (_DistNoRoot <= size_mod) { return true; } @@ -887,6 +910,8 @@ bool Mob::CheckLosFN(Mob* other) { if(other) Result = CheckLosFN(other->GetX(), other->GetY(), other->GetZ(), other->GetSize()); + SetLastLosState(Result); + return Result; } diff --git a/zone/common.h b/zone/common.h index 3cc1af1cf..0c1fe28bf 100644 --- a/zone/common.h +++ b/zone/common.h @@ -127,7 +127,8 @@ enum { FLEE_PERCENT = 37, ALLOW_BENEFICIAL = 38, DISABLE_MELEE = 39, - MAX_SPECIAL_ATTACK = 40 + NPC_CHASE_DISTANCE = 40, + MAX_SPECIAL_ATTACK = 41 }; diff --git a/zone/mob.cpp b/zone/mob.cpp index f9cdba950..0d7002253 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -183,6 +183,7 @@ Mob::Mob(const char* in_name, has_MGB = false; has_ProjectIllusion = false; SpellPowerDistanceMod = 0; + last_los_check = false; if(in_aa_title>0) aa_title = in_aa_title; @@ -341,6 +342,7 @@ Mob::Mob(const char* in_name, viral_spells[i] = 0; } pStandingPetOrder = SPO_Follow; + pseudo_rooted = false; see_invis = in_see_invis; see_invis_undead = in_see_invis_undead != 0; diff --git a/zone/mob.h b/zone/mob.h index fe0919f7e..55a57892b 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -464,6 +464,8 @@ public: bool CheckLosFN(float posX, float posY, float posZ, float mobSize); inline void SetChanged() { pLastChange = Timer::GetCurrentTime(); } inline const uint32 LastChange() const { return pLastChange; } + inline void SetLastLosState(bool value) { last_los_check = value; } + inline bool CheckLastLosState() const { return last_los_check; } //Quest void QuestReward(Client *c = nullptr, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0); @@ -752,7 +754,8 @@ public: inline const bool IsRooted() const { return rooted || permarooted; } inline const bool HasVirus() const { return has_virus; } int GetSnaredAmount(); - + inline const bool IsPseudoRooted() const { return pseudo_rooted; } + inline void SetPseudoRoot(bool prState) { pseudo_rooted = prState; } int GetCurWp() { return cur_wp; } @@ -1119,6 +1122,8 @@ protected: bool has_MGB; bool has_ProjectIllusion; int16 SpellPowerDistanceMod; + bool last_los_check; + bool pseudo_rooted; // Bind wound Timer bindwound_timer; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index abc94f8f5..a523afa34 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -965,6 +965,9 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item void NPC::RangedAttack(Mob* other) { + + if (!other) + return; //make sure the attack and ranged timers are up //if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow if((attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check())) @@ -973,6 +976,9 @@ void NPC::RangedAttack(Mob* other) return; } + if(!CheckLosFN(other)) + return; + int attacks = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 0); attacks = attacks > 0 ? attacks : 1; for(int i = 0; i < attacks; ++i) {