mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
* [Zone] Make zone controller less likely to be visible, immune to all forms of combat * Exclude zone controller from scanning
1949 lines
92 KiB
C++
1949 lines
92 KiB
C++
|
|
/* EQEMu: Everquest Server Emulator
|
|
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org)
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
|
are required to give you total support for your newly bought product;
|
|
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
#ifndef MOB_H
|
|
#define MOB_H
|
|
|
|
#include "common.h"
|
|
#include "data_bucket.h"
|
|
#include "entity.h"
|
|
#include "hate_list.h"
|
|
#include "pathfinder_interface.h"
|
|
#include "position.h"
|
|
#include "aa_ability.h"
|
|
#include "aa.h"
|
|
#include "../common/light_source.h"
|
|
#include "../common/emu_constants.h"
|
|
#include "combat_record.h"
|
|
#include "event_codes.h"
|
|
|
|
#include <any>
|
|
#include <set>
|
|
#include <vector>
|
|
#include <memory>
|
|
|
|
#include "heal_rotation.h"
|
|
|
|
char* strn0cpy(char* dest, const char* source, uint32 size);
|
|
|
|
class Client;
|
|
class EQApplicationPacket;
|
|
class Group;
|
|
class NPC;
|
|
class Raid;
|
|
class Aura;
|
|
struct AuraRecord;
|
|
struct NewSpawn_Struct;
|
|
struct PlayerPositionUpdateServer_Struct;
|
|
class MobMovementManager;
|
|
|
|
const int COLLISION_BOX_SIZE = 8;
|
|
|
|
namespace EQ
|
|
{
|
|
struct ItemData;
|
|
class ItemInstance;
|
|
}
|
|
|
|
namespace DeathSave {
|
|
constexpr uint32 HP300 = 1;
|
|
constexpr uint32 HP8000 = 2;
|
|
}
|
|
|
|
enum class eSpecialAttacks : int {
|
|
None,
|
|
Rampage,
|
|
AERampage,
|
|
ChaoticStab
|
|
};
|
|
|
|
struct AppearanceStruct {
|
|
uint8 aa_title = UINT8_MAX;
|
|
uint8 beard = UINT8_MAX;
|
|
uint8 beard_color = UINT8_MAX;
|
|
uint32 drakkin_details = UINT32_MAX;
|
|
uint32 drakkin_heritage = UINT32_MAX;
|
|
uint32 drakkin_tattoo = UINT32_MAX;
|
|
uint8 eye_color_one = UINT8_MAX;
|
|
uint8 eye_color_two = UINT8_MAX;
|
|
uint8 face = UINT8_MAX;
|
|
uint8 gender_id = UINT8_MAX;
|
|
uint8 hair = UINT8_MAX;
|
|
uint8 hair_color = UINT8_MAX;
|
|
uint8 helmet_texture = UINT8_MAX;
|
|
uint16 race_id = Race::Doug;
|
|
bool send_effects = true;
|
|
float size = -1.0f;
|
|
Client *target = nullptr;
|
|
uint8 texture = UINT8_MAX;
|
|
};
|
|
|
|
class DataBucketKey;
|
|
class Mob : public Entity {
|
|
public:
|
|
enum CLIENT_CONN_STATUS { CLIENT_CONNECTING, CLIENT_CONNECTED, CLIENT_LINKDEAD,
|
|
CLIENT_KICKED, DISCONNECTED, CLIENT_ERROR, CLIENT_CONNECTINGALL };
|
|
enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard, SPO_FeignDeath };
|
|
|
|
struct MobSpecialAbility {
|
|
MobSpecialAbility() {
|
|
level = 0;
|
|
timer = nullptr;
|
|
for (int i = 0; i < SpecialAbility::MaxParameters; ++i) {
|
|
params[i] = 0;
|
|
}
|
|
}
|
|
|
|
~MobSpecialAbility() {
|
|
safe_delete(timer);
|
|
}
|
|
|
|
int level;
|
|
Timer *timer;
|
|
int params[SpecialAbility::MaxParameters];
|
|
};
|
|
|
|
struct AuraInfo {
|
|
char name[64];
|
|
int spawn_id;
|
|
int icon;
|
|
Aura *aura;
|
|
AuraInfo() : spawn_id(0), icon(0), aura(nullptr)
|
|
{
|
|
memset(name, 0, 64);
|
|
}
|
|
};
|
|
|
|
struct AuraMgr {
|
|
int count; // active auras
|
|
AuraInfo auras[AURA_HARDCAP];
|
|
AuraMgr() : count(0) { }
|
|
};
|
|
|
|
Mob(
|
|
const char *in_name,
|
|
const char *in_lastname,
|
|
int64 in_cur_hp,
|
|
int64 in_max_hp,
|
|
uint8 in_gender,
|
|
uint16 in_race,
|
|
uint8 in_class,
|
|
uint8 in_bodytype,
|
|
uint8 in_deity,
|
|
uint8 in_level,
|
|
uint32 in_npctype_id,
|
|
float in_size,
|
|
float in_runspeed,
|
|
const glm::vec4 &position,
|
|
uint8 in_light,
|
|
uint8 in_texture,
|
|
uint8 in_helmtexture,
|
|
uint16 in_ac,
|
|
uint16 in_atk,
|
|
uint16 in_str,
|
|
uint16 in_sta,
|
|
uint16 in_dex,
|
|
uint16 in_agi,
|
|
uint16 in_int,
|
|
uint16 in_wis,
|
|
uint16 in_cha,
|
|
uint8 in_haircolor,
|
|
uint8 in_beardcolor,
|
|
uint8 in_eyecolor1, // the eyecolors always seem to be the same, maybe left and right eye?
|
|
uint8 in_eyecolor2,
|
|
uint8 in_hairstyle,
|
|
uint8 in_luclinface,
|
|
uint8 in_beard,
|
|
uint32 in_drakkin_heritage,
|
|
uint32 in_drakkin_tattoo,
|
|
uint32 in_drakkin_details,
|
|
EQ::TintProfile in_armor_tint,
|
|
uint8 in_aa_title,
|
|
uint16 in_see_invis, // see through invis
|
|
uint16 in_see_invis_undead, // see through invis vs. undead
|
|
uint8 in_see_hide,
|
|
uint8 in_see_improved_hide,
|
|
int64 in_hp_regen,
|
|
int64 in_mana_regen,
|
|
uint8 in_qglobal,
|
|
uint8 in_maxlevel,
|
|
uint32 in_scalerate,
|
|
uint8 in_armtexture,
|
|
uint8 in_bracertexture,
|
|
uint8 in_handtexture,
|
|
uint8 in_legtexture,
|
|
uint8 in_feettexture,
|
|
uint16 in_usemodel,
|
|
bool in_always_aggros_foes,
|
|
int32 in_heroic_strikethrough,
|
|
bool keeps_sold_items,
|
|
int64 in_hp_regen_per_second = 0
|
|
);
|
|
virtual ~Mob();
|
|
|
|
inline virtual bool IsMob() const { return true; }
|
|
inline virtual bool InZone() const { return true; }
|
|
|
|
void DisplayInfo(Mob *mob);
|
|
|
|
std::unordered_map<uint16, Mob *> m_close_mobs;
|
|
std::unordered_map<int, glm::vec4> m_last_seen_mob_position;
|
|
Timer m_scan_close_mobs_timer;
|
|
Timer m_see_close_mobs_timer;
|
|
Timer m_mob_check_moving_timer;
|
|
|
|
// Bot attack flag
|
|
Timer bot_attack_flag_timer;
|
|
|
|
//Somewhat sorted: needs documenting!
|
|
|
|
//Attack
|
|
virtual void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10);
|
|
virtual void RogueAssassinate(Mob* other);
|
|
float MobAngle(Mob *other = 0, float ourx = 0.0f, float oury = 0.0f) const;
|
|
// greater than 90 is behind
|
|
inline bool BehindMob(Mob *other = 0, float ourx = 0.0f, float oury = 0.0f) const
|
|
{ return (!other || other == this) ? true : MobAngle(other, ourx, oury) > 90.0f; }
|
|
// less than 56 is in front, greater than 56 is usually where the client generates the messages
|
|
inline bool InFrontMob(Mob *other = 0, float ourx = 0.0f, float oury = 0.0f) const
|
|
{ return (!other || other == this) ? true : MobAngle(other, ourx, oury) < 56.0f; }
|
|
bool IsFacingMob(Mob *other); // kind of does the same as InFrontMob, but derived from client
|
|
float HeadingAngleToMob(Mob *other) { return HeadingAngleToMob(other->GetX(), other->GetY()); }
|
|
float HeadingAngleToMob(float other_x, float other_y); // to keep consistent with client generated messages
|
|
virtual void RangedAttack(Mob* other) { }
|
|
virtual void ThrowingAttack(Mob* other) { }
|
|
// 13 = Primary (default), 14 = secondary
|
|
virtual bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
|
|
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr);
|
|
void DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr, bool FromRiposte = false);
|
|
int MonkSpecialAttack(Mob* other, uint8 skill_used);
|
|
virtual void TryBackstab(Mob *other,int ReuseTime = 10);
|
|
bool AvoidDamage(Mob *attacker, DamageHitInfo &hit);
|
|
int compute_tohit(EQ::skills::SkillType skillinuse);
|
|
int GetTotalToHit(EQ::skills::SkillType skill, int chance_mod); // compute_tohit + spell bonuses
|
|
int compute_defense();
|
|
int GetTotalDefense(); // compute_defense + spell bonuses
|
|
bool CheckHitChance(Mob* attacker, DamageHitInfo &hit);
|
|
void TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
|
|
void TryPetCriticalHit(Mob *defender, DamageHitInfo &hit);
|
|
virtual bool TryFinishingBlow(Mob *defender, int64 &damage);
|
|
int TryHeadShot(Mob* defender, EQ::skills::SkillType skillInUse);
|
|
int TryAssassinate(Mob* defender, EQ::skills::SkillType skillInUse);
|
|
virtual void DoRiposte(Mob* defender);
|
|
void ApplyMeleeDamageMods(uint16 skill, int64 &damage, Mob * defender = nullptr, ExtraAttackOptions *opts = nullptr);
|
|
int ACSum(bool skip_caps = false);
|
|
inline int GetDisplayAC() { return 1000 * (ACSum(true) + compute_defense()) / 847; }
|
|
int offense(EQ::skills::SkillType skill);
|
|
int GetBestMeleeSkill();
|
|
void CalcAC() { mitigation_ac = ACSum(); }
|
|
int GetACSoftcap();
|
|
double GetSoftcapReturns();
|
|
int GetClassRaceACBonus();
|
|
inline int GetMitigationAC() { return mitigation_ac; }
|
|
void MeleeMitigation(Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
|
|
double RollD20(int offense, int mitigation); // CALL THIS FROM THE DEFENDER
|
|
bool CombatRange(Mob* other, float fixed_size_mod = 1.0, bool aeRampage = false, ExtraAttackOptions *opts = nullptr);
|
|
virtual inline bool IsBerserk() { return false; } // only clients
|
|
void RogueEvade(Mob *other);
|
|
void CommonOutgoingHitSuccess(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
|
|
bool HasDied();
|
|
virtual bool CheckDualWield();
|
|
void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, bool rampage = false);
|
|
void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, bool rampage = false);
|
|
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, bool rampage = false)
|
|
{
|
|
if (target) {
|
|
DoMainHandAttackRounds(target, opts, rampage);
|
|
if (CanThisClassDualWield()) {
|
|
DoOffHandAttackRounds(target, opts, rampage);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
bool HasAnInvisibilityEffect();
|
|
void BreakCharmPetIfConditionsMet();
|
|
//Invisible
|
|
bool IsInvisible(Mob* other = 0) const;
|
|
void SetInvisible(uint8 state, bool set_on_bonus_calc = false);
|
|
|
|
void CalcSeeInvisibleLevel();
|
|
void CalcInvisibleLevel();
|
|
void ZeroInvisibleVars(uint8 invisible_type);
|
|
|
|
inline uint8 GetSeeInvisibleLevelFromNPCStat(uint16 in_see_invis);
|
|
|
|
void BreakInvisibleSpells();
|
|
virtual void CancelSneakHide();
|
|
void CommonBreakInvisible();
|
|
void CommonBreakInvisibleFromCombat();
|
|
|
|
inline uint8 GetInvisibleLevel() const { return invisible; }
|
|
inline uint8 GetInvisibleUndeadLevel() const { return invisible_undead; }
|
|
|
|
inline bool SeeHide() const { return see_hide; }
|
|
inline bool SeeImprovedHide() const { return see_improved_hide; }
|
|
inline uint8 SeeInvisibleUndead() const { return see_invis_undead; }
|
|
inline uint8 SeeInvisible() const { return see_invis; }
|
|
|
|
inline void SetInnateSeeInvisible(uint8 val) { innate_see_invis = val; }
|
|
inline void SetSeeInvisibleUndead(uint8 val) { see_invis_undead = val; }
|
|
|
|
uint32 tmHidden; // timestamp of hide, only valid while hidden == true
|
|
uint8 invisible, nobuff_invisible, invisible_undead, invisible_animals;
|
|
uint8 see_invis, innate_see_invis, see_invis_undead; //TODO: do we need a see_invis_animal ?
|
|
|
|
bool sneaking, hidden, improved_hidden;
|
|
bool see_hide, see_improved_hide;
|
|
|
|
/**
|
|
************************************************
|
|
* Appearance
|
|
************************************************
|
|
*/
|
|
|
|
EQ::InternalTextureProfile mob_texture_profile = {};
|
|
|
|
EQ::skills::SkillType AttackAnimation(int Hand, const EQ::ItemInstance* weapon, EQ::skills::SkillType skillinuse = EQ::skills::Skill1HBlunt);
|
|
|
|
uint32 GetTextureProfileMaterial(uint8 material_slot) const;
|
|
uint32 GetTextureProfileColor(uint8 material_slot) const;
|
|
uint32 GetTextureProfileHeroForgeModel(uint8 material_slot) const;
|
|
|
|
virtual void SendArmorAppearance(Client *one_client = nullptr);
|
|
virtual void SendTextureWC(uint8 slot, uint32 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0, uint32 unknown06 = 0, uint32 unknown18 = 0);
|
|
virtual void SendWearChange(uint8 material_slot, Client *one_client = nullptr);
|
|
virtual void SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint);
|
|
virtual void WearChange(uint8 material_slot, uint32 texture, uint32 color = 0, uint32 hero_forge_model = 0);
|
|
|
|
void ChangeSize(float in_size, bool unrestricted = false);
|
|
void DoAnim(const int animation_id, int animation_speed = 0, bool ackreq = true, eqFilterType filter = FilterNone);
|
|
void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0, float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr, EQ::skills::SkillType skillInUse = EQ::skills::SkillArchery);
|
|
void SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target=nullptr, uint32 value1slot = 1, uint32 value1ground = 1, uint32 value2slot = 1, uint32 value2ground = 1,
|
|
uint32 value3slot = 1, uint32 value3ground = 1, uint32 value4slot = 1, uint32 value4ground = 1, uint32 value5slot = 1, uint32 value5ground = 1);
|
|
void SendLevelAppearance();
|
|
void SendTargetable(bool on, Client *specific_target = nullptr);
|
|
void SetMobTextureProfile(uint8 material_slot, uint32 texture, uint32 color = 0, uint32 hero_forge_model = 0);
|
|
|
|
//Spell
|
|
void SendSpellEffect(uint32 effect_id, uint32 duration, uint32 finish_delay, bool zone_wide,
|
|
uint32 unk020, bool perm_effect = false, Client *c = nullptr, uint32 caster_id = 0, uint32 target_id = 0);
|
|
bool IsBeneficialAllowed(Mob *target);
|
|
virtual int GetCasterLevel(uint16 spell_id);
|
|
void ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterID = 0,
|
|
uint8 WornType = 0, int32 ticsremaining = 0, int buffslot = -1, int instrument_mod = 10,
|
|
bool IsAISpellEffect = false, uint16 effect_id = 0, int32 se_base = 0, int32 se_limit = 0, int32 se_max = 0);
|
|
void NegateSpellEffectBonuses(uint16 spell_id);
|
|
bool NegateSpellEffect(uint16 spell_id, int effect_id);
|
|
float GetActSpellRange(uint16 spell_id, float range);
|
|
int64 GetActSpellDamage(uint16 spell_id, int64 value, Mob* target = nullptr);
|
|
int64 GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_buff_tic = true);
|
|
int64 GetActSpellHealing(uint16 spell_id, int64 value, Mob* target = nullptr, bool from_buff_tic = false);
|
|
int32 GetActSpellCost(uint16 spell_id, int32 cost);
|
|
virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration);
|
|
int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
|
|
virtual int64 GetActReflectedSpellDamage(uint16 spell_id, int64 value, int effectiveness);
|
|
float ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override = false,
|
|
int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false,
|
|
int level_override = -1);
|
|
int GetResist(uint8 resist_type);
|
|
int ResistPhysical(int level_diff, uint8 caster_level);
|
|
int ResistElementalWeaponDmg(const EQ::ItemInstance *item);
|
|
int CheckBaneDamage(const EQ::ItemInstance *item);
|
|
uint16 GetSpecializeSkillValue(uint16 spell_id) const;
|
|
void SendSpellBarDisable();
|
|
void SendSpellBarEnable(uint16 spellid);
|
|
void ZeroCastingVars();
|
|
virtual void SpellProcess();
|
|
virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, int32 casttime = -1,
|
|
int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF,
|
|
uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, int16 *resist_adjust = nullptr,
|
|
uint32 aa_id = 0);
|
|
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, int32 casttime = -1,
|
|
int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF,
|
|
uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, int16 resist_adjust = 0,
|
|
uint32 aa_id = 0);
|
|
void CastedSpellFinished(uint16 spell_id, uint32 target_id, EQ::spells::CastingSlot slot, int mana_used,
|
|
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0);
|
|
bool SpellFinished(uint16 spell_id, Mob *target, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, int mana_used = 0,
|
|
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false, int level_override = -1, uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, bool from_casted_spell = false, uint32 aa_id = 0);
|
|
void SendBeginCast(uint16 spell_id, uint32 casttime);
|
|
virtual bool SpellOnTarget(
|
|
uint16 spell_id,
|
|
Mob* spelltar,
|
|
int reflect_effectiveness = 0,
|
|
bool use_resist_adjust = false,
|
|
int16 resist_adjust = 0,
|
|
bool isproc = false,
|
|
int level_override = -1,
|
|
int duration_override = 0,
|
|
bool disable_buff_overwrite = false
|
|
);
|
|
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1, int reflect_effectiveness = 0, int32 duration_override = 0, bool disable_buff_overwrite = false);
|
|
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center,
|
|
CastAction_type &CastAction, EQ::spells::CastingSlot slot, bool isproc = false);
|
|
bool DoCastingChecksOnCaster(int32 spell_id, EQ::spells::CastingSlot slot);
|
|
bool DoCastingChecksZoneRestrictions(bool check_on_casting, int32 spell_id);
|
|
bool DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob* spell_target);
|
|
virtual bool CheckFizzle(uint16 spell_id);
|
|
virtual bool CheckSpellLevelRestriction(Mob *caster, uint16 spell_id);
|
|
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
|
|
|
|
virtual float GetAOERange(uint16 spell_id);
|
|
void InterruptSpell(uint16 spellid = SPELL_UNKNOWN);
|
|
void InterruptSpell(uint16, uint16, uint16 spellid = SPELL_UNKNOWN);
|
|
void StopCasting();
|
|
void StopCastSpell(int32 spell_id, bool send_spellbar_enable);
|
|
inline bool IsCasting() const { return((casting_spell_id != 0)); }
|
|
uint16 CastingSpellID() const { return casting_spell_id; }
|
|
bool TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier);
|
|
bool TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed = 1.5f);
|
|
void ResourceTap(int64 damage, uint16 spell_id);
|
|
void TryTriggerThreshHold(int64 damage, int effect_id, Mob* attacker);
|
|
void CalcDestFromHeading(float heading, float distance, float MaxZDiff, float StartX, float StartY, float &dX, float &dY, float &dZ);
|
|
void BeamDirectional(uint16 spell_id, int16 resist_adjust);
|
|
void ConeDirectional(uint16 spell_id, int16 resist_adjust);
|
|
void ApplyHealthTransferDamage(Mob *caster, Mob *target, uint16 spell_id);
|
|
void ApplySpellEffectIllusion(int32 spell_id, Mob* caster, int buffslot, int base, int limit, int max);
|
|
void ApplyIllusionToCorpse(int32 spell_id, Corpse* new_corpse);
|
|
void SendIllusionWearChange(Client* c);
|
|
int16 GetItemSlotToConsumeCharge(int32 spell_id, uint32 inventory_slot);
|
|
bool CheckItemRaceClassDietyRestrictionsOnCast(uint32 inventory_slot);
|
|
bool IsFromTriggeredSpell(EQ::spells::CastingSlot slot, uint32 item_slot = 0xFFFFFFFF);
|
|
|
|
//Bard
|
|
bool ApplyBardPulse(int32 spell_id, Mob *spell_target, EQ::spells::CastingSlot slot);
|
|
bool IsActiveBardSong(int32 spell_id);
|
|
bool HasActiveSong() const { return(bardsong != 0); }
|
|
void ZeroBardPulseVars();
|
|
void DoBardCastingFromItemClick(bool is_casting_bard_song, uint32 cast_time, int32 spell_id, uint16 target_id, EQ::spells::CastingSlot slot, uint32 item_slot,
|
|
uint32 recast_type , uint32 recast_delay);
|
|
bool UseBardSpellLogic(uint16 spell_id = 0xffff, int slot = -1);
|
|
|
|
//Buff
|
|
void BuffProcess();
|
|
virtual void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr);
|
|
void BuffFadeBySpellID(uint16 spell_id);
|
|
void BuffFadeBySpellIDAndCaster(uint16 spell_id, uint16 caster_id);
|
|
void BuffFadeByEffect(int effect_id, int slot_to_skip = -1);
|
|
void BuffFadeAll();
|
|
void BuffFadeBeneficial();
|
|
void BuffFadeNonPersistDeath();
|
|
void BuffFadeDetrimental();
|
|
void BuffFadeBySlot(int slot, bool iRecalcBonuses = true);
|
|
void BuffFadeDetrimentalByCaster(Mob *caster);
|
|
void BuffFadeBySitModifier();
|
|
void BuffFadeSongs();
|
|
void BuffDetachCaster(Mob *caster);
|
|
bool IsAffectedByBuffByGlobalGroup(GlobalGroup group);
|
|
void BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration);
|
|
int AddBuff(Mob *caster, const uint16 spell_id, int duration = 0, int32 level_override = -1, bool disable_buff_overwrite = false);
|
|
int CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite = false);
|
|
int CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caster_level_override = -1);
|
|
void SendPetBuffsToClient();
|
|
virtual int GetCurrentBuffSlots() const { return 0; }
|
|
virtual int GetCurrentSongSlots() const { return 0; }
|
|
virtual int GetCurrentDiscSlots() const { return 0; }
|
|
virtual int GetMaxBuffSlots() const { return 0; }
|
|
virtual int GetMaxSongSlots() const { return 0; }
|
|
virtual int GetMaxDiscSlots() const { return 0; }
|
|
virtual int GetMaxTotalSlots() const { return 0; }
|
|
bool HasDiscBuff();
|
|
virtual uint32 GetFirstBuffSlot(bool disc, bool song);
|
|
virtual uint32 GetLastBuffSlot(bool disc, bool song);
|
|
virtual void InitializeBuffSlots() { buffs = nullptr; }
|
|
virtual void UninitializeBuffSlots() { }
|
|
EQApplicationPacket *MakeBuffsPacket(bool for_target = true, bool clear_buffs = false);
|
|
void SendBuffsToClient(Client *c);
|
|
inline Buffs_Struct* GetBuffs() { return buffs; }
|
|
void DoGravityEffect();
|
|
void DamageShield(Mob* other, bool spell_ds = false);
|
|
int32 RuneAbsorb(int64 damage, uint16 type);
|
|
std::vector<uint16> GetBuffSpellIDs();
|
|
bool FindBuff(uint16 spell_id, uint16 caster_id = 0);
|
|
uint16 FindBuffBySlot(int slot);
|
|
uint32 BuffCount(bool is_beneficial = true, bool is_detrimental = true);
|
|
bool FindType(uint16 type, bool bOffensive = false, uint16 threshold = 100);
|
|
int16 GetBuffSlotFromType(uint16 type);
|
|
uint16 GetSpellIDFromSlot(uint8 slot);
|
|
int CountDispellableBuffs();
|
|
void CheckNumHitsRemaining(NumHit type, int32 buff_slot = -1, uint16 spell_id = SPELL_UNKNOWN);
|
|
bool HasNumhits() const { return has_numhits; }
|
|
inline void Numhits(bool val) { has_numhits = val; }
|
|
bool HasMGB() const { return has_MGB; }
|
|
inline void SetMGB(bool val) { has_MGB = val; }
|
|
bool HasProjectIllusion() const { return has_ProjectIllusion ; }
|
|
inline void SetProjectIllusion(bool val) { has_ProjectIllusion = val; }
|
|
bool IsNimbusEffectActive(uint32 nimbus_effect);
|
|
void SetNimbusEffect(uint32 nimbus_effect);
|
|
inline virtual uint32 GetNimbusEffect1() const { return nimbus_effect1; }
|
|
inline virtual uint32 GetNimbusEffect2() const { return nimbus_effect2; }
|
|
inline virtual uint32 GetNimbusEffect3() const { return nimbus_effect3; }
|
|
void AddNimbusEffect(int effect_id);
|
|
void RemoveNimbusEffect(int effect_id);
|
|
void RemoveAllNimbusEffects();
|
|
inline const glm::vec3& GetTargetRingLocation() const { return m_TargetRing; }
|
|
inline float GetTargetRingX() const { return m_TargetRing.x; }
|
|
inline float GetTargetRingY() const { return m_TargetRing.y; }
|
|
inline float GetTargetRingZ() const { return m_TargetRing.z; }
|
|
inline bool HasEndurUpkeep() const { return endur_upkeep; }
|
|
inline void SetEndurUpkeep(bool val) { endur_upkeep = val; }
|
|
bool HasBuffWithSpellGroup(int spell_group);
|
|
void SetAppearanceEffects(int32 slot, int32 value);
|
|
void ListAppearanceEffects(Client* c);
|
|
void ClearAppearanceEffects();
|
|
void SendSavedAppearanceEffects(Client *receiver);
|
|
void SetBuffDuration(int spell_id, int duration = 0, int level_override = -1);
|
|
void ApplySpellBuff(int spell_id, int duration = 0, int level_override = -1);
|
|
int GetBuffStatValueBySpell(int32 spell_id, const char* stat_identifier);
|
|
int GetBuffStatValueBySlot(uint8 slot, const char* stat_identifier);
|
|
virtual bool GetIllusionBlock() const { return false; }
|
|
|
|
//Basic Stats/Inventory
|
|
virtual void SetLevel(uint8 in_level, bool command = false) { level = in_level; }
|
|
void TempName(const char *newname = nullptr);
|
|
void SetTargetable(bool on);
|
|
bool IsTargetable() const { return m_targetable; }
|
|
bool HasShieldEquipped() const { return has_shield_equipped; }
|
|
inline void SetShieldEquipped(bool val) { has_shield_equipped = val; }
|
|
bool HasTwoHandBluntEquipped() const { return has_two_hand_blunt_equipped; }
|
|
inline void SetTwoHandBluntEquipped(bool val) { has_two_hand_blunt_equipped = val; }
|
|
bool HasTwoHanderEquipped() { return has_two_hander_equipped; }
|
|
void SetTwoHanderEquipped(bool val) { has_two_hander_equipped = val; }
|
|
bool HasDualWeaponsEquipped() const { return has_dual_weapons_equipped; }
|
|
bool HasBowEquipped() const { return has_bowequipped; }
|
|
void SetBowEquipped(bool val) { has_bowequipped = val; }
|
|
bool HasArrowEquipped() const { return has_arrowequipped; }
|
|
void SetArrowEquipped(bool val) { has_arrowequipped = val; }
|
|
bool HasBowAndArrowEquipped() const { return HasBowEquipped() && HasArrowEquipped(); }
|
|
inline void SetDualWeaponsEquipped(bool val) { has_dual_weapons_equipped = val; }
|
|
bool CanFacestab() { return can_facestab; }
|
|
void SetFacestab(bool val) { can_facestab = val; }
|
|
virtual uint8 ConvertItemTypeToSkillID(uint8 item_type);
|
|
virtual uint16 GetSkill(EQ::skills::SkillType skill_num) const { return 0; }
|
|
virtual uint32 GetEquippedItemFromTextureSlot(uint8 material_slot) const { return(0); }
|
|
virtual uint32 GetEquipmentMaterial(uint8 material_slot) const;
|
|
virtual uint8 GetEquipmentType(uint8 material_slot) const;
|
|
virtual uint32 GetHerosForgeModel(uint8 material_slot) const;
|
|
virtual uint32 GetEquipmentColor(uint8 material_slot) const;
|
|
virtual uint32 IsEliteMaterialItem(uint8 material_slot) const;
|
|
bool CanClassEquipItem(uint32 item_id);
|
|
bool CanRaceEquipItem(uint32 item_id);
|
|
bool AffectedBySpellExcludingSlot(int slot, int effect);
|
|
virtual bool Death(Mob* killer_mob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, KilledByTypes killed_by = KilledByTypes::Killed_NPC, bool is_buff_tic = false) = 0;
|
|
virtual void Damage(Mob* from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill,
|
|
bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) = 0;
|
|
void SetHP(int64 hp);
|
|
inline void SetOOCRegen(int64 new_ooc_regen) { ooc_regen = new_ooc_regen; }
|
|
virtual void HealDamage(uint64 ammount, Mob* caster = nullptr, uint16 spell_id = SPELL_UNKNOWN);
|
|
virtual void SetMaxHP() { current_hp = max_hp; }
|
|
virtual inline uint16 GetBaseRace() const { return base_race; }
|
|
virtual inline uint8 GetBaseGender() const { return base_gender; }
|
|
virtual uint16 GetFactionRace();
|
|
virtual inline uint16 GetDeity() const { return deity; }
|
|
virtual uint32 GetDeityBit() { return Deity::GetBitmask(deity); }
|
|
inline uint16 GetRace() const { return race; }
|
|
inline uint16 GetModel() const { return (use_model == 0) ? race : use_model; }
|
|
inline uint8 GetGender() const { return gender; }
|
|
inline uint8 GetTexture() const { return texture; }
|
|
inline uint8 GetHelmTexture() const { return helmtexture; }
|
|
inline uint8 GetHairColor() const { return haircolor; }
|
|
inline uint8 GetBeardColor() const { return beardcolor; }
|
|
inline uint8 GetEyeColor1() const { return eyecolor1; }
|
|
inline uint8 GetEyeColor2() const { return eyecolor2; }
|
|
inline uint8 GetHairStyle() const { return hairstyle; }
|
|
inline uint8 GetLuclinFace() const { return luclinface; }
|
|
inline uint8 GetBeard() const { return beard; }
|
|
inline uint8 GetDrakkinHeritage() const { return drakkin_heritage; }
|
|
inline uint8 GetDrakkinTattoo() const { return drakkin_tattoo; }
|
|
inline uint8 GetDrakkinDetails() const { return drakkin_details; }
|
|
inline void ChangeRace(uint16 in) { race = in; }
|
|
inline void ChangeGender(uint8 in) { gender = in;}
|
|
inline void ChangeTexture(uint8 in) { texture = in; }
|
|
inline void ChangeHelmTexture(uint8 in) { helmtexture = in; }
|
|
inline void ChangeHairColor(uint8 in) { haircolor = in; }
|
|
inline void ChangeBeardColor(uint8 in) { beardcolor = in; }
|
|
inline void ChangeEyeColor1(uint8 in) { eyecolor1 = in; }
|
|
inline void ChangeEyeColor2(uint8 in) { eyecolor2 = in; }
|
|
inline void ChangeHairStyle(uint8 in) { hairstyle = in; }
|
|
inline void ChangeLuclinFace(uint8 in) { luclinface = in; }
|
|
inline void ChangeBeard(uint8 in) { beard = in; }
|
|
inline void ChangeDrakkinHeritage(uint8 in) { drakkin_heritage = in; }
|
|
inline void ChangeDrakkinTattoo(uint8 in) { drakkin_tattoo = in; }
|
|
inline void ChangeDrakkinDetails(uint8 in) { drakkin_details = in; }
|
|
inline uint32 GetArmorTint(uint8 i) const { return armor_tint.Slot[(i < EQ::textures::materialCount) ? i : 0].Color; }
|
|
inline uint8 GetClass() const { return class_; }
|
|
inline uint8 GetLevel() const { return level; }
|
|
inline uint8 GetOrigLevel() const { return orig_level; }
|
|
inline const char* GetName() const { return name; }
|
|
inline const char* GetOrigName() const { return orig_name; }
|
|
inline const char* GetLastName() const { return lastname; }
|
|
inline const eStandingPetOrder GetPreviousPetOrder() const { return m_previous_pet_order; }
|
|
const char *GetCleanName();
|
|
virtual void SetName(const char *new_name = nullptr) { new_name ? strn0cpy(name, new_name, 64) :
|
|
strn0cpy(name, GetName(), 64); return; };
|
|
inline Mob* GetTarget() const { return target; }
|
|
std::string GetTargetDescription(Mob* target, uint8 description_type = TargetDescriptionType::LCSelf, uint16 entity_id_override = 0);
|
|
virtual void SetTarget(Mob* mob);
|
|
inline bool HasTargetReflection() const { return (target && target != this && target->target == this); }
|
|
virtual inline float GetHPRatio() const { return max_hp == 0 ? 0 : ((float) current_hp / max_hp * 100); }
|
|
virtual inline int GetIntHPRatio() const { return max_hp == 0 ? 0 : static_cast<int>(GetHPRatio()); }
|
|
inline int32 GetAC() const { return AC; }
|
|
inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK; }
|
|
inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
|
|
inline virtual int32 GetSTR() const { return STR + itembonuses.STR + spellbonuses.STR; }
|
|
inline virtual int32 GetSTA() const { return STA + itembonuses.STA + spellbonuses.STA; }
|
|
inline virtual int32 GetDEX() const { return DEX + itembonuses.DEX + spellbonuses.DEX; }
|
|
inline virtual int32 GetAGI() const { return AGI + itembonuses.AGI + spellbonuses.AGI; }
|
|
inline virtual int32 GetINT() const { return INT + itembonuses.INT + spellbonuses.INT; }
|
|
inline virtual int32 GetWIS() const { return WIS + itembonuses.WIS + spellbonuses.WIS; }
|
|
inline virtual int32 GetCHA() const { return CHA + itembonuses.CHA + spellbonuses.CHA; }
|
|
inline virtual int32 GetHeroicMR() const { return 0; }
|
|
inline virtual int32 GetHeroicFR() const { return 0; }
|
|
inline virtual int32 GetHeroicDR() const { return 0; }
|
|
inline virtual int32 GetHeroicPR() const { return 0; }
|
|
inline virtual int32 GetHeroicCR() const { return 0; }
|
|
inline virtual int32 GetMR() const { return MR + itembonuses.MR + spellbonuses.MR; }
|
|
inline virtual int32 GetFR() const { return FR + itembonuses.FR + spellbonuses.FR; }
|
|
inline virtual int32 GetDR() const { return DR + itembonuses.DR + spellbonuses.DR; }
|
|
inline virtual int32 GetPR() const { return PR + itembonuses.PR + spellbonuses.PR; }
|
|
inline virtual int32 GetCR() const { return CR + itembonuses.CR + spellbonuses.CR; }
|
|
inline virtual int32 GetCorrup() const { return Corrup + itembonuses.Corrup + spellbonuses.Corrup; }
|
|
inline virtual int32 GetPhR() const { return PhR; } // PhR bonuses not implemented yet
|
|
inline StatBonuses GetItemBonuses() const { return itembonuses; }
|
|
inline StatBonuses GetSpellBonuses() const { return spellbonuses; }
|
|
inline StatBonuses GetAABonuses() const { return aabonuses; }
|
|
inline StatBonuses* GetItemBonusesPtr() { return &itembonuses; }
|
|
inline StatBonuses* GetSpellBonusesPtr() { return &spellbonuses; }
|
|
inline StatBonuses* GetAABonusesPtr() { return &aabonuses; }
|
|
inline virtual int32 GetHeroicSTR() const { return 0; }
|
|
inline virtual int32 GetHeroicSTA() const { return 0; }
|
|
inline virtual int32 GetHeroicDEX() const { return 0; }
|
|
inline virtual int32 GetHeroicAGI() const { return 0; }
|
|
inline virtual int32 GetHeroicINT() const { return 0; }
|
|
inline virtual int32 GetHeroicWIS() const { return 0; }
|
|
inline virtual int32 GetHeroicCHA() const { return 0; }
|
|
inline virtual int32 GetMaxSTR() const { return GetSTR(); }
|
|
inline virtual int32 GetMaxSTA() const { return GetSTA(); }
|
|
inline virtual int32 GetMaxDEX() const { return GetDEX(); }
|
|
inline virtual int32 GetMaxAGI() const { return GetAGI(); }
|
|
inline virtual int32 GetMaxINT() const { return GetINT(); }
|
|
inline virtual int32 GetMaxWIS() const { return GetWIS(); }
|
|
inline virtual int32 GetMaxCHA() const { return GetCHA(); }
|
|
inline virtual int32 GetMaxMR() const { return 255; }
|
|
inline virtual int32 GetMaxPR() const { return 255; }
|
|
inline virtual int32 GetMaxDR() const { return 255; }
|
|
inline virtual int32 GetMaxCR() const { return 255; }
|
|
inline virtual int32 GetMaxFR() const { return 255; }
|
|
inline virtual int32 GetDelayDeath() const { return 0; }
|
|
inline int64 GetHP() const { return current_hp; }
|
|
inline int64 GetMaxHP() const { return max_hp; }
|
|
virtual int64 CalcMaxHP();
|
|
virtual int64 CalcHPRegenCap() { return 0; }
|
|
inline int64 GetMaxMana() const { return max_mana; }
|
|
virtual int64 CalcManaRegenCap() { return 0; }
|
|
inline int64 GetMana() const { return current_mana; }
|
|
virtual int64 GetEndurance() const { return 0; }
|
|
virtual int64 GetMaxEndurance() const { return 0; }
|
|
virtual int64 CalcEnduranceRegenCap() { return 0; }
|
|
virtual void SetEndurance(int32 newEnd) { return; }
|
|
int64 GetItemHPBonuses();
|
|
int64 GetSpellHPBonuses();
|
|
const int64& SetMana(int64 amount);
|
|
inline float GetManaRatio() const { return max_mana == 0 ? 100 :
|
|
((static_cast<float>(current_mana) / max_mana) * 100); }
|
|
virtual int64 CalcMaxMana();
|
|
uint32 GetNPCTypeID() const { return npctype_id; }
|
|
inline bool IsZoneController() const { return npctype_id == ZONE_CONTROLLER_NPC_ID; }
|
|
void SetNPCTypeID(uint32 npctypeid) { npctype_id = npctypeid; }
|
|
inline const glm::vec4& GetPosition() const { return m_Position; }
|
|
inline void SetPosition(const float x, const float y, const float z) { m_Position.x = x; m_Position.y = y; m_Position.z = z; }
|
|
inline const float GetX() const { return m_Position.x; }
|
|
inline const float GetY() const { return m_Position.y; }
|
|
inline const float GetZ() const { return m_Position.z; }
|
|
inline const float GetHeading() const { return m_Position.w; }
|
|
inline const glm::vec4& GetRelativePosition() const { return m_RelativePosition; }
|
|
inline void SetRelativePosition(const float x, const float y, const float z) { m_RelativePosition.x = x; m_RelativePosition.y = y; m_RelativePosition.z = z; }
|
|
inline const float GetRelativeX() const { return m_RelativePosition.x; }
|
|
inline const float GetRelativeY() const { return m_RelativePosition.y; }
|
|
inline const float GetRelativeZ() const { return m_RelativePosition.z; }
|
|
inline const float GetRelativeHeading() const { return m_RelativePosition.w; }
|
|
inline const float GetSize() const { return size; }
|
|
inline const float GetBaseSize() const { return base_size; }
|
|
inline const float SetBestZ(float z_coord) const { return z_coord + GetZOffset(); }
|
|
inline const GravityBehavior GetFlyMode() const { return flymode; }
|
|
bool IsBoat() const; // Checks races - used on mob instantiation
|
|
bool GetIsBoat() const { return is_boat; } // Set on instantiation for speed
|
|
void SetIsBoat(bool boat) { is_boat = boat; }
|
|
bool IsControllableBoat() const;
|
|
inline const bool AlwaysAggro() const { return always_aggro; }
|
|
inline int32 GetHeroicStrikethrough() const { return heroic_strikethrough; }
|
|
inline const bool GetKeepsSoldItems() const { return keeps_sold_items; }
|
|
inline void SetKeepsSoldItems(bool in_keeps_sold_items) { keeps_sold_items = in_keeps_sold_items; }
|
|
virtual int32 GetHealAmt() const { return 0; }
|
|
virtual int32 GetSpellDmg() const { return 0; }
|
|
void ProcessItemCaps();
|
|
virtual int32 CalcItemATKCap() { return 0; }
|
|
virtual bool IsSitting() const { return false; }
|
|
|
|
void CopyHateList(Mob* to);
|
|
|
|
//Group
|
|
virtual bool HasRaid() = 0;
|
|
virtual bool HasGroup() = 0;
|
|
virtual Raid* GetRaid() = 0;
|
|
virtual Group* GetGroup() = 0;
|
|
bool IsInGroupOrRaid(Mob* other, bool same_raid_group = false);
|
|
|
|
//Faction
|
|
virtual inline int32 GetPrimaryFaction() const { return 0; }
|
|
|
|
//Movement
|
|
inline bool IsMoving() const { return moving; }
|
|
virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); }
|
|
virtual void GoToBind(uint8 bindnum = 0) { }
|
|
virtual void Gate(uint8 bindnum = 0);
|
|
virtual int GetWalkspeed() const { return(_GetWalkSpeed()); }
|
|
virtual int GetRunspeed() const { return(_GetRunSpeed()); }
|
|
int GetBaseRunspeed() const { return base_runspeed; }
|
|
int GetBaseWalkspeed() const { return base_walkspeed; }
|
|
int GetBaseFearSpeed() const { return base_fearspeed; }
|
|
float GetMovespeed() const { return IsRunning() ? GetRunspeed() : GetWalkspeed(); }
|
|
bool IsRunning() const { return m_is_running; }
|
|
void SetRunning(bool val) { m_is_running = val; }
|
|
float GetCurrentSpeed() { return current_speed; }
|
|
virtual void GMMove(float x, float y, float z, float heading = 0.01, bool save_guard_spot = true);
|
|
virtual void GMMove(const glm::vec4 &position, bool save_guard_spot = true);
|
|
void SetDelta(const glm::vec4& delta);
|
|
void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu);
|
|
void SentPositionPacket(float dx, float dy, float dz, float dh, int anim, bool send_to_self = false);
|
|
virtual void StopMoving();
|
|
virtual void StopMoving(float new_heading);
|
|
void SetSpawned() { spawned = true; };
|
|
bool Spawned() { return spawned; };
|
|
virtual bool ShouldISpawnFor(Client *c) { return true; }
|
|
void SetFlyMode(GravityBehavior in_flymode);
|
|
void Teleport(const glm::vec3 &pos);
|
|
void Teleport(const glm::vec4 &pos);
|
|
void TryMoveAlong(float distance, float angle, bool send = true);
|
|
glm::vec4 TryMoveAlong(const glm::vec4 &start, float distance, float angle);
|
|
void ProcessForcedMovement();
|
|
inline void IncDeltaX(float in) { m_Delta.x += in; }
|
|
inline void IncDeltaY(float in) { m_Delta.y += in; }
|
|
inline void IncDeltaZ(float in) { m_Delta.z += in; }
|
|
inline void SetForcedMovement(int in) { ForcedMovement = in; }
|
|
void SetHeading(float iHeading) { m_Position.w = iHeading; }
|
|
|
|
//AI
|
|
static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel);
|
|
inline uint32 GetLevelCon(uint8 iOtherLevel) const { return GetLevelCon(GetLevel(), iOtherLevel); }
|
|
void AddToHateList(Mob* other, int64 hate = 0, int64 damage = 0, bool iYellForHelp = true,
|
|
bool bFrenzy = false, bool iBuffTic = false, uint16 spell_id = SPELL_UNKNOWN, bool pet_comand = false);
|
|
bool RemoveFromHateList(Mob* mob);
|
|
void SetHateAmountOnEnt(Mob* other, int64 hate = 0, int64 damage = 0) { hate_list.SetHateAmountOnEnt(other,hate,damage);}
|
|
void HalveAggro(Mob *other) { int64 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate > 1 ? in_hate / 2 : 1)); }
|
|
void DoubleAggro(Mob *other) { int64 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate ? in_hate * 2 : 1)); }
|
|
int64 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHateAmount(tmob,is_dam);}
|
|
int64 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHateAmount(tmob, true);}
|
|
int GetHateRatio(Mob *first, Mob *with) { return hate_list.GetHateRatio(first, with); }
|
|
Mob* GetHateTop() { return hate_list.GetMobWithMostHateOnList(this);}
|
|
Bot* GetHateTopBot() { return hate_list.GetMobWithMostHateOnList(this, nullptr, false, EntityFilterType::Bots)->CastToBot();}
|
|
Client* GetHateTopClient() { return hate_list.GetMobWithMostHateOnList(this, nullptr, false, EntityFilterType::Clients)->CastToClient();}
|
|
NPC* GetHateTopNPC() { return hate_list.GetMobWithMostHateOnList(this, nullptr, false, EntityFilterType::NPCs)->CastToNPC();}
|
|
Mob* GetSecondaryHate(Mob *skip) { return hate_list.GetMobWithMostHateOnList(this, skip); }
|
|
Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTopOnHateList(other);}
|
|
Mob* GetHateRandom() { return hate_list.GetRandomMobOnHateList(); }
|
|
Bot* GetHateRandomBot() { return hate_list.GetRandomMobOnHateList(EntityFilterType::Bots)->CastToBot(); }
|
|
Client* GetHateRandomClient() { return hate_list.GetRandomMobOnHateList(EntityFilterType::Clients)->CastToClient(); }
|
|
NPC* GetHateRandomNPC() { return hate_list.GetRandomMobOnHateList(EntityFilterType::NPCs)->CastToNPC(); }
|
|
Mob* GetHateMost() { return hate_list.GetMobWithMostHateOnList();}
|
|
Mob* GetHateClosest(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed); }
|
|
Bot* GetHateClosestBot(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed, EntityFilterType::Bots)->CastToBot(); }
|
|
Client* GetHateClosestClient(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed, EntityFilterType::Clients)->CastToClient(); }
|
|
NPC* GetHateClosestNPC(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed, EntityFilterType::NPCs)->CastToNPC(); }
|
|
bool IsEngaged() { return(!hate_list.IsHateListEmpty()); }
|
|
inline uint32 GetHateListCount(HateListCountType count_type = HateListCountType::All) { return hate_list.GetHateListCount(count_type); }
|
|
bool HasPrimaryAggro() { return PrimaryAggro; }
|
|
bool HasAssistAggro() { return AssistAggro; }
|
|
void SetPrimaryAggro(bool value) { PrimaryAggro = value; if (value) AssistAggro = false; }
|
|
void SetAssistAggro(bool value) { AssistAggro = value; if (PrimaryAggro) AssistAggro = false; }
|
|
bool HateSummon();
|
|
void FaceTarget(Mob* mob_to_face = 0);
|
|
void WipeHateList(bool npc_only = false);
|
|
void AddFeignMemory(Mob* attacker);
|
|
void RemoveFromFeignMemory(Mob* attacker);
|
|
void ClearFeignMemory();
|
|
bool IsOnFeignMemory(Mob *attacker) const;
|
|
void PrintHateListToClient(Client *who) { hate_list.PrintHateListToClient(who); }
|
|
std::list<struct_HateList*>& GetHateList() { return hate_list.GetHateList(); }
|
|
bool CheckLosFN(Mob* other);
|
|
bool CheckLosFN(float posX, float posY, float posZ, float mobSize);
|
|
static bool CheckLosFN(glm::vec3 posWatcher, float sizeWatcher, glm::vec3 posTarget, float sizeTarget);
|
|
virtual bool CheckWaterLoS(Mob* m);
|
|
bool CheckPositioningLosFN(Mob* other, float posX, float posY, float posZ);
|
|
bool CheckLosCheat(Mob* other); //door skipping checks for LoS
|
|
bool CheckLosCheatExempt(Mob* other); //exemptions to bypass los
|
|
bool DoLosChecks(Mob* other);
|
|
inline void SetLastLosState(bool value) { last_los_check = value; }
|
|
inline bool CheckLastLosState() const { return last_los_check; }
|
|
std::string GetMobDescription();
|
|
|
|
std::list<struct_HateList*> GetFilteredHateList(
|
|
EntityFilterType filter_type = EntityFilterType::All,
|
|
uint32 distance = 0
|
|
) {
|
|
return hate_list.GetFilteredHateList(filter_type, distance);
|
|
}
|
|
|
|
void DamageHateList(
|
|
int64 damage,
|
|
uint32 distance = 0,
|
|
EntityFilterType filter_type = EntityFilterType::All,
|
|
bool is_percentage = false
|
|
) {
|
|
hate_list.DamageHateList(damage, distance, filter_type, is_percentage);
|
|
}
|
|
|
|
void DamageArea(
|
|
int64 damage,
|
|
uint32 distance = 0,
|
|
EntityFilterType filter_type = EntityFilterType::All,
|
|
bool is_percentage = false
|
|
) {
|
|
entity_list.DamageArea(this, damage, distance, filter_type, is_percentage);
|
|
}
|
|
|
|
//Quest
|
|
void CameraEffect(uint32 duration, float intensity, Client *c = nullptr, bool global = false);
|
|
inline bool GetQglobal() const { return qglobal; }
|
|
|
|
//Other Packet
|
|
void CreateDespawnPacket(EQApplicationPacket* app, bool Decay);
|
|
void CreateHorseSpawnPacket(EQApplicationPacket* app, Mob* m = nullptr);
|
|
void CreateSpawnPacket(EQApplicationPacket* app, Mob* ForWho = 0);
|
|
static void CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns);
|
|
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
|
|
void CreateHPPacket(EQApplicationPacket* app);
|
|
void SendHPUpdate(bool force_update_all = false);
|
|
virtual void ResetHPUpdateTimer() {}; // does nothing
|
|
static void SetSpawnLastNameByClass(NewSpawn_Struct* ns);
|
|
void SendRename(Mob* sender, const char* old_name, const char* new_name);
|
|
|
|
//Util
|
|
static uint32 RandomTimer(int min, int max);
|
|
static uint8 GetDefaultGender(uint16 in_race, uint8 in_gender = 0xFF);
|
|
EQ::skills::SkillType GetSkillByItemType(int ItemType);
|
|
uint8 GetItemTypeBySkill(EQ::skills::SkillType skill);
|
|
virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr);
|
|
virtual void MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, const char *petname = nullptr, float in_size = 0.0f);
|
|
bool IsWarriorClass() const;
|
|
bool IsIntelligenceCasterClass() const;
|
|
bool IsPureMeleeClass() const;
|
|
bool IsWisdomCasterClass() const;
|
|
uint8 GetArchetype() const;
|
|
const std::string GetArchetypeName();
|
|
void SetZone(uint32 zone_id, uint32 instance_id);
|
|
void SendStatsWindow(Client* c, bool use_window);
|
|
void ShowStats(Client* client);
|
|
void ShowBuffs(Client* c);
|
|
bool PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, float &z_dest, bool lookForAftArc = true);
|
|
|
|
virtual int GetKillExpMod() const { return 100; }
|
|
|
|
// aura functions
|
|
void MakeAura(uint16 spell_id);
|
|
inline int GetAuraSlots() { return 1 + aabonuses.aura_slots + itembonuses.aura_slots + spellbonuses.aura_slots; }
|
|
inline int GetTrapSlots() { return 1 + aabonuses.trap_slots + itembonuses.trap_slots + spellbonuses.trap_slots; }
|
|
inline bool HasFreeAuraSlots() { return aura_mgr.count < GetAuraSlots(); }
|
|
inline bool HasFreeTrapSlots() { return trap_mgr.count < GetTrapSlots(); }
|
|
void AddAura(Aura *aura, AuraRecord &record);
|
|
void AddTrap(Aura *aura, AuraRecord &record);
|
|
bool CanSpawnAura(bool trap);
|
|
void RemoveAura(int spawn_id, bool skip_strip = false, bool expired = false);
|
|
void RemoveAllAuras();
|
|
inline AuraMgr &GetAuraMgr() { return aura_mgr; } // mainly used for zone db loading/saving
|
|
|
|
//Procs
|
|
void TriggerDefensiveProcs(Mob *on, uint16 hand = EQ::invslot::slotPrimary, bool FromSkillProc = false, int64 damage = 0);
|
|
bool AddRangedProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN, uint32 proc_reuse_time = 0);
|
|
bool RemoveRangedProc(uint16 spell_id, bool bAll = false);
|
|
bool HasRangedProcs() const;
|
|
bool AddDefensiveProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN, uint32 proc_reuse_time = 0);
|
|
bool RemoveDefensiveProc(uint16 spell_id, bool bAll = false);
|
|
bool HasDefensiveProcs() const;
|
|
bool HasSkillProcs() const;
|
|
bool HasSkillProcSuccess() const;
|
|
bool AddProcToWeapon(uint16 spell_id, bool bPerma = false, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN, int level_override = -1, uint32 proc_reuse_time = 0);
|
|
bool RemoveProcFromWeapon(uint16 spell_id, bool bAll = false);
|
|
bool HasProcs() const;
|
|
bool IsCombatProc(uint16 spell_id);
|
|
|
|
//More stuff to sort:
|
|
virtual bool IsRaidTarget() const { return false; };
|
|
virtual bool IsAttackAllowed(Mob *target, bool isSpellAttack = false);
|
|
bool IsTargeted() const { return (targeted > 0); }
|
|
inline void IsTargeted(int in_tar) { targeted += in_tar; if(targeted < 0) targeted = 0;}
|
|
void SetFollowID(uint32 id) { follow_id = id; }
|
|
void SetFollowDistance(uint32 dist) { follow_dist = dist; }
|
|
void SetFollowCanRun(bool v) { follow_run = v; }
|
|
uint32 GetFollowID() const { return follow_id; }
|
|
uint32 GetFollowDistance() const { return follow_dist; }
|
|
bool GetFollowCanRun() const { return follow_run; }
|
|
inline bool IsRareSpawn() const { return rare_spawn; }
|
|
inline void SetRareSpawn(bool in) { rare_spawn = in; }
|
|
|
|
virtual void Message(uint32 type, const char* message, ...) { }
|
|
virtual void MessageString(uint32 type, uint32 string_id, uint32 distance = 0) { }
|
|
virtual void MessageString(uint32 type, uint32 string_id, const char* message, const char* message2 = 0,
|
|
const char* message3 = 0, const char* message4 = 0, const char* message5 = 0, const char* message6 = 0,
|
|
const char* message7 = 0, const char* message8 = 0, const char* message9 = 0, uint32 distance = 0) { }
|
|
virtual void FilteredMessageString(Mob *sender, uint32 type, eqFilterType filter, uint32 string_id) { }
|
|
virtual void FilteredMessageString(Mob *sender, uint32 type, eqFilterType filter,
|
|
uint32 string_id, const char *message1, const char *message2 = nullptr,
|
|
const char *message3 = nullptr, const char *message4 = nullptr,
|
|
const char *message5 = nullptr, const char *message6 = nullptr,
|
|
const char *message7 = nullptr, const char *message8 = nullptr,
|
|
const char *message9 = nullptr) { }
|
|
void Say(const char *format, ...);
|
|
void SayString(uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0,
|
|
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
|
|
void SayString(uint32 type, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0,
|
|
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
|
|
void SayString(Client *to, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0,
|
|
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
|
|
void SayString(Client *to, uint32 type, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0,
|
|
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
|
|
void Shout(const char *format, ...);
|
|
void Emote(const char *format, ...);
|
|
void QuestJournalledSay(Client *QuestInitiator, const char *str, Journal::Options &opts);
|
|
const int GetItemStat(uint32 item_id, std::string identifier);
|
|
|
|
int64 CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus=false, uint16 casterid = 0, Mob *caster = nullptr);
|
|
uint8 IsFocusEffect(uint16 spellid, int effect_index, bool AA=false,uint32 aa_effect=0);
|
|
void SendIllusionPacket(const AppearanceStruct& a);
|
|
void CloneAppearance(Mob* other, bool clone_name = false);
|
|
void SetFaceAppearance(const FaceChange_Struct& face, bool skip_sender = false);
|
|
bool RandomizeFeatures(bool send_illusion = true, bool set_variables = true);
|
|
virtual void Stun(int duration);
|
|
virtual void UnStun();
|
|
inline void Silence(bool newval) { silenced = newval; }
|
|
inline void Amnesia(bool newval) { amnesiad = newval; }
|
|
void TemporaryPets(uint16 spell_id, Mob *target, const char *name_override = nullptr, uint32 duration_override = 0, bool followme=true, bool sticktarg=false, uint16 *controlled_pet_id = nullptr);
|
|
void TypesTemporaryPets(uint32 typesid, Mob *target, const char *name_override = nullptr, uint32 duration_override = 0, bool followme=true, bool sticktarg=false);
|
|
void WakeTheDead(uint16 spell_id, Corpse *corpse_to_use, Mob *target, uint32 duration);
|
|
void Spin();
|
|
void Kill();
|
|
bool PassCharismaCheck(Mob* caster, uint16 spell_id);
|
|
bool TryDeathSave();
|
|
bool TryDivineSave();
|
|
void TryTriggerOnCastFocusEffect(focusType type, uint16 spell_id);
|
|
bool TryTriggerOnCastProc(uint16 focusspellid, uint16 spell_id, uint16 proc_spellid);
|
|
bool TrySpellTrigger(Mob *target, uint32 spell_id, int effect);
|
|
void TryTriggerOnCastRequirement();
|
|
void TryTwincast(Mob *caster, Mob *target, uint32 spell_id);
|
|
void TrySympatheticProc(Mob *target, uint32 spell_id);
|
|
uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id);
|
|
bool TryFadeEffect(int slot);
|
|
void DispelMagic(Mob* casterm, uint16 spell_id, int effect_value);
|
|
uint16 GetSpellEffectResistChance(uint16 spell_id);
|
|
int32 GetVulnerability(Mob *caster, uint32 spell_id, uint32 ticsremaining, bool from_buff_tic = false);
|
|
int64 GetFcDamageAmtIncoming(Mob *caster, int32 spell_id, bool from_buff_tic = false);
|
|
int64 GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id); //**** This can be removed when bot healing focus code is updated ****
|
|
int32 GetSkillDmgTaken(const EQ::skills::SkillType skill_used, ExtraAttackOptions *opts = nullptr);
|
|
int32 GetPositionalDmgTaken(Mob *attacker);
|
|
int32 GetPositionalDmgTakenAmt(Mob *attacker);
|
|
void DoKnockback(Mob *caster, uint32 push_back, uint32 push_up);
|
|
int16 CalcResistChanceBonus();
|
|
int16 CalcFearResistChance();
|
|
void TrySpellOnKill(uint8 level, uint16 spell_id);
|
|
bool TrySpellOnDeath();
|
|
void CastOnCurer(uint32 spell_id);
|
|
void CastOnCure(uint32 spell_id);
|
|
void CastOnNumHitFade(uint32 spell_id);
|
|
void SlowMitigation(Mob* caster);
|
|
int16 GetCritDmgMod(uint16 skill, Mob* owner = nullptr);
|
|
int16 GetMeleeDamageMod_SE(uint16 skill);
|
|
int16 GetMeleeMinDamageMod_SE(uint16 skill);
|
|
int16 GetCrippBlowChance();
|
|
int16 GetMeleeDmgPositionMod(Mob* defender);
|
|
int16 GetSkillReuseTime(uint16 skill);
|
|
int GetCriticalChanceBonus(uint16 skill);
|
|
int GetSkillDmgAmt(int skill_id);
|
|
int16 GetPositionalDmgAmt(Mob* defender);
|
|
inline bool CanBlockSpell() const { return(spellbonuses.FocusEffects[focusBlockNextSpell]); }
|
|
bool DoHPToManaCovert(int32 mana_cost = 0);
|
|
int8 GetDecayEffectValue(uint16 spell_id, uint16 spelleffect);
|
|
int64 GetExtraSpellAmt(uint16 spell_id, int64 extra_spell_amt, int64 base_spell_dmg);
|
|
void MeleeLifeTap(int64 damage);
|
|
bool PassCastRestriction(int value);
|
|
void SendCastRestrictionMessage(int requirement_id, bool is_target_requirement = true, bool is_discipline = false);
|
|
bool ImprovedTaunt();
|
|
bool TryRootFadeByDamage(int buffslot, Mob* attacker);
|
|
float GetSlowMitigation() const { return slow_mitigation; }
|
|
void CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster = nullptr);
|
|
inline int16 GetSpellPowerDistanceMod() const { return SpellPowerDistanceMod; };
|
|
inline void SetSpellPowerDistanceMod(int16 value) { SpellPowerDistanceMod = value; };
|
|
int32 GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot = 0);
|
|
bool HarmonySpellLevelCheck(int32 spell_id, Mob* target = nullptr);
|
|
bool PassCharmTargetRestriction(Mob *target);
|
|
bool CanFocusUseRandomEffectivenessByType(focusType type);
|
|
int GetFocusRandomEffectivenessValue(int focus_base, int focus_base2, bool best_focus = 0);
|
|
int GetHealRate() const { return itembonuses.HealRate + spellbonuses.HealRate + aabonuses.HealRate; }
|
|
int GetMemoryBlurChance(int base_chance);
|
|
inline bool HasBaseEffectFocus() const { return (spellbonuses.FocusEffects[focusFcBaseEffects] || aabonuses.FocusEffects[focusFcBaseEffects] || itembonuses.FocusEffects[focusFcBaseEffects]); }
|
|
int32 GetDualWieldingSameDelayWeapons() const { return dw_same_delay; }
|
|
inline void SetDualWieldingSameDelayWeapons(int32 val) { dw_same_delay = val; }
|
|
bool IsTargetedFocusEffect(int focus_type);
|
|
bool HasPersistDeathIllusion(int32 spell_id);
|
|
void DoShieldDamageOnShielderSpellEffect(Mob* shield_target, int64 hit_damage_done, EQ::skills::SkillType skillInUse);
|
|
|
|
|
|
bool TryDoubleMeleeRoundEffect();
|
|
bool GetUseDoubleMeleeRoundDmgBonus() const { return use_double_melee_round_dmg_bonus; }
|
|
inline void SetUseDoubleMeleeRoundDmgBonus(bool val) { use_double_melee_round_dmg_bonus = val; }
|
|
|
|
void CastSpellOnLand(Mob* caster, int32 spell_id);
|
|
|
|
bool IsFocusProcLimitTimerActive(int32 focus_spell_id);
|
|
void SetFocusProcLimitTimer(int32 focus_spell_id, uint32 focus_reuse_time);
|
|
bool IsProcLimitTimerActive(int32 base_spell_id, uint32 proc_reuse_time, int proc_type);
|
|
void SetProcLimitTimer(int32 base_spell_id, uint32 proc_reuse_time, int proc_type);
|
|
|
|
void VirusEffectProcess();
|
|
void SpreadVirusEffect(int32 spell_id, uint32 caster_id, int32 buff_tics_remaining);
|
|
|
|
void ModSkillDmgTaken(EQ::skills::SkillType skill_num, int value);
|
|
int16 GetModSkillDmgTaken(const EQ::skills::SkillType skill_num);
|
|
void ModVulnerability(uint8 resist, int16 value);
|
|
int16 GetModVulnerability(const uint8 resist);
|
|
|
|
void SetAllowBeneficial(bool value) { m_AllowBeneficial = value; }
|
|
bool GetAllowBeneficial() { if (m_AllowBeneficial || GetSpecialAbility(SpecialAbility::AllowBeneficial)){return true;} return false; }
|
|
void SetDisableMelee(bool value) { m_DisableMelee = value; }
|
|
bool IsMeleeDisabled() { if (m_DisableMelee || GetSpecialAbility(SpecialAbility::DisableMelee)){return true;} return false; }
|
|
|
|
bool IsOffHandAtk() const { return offhand; }
|
|
inline void OffHandAtk(bool val) { offhand = val; }
|
|
|
|
void SetFlurryChance(uint8 value) { SetSpecialAbilityParam(SpecialAbility::Flurry, 0, value); }
|
|
uint8 GetFlurryChance() { return GetSpecialAbilityParam(SpecialAbility::Flurry, 0); }
|
|
|
|
static uint32 GetAppearanceValue(EmuAppearance in_appearance);
|
|
void SendAppearancePacket(uint32 type, uint32 value, bool whole_zone = true, bool ignore_self = false, Client* target = nullptr);
|
|
void SetAppearance(EmuAppearance app, bool ignore_self = true);
|
|
inline EmuAppearance GetAppearance() const { return _appearance; }
|
|
inline const int GetAnimation() const { return animation; }
|
|
inline void SetAnimation(int a) { animation = a; }
|
|
inline const uint8 GetRunAnimSpeed() const { return pRunAnimSpeed; }
|
|
inline void SetRunAnimSpeed(int8 in) { pRunAnimSpeed = in; }
|
|
bool IsDestructibleObject() { return destructibleobject; }
|
|
void SetDestructibleObject(bool in) { destructibleobject = in; }
|
|
|
|
inline uint8 GetInnateLightType() { return m_Light.Type[EQ::lightsource::LightInnate]; }
|
|
inline uint8 GetEquipmentLightType() { return m_Light.Type[EQ::lightsource::LightEquipment]; }
|
|
inline uint8 GetSpellLightType() { return m_Light.Type[EQ::lightsource::LightSpell]; }
|
|
|
|
virtual void UpdateEquipmentLight() { m_Light.Type[EQ::lightsource::LightEquipment] = 0; m_Light.Level[EQ::lightsource::LightEquipment] = 0; }
|
|
inline void SetSpellLightType(uint8 light_type) { m_Light.Type[EQ::lightsource::LightSpell] = (light_type & 0x0F); m_Light.Level[EQ::lightsource::LightSpell] = EQ::lightsource::TypeToLevel(m_Light.Type[EQ::lightsource::LightSpell]); }
|
|
|
|
void SendWearChangeAndLighting(int8 last_texture);
|
|
inline uint8 GetActiveLightType() { return m_Light.Type[EQ::lightsource::LightActive]; }
|
|
bool UpdateActiveLight(); // returns true if change, false if no change
|
|
|
|
EQ::LightSourceProfile* GetLightProfile() { return &m_Light; }
|
|
|
|
Mob* GetPet();
|
|
void SetPet(Mob* newpet);
|
|
virtual Mob* GetOwner();
|
|
virtual Mob* GetOwnerOrSelf();
|
|
Mob* GetUltimateOwner();
|
|
void SetPetID(uint16 NewPetID);
|
|
inline uint16 GetPetID() const { return petid; }
|
|
inline PetType GetPetType() const { return type_of_pet; }
|
|
void SetPetType(PetType p) { type_of_pet = p; }
|
|
inline int16 GetPetPower() const { return (petpower < 0) ? 0 : petpower; }
|
|
void SetPetPower(int16 p) { if (p < 0) petpower = 0; else petpower = p; }
|
|
bool IsFamiliar() const { return type_of_pet == petFamiliar; }
|
|
bool IsAnimation() const { return type_of_pet == petAnimation; }
|
|
bool IsCharmed() const { return type_of_pet == petCharmed; }
|
|
bool IsTargetLockPet() const { return type_of_pet == petTargetLock; }
|
|
inline uint32 GetPetTargetLockID() { return pet_targetlock_id; };
|
|
inline void SetPetTargetLockID(uint32 value) { pet_targetlock_id = value; };
|
|
void SetOwnerID(uint16 new_owner_id);
|
|
inline uint16 GetOwnerID() const { return ownerid; }
|
|
inline virtual bool HasOwner() { if (!GetOwnerID()){ return false; } return entity_list.GetMob(GetOwnerID()) != 0; }
|
|
inline virtual bool IsPet() { return HasOwner() && !IsMerc(); }
|
|
bool HasPet() const;
|
|
virtual bool IsCharmedPet() { return IsPet() && IsCharmed(); }
|
|
inline bool HasTempPetsActive() const { return(hasTempPet); }
|
|
inline void SetTempPetsActive(bool i) { hasTempPet = i; }
|
|
inline int16 GetTempPetCount() const { return count_TempPet; }
|
|
inline void SetTempPetCount(int16 i) { count_TempPet = i; }
|
|
bool HasPetAffinity() { if (aabonuses.GivePetGroupTarget || itembonuses.GivePetGroupTarget || spellbonuses.GivePetGroupTarget) return true; return false; }
|
|
inline bool IsPetOwnerBot() const { return pet_owner_bot; }
|
|
inline void SetPetOwnerBot(bool b) { pet_owner_bot = b; }
|
|
inline bool IsPetOwnerClient() const { return pet_owner_client; }
|
|
inline void SetPetOwnerClient(bool b) { pet_owner_client = b; }
|
|
inline bool IsPetOwnerNPC() const { return pet_owner_npc; }
|
|
inline void SetPetOwnerNPC(bool b) { pet_owner_npc = b; }
|
|
inline bool IsPetOwnerOfClientBot() const { return pet_owner_bot || pet_owner_client; }
|
|
inline bool IsTempPet() const { return _IsTempPet; }
|
|
inline void SetTempPet(bool value) { _IsTempPet = value; }
|
|
inline bool IsHorse() { return is_horse; }
|
|
int GetPetAvoidanceBonusFromOwner();
|
|
int GetPetACBonusFromOwner();
|
|
int GetPetATKBonusFromOwner();
|
|
|
|
inline const uint8 GetBodyType() const { return bodytype; }
|
|
inline const uint8 GetOrigBodyType() const { return orig_bodytype; }
|
|
void SetBodyType(uint8 new_body, bool overwrite_orig);
|
|
|
|
bool invulnerable;
|
|
bool qglobal;
|
|
|
|
inline std::vector<uint32> GetBotAttackFlags() { return bot_attack_flags; }
|
|
inline void SetBotAttackFlag(uint32 value) { bot_attack_flags.push_back(value); }
|
|
inline void ClearBotAttackFlags() { bot_attack_flags.clear(); }
|
|
bool HasBotAttackFlag(Mob* tar);
|
|
|
|
virtual void SetAttackTimer();
|
|
inline void SetInvul(bool invul) { invulnerable=invul; }
|
|
inline bool GetInvul(void) { return invulnerable; }
|
|
void SetExtraHaste(int haste, bool need_to_save = true);
|
|
inline int GetExtraHaste() { return extra_haste; }
|
|
virtual int GetHaste();
|
|
int32 GetMeleeMitigation();
|
|
|
|
uint8 GetWeaponDamageBonus(const EQ::ItemData* weapon, bool offhand = false);
|
|
const DamageTable &GetDamageTable() const;
|
|
int GetMobFixedOffenseSkill();
|
|
int GetMobFixedWeaponSkill();
|
|
void ApplyDamageTable(DamageHitInfo &hit);
|
|
virtual int GetHandToHandDamage(void);
|
|
|
|
bool CanThisClassDoubleAttack(void) const;
|
|
bool CanThisClassTripleAttack() const;
|
|
bool CanThisClassDualWield(void) const;
|
|
bool CanThisClassRiposte(void) const;
|
|
bool CanThisClassDodge(void) const;
|
|
bool CanThisClassParry(void) const;
|
|
bool CanThisClassBlock(void) const;
|
|
|
|
int GetHandToHandDelay(void);
|
|
uint32 GetClassLevelFactor();
|
|
void Mesmerize();
|
|
inline bool IsMezzed() const { return mezzed; }
|
|
inline bool IsStunned() const { return stunned; }
|
|
inline bool IsSilenced() const { return silenced; }
|
|
inline bool IsAmnesiad() const { return amnesiad; }
|
|
|
|
int64 ReduceDamage(int64 damage);
|
|
int64 AffectMagicalDamage(int64 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker);
|
|
int64 ReduceAllDamage(int64 damage);
|
|
|
|
void DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int base_damage, int min_damage = 0, int32 hate_override = -1, int ReuseTime = 10);
|
|
void DoThrowingAttackDmg(Mob* other, const EQ::ItemInstance* RangeWeapon = nullptr, const EQ::ItemData* AmmoItem = nullptr, int32 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, int AmmoSlot = 0, float speed = 4.0f, bool DisableProcs = false);
|
|
void DoMeleeSkillAttackDmg(Mob* other, int32 weapon_damage, EQ::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool can_riposte = false, int ReuseTime = 0);
|
|
void DoArcheryAttackDmg(Mob* other, const EQ::ItemInstance* RangeWeapon = nullptr, const EQ::ItemInstance* Ammo = nullptr, int32 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, uint32 ammo_id = 0, const EQ::ItemData *AmmoItem = nullptr, int AmmoSlot = 0, float speed = 4.0f, bool DisableProcs = false);
|
|
bool TryProjectileAttack(Mob* other, const EQ::ItemData *item, EQ::skills::SkillType skillInUse, uint64 weapon_dmg, const EQ::ItemInstance* RangeWeapon, const EQ::ItemInstance* Ammo, int AmmoSlot, float speed, bool DisableProcs = false);
|
|
void ProjectileAttack();
|
|
inline bool HasProjectileAttack() const { return ActiveProjectileATK; }
|
|
inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; }
|
|
float GetRangeDistTargetSizeMod(Mob* other);
|
|
bool CanDoSpecialAttack(Mob *other);
|
|
bool Flurry(ExtraAttackOptions *opts);
|
|
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);
|
|
inline bool IsSpecialAttack(eSpecialAttacks in) { return m_specialattacks == in; }
|
|
|
|
void StartEnrage();
|
|
void ProcessEnrage();
|
|
bool IsEnraged();
|
|
void Taunt(NPC *who, bool always_succeed, int chance_bonus = 0, bool from_spell = false, int32 bonus_hate = 0);
|
|
|
|
virtual void AI_Init();
|
|
virtual void AI_Start(uint32 iMoveDelay = 0);
|
|
virtual void AI_Stop();
|
|
virtual void AI_ShutDown();
|
|
virtual void AI_Process();
|
|
|
|
bool ClearEntityVariables();
|
|
bool DeleteEntityVariable(std::string variable_name);
|
|
std::string GetEntityVariable(std::string variable_name);
|
|
std::vector<std::string> GetEntityVariables();
|
|
void SetEntityVariable(std::string variable_name, std::string variable_value);
|
|
bool EntityVariableExists(std::string variable_name);
|
|
|
|
void AI_Event_Engaged(Mob* attacker, bool yell_for_help = true);
|
|
void AI_Event_NoLongerEngaged();
|
|
|
|
FACTION_VALUE GetSpecialFactionCon(Mob* iOther);
|
|
inline const bool IsAIControlled() const { return pAIControlled; }
|
|
inline const float GetAggroRange() const { return (spellbonuses.AggroRange == -1) ? pAggroRange : spellbonuses.AggroRange; }
|
|
inline const float GetAssistRange() const { return (spellbonuses.AssistRange == -1) ? pAssistRange : spellbonuses.AssistRange; }
|
|
|
|
|
|
void SetPetOrder(eStandingPetOrder i);
|
|
inline const eStandingPetOrder GetPetOrder() const { return pStandingPetOrder; }
|
|
inline void SetHeld(bool nState) { held = nState; }
|
|
inline const bool IsHeld() const { return held; }
|
|
inline void SetGHeld(bool nState) { gheld = nState; }
|
|
inline const bool IsGHeld() const { return gheld; }
|
|
inline void SetNoCast(bool nState) { nocast = nState; }
|
|
inline const bool IsNoCast() const { return nocast; }
|
|
inline void SetFocused(bool nState) { focused = nState; }
|
|
inline const bool IsFocused() const { return focused; }
|
|
inline void SetPetStop(bool nState) { pet_stop = nState; }
|
|
inline const bool IsPetStop() const { return pet_stop; }
|
|
inline void SetPetRegroup(bool nState) { pet_regroup = nState; }
|
|
inline const bool IsPetRegroup() const { return pet_regroup; }
|
|
inline const bool IsRoamer() const { return roamer; }
|
|
inline const int GetWanderType() const { return wandertype; }
|
|
inline const bool IsRooted() const { return rooted || permarooted; }
|
|
inline const bool IsPermaRooted() const { return permarooted; }
|
|
int GetSnaredAmount();
|
|
inline const bool IsPseudoRooted() const { return pseudo_rooted; }
|
|
inline void SetPseudoRoot(bool prState) { pseudo_rooted = prState; }
|
|
|
|
int GetCurWp() { return cur_wp; }
|
|
|
|
//old fear function
|
|
//void SetFeared(Mob *caster, uint32 duration, bool flee = false);
|
|
int GetFearSpeed() { return _GetFearSpeed(); }
|
|
bool IsFeared() { return (spellbonuses.IsFeared || flee_mode); } // This returns true if the mob is feared or fleeing due to low HP
|
|
inline void StartFleeing() { flee_mode = true; CalculateNewFearpoint(); }
|
|
void StopFleeing();
|
|
inline bool IsFleeing() { return flee_mode; }
|
|
void ProcessFlee();
|
|
void CheckFlee();
|
|
void FleeInfo(Mob* client);
|
|
int GetFleeRatio(Mob* other = nullptr);
|
|
inline bool IsBlind() { return spellbonuses.IsBlind; }
|
|
|
|
inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);}
|
|
float CalculateHeadingToTarget(float in_x, float in_y) { return HeadingAngleToMob(in_x, in_y); }
|
|
virtual void WalkTo(float x, float y, float z);
|
|
virtual void RunTo(float x, float y, float z);
|
|
void NavigateTo(float x, float y, float z);
|
|
void RotateTo(float new_heading);
|
|
void RotateToWalking(float new_heading);
|
|
void RotateToRunning(float new_heading);
|
|
void StopNavigation();
|
|
float CalculateDistance(float x, float y, float z);
|
|
float CalculateDistance(Mob* mob);
|
|
float GetGroundZ(float new_x, float new_y, float z_offset=0.0);
|
|
void SendTo(float new_x, float new_y, float new_z);
|
|
void SendToFixZ(float new_x, float new_y, float new_z);
|
|
float GetZOffset() const;
|
|
float GetDefaultRaceSize(int race_id = -1, int gender_id = -1) const;
|
|
void FixZ(int32 z_find_offset = 5, bool fix_client_z = false);
|
|
float GetFixedZ(const glm::vec3 &destination, int32 z_find_offset = 5);
|
|
virtual int GetStuckBehavior() const { return 0; }
|
|
|
|
void NPCSpecialAttacks(const char *parse, int permtag, bool reset = true, bool remove = false);
|
|
inline uint32 DontHealMeBefore() const { return m_dont_heal_me_before; }
|
|
inline uint32 DontBuffMeBefore() const { return m_dont_buff_me_before; }
|
|
inline uint32 DontDotMeBefore() const { return m_dont_dot_me_before; }
|
|
inline uint32 DontRootMeBefore() const { return m_dont_root_me_before; }
|
|
inline uint32 DontSnareMeBefore() const { return m_dont_snare_me_before; }
|
|
inline uint32 DontCureMeBefore() const { return m_dont_cure_me_before; }
|
|
|
|
void SetDontRootMeBefore(uint32 time) { m_dont_root_me_before = time; }
|
|
void SetDontHealMeBefore(uint32 time) { m_dont_heal_me_before = time; }
|
|
void SetDontBuffMeBefore(uint32 time) { m_dont_buff_me_before = time; }
|
|
void SetDontDotMeBefore(uint32 time) { m_dont_dot_me_before = time; }
|
|
void SetDontSnareMeBefore(uint32 time) { m_dont_snare_me_before = time; }
|
|
void SetDontCureMeBefore(uint32 time) { m_dont_cure_me_before = time; }
|
|
|
|
// calculate interruption of spell via movement of mob
|
|
void SaveSpellLoc() { m_SpellLocation = glm::vec3(m_Position); }
|
|
inline float GetSpellX() const {return m_SpellLocation.x;}
|
|
inline float GetSpellY() const {return m_SpellLocation.y;}
|
|
inline float GetSpellZ() const {return m_SpellLocation.z;}
|
|
inline bool IsGrouped() const { return isgrouped; }
|
|
void SetGrouped(bool v);
|
|
inline bool IsRaidGrouped() const { return israidgrouped; }
|
|
void SetRaidGrouped(bool v);
|
|
inline uint16 IsLooting() const { return entity_id_being_looted; }
|
|
void SetLooting(uint16 val) { entity_id_being_looted = val; }
|
|
|
|
bool CheckWillAggro(Mob *mob);
|
|
bool IsPetAggroExempt(Mob *pet_owner);
|
|
|
|
void InstillDoubt(Mob *who);
|
|
bool Charmed() const { return type_of_pet == petCharmed; }
|
|
static uint32 GetLevelHP(uint8 tlevel);
|
|
uint32 GetZoneID() const; //for perl
|
|
uint16 GetInstanceVersion() const; //for perl
|
|
virtual int32 CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc = false);
|
|
virtual int32 CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possible = 0);
|
|
|
|
//uint32 GetInstrumentMod(uint16 spell_id) const;
|
|
uint32 GetInstrumentMod(uint16 spell_id);
|
|
int64 CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, uint32 instrument_mod = 10, Mob *caster = nullptr, int ticsremaining = 0,uint16 casterid=0);
|
|
int64 CalcSpellEffectValue_formula(uint32 formula, int64 base_value, int64 max_value, int caster_level, uint16 spell_id, int ticsremaining = 0);
|
|
virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr, int buffslot = -1);
|
|
uint32 GetCastedSpellInvSlot() const { return casting_spell_inventory_slot; }
|
|
|
|
// HP Event
|
|
inline int GetNextHPEvent() const { return nexthpevent; }
|
|
void SetNextHPEvent( int hpevent );
|
|
void SendItemAnimation(Mob *to, const EQ::ItemData *item, EQ::skills::SkillType skillInUse, float velocity = 4.0);
|
|
inline int& GetNextIncHPEvent() { return nextinchpevent; }
|
|
void SetNextIncHPEvent( int inchpevent );
|
|
|
|
inline bool DivineAura() const { return spellbonuses.DivineAura; }
|
|
inline bool Sanctuary() const { return spellbonuses.Sanctuary; }
|
|
|
|
bool HasNPCSpecialAtk(const char* parse);
|
|
bool HasSpecialAbilities();
|
|
int GetSpecialAbility(int ability);
|
|
int GetSpecialAbilityParam(int ability, int param);
|
|
void SetSpecialAbility(int ability, int level);
|
|
void SetSpecialAbilityParam(int ability, int param, int value);
|
|
void StartSpecialAbilityTimer(int ability, uint32 time);
|
|
void StopSpecialAbilityTimer(int ability);
|
|
Timer *GetSpecialAbilityTimer(int ability);
|
|
void ClearSpecialAbilities();
|
|
void ProcessSpecialAbilities(const std::string &str);
|
|
bool IsMoved() { return moved; }
|
|
void SetMoved(bool moveflag) { moved = moveflag; }
|
|
|
|
Trade* trade;
|
|
|
|
bool ShieldAbility(uint32 target_id, int shielder_max_distance = 15, int shield_duration = 12000, int shield_target_mitigation = 50, int shielder_mitigation = 75, bool use_aa = false, bool can_shield_npc = true);
|
|
void DoShieldDamageOnShielder(Mob *shield_target, int64 hit_damage_done, EQ::skills::SkillType skillInUse);
|
|
void ShieldAbilityFinish();
|
|
void ShieldAbilityClearVariables();
|
|
inline uint32 GetShielderID() const { return m_shielder_id; }
|
|
inline void SetShielderID(uint32 val) { m_shielder_id = val; }
|
|
inline uint32 GetShieldTargetID() const { return m_shield_target_id; }
|
|
inline void SetShieldTargetID(uint32 val) { m_shield_target_id = val; }
|
|
inline int GetShieldTargetMitigation() const { return m_shield_target_mitigation; }
|
|
inline void SetShieldTargetMitigation(int val) { m_shield_target_mitigation = val; }
|
|
inline int GetShielderMitigation() const { return m_shielder_mitigation; }
|
|
inline void SetShielderMitigation(int val) { m_shielder_mitigation = val; }
|
|
inline int GetMaxShielderDistance() const { return m_shielder_max_distance; }
|
|
inline void SetShielderMaxDistance(int val) { m_shielder_max_distance = val; }
|
|
|
|
WeaponStance_Struct weaponstance;
|
|
bool IsWeaponStanceEnabled() const { return weaponstance.enabled; }
|
|
inline void SetWeaponStanceEnabled(bool val) { weaponstance.enabled = val; }
|
|
|
|
|
|
inline glm::vec4 GetCurrentWayPoint() const { return m_CurrentWayPoint; }
|
|
inline float GetCWPP() const { return(static_cast<float>(cur_wp_pause)); }
|
|
inline int GetCWP() const { return(cur_wp); }
|
|
void SetCurrentWP(int waypoint) { cur_wp = waypoint; }
|
|
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENTLY; }
|
|
|
|
virtual const bool IsUnderwaterOnly() const { return false; }
|
|
inline bool IsTrackable() const { return(trackable); }
|
|
Timer* GetAIThinkTimer() { return AI_think_timer.get(); }
|
|
Timer* GetAIMovementTimer() { return AI_movement_timer.get(); }
|
|
Timer GetAttackTimer() { return attack_timer; }
|
|
Timer GetAttackDWTimer() { return attack_dw_timer; }
|
|
inline bool IsFindable() { return findable; }
|
|
inline uint8 GetManaPercent() { return (uint8)((float)current_mana / (float)max_mana * 100.0f); }
|
|
virtual uint8 GetEndurancePercent() { return 0; }
|
|
|
|
inline virtual bool IsBlockedBuff(int32 SpellID) { return false; }
|
|
inline virtual bool IsBlockedPetBuff(int32 SpellID) { return false; }
|
|
|
|
inline void RestoreEndurance() { SetEndurance(GetMaxEndurance()); }
|
|
inline void RestoreHealth() { SetMaxHP(); SendHPUpdate(); }
|
|
inline void RestoreMana() { SetMana(GetMaxMana()); }
|
|
|
|
std::string GetGlobal(const char *varname);
|
|
void SetGlobal(const char *varname, const char *newvalue, int options, const char *duration, Mob *other = nullptr);
|
|
void TarGlobal(const char *varname, const char *value, const char *duration, int npcid, int charid, int zoneid);
|
|
void DelGlobal(const char *varname);
|
|
|
|
inline void SetEmoteID(uint32 emote) { emoteid = emote; }
|
|
inline uint32 GetEmoteID() { return emoteid; }
|
|
|
|
bool HasSpellEffect(int effect_id);
|
|
|
|
std::string GetRacePlural();
|
|
std::string GetClassPlural();
|
|
|
|
inline void SetMerchantSessionEntityID(uint16 value) { m_merchant_session_entity_id = value; }
|
|
inline uint16 GetMerchantSessionEntityID() { return m_merchant_session_entity_id; }
|
|
|
|
//Command #Tune functions
|
|
void TuneGetStats(Mob* defender, Mob *attacker);
|
|
void TuneGetACByPctMitigation(Mob* defender, Mob *attacker, float pct_mitigation, int interval = 10, int max_loop = 1000, int atk_override = 0, int Msg = 0);
|
|
void TuneGetATKByPctMitigation(Mob* defender, Mob *attacker, float pct_mitigation, int interval = 10, int max_loop = 1000, int ac_override = 0, int Msg = 0);
|
|
void TuneGetAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int accuracy_override, int Msg);
|
|
void TuneGetAccuracyByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int avoidance_override, int Msg);
|
|
/*support functions*/
|
|
int64 TuneClientGetMeanDamage(Mob* other, int ac_override = 0, int atk_override = 0, int add_ac = 0, int add_atk = 0);
|
|
int64 TuneClientGetMaxDamage(Mob* other);
|
|
int64 TuneClientGetMinDamage(Mob* other, int max_hit);
|
|
float TuneGetACMitigationPct(Mob* defender, Mob *attacker);
|
|
int64 TuneGetOffense(Mob* defender, Mob *attacker, int atk_override = 0);
|
|
int64 TuneGetAccuracy(Mob* defender, Mob *attacker, int accuracy_override = 0, int add_accuracy = 0);
|
|
int64 TuneGetAvoidance(Mob* defender, Mob *attacker, int avoidance_override = 0, int add_avoidance = 0);
|
|
float TuneGetHitChance(Mob* defender, Mob *attacker, int avoidance_override = 0, int accuracy_override = 0, int add_avoidance = 0, int add_accuracy = 0);
|
|
float TuneGetAvoidMeleeChance(Mob* defender, Mob *attacker, int type);
|
|
int64 TuneCalcEvasionBonus(int final_avoidance, int base_avoidance);
|
|
/*modified combat code - These SYNC to attack.cpp, relevant changes to these functions in attack.cpp should be changed to the below as well*/
|
|
int64 TuneNPCAttack(Mob* other, bool no_avoid = true, bool no_hit_chance = true, int hit_chance_bonus = 10000, int ac_override = 0, int atk_override = 0, int add_ac = 0, int add_atk = 0,
|
|
bool get_offense = false, bool get_accuracy = false, int avoidance_override = 0, int accuracy_override = 0, int add_avoidance = 0, int add_accuracy = 0);
|
|
int64 TuneClientAttack(Mob* other, bool no_avoid = true, bool no_hit_chance = true, int hit_chance_bonus = 10000, int ac_override = 0, int atk_override = 0, int add_ac = 0, int add_atk = 0,
|
|
bool get_offense = false, bool get_accuracy = false, int avoidance_override = 0, int accuracy_override = 0, int add_avoidance = 0, int add_accuracy = 0);
|
|
void TuneDoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr, bool no_avoid = true, bool no_hit_chance = true, int ac_override = 0, int add_ac = 0,
|
|
int avoidance_override = 0, int accuracy_override = 0, int add_avoidance = 0, int add_accuracy = 0);
|
|
void TuneMeleeMitigation(Mob *attacker, DamageHitInfo &hit, int ac_override, int add_ac);
|
|
int64 Tuneoffense(EQ::skills::SkillType skill, int atk_override = 0, int add_atk = 0);
|
|
int64 TuneACSum(bool skip_caps=false, int ac_override = 0, int add_ac = 0);
|
|
int64 TuneGetTotalToHit(EQ::skills::SkillType skill, int chance_mod, int accuracy_override = 0, int add_accurracy = 0); // compute_tohit + spell bonuses
|
|
int64 Tunecompute_tohit(EQ::skills::SkillType skillinuse, int accuracy_override = 0, int add_accuracy = 0);
|
|
int64 TuneGetTotalDefense(int avoidance_override = 0, int add_avoidance = 0);
|
|
int64 Tunecompute_defense(int avoidance_override = 0, int add_avoidance = 0);
|
|
bool TuneCheckHitChance(Mob* other, DamageHitInfo &hit, int avoidance_override = 0, int add_avoidance = 0);
|
|
EQ::skills::SkillType TuneAttackAnimation(int Hand, const EQ::ItemInstance* weapon, EQ::skills::SkillType skillinuse = EQ::skills::Skill1HBlunt);
|
|
void TuneCommonOutgoingHitSuccess(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr);
|
|
|
|
//aa new
|
|
uint32 GetAA(uint32 rank_id, uint32 *charges = nullptr) const;
|
|
uint32 GetAAByAAID(uint32 aa_id, uint32 *charges = nullptr) const;
|
|
bool SetAA(uint32 rank_id, uint32 new_value, uint32 charges = 0);
|
|
void ClearAAs() { aa_ranks.clear(); }
|
|
bool CanUseAlternateAdvancementRank(AA::Rank *rank);
|
|
bool CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price, bool check_grant);
|
|
int GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in);
|
|
void ExpendAlternateAdvancementCharge(uint32 aa_id);
|
|
void CalcAABonuses(StatBonuses* newbon);
|
|
int64 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id);
|
|
void ApplyAABonuses(const AA::Rank &rank, StatBonuses* newbon);
|
|
bool CheckAATimer(int timer);
|
|
|
|
void CalcItemBonuses(StatBonuses* b);
|
|
void AddItemBonuses(const EQ::ItemInstance* inst, StatBonuses* b, bool is_augment = false, bool is_tribute = false, int recommended_level_override = 0, bool is_ammo_item = false);
|
|
void AdditiveWornBonuses(const EQ::ItemInstance* inst, StatBonuses* b, bool is_augment = false);
|
|
int CalcRecommendedLevelBonus(uint8 current_level, uint8 recommended_level, int base_stat);
|
|
|
|
int NPCAssistCap() { return npc_assist_cap; }
|
|
void AddAssistCap() { ++npc_assist_cap; }
|
|
void DelAssistCap() { --npc_assist_cap; }
|
|
void ResetAssistCap() { npc_assist_cap = 0; }
|
|
int64 GetWeaponDamage(Mob *against, const EQ::ItemData *weapon_item);
|
|
int64 GetWeaponDamage(Mob *against, const EQ::ItemInstance *weapon_item, int64 *hate = nullptr);
|
|
int64 DoDamageCaps(int64 base_damage);
|
|
|
|
int64 GetHPRegen() const;
|
|
int64 GetHPRegenPerSecond() const;
|
|
int64 GetManaRegen() const;
|
|
int64 GetEnduranceRegen() const;
|
|
|
|
bool CanOpenDoors() const;
|
|
void SetCanOpenDoors(bool can_open);
|
|
|
|
void SetFeigned(bool in_feigned);
|
|
/// this cures timing issues cuz dead animation isn't done but server side feigning is?
|
|
inline bool GetFeigned() const { return(feigned); }
|
|
|
|
// Data Bucket Methods
|
|
void DeleteBucket(std::string bucket_name);
|
|
std::string GetBucket(std::string bucket_name);
|
|
std::string GetBucketExpires(std::string bucket_name);
|
|
std::string GetBucketRemaining(std::string bucket_name);
|
|
void SetBucket(std::string bucket_name, std::string bucket_value, std::string expiration = "");
|
|
|
|
uint32 GetMobTypeIdentifier();
|
|
|
|
// Heroic Stat Benefits
|
|
float CheckHeroicBonusesDataBuckets(std::string bucket_name);
|
|
|
|
int DispatchZoneControllerEvent(QuestEventID evt, Mob* init, const std::string& data, uint32 extra, std::vector<std::any>* pointers);
|
|
|
|
// Bots HealRotation methods
|
|
bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); }
|
|
bool JoinHealRotationTargetPool(std::shared_ptr<HealRotation>* heal_rotation);
|
|
bool LeaveHealRotationTargetPool();
|
|
|
|
uint32 HealRotationHealCount();
|
|
uint32 HealRotationExtendedHealCount();
|
|
float HealRotationHealFrequency();
|
|
float HealRotationExtendedHealFrequency();
|
|
|
|
const std::shared_ptr<HealRotation>* TargetOfHealRotation() const { return &m_target_of_heal_rotation; }
|
|
|
|
|
|
// not Bots HealRotation methods
|
|
void SetManualFollow(bool flag) { m_manual_follow = flag; }
|
|
bool GetManualFollow() const { return m_manual_follow; }
|
|
|
|
void DrawDebugCoordinateNode(std::string node_name, const glm::vec4 vec);
|
|
|
|
void CalcHeroicBonuses(StatBonuses* newbon);
|
|
|
|
DataBucketKey GetScopedBucketKeys();
|
|
|
|
bool IsCloseToBanker();
|
|
|
|
std::unordered_map<uint16, Mob *> &GetCloseMobList(float distance = 0.0f);
|
|
void CheckScanCloseMobsMovingTimer();
|
|
|
|
void ClearDataBucketCache();
|
|
bool IsGuildmaster() const;
|
|
|
|
protected:
|
|
void CommonDamage(Mob* other, int64 &damage, const uint16 spell_id, const EQ::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks specal = eSpecialAttacks::None);
|
|
static uint16 GetProcID(uint16 spell_id, uint8 effect_index);
|
|
int _GetWalkSpeed() const;
|
|
int _GetRunSpeed() const;
|
|
int _GetFearSpeed() const;
|
|
|
|
Timer m_z_clip_check_timer;
|
|
|
|
// dynamically set via memory on constructor
|
|
int8 m_max_procs = 0;
|
|
|
|
virtual bool AI_EngagedCastCheck() { return(false); }
|
|
virtual bool AI_PursueCastCheck() { return(false); }
|
|
virtual bool AI_IdleCastCheck() { return(false); }
|
|
|
|
bool moved;
|
|
|
|
std::vector<uint16> RampageArray;
|
|
std::map<std::string, std::string> m_EntityVariables;
|
|
|
|
int16 SkillDmgTaken_Mod[EQ::skills::HIGHEST_SKILL + 2];
|
|
int16 Vulnerability_Mod[HIGHEST_RESIST+2];
|
|
bool m_AllowBeneficial;
|
|
bool m_DisableMelee;
|
|
|
|
bool isgrouped;
|
|
bool israidgrouped;
|
|
uint16 entity_id_being_looted; //the id of the entity being looted, 0 if not looting.
|
|
uint8 texture;
|
|
uint8 helmtexture;
|
|
uint8 armtexture;
|
|
uint8 bracertexture;
|
|
uint8 handtexture;
|
|
uint8 legtexture;
|
|
uint8 feettexture;
|
|
bool multitexture;
|
|
|
|
int AC;
|
|
int mitigation_ac; // cached Mob::ACSum
|
|
int32 ATK;
|
|
int32 STR;
|
|
int32 STA;
|
|
int32 DEX;
|
|
int32 AGI;
|
|
int32 INT;
|
|
int32 WIS;
|
|
int32 CHA;
|
|
int32 MR;
|
|
int32 CR;
|
|
int32 FR;
|
|
int32 DR;
|
|
int32 PR;
|
|
int32 Corrup;
|
|
int32 PhR;
|
|
bool moving;
|
|
int targeted;
|
|
bool findable;
|
|
bool trackable;
|
|
int64 current_hp;
|
|
int64 max_hp;
|
|
int64 base_hp;
|
|
int64 current_mana;
|
|
int64 max_mana;
|
|
int64 hp_regen;
|
|
int64 hp_regen_per_second;
|
|
int64 mana_regen;
|
|
int64 ooc_regen;
|
|
uint8 maxlevel;
|
|
uint32 scalerate;
|
|
Buffs_Struct *buffs;
|
|
StatBonuses itembonuses;
|
|
StatBonuses spellbonuses;
|
|
StatBonuses aabonuses;
|
|
uint16 petid;
|
|
uint16 ownerid;
|
|
PetType type_of_pet;
|
|
int16 petpower;
|
|
uint32 follow_id;
|
|
uint32 follow_dist;
|
|
bool follow_run;
|
|
bool no_target_hotkey;
|
|
bool rare_spawn;
|
|
int32 heroic_strikethrough;
|
|
bool keeps_sold_items;
|
|
|
|
uint32 m_PlayerState;
|
|
uint32 GetPlayerState() { return m_PlayerState; }
|
|
void AddPlayerState(uint32 new_state) { m_PlayerState |= new_state; }
|
|
void RemovePlayerState(uint32 old_state) { m_PlayerState &= ~old_state; }
|
|
void SendAddPlayerState(PlayerState new_state);
|
|
void SendRemovePlayerState(PlayerState old_state);
|
|
|
|
uint8 gender;
|
|
uint16 race;
|
|
uint16 use_model;
|
|
uint8 base_gender;
|
|
uint16 base_race;
|
|
uint8 class_;
|
|
uint8 bodytype;
|
|
uint8 orig_bodytype;
|
|
uint16 deity;
|
|
uint8 level;
|
|
uint8 orig_level;
|
|
uint32 npctype_id;
|
|
|
|
glm::vec4 m_Position;
|
|
glm::vec4 m_RelativePosition;
|
|
int animation; // this is really what MQ2 calls SpeedRun just packed like (int)(SpeedRun * 40.0f)
|
|
float base_size;
|
|
float size;
|
|
float runspeed;
|
|
float walkspeed;
|
|
float fearspeed;
|
|
int base_runspeed;
|
|
int base_walkspeed;
|
|
int base_fearspeed;
|
|
int current_speed;
|
|
eSpecialAttacks m_specialattacks;
|
|
|
|
bool held;
|
|
bool gheld;
|
|
bool nocast;
|
|
bool focused;
|
|
bool pet_stop;
|
|
bool pet_regroup;
|
|
bool spawned;
|
|
void CalcSpellBonuses(StatBonuses* newbon);
|
|
virtual void CalcBonuses();
|
|
void TrySkillProc(Mob *on, EQ::skills::SkillType skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); // hand if 0 means its a skill ability for proc rate checks, otherwise hand is passed.
|
|
bool PassLimitToSkill(EQ::skills::SkillType skill, int32 spell_id, int proc_type, int aa_id=0);
|
|
bool PassLimitClass(uint32 Classes_, uint16 Class_);
|
|
void TryCastOnSkillUse(Mob *on, EQ::skills::SkillType skill);
|
|
void TryDefensiveProc(Mob *on, uint16 hand = EQ::invslot::slotPrimary);
|
|
void TryWeaponProc(const EQ::ItemInstance* inst, const EQ::ItemData* weapon, Mob *on, uint16 hand = EQ::invslot::slotPrimary);
|
|
void TrySpellProc(const EQ::ItemInstance* inst, const EQ::ItemData* weapon, Mob *on, uint16 hand = EQ::invslot::slotPrimary);
|
|
void TryCombatProcs(const EQ::ItemInstance* weapon, Mob *on, uint16 hand = EQ::invslot::slotPrimary, const EQ::ItemData* weapon_data = nullptr);
|
|
void ExecWeaponProc(const EQ::ItemInstance* weapon, uint16 spell_id, Mob *on, int level_override = -1);
|
|
virtual float GetProcChances(float ProcBonus, uint16 hand = EQ::invslot::slotPrimary);
|
|
virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = EQ::invslot::slotPrimary, Mob *on = nullptr);
|
|
virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm?
|
|
uint16 GetWeaponSpeedbyHand(uint16 hand);
|
|
virtual int GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target = nullptr);
|
|
virtual int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false);
|
|
virtual EQ::InventoryProfile& GetInv() { return m_inv; }
|
|
void CalculateNewFearpoint();
|
|
float FindGroundZ(float new_x, float new_y, float z_offset=0.0);
|
|
float FindDestGroundZ(glm::vec3 dest, float z_offset=0.0);
|
|
|
|
virtual float GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 ItemProcRate = 0);
|
|
int16 GetSympatheticSpellProcRate(uint16 spell_id);
|
|
uint16 GetSympatheticSpellProcID(uint16 spell_id);
|
|
|
|
enum {MAX_PROCS = 10};
|
|
tProc PermaProcs[MAX_PROCS];
|
|
tProc SpellProcs[MAX_PROCS];
|
|
tProc DefensiveProcs[MAX_PROCS];
|
|
tProc RangedProcs[MAX_PROCS];
|
|
|
|
char name[64];
|
|
char orig_name[64];
|
|
char clean_name[64];
|
|
char lastname[64];
|
|
|
|
glm::vec4 m_Delta;
|
|
// just locs around them to double check, if we do expand collision this should be cached on movement
|
|
// ideally we should use real models, but this should be quick and work mostly
|
|
glm::vec4 m_CollisionBox[COLLISION_BOX_SIZE];
|
|
|
|
EQ::LightSourceProfile m_Light;
|
|
|
|
EmuAppearance _appearance;
|
|
uint8 pRunAnimSpeed;
|
|
bool m_is_running;
|
|
|
|
Timer attack_timer;
|
|
Timer attack_dw_timer;
|
|
Timer ranged_timer;
|
|
float attack_speed; //% increase/decrease in attack speed (not haste)
|
|
int attack_delay; //delay between attacks in 10ths of seconds
|
|
bool always_aggro;
|
|
int16 slow_mitigation; // Allows for a slow mitigation (100 = 100%, 50% = 50%)
|
|
Timer hp_regen_per_second_timer;
|
|
Timer tic_timer;
|
|
Timer mana_timer;
|
|
int32 dw_same_delay;
|
|
|
|
Timer focusproclimit_timer[MAX_FOCUS_PROC_LIMIT_TIMERS]; //SPA 511
|
|
int32 focusproclimit_spellid[MAX_FOCUS_PROC_LIMIT_TIMERS]; //SPA 511
|
|
|
|
Timer spell_proclimit_timer[MAX_PROC_LIMIT_TIMERS]; //SPA 512
|
|
int32 spell_proclimit_spellid[MAX_PROC_LIMIT_TIMERS]; //SPA 512
|
|
Timer ranged_proclimit_timer[MAX_PROC_LIMIT_TIMERS]; //SPA 512
|
|
int32 ranged_proclimit_spellid[MAX_PROC_LIMIT_TIMERS]; //SPA 512
|
|
Timer def_proclimit_timer[MAX_PROC_LIMIT_TIMERS]; //SPA 512
|
|
int32 def_proclimit_spellid[MAX_PROC_LIMIT_TIMERS]; //SPA 512
|
|
|
|
int32 appearance_effects_id[MAX_APPEARANCE_EFFECTS];
|
|
int32 appearance_effects_slot[MAX_APPEARANCE_EFFECTS];
|
|
|
|
Timer shield_timer;
|
|
uint32 m_shield_target_id;
|
|
uint32 m_shielder_id;
|
|
int m_shield_target_mitigation;
|
|
int m_shielder_mitigation;
|
|
int m_shielder_max_distance;
|
|
|
|
//spell casting vars
|
|
Timer spellend_timer;
|
|
uint16 casting_spell_id;
|
|
glm::vec3 m_SpellLocation;
|
|
int attacked_count;
|
|
bool delaytimer;
|
|
uint16 casting_spell_targetid;
|
|
EQ::spells::CastingSlot casting_spell_slot;
|
|
int32 casting_spell_mana;
|
|
uint32 casting_spell_inventory_slot;
|
|
uint32 casting_spell_timer;
|
|
uint32 casting_spell_timer_duration;
|
|
int16 casting_spell_resist_adjust;
|
|
uint32 casting_spell_aa_id;
|
|
uint32 casting_spell_recast_adjust;
|
|
bool casting_spell_checks;
|
|
uint16 bardsong;
|
|
EQ::spells::CastingSlot bardsong_slot;
|
|
uint32 bardsong_target_id;
|
|
|
|
bool ActiveProjectileATK;
|
|
tProjatk ProjectileAtk[MAX_SPELL_PROJECTILE];
|
|
|
|
glm::vec3 m_RewindLocation;
|
|
|
|
Timer rewind_timer;
|
|
|
|
// Currently 3 max nimbus particle effects at a time
|
|
uint32 nimbus_effect1;
|
|
uint32 nimbus_effect2;
|
|
uint32 nimbus_effect3;
|
|
|
|
uint8 haircolor;
|
|
uint8 beardcolor;
|
|
uint8 eyecolor1; // the eyecolors always seem to be the same, maybe left and right eye?
|
|
uint8 eyecolor2;
|
|
uint8 hairstyle;
|
|
uint8 luclinface; //
|
|
uint8 beard;
|
|
uint32 drakkin_heritage;
|
|
uint32 drakkin_tattoo;
|
|
uint32 drakkin_details;
|
|
EQ::TintProfile armor_tint;
|
|
|
|
uint8 aa_title;
|
|
|
|
int extra_haste; // for the #haste command
|
|
bool mezzed;
|
|
bool stunned;
|
|
bool charmed; //this isnt fully implemented yet
|
|
bool rooted;
|
|
bool silenced;
|
|
bool amnesiad;
|
|
bool offhand;
|
|
bool has_shield_equipped;
|
|
bool has_two_hand_blunt_equipped;
|
|
bool has_two_hander_equipped;
|
|
bool has_dual_weapons_equipped;
|
|
bool has_bowequipped = false;
|
|
bool has_arrowequipped = false;
|
|
bool use_double_melee_round_dmg_bonus;
|
|
bool can_facestab;
|
|
bool has_numhits;
|
|
bool has_MGB;
|
|
bool has_ProjectIllusion;
|
|
int16 SpellPowerDistanceMod;
|
|
bool last_los_check;
|
|
bool pseudo_rooted;
|
|
bool endur_upkeep;
|
|
bool degenerating_effects; // true if we have a buff that needs to be recalced every tick
|
|
bool spawned_in_water;
|
|
bool is_boat;
|
|
|
|
CombatRecord m_combat_record{};
|
|
|
|
public:
|
|
const CombatRecord &GetCombatRecord() const;
|
|
|
|
public:
|
|
bool GetWasSpawnedInWater() const;
|
|
|
|
void SetSpawnedInWater(bool spawned_in_water);
|
|
bool turning;
|
|
|
|
protected:
|
|
|
|
// Bind wound
|
|
Timer bindwound_timer;
|
|
Mob* bindwound_target;
|
|
|
|
Timer stunned_timer;
|
|
Timer spun_timer;
|
|
Timer bardsong_timer;
|
|
Timer gravity_timer;
|
|
Timer viral_timer;
|
|
|
|
// MobAI stuff
|
|
eStandingPetOrder pStandingPetOrder;
|
|
eStandingPetOrder m_previous_pet_order;
|
|
uint32 minLastFightingDelayMoving;
|
|
uint32 maxLastFightingDelayMoving;
|
|
float pAggroRange = 0;
|
|
float pAssistRange = 0;
|
|
std::unique_ptr<Timer> AI_think_timer;
|
|
std::unique_ptr<Timer> AI_movement_timer;
|
|
std::unique_ptr<Timer> AI_target_check_timer;
|
|
int8 ForcedMovement; // push
|
|
bool permarooted;
|
|
std::unique_ptr<Timer> AI_scan_area_timer;
|
|
std::unique_ptr<Timer> AI_walking_timer;
|
|
std::unique_ptr<Timer> AI_feign_remember_timer;
|
|
std::unique_ptr<Timer> AI_check_signal_timer;
|
|
std::unique_ptr<Timer> AI_scan_door_open_timer;
|
|
uint32 time_until_can_move;
|
|
HateList hate_list;
|
|
std::set<uint32> feign_memory_list;
|
|
// This is to keep track of the current (one only) faction mod (alliance)
|
|
uint32 current_alliance_faction;
|
|
int32 current_alliance_mod;
|
|
void AddFactionBonus(uint32 pFactionID,int32 bonus);
|
|
int32 GetFactionBonus(uint32 pFactionID);
|
|
// This is to keep track of item faction modifiers
|
|
std::map<uint32,int32> item_faction_bonuses; // Primary FactionID, Bonus
|
|
void AddItemFactionBonus(uint32 pFactionID,int32 bonus);
|
|
int32 GetItemFactionBonus(uint32 pFactionID);
|
|
void ClearItemFactionBonuses();
|
|
Timer hate_list_cleanup_timer;
|
|
|
|
bool flee_mode;
|
|
Timer flee_timer;
|
|
Timer attack_anim_timer;
|
|
Timer position_update_melee_push_timer;
|
|
|
|
bool pAIControlled;
|
|
bool roamer;
|
|
|
|
int wandertype;
|
|
int pausetype;
|
|
|
|
int8 last_hp_percent;
|
|
int32 last_hp;
|
|
|
|
int cur_wp;
|
|
glm::vec4 m_CurrentWayPoint;
|
|
int cur_wp_pause;
|
|
|
|
bool PrimaryAggro;
|
|
bool AssistAggro;
|
|
int npc_assist_cap;
|
|
Timer assist_cap_timer; // clear assist cap so more nearby mobs can be called for help
|
|
|
|
int patrol;
|
|
glm::vec3 m_FearWalkTarget;
|
|
bool currently_fleeing;
|
|
|
|
bool pause_timer_complete;
|
|
bool DistractedFromGrid;
|
|
uint32 m_dont_heal_me_before;
|
|
uint32 m_dont_buff_me_before;
|
|
uint32 m_dont_dot_me_before;
|
|
uint32 m_dont_root_me_before;
|
|
uint32 m_dont_snare_me_before;
|
|
uint32 m_dont_cure_me_before;
|
|
|
|
// hp event
|
|
int nexthpevent;
|
|
int nextinchpevent;
|
|
|
|
//temppet
|
|
bool hasTempPet;
|
|
bool _IsTempPet;
|
|
int16 count_TempPet;
|
|
bool pet_owner_bot; // Flags pets as belonging to a Bot
|
|
bool pet_owner_client; // Flags pets as belonging to a Client
|
|
bool pet_owner_npc; // Flags pets as belonging to an NPC
|
|
uint32 pet_targetlock_id;
|
|
|
|
//bot attack flags
|
|
std::vector<uint32> bot_attack_flags;
|
|
|
|
glm::vec3 m_TargetRing;
|
|
|
|
GravityBehavior flymode;
|
|
bool m_targetable;
|
|
int QGVarDuration(const char *fmt);
|
|
void InsertQuestGlobal(int charid, int npcid, int zoneid, const char *name, const char *value, int expdate);
|
|
uint32 emoteid;
|
|
|
|
MobSpecialAbility SpecialAbilities[SpecialAbility::Max];
|
|
bool bEnraged;
|
|
bool destructibleobject;
|
|
|
|
std::unordered_map<uint32, std::pair<uint32, uint32>> aa_ranks;
|
|
Timer aa_timers[aaTimerMax];
|
|
|
|
bool is_horse;
|
|
|
|
AuraMgr aura_mgr;
|
|
AuraMgr trap_mgr;
|
|
|
|
bool feigned;
|
|
Timer forget_timer; // our 2 min everybody forgets you timer
|
|
|
|
bool m_can_open_doors;
|
|
|
|
MobMovementManager *mMovementManager;
|
|
|
|
uint16 m_merchant_session_entity_id;
|
|
|
|
private:
|
|
Mob* target;
|
|
EQ::InventoryProfile m_inv;
|
|
std::shared_ptr<HealRotation> m_target_of_heal_rotation;
|
|
bool m_manual_follow;
|
|
|
|
void SetHeroicStrBonuses(StatBonuses* n);
|
|
void SetHeroicStaBonuses(StatBonuses* n);
|
|
void SetHeroicAgiBonuses(StatBonuses* n);
|
|
void SetHeroicDexBonuses(StatBonuses* n);
|
|
void SetHeroicIntBonuses(StatBonuses* n);
|
|
void SetHeroicWisBonuses(StatBonuses* n);
|
|
|
|
void DoSpellInterrupt(uint16 spell_id, int32 mana_cost, int my_curmana);
|
|
void HandleDoorOpen();
|
|
};
|
|
|
|
#endif
|
|
|