mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
* [Bots] Cleanup GetFocusEffect & GetActSpellDamage * Remove unused CalcBotFocusEffect * Cleanup unneeded derived class methods * compile error
697 lines
25 KiB
C++
697 lines
25 KiB
C++
/* EQEMu: Everquest Server Emulator
|
|
Copyright (C) 2001-2002 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 NPC_H
|
|
#define NPC_H
|
|
|
|
#include "../common/rulesys.h"
|
|
|
|
#include "mob.h"
|
|
#include "qglobals.h"
|
|
#include "zonedb.h"
|
|
#include "../common/zone_store.h"
|
|
#include "zonedump.h"
|
|
#include "../common/loottable.h"
|
|
|
|
#include <any>
|
|
#include <deque>
|
|
#include <list>
|
|
|
|
|
|
#ifdef _WINDOWS
|
|
#define M_PI 3.141592
|
|
#endif
|
|
|
|
typedef struct {
|
|
float min_x;
|
|
float max_x;
|
|
float min_y;
|
|
float max_y;
|
|
float min_z;
|
|
float max_z;
|
|
bool say;
|
|
bool proximity_set;
|
|
} NPCProximity;
|
|
|
|
struct AISpells_Struct {
|
|
uint32 type; // 0 = never, must be one (and only one) of the defined values
|
|
uint16 spellid; // <= 0 = no spell
|
|
int16 manacost; // -1 = use spdat, -2 = no cast time
|
|
uint32 time_cancast; // when we can cast this spell next
|
|
int32 recast_delay;
|
|
int16 priority;
|
|
int16 resist_adjust;
|
|
int8 min_hp; // >0 won't cast if HP is below
|
|
int8 max_hp; // >0 won't cast if HP is above
|
|
};
|
|
|
|
struct AISpellsEffects_Struct {
|
|
uint16 spelleffectid;
|
|
int32 base_value;
|
|
int32 limit;
|
|
int32 max_value;
|
|
};
|
|
|
|
struct AISpellsVar_Struct {
|
|
uint32 fail_recast;
|
|
uint32 engaged_no_sp_recast_min;
|
|
uint32 engaged_no_sp_recast_max;
|
|
uint8 engaged_beneficial_self_chance;
|
|
uint8 engaged_beneficial_other_chance;
|
|
uint8 engaged_detrimental_chance;
|
|
uint32 pursue_no_sp_recast_min;
|
|
uint32 pursue_no_sp_recast_max;
|
|
uint8 pursue_detrimental_chance;
|
|
uint32 idle_no_sp_recast_min;
|
|
uint32 idle_no_sp_recast_max;
|
|
uint8 idle_beneficial_chance;
|
|
};
|
|
|
|
class SwarmPet;
|
|
class Client;
|
|
class Group;
|
|
class Raid;
|
|
class Spawn2;
|
|
class Aura;
|
|
|
|
namespace EQ
|
|
{
|
|
struct ItemData;
|
|
}
|
|
|
|
class NPC : public Mob
|
|
{
|
|
public:
|
|
static NPC* SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* client = nullptr);
|
|
static bool SpawnZoneController();
|
|
static int8 GetAILevel(bool iForceReRead = false);
|
|
|
|
// loot recording / simulator
|
|
bool IsRecordLootStats() const;
|
|
void SetRecordLootStats(bool record_loot_stats);
|
|
void FlushLootStats();
|
|
const std::vector<uint32> &GetRolledItems() const;
|
|
int GetRolledItemCount(uint32 item_id);
|
|
|
|
NPC(const NPCType* npc_type_data, Spawn2* respawn, const glm::vec4& position, GravityBehavior iflymode, bool IsCorpse = false);
|
|
|
|
virtual ~NPC();
|
|
|
|
static NPC *SpawnNodeNPC(std::string name, std::string last_name, const glm::vec4 &position);
|
|
static void SpawnGridNodeNPC(const glm::vec4 &position, int32 grid_id, int32 grid_number, int32 zoffset);
|
|
static NPC * SpawnZonePointNodeNPC(std::string name, const glm::vec4 &position);
|
|
|
|
//abstract virtual function implementations requird by base abstract class
|
|
virtual bool Death(Mob* killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill);
|
|
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);
|
|
virtual bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
|
|
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr);
|
|
virtual bool HasRaid() { return false; }
|
|
virtual bool HasGroup() { return false; }
|
|
virtual Raid* GetRaid() { return 0; }
|
|
virtual Group* GetGroup() { return 0; }
|
|
|
|
virtual bool IsNPC() const { return true; }
|
|
|
|
virtual bool Process();
|
|
virtual void AI_Init();
|
|
virtual void AI_Start(uint32 iMoveDelay = 0);
|
|
virtual void AI_Stop();
|
|
void AI_DoMovement();
|
|
void AI_SetupNextWaypoint();
|
|
bool AI_AddNPCSpells(uint32 iDBSpellsID);
|
|
bool AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID);
|
|
virtual bool AI_EngagedCastCheck();
|
|
bool AI_HasSpells() { return HasAISpell; }
|
|
bool AI_HasSpellsEffects() { return HasAISpellEffects; }
|
|
void ApplyAISpellEffects(StatBonuses* newbon);
|
|
|
|
virtual bool AI_PursueCastCheck();
|
|
virtual bool AI_IdleCastCheck();
|
|
virtual void AI_Event_SpellCastFinished(bool iCastSucceeded, uint16 slot);
|
|
|
|
bool AICheckCloseBeneficialSpells(NPC* caster, uint8 chance, float cast_range, uint32 spell_types);
|
|
void AIYellForHelp(Mob* sender, Mob* attacker);
|
|
|
|
void LevelScale();
|
|
|
|
virtual void SetTarget(Mob* mob);
|
|
virtual uint16 GetSkill(EQ::skills::SkillType skill_num) const { if (skill_num <= EQ::skills::HIGHEST_SKILL) { return skills[skill_num]; } return 0; }
|
|
|
|
void CalcItemBonuses(StatBonuses *newbon);
|
|
virtual void CalcBonuses();
|
|
virtual int GetCurrentBuffSlots() const { return RuleI(Spells, MaxBuffSlotsNPC); }
|
|
virtual int GetCurrentSongSlots() const { return RuleI(Spells, MaxSongSlotsNPC); }
|
|
virtual int GetCurrentDiscSlots() const { return RuleI(Spells, MaxDiscSlotsNPC); }
|
|
virtual int GetMaxBuffSlots() const { return RuleI(Spells, MaxBuffSlotsNPC); }
|
|
virtual int GetMaxSongSlots() const { return RuleI(Spells, MaxSongSlotsNPC); }
|
|
virtual int GetMaxDiscSlots() const { return RuleI(Spells, MaxDiscSlotsNPC); }
|
|
virtual int GetMaxTotalSlots() const { return RuleI(Spells, MaxTotalSlotsNPC); }
|
|
virtual int GetPetMaxTotalSlots() const { return RuleI(Spells, MaxTotalSlotsPET); }
|
|
virtual void InitializeBuffSlots();
|
|
virtual void UninitializeBuffSlots();
|
|
|
|
virtual void SetAttackTimer();
|
|
virtual void RangedAttack(Mob* other);
|
|
virtual void ThrowingAttack(Mob* other) { }
|
|
int32 GetNumberOfAttacks() const { return attack_count; }
|
|
void DoRangedAttackDmg(Mob* other, bool Launch = true, int16 damage_mod = 0, int16 chance_mod = 0, EQ::skills::SkillType skill = EQ::skills::SkillArchery, float speed = 4.0f, const char *IDFile = nullptr);
|
|
|
|
bool DatabaseCastAccepted(int spell_id);
|
|
bool IsFactionListAlly(uint32 other_faction);
|
|
bool IsGuard();
|
|
FACTION_VALUE CheckNPCFactionAlly(int32 other_faction);
|
|
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther);
|
|
|
|
void GoToBind(uint8 bind_number = 0) { GMMove(m_SpawnPoint.x, m_SpawnPoint.y, m_SpawnPoint.z, m_SpawnPoint.w); }
|
|
void Gate(uint8 bind_number = 0);
|
|
|
|
void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name);
|
|
void SetPetState(SpellBuff_Struct *buffs, uint32 *items);
|
|
void InteractiveChat(uint8 chan_num, uint8 language, const char * message, const char* targetname,Mob* sender);
|
|
void TakenAction(uint8 action,Mob* actiontaker);
|
|
virtual void SpellProcess();
|
|
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
|
|
|
|
void AddItem(const EQ::ItemData* item, uint16 charges, bool equipitem = true);
|
|
void AddItem(uint32 itemid, uint16 charges, bool equipitem = true, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0);
|
|
void AddLootTable();
|
|
void AddLootTable(uint32 ldid);
|
|
void CheckGlobalLootTables();
|
|
void DescribeAggro(Client *to_who, Mob *mob, bool verbose);
|
|
void RemoveItem(uint32 item_id, uint16 quantity = 0, uint16 slot = 0);
|
|
void CheckTrivialMinMaxLevelDrop(Mob *killer);
|
|
void ClearItemList();
|
|
inline const ItemList &GetItemList() { return itemlist; }
|
|
ServerLootItem_Struct* GetItem(int slot_id);
|
|
void AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_platinum);
|
|
void AddCash();
|
|
void RemoveCash();
|
|
void QueryLoot(Client* to, bool is_pet_query = false);
|
|
bool HasItem(uint32 item_id);
|
|
uint16 CountItem(uint32 item_id);
|
|
uint32 GetItemIDBySlot(uint16 loot_slot);
|
|
uint16 GetFirstSlotByItemID(uint32 item_id);
|
|
std::vector<int> GetLootList();
|
|
uint32 CountLoot();
|
|
inline uint32 GetLoottableID() const { return loottable_id; }
|
|
virtual void UpdateEquipmentLight();
|
|
inline bool DropsGlobalLoot() const { return !skip_global_loot; }
|
|
|
|
inline uint32 GetCopper() const { return copper; }
|
|
inline uint32 GetSilver() const { return silver; }
|
|
inline uint32 GetGold() const { return gold; }
|
|
inline uint32 GetPlatinum() const { return platinum; }
|
|
|
|
inline void SetCopper(uint32 amt) { copper = amt; }
|
|
inline void SetSilver(uint32 amt) { silver = amt; }
|
|
inline void SetGold(uint32 amt) { gold = amt; }
|
|
inline void SetPlatinum(uint32 amt) { platinum = amt; }
|
|
|
|
|
|
virtual int64 CalcMaxMana();
|
|
void SetGrid(int32 grid_){ grid=grid_; }
|
|
void SetSpawnGroupId(uint32 sg2){ spawn_group_id =sg2; }
|
|
void SetWaypointMax(uint16 wp_){ wp_m=wp_; }
|
|
void SetSaveWaypoint(uint16 wp_){ save_wp=wp_; }
|
|
|
|
uint16 GetWaypointMax() const { return wp_m; }
|
|
int32 GetGrid() const { return grid; }
|
|
uint32 GetSpawnGroupId() const { return spawn_group_id; }
|
|
uint32 GetSpawnPointID() const;
|
|
|
|
glm::vec4 const GetSpawnPoint() const { return m_SpawnPoint; }
|
|
glm::vec4 const GetGuardPoint() const { return m_GuardPoint; }
|
|
EmuAppearance GetGuardPointAnim() const { return guard_anim; }
|
|
void SaveGuardPointAnim(EmuAppearance anim) { guard_anim = anim; }
|
|
|
|
uint8 GetPrimSkill() const { return prim_melee_type; }
|
|
uint8 GetSecSkill() const { return sec_melee_type; }
|
|
uint8 GetRangedSkill() const { return ranged_type; }
|
|
void SetPrimSkill(uint8 skill_type) { prim_melee_type = skill_type; }
|
|
void SetSecSkill(uint8 skill_type) { sec_melee_type = skill_type; }
|
|
void SetRangedSkill(uint8 skill_type) { ranged_type = skill_type; }
|
|
|
|
uint32 MerchantType;
|
|
bool merchant_open;
|
|
inline void MerchantOpenShop() { merchant_open = true; }
|
|
inline void MerchantCloseShop() { merchant_open = false; }
|
|
inline bool IsMerchantOpen() { return merchant_open; }
|
|
void Depop(bool StartSpawnTimer = false);
|
|
void Stun(int duration);
|
|
void UnStun();
|
|
uint32 GetSwarmOwner();
|
|
uint32 GetSwarmTarget();
|
|
void SetSwarmTarget(int target_id = 0);
|
|
void DepopSwarmPets();
|
|
void TryDepopTargetLockedPets(Mob* current_target);
|
|
void PetOnSpawn(NewSpawn_Struct* ns);
|
|
|
|
void SignalNPC(int _signal_id);
|
|
void SendPayload(int payload_id, std::string payload_value = std::string());
|
|
|
|
inline int32 GetNPCFactionID() const
|
|
{ return npc_faction_id; }
|
|
|
|
inline int32 GetPrimaryFaction() const
|
|
{ return primary_faction; }
|
|
|
|
inline int32 GetFactionAmount() const
|
|
{ return faction_amount; }
|
|
|
|
int64 GetNPCHate(Mob *in_ent)
|
|
{ return hate_list.GetEntHateAmount(in_ent); }
|
|
|
|
bool IsOnHatelist(Mob *p)
|
|
{ return hate_list.IsEntOnHateList(p); }
|
|
|
|
void SetNPCFactionID(int32 in)
|
|
{
|
|
npc_faction_id = in;
|
|
content_db.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction);
|
|
}
|
|
|
|
glm::vec4 m_SpawnPoint;
|
|
|
|
uint32 GetMaxDMG() const {return max_dmg;}
|
|
uint32 GetMinDMG() const {return min_dmg;}
|
|
int GetBaseDamage() const { return base_damage; }
|
|
int GetMinDamage() const { return min_damage; }
|
|
float GetSlowMitigation() const { return slow_mitigation; }
|
|
float GetAttackSpeed() const {return attack_speed;}
|
|
int GetAttackDelay() const {return attack_delay;}
|
|
bool IsAnimal() const { return(bodytype == BT_Animal); }
|
|
uint16 GetPetSpellID() const {return pet_spell_id;}
|
|
void SetPetSpellID(uint16 amt) {pet_spell_id = amt;}
|
|
uint32 GetMaxDamage(uint8 tlevel);
|
|
void SetTaunting(bool tog) {taunting = tog;}
|
|
bool IsTaunting() const { return taunting; }
|
|
void PickPocket(Client* thief);
|
|
void Disarm(Client* client, int chance);
|
|
void StartSwarmTimer(uint32 duration) { swarm_timer.Start(duration); }
|
|
void DisableSwarmTimer() { swarm_timer.Disable(); }
|
|
|
|
void AddLootDrop(
|
|
const EQ::ItemData *item2,
|
|
ItemList *itemlist,
|
|
LootDropEntries_Struct loot_drop,
|
|
bool wear_change = false,
|
|
uint32 aug1 = 0,
|
|
uint32 aug2 = 0,
|
|
uint32 aug3 = 0,
|
|
uint32 aug4 = 0,
|
|
uint32 aug5 = 0,
|
|
uint32 aug6 = 0
|
|
);
|
|
|
|
bool MeetsLootDropLevelRequirements(LootDropEntries_Struct loot_drop, bool verbose=false);
|
|
|
|
void CheckSignal();
|
|
|
|
virtual void DoClassAttacks(Mob *target);
|
|
inline bool IsNotTargetableWithHotkey() const { return no_target_hotkey; }
|
|
int64 GetNPCHPRegen() const { return hp_regen + itembonuses.HPRegen + spellbonuses.HPRegen; }
|
|
inline const char* GetAmmoIDfile() const { return ammo_idfile; }
|
|
|
|
void ModifyStatsOnCharm(bool is_charm_removed);
|
|
|
|
//waypoint crap
|
|
int GetMaxWp() const { return max_wp; }
|
|
void DisplayWaypointInfo(Client *client);
|
|
void CalculateNewWaypoint();
|
|
void AssignWaypoints(int32 grid_id, int start_wp = 0);
|
|
void SetWaypointPause();
|
|
void UpdateWaypoint(int wp_index);
|
|
|
|
// quest wandering commands
|
|
void StopWandering();
|
|
void ResumeWandering();
|
|
void PauseWandering(int pausetime);
|
|
void MoveTo(const glm::vec4& position, bool saveguardspot);
|
|
void GetClosestWaypoints(std::list<wplist> &wp_list, int count, const glm::vec3& location);
|
|
int GetClosestWaypoint(const glm::vec3& location);
|
|
|
|
uint32 GetEquippedItemFromTextureSlot(uint8 material_slot) const; // returns item id
|
|
int32 GetEquipmentMaterial(uint8 material_slot) const;
|
|
|
|
void NextGuardPosition();
|
|
void SaveGuardSpot(bool ClearGuardSpot = false);
|
|
void SaveGuardSpot(const glm::vec4 &pos);
|
|
inline bool IsGuarding() const { return(m_GuardPoint.w != 0); }
|
|
void SaveGuardSpotCharm();
|
|
|
|
uint16 GetMeleeTexture1() const;
|
|
uint16 GetMeleeTexture2() const;
|
|
|
|
void RestoreGuardSpotCharm();
|
|
|
|
void AI_SetRoambox(
|
|
float max_distance,
|
|
float roam_distance_variance,
|
|
uint32 delay = 2500,
|
|
uint32 min_delay = 2500
|
|
);
|
|
|
|
void AI_SetRoambox(float distance, float max_x, float min_x, float max_y, float min_y, uint32 delay = 2500, uint32 min_delay = 2500);
|
|
|
|
//mercenary stuff
|
|
void LoadMercTypes();
|
|
void LoadMercs();
|
|
std::list<MercType> GetMercTypesList() {return mercTypeList; };
|
|
std::list<MercType> GetMercTypesList( uint32 expansion );
|
|
std::list<MercData> GetMercsList() {return mercDataList; };
|
|
std::list<MercData> GetMercsList( uint32 expansion );
|
|
int GetNumMercTypes() { return static_cast<int>(mercTypeList.size()); };
|
|
int GetNumMercTypes( uint32 expansion );
|
|
int GetNumMercs() { return static_cast<int>(mercDataList.size()); };
|
|
int GetNumMercs( uint32 expansion );
|
|
|
|
inline bool WillAggroNPCs() const { return(npc_aggro); }
|
|
|
|
inline void GiveNPCTypeData(NPCType *ours) { NPCTypedata_ours = ours; }
|
|
inline const uint32 GetNPCSpellsID() const { return npc_spells_id; }
|
|
inline const uint32 GetNPCSpellsEffectsID() const { return npc_spells_effects_id; }
|
|
|
|
float GetProximityMinX();
|
|
float GetProximityMaxX();
|
|
float GetProximityMinY();
|
|
float GetProximityMaxY();
|
|
float GetProximityMinZ();
|
|
float GetProximityMaxZ();
|
|
bool IsProximitySet();
|
|
|
|
ItemList itemlist; //kathgar - why is this public? Doing other things or I would check the code
|
|
|
|
NPCProximity* proximity;
|
|
Spawn2* respawn2;
|
|
QGlobalCache *GetQGlobals() { return qGlobals; }
|
|
QGlobalCache *CreateQGlobals() { qGlobals = new QGlobalCache(); return qGlobals; }
|
|
|
|
SwarmPet *GetSwarmInfo() { return (swarmInfoPtr); }
|
|
void SetSwarmInfo(SwarmPet *mSwarmInfo) { swarmInfoPtr = mSwarmInfo; }
|
|
|
|
int32 GetAccuracyRating() const { return (accuracy_rating); }
|
|
void SetAccuracyRating(int32 d) { accuracy_rating = d;}
|
|
int32 GetAvoidanceRating() const { return (avoidance_rating); }
|
|
void SetAvoidanceRating(int32 d) { avoidance_rating = d;}
|
|
int32 GetRawAC() const { return AC; }
|
|
|
|
float GetNPCStat(std::string stat);
|
|
void ModifyNPCStat(std::string stat, std::string value);
|
|
virtual void SetLevel(uint8 in_level, bool command = false);
|
|
|
|
bool IsLDoNTrapped() const { return (ldon_trapped); }
|
|
void SetLDoNTrapped(bool n) { ldon_trapped = n; }
|
|
|
|
uint8 GetLDoNTrapType() const { return (ldon_trap_type); }
|
|
void SetLDoNTrapType(uint8 n) { ldon_trap_type = n; }
|
|
|
|
uint16 GetLDoNTrapSpellID() const { return (ldon_spell_id); }
|
|
void SetLDoNTrapSpellID(uint16 n) { ldon_spell_id = n; }
|
|
|
|
bool IsLDoNLocked() const { return (ldon_locked); }
|
|
void SetLDoNLocked(bool n) { ldon_locked = n; }
|
|
|
|
uint16 GetLDoNLockedSkill() const { return (ldon_locked_skill); }
|
|
void SetLDoNLockedSkill(uint16 n) { ldon_locked_skill = n; }
|
|
|
|
bool IsLDoNTrapDetected() const { return (ldon_trap_detected); }
|
|
void SetLDoNTrapDetected(bool n) { ldon_trap_detected = n; }
|
|
|
|
const bool GetCombatEvent() const { return combat_event; }
|
|
void SetCombatEvent(bool b) { combat_event = b; }
|
|
|
|
/* Only allows players that killed corpse to loot */
|
|
const bool HasPrivateCorpse() const { return NPCTypedata_ours ? NPCTypedata_ours->private_corpse : NPCTypedata->private_corpse; }
|
|
|
|
virtual const bool IsUnderwaterOnly() const { return NPCTypedata_ours ? NPCTypedata_ours->underwater : NPCTypedata->underwater; }
|
|
const char* GetRawNPCTypeName() const { return NPCTypedata_ours ? NPCTypedata_ours->name : NPCTypedata->name; }
|
|
|
|
virtual int GetKillExpMod() const { return NPCTypedata_ours ? NPCTypedata_ours->exp_mod : NPCTypedata->exp_mod; }
|
|
|
|
void ChangeLastName(std::string last_name);
|
|
void ClearLastName();
|
|
|
|
bool GetDepop() { return p_depop; }
|
|
|
|
void NPCSlotTexture(uint8 slot, uint16 texture); // Sets new material values for slots
|
|
|
|
uint32 GetAdventureTemplate() const { return adventure_template_id; }
|
|
void AddSpellToNPCList(int16 iPriority, uint16 iSpellID, uint32 iType, int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust, int8 min_hp, int8 max_hp);
|
|
void AddSpellEffectToNPCList(uint16 iSpellEffectID, int32 base_value, int32 limit, int32 max_value, bool apply_bonus = false);
|
|
void RemoveSpellFromNPCList(uint16 spell_id);
|
|
void RemoveSpellEffectFromNPCList(uint16 iSpellEffectID, bool apply_bonus = false);
|
|
bool HasAISpellEffect(uint16 spell_effect_id);
|
|
Timer *GetRefaceTimer() const { return reface_timer; }
|
|
const uint32 GetAltCurrencyType() const { return NPCTypedata->alt_currency_type; }
|
|
|
|
NPC_Emote_Struct* GetNPCEmote(uint32 emoteid, uint8 event_);
|
|
void DoNPCEmote(uint8 event_, uint32 emoteid);
|
|
bool CanTalk();
|
|
void DoQuestPause(Mob *other);
|
|
|
|
inline void SetSpellScale(float amt) { spellscale = amt; }
|
|
inline float GetSpellScale() { return spellscale; }
|
|
|
|
inline void SetHealScale(float amt) { healscale = amt; }
|
|
inline float GetHealScale() { return healscale; }
|
|
|
|
inline void SetSpellFocusDMG(int32 NewSpellFocusDMG) {SpellFocusDMG = NewSpellFocusDMG;}
|
|
inline int32 GetSpellFocusDMG() const { return SpellFocusDMG;}
|
|
|
|
inline void SetSpellFocusHeal(int32 NewSpellFocusHeal) {SpellFocusHeal = NewSpellFocusHeal;}
|
|
inline int32 GetSpellFocusHeal() const {return SpellFocusHeal;}
|
|
|
|
uint32 GetSpawnKillCount();
|
|
int GetScore();
|
|
void mod_prespawn(Spawn2 *sp);
|
|
int mod_npc_damage(int64 damage, EQ::skills::SkillType skillinuse, int hand, const EQ::ItemData* weapon, Mob* other);
|
|
void mod_npc_killed_merit(Mob* c);
|
|
void mod_npc_killed(Mob* oos);
|
|
void AISpellsList(Client *c);
|
|
uint16 GetInnateProcSpellID() const { return innate_proc_spell_id; }
|
|
|
|
uint32 GetHeroForgeModel() const { return herosforgemodel; }
|
|
void SetHeroForgeModel(uint32 model) { herosforgemodel = model; }
|
|
|
|
bool IsRaidTarget() const { return raid_target; };
|
|
bool IsRareSpawn() const { return rare_spawn; }
|
|
void ResetHPUpdateTimer() { send_hp_update_timer.Start(); }
|
|
|
|
bool IgnoreDespawn() { return ignore_despawn; }
|
|
|
|
void SetSimpleRoamBox(float box_size, float move_distance = 0, int move_delay = 0);
|
|
|
|
float GetRoamboxMaxX() const;
|
|
float GetRoamboxMaxY() const;
|
|
float GetRoamboxMinX() const;
|
|
float GetRoamboxMinY() const;
|
|
float GetRoamboxDistance() const;
|
|
float GetRoamboxDestinationX() const;
|
|
float GetRoamboxDestinationY() const;
|
|
float GetRoamboxDestinationZ() const;
|
|
uint32 GetRoamboxDelay() const;
|
|
uint32 GetRoamboxMinDelay() const;
|
|
|
|
inline uint8 GetArmTexture() { return armtexture; }
|
|
inline uint8 GetBracerTexture() { return bracertexture; }
|
|
inline uint8 GetHandTexture() { return handtexture; }
|
|
inline uint8 GetFeetTexture() { return feettexture; }
|
|
inline uint8 GetLegTexture() { return legtexture; }
|
|
|
|
inline int GetCharmedAccuracy() { return charm_accuracy_rating; }
|
|
inline int GetCharmedArmorClass() { return charm_ac; }
|
|
inline int GetCharmedAttack() { return charm_atk; }
|
|
inline int GetCharmedAttackDelay() { return charm_attack_delay; }
|
|
inline int GetCharmedAvoidance() { return charm_avoidance_rating; }
|
|
inline int GetCharmedMaxDamage() { return charm_max_dmg; }
|
|
inline int GetCharmedMinDamage() { return charm_min_dmg; }
|
|
|
|
inline bool GetAlwaysAggro() { return always_aggro; }
|
|
inline bool GetNPCAggro() { return npc_aggro; }
|
|
inline bool GetIgnoreDespawn() { return ignore_despawn; }
|
|
inline bool GetSkipGlobalLoot() { return skip_global_loot; }
|
|
|
|
std::unique_ptr<Timer> AIautocastspell_timer;
|
|
|
|
virtual int GetStuckBehavior() const { return NPCTypedata_ours ? NPCTypedata_ours->stuck_behavior : NPCTypedata->stuck_behavior; }
|
|
|
|
inline bool IsSkipAutoScale() const { return skip_auto_scale; }
|
|
|
|
void ScaleNPC(uint8 npc_level);
|
|
|
|
void RecalculateSkills();
|
|
void ReloadSpells();
|
|
|
|
static LootDropEntries_Struct NewLootDropEntry();
|
|
|
|
int DispatchZoneControllerEvent(QuestEventID evt, Mob* init, const std::string& data, uint32 extra, std::vector<std::any>* pointers);
|
|
|
|
protected:
|
|
|
|
const NPCType* NPCTypedata;
|
|
NPCType* NPCTypedata_ours; //special case for npcs with uniquely created data.
|
|
|
|
friend class EntityList;
|
|
friend class Aura;
|
|
std::list<struct NPCFaction*> faction_list;
|
|
uint32 copper;
|
|
uint32 silver;
|
|
uint32 gold;
|
|
uint32 platinum;
|
|
int32 grid;
|
|
uint32 spawn_group_id;
|
|
uint16 wp_m;
|
|
|
|
int32 npc_faction_id;
|
|
int32 primary_faction;
|
|
int32 faction_amount;
|
|
|
|
Timer attacked_timer; //running while we are being attacked (damaged)
|
|
Timer swarm_timer;
|
|
Timer monkattack_timer; //additional timer for tiger claw usage
|
|
Timer classattack_timer;
|
|
Timer knightattack_timer;
|
|
Timer assist_timer; //ask for help from nearby mobs
|
|
Timer qglobal_purge_timer;
|
|
|
|
bool combat_event; //true if we are in combat, false otherwise
|
|
Timer send_hp_update_timer;
|
|
Timer enraged_timer;
|
|
Timer *reface_timer;
|
|
|
|
uint32 npc_spells_id;
|
|
uint8 casting_spell_AIindex;
|
|
|
|
uint32* pDontCastBefore_casting_spell;
|
|
std::vector<AISpells_Struct> AIspells;
|
|
bool HasAISpell;
|
|
virtual bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates = false);
|
|
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
|
|
AISpellsVar_Struct AISpellVar;
|
|
int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false);
|
|
uint16 innate_proc_spell_id;
|
|
|
|
uint32 npc_spells_effects_id;
|
|
std::vector<AISpellsEffects_Struct> AIspellsEffects;
|
|
bool HasAISpellEffects;
|
|
|
|
uint32 max_dmg;
|
|
uint32 min_dmg;
|
|
int base_damage;
|
|
int min_damage;
|
|
int32 accuracy_rating;
|
|
int32 avoidance_rating;
|
|
int16 attack_count;
|
|
uint64 npc_mana;
|
|
float spellscale;
|
|
float healscale;
|
|
int32 SpellFocusDMG;
|
|
int32 SpellFocusHeal;
|
|
|
|
// stats to switch back to after charm wears off
|
|
// could probably pick a better name, but these probably aren't taken so ...
|
|
int default_ac;
|
|
int default_min_dmg;
|
|
int default_max_dmg;
|
|
int default_attack_delay;
|
|
int default_accuracy_rating;
|
|
int default_avoidance_rating;
|
|
int default_atk;
|
|
char default_special_abilities[512];
|
|
|
|
// when charmed, switch to these
|
|
int charm_ac;
|
|
int charm_min_dmg;
|
|
int charm_max_dmg;
|
|
int charm_attack_delay;
|
|
int charm_accuracy_rating;
|
|
int charm_avoidance_rating;
|
|
int charm_atk;
|
|
|
|
//pet crap:
|
|
uint16 pet_spell_id;
|
|
bool taunting;
|
|
Timer taunt_timer; //for pet taunting
|
|
|
|
bool npc_aggro;
|
|
|
|
std::deque<int> signal_q;
|
|
|
|
//waypoint crap:
|
|
std::vector<wplist> Waypoints;
|
|
void _ClearWaypints();
|
|
int max_wp;
|
|
int save_wp;
|
|
glm::vec4 m_GuardPoint;
|
|
glm::vec4 m_GuardPointSaved;
|
|
EmuAppearance guard_anim;
|
|
float roambox_max_x;
|
|
float roambox_max_y;
|
|
float roambox_min_x;
|
|
float roambox_min_y;
|
|
float roambox_distance;
|
|
float roambox_destination_x;
|
|
float roambox_destination_y;
|
|
float roambox_destination_z;
|
|
uint32 roambox_delay;
|
|
uint32 roambox_min_delay;
|
|
|
|
uint16 skills[EQ::skills::HIGHEST_SKILL + 1];
|
|
|
|
uint32 equipment[EQ::invslot::EQUIPMENT_COUNT]; //this is an array of item IDs
|
|
|
|
uint32 herosforgemodel; //this is the Hero Forge Armor Model (i.e 63 or 84 or 203)
|
|
uint16 d_melee_texture1;
|
|
//this is an item Material value
|
|
uint16 d_melee_texture2; //this is an item Material value (offhand)
|
|
const char* ammo_idfile; //this determines projectile graphic "IT###" (see item field 'idfile')
|
|
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
|
|
uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation
|
|
uint8 ranged_type; //Sets the Ranged Weapon attack message and animation
|
|
|
|
SwarmPet *swarmInfoPtr;
|
|
|
|
bool ldon_trapped;
|
|
uint8 ldon_trap_type;
|
|
uint16 ldon_spell_id;
|
|
bool ldon_locked;
|
|
uint16 ldon_locked_skill;
|
|
bool ldon_trap_detected;
|
|
QGlobalCache *qGlobals;
|
|
uint32 adventure_template_id;
|
|
|
|
//mercenary stuff
|
|
std::list<MercType> mercTypeList;
|
|
std::list<MercData> mercDataList;
|
|
|
|
bool raid_target;
|
|
bool ignore_despawn; //NPCs with this set to 1 will ignore the despawn value in spawngroup
|
|
|
|
|
|
private:
|
|
uint32 loottable_id;
|
|
bool skip_global_loot;
|
|
bool skip_auto_scale;
|
|
bool p_depop;
|
|
bool m_record_loot_stats;
|
|
std::vector<uint32> m_rolled_items = {};
|
|
};
|
|
|
|
#endif
|
|
|