Alex King c1b07afae9
[Quest API] Add EVENT_LOOT_ADDED to Perl/Lua (#3739)
* [Quest API] Add EVENT_ADDED_LOOT to Perl/Lua

# Perl
- Add `EVENT_ADDED_LOOT`.
- Exports `$item`, `$item_id`, `$item_name`, `$item_charges`, `$augment_one`, `$augment_two`, `$augment_three`, `$augment_four`, `$augment_five`, and `$augment_six`.

# Lua
- Add `event_added_loot`.
- Exports `e.item`, `e.item_id`, `e.item_name`, `e.item_charges`, `e.augment_one`, `e.augment_two`, `e.augment_three`, `e.augment_four`, `e.augment_five`, and `e.augment_six`.

# Notes
- Allows operators to perform events when loot is added to an NPC, such as removing the loot or keeping track of it.

* Update lua_parser_events.cpp

* Rename event.

* loot_added

* AddItem changese
2023-12-16 22:25:09 -06:00

705 lines
24 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 <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;
};
struct Roambox {
float max_x;
float max_y;
float min_x;
float min_y;
float distance;
float dest_x;
float dest_y;
float dest_z;
uint32 delay;
uint32 min_delay;
};
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();
// loot recording / simulator
bool IsRecordLootStats() const;
void SetRecordLootStats(bool record_loot_stats);
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);
bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) override;
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; }
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 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);
virtual void SpellProcess();
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
void AddItem(const EQ::ItemData *item, uint16 charges, bool equip_item = true);
void AddItem(
uint32 item_id,
uint16 charges,
bool equip_item = true,
uint32 augment_one = 0,
uint32 augment_two = 0,
uint32 augment_three = 0,
uint32 augment_four = 0,
uint32 augment_five = 0,
uint32 augment_six = 0
);
void AddLootTable();
void AddLootTable(uint32 loottable_id);
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 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 start_spawn_timer = 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 is_taunting);
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 augment_one = 0,
uint32 augment_two = 0,
uint32 augment_three = 0,
uint32 augment_four = 0,
uint32 augment_five = 0,
uint32 augment_six = 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
uint32 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(const std::string& stat);
void ModifyNPCStat(const std::string& stat, const 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 m_is_underwater_only; }
virtual const bool IsQuestNPC() const { return m_is_quest_npc; }
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, uint32 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 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, bool always_scale = false, bool override_special_abilities = false);
void RecalculateSkills();
void ReloadSpells();
void SendPositionToClients();
static LootDropEntries_Struct NewLootDropEntry();
bool CanPathTo(float x, float y, float z);
protected:
void HandleRoambox();
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;
std::vector<AISpells_Struct> AIspells;
bool HasAISpell;
virtual bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates = false);
virtual bool AIDoSpellCast(int32 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) override;
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;
int max_wp;
int save_wp;
glm::vec4 m_GuardPoint;
glm::vec4 m_GuardPointSaved;
EmuAppearance guard_anim;
Roambox m_roambox = {};
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)
uint32 d_melee_texture1;
//this is an item Material value
uint32 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;
bool m_is_underwater_only = false;
bool m_is_quest_npc = false;
//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