/* EQEmu: EQEmulator Copyright (C) 2001-2026 EQEmu Development Team 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; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 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, see . */ #pragma once class Client; class EQApplicationPacket; class DynamicZone; class DzLockout; class ExpeditionRequest; class Group; class NPC; class Object; class Raid; class Seperator; class ServerPacket; struct DynamicZoneLocation; enum WaterRegionType : int; enum class DynamicZoneMemberStatus; namespace EQ { struct ItemData; } #include "zone/aggromanager.h" #include "zone/bot_structs.h" #include "zone/cheat_manager.h" #include "zone/common.h" #include "zone/merc.h" #include "zone/mob.h" #include "zone/qglobals.h" #include "zone/questmgr.h" #include "zone/task_client_state.h" #include "zone/task_manager.h" #include "zone/xtargetautohaters.h" #include "zone/zone.h" #include "zone/zonedb.h" #include "common/data_verification.h" #include "common/emu_constants.h" #include "common/emu_opcodes.h" #include "common/eq_packet_structs.h" #include "common/eq_packet.h" #include "common/eq_stream_intf.h" #include "common/events/player_events.h" #include "common/extprofile.h" #include "common/guild_base.h" #include "common/guilds.h" #include "common/inventory_profile.h" #include "common/linked_list.h" #include "common/ptimer.h" #include "common/races.h" #include "common/repositories/buyer_buy_lines_repository.h" #include "common/repositories/character_evolving_items_repository.h" #include "common/repositories/character_parcels_repository.h" #include "common/repositories/player_titlesets_repository.h" #include "common/repositories/trader_repository.h" #include "common/seperator.h" #include "common/timer.h" #include "common/zone_store.h" #include #include #include #include #include #define CLIENT_LD_TIMEOUT 30000 // length of time client stays in zone after LDing #define TARGETING_RANGE 200 // range for /assist and /target #define XTARGET_HARDCAP 20 #define MAX_SPECIALIZED_SKILL 50 extern Zone* zone; class CLIENTPACKET { public: CLIENTPACKET(); ~CLIENTPACKET(); EQApplicationPacket *app; bool ack_req; }; #define SPELLBAR_UNLOCK 0x2bc enum { //scribing argument to MemorizeSpell memSpellUnknown = -1, // this modifies some state data memSpellScribing = 0, memSpellMemorize = 1, memSpellForget = 2, memSpellSpellbar = 3 }; //Modes for the zoning state of the client. enum ZoneMode { ZoneToSafeCoords, // Always send ZonePlayerToBind_Struct to client: Succor/Evac GMSummon, // Always send ZonePlayerToBind_Struct to client: Only a GM Summon GMHiddenSummon, // Always send ZonePlayerToBind_Struct to client silently: Only a GM Summon ZoneToBindPoint, // Always send ZonePlayerToBind_Struct to client: Death Only ZoneSolicited, // Always send ZonePlayerToBind_Struct to client: Portal, Translocate, Evac spells that have a x y z coord in the spell data ZoneUnsolicited, GateToBindPoint, // Always send RequestClientZoneChange_Struct to client: Gate spell or Translocate To Bind Point spell SummonPC, // In-zone GMMove() always: Call of the Hero spell or some other type of in zone only summons Rewind, // Summon to /rewind location. EvacToSafeCoords }; // translate above enum to a string std::string GetZoneModeString(ZoneMode mode); enum { HideCorpseNone = 0, HideCorpseAll = 1, HideCorpseAllButGroup = 2, HideCorpseLooted = 3, HideCorpseNPC = 5 }; enum ShowSpellType { Disciplines, Spells }; enum XTargetType { Empty = 0, Auto = 1, CurrentTargetPC = 2, CurrentTargetNPC = 3, TargetsTarget = 4, GroupTank = 5, GroupTankTarget = 6, GroupAssist = 7, GroupAssistTarget = 8, Puller = 9, PullerTarget = 10, GroupMarkTarget1 = 11, GroupMarkTarget2 = 12, GroupMarkTarget3 = 13, RaidAssist1 = 14, RaidAssist2 = 15, RaidAssist3 = 16, RaidAssist1Target = 17, RaidAssist2Target = 18, RaidAssist3Target = 19, RaidMarkTarget1 = 20, RaidMarkTarget2 = 21, RaidMarkTarget3 = 22, MyPet = 23, MyPetTarget = 24, MyMercenary = 25, MyMercenaryTarget = 26 }; struct XTarget_Struct { XTargetType Type; bool dirty; uint16 ID; char Name[65]; }; struct RespawnOption { std::string name; uint32 zone_id; uint16 instance_id; float x; float y; float z; float heading; }; struct BotCommandHelpParams { std::vector description = {}; std::vector notes = {}; std::vector example_format = {}; std::vector examples_one = {}; std::vector examples_two = {}; std::vector examples_three = {}; std::vector actionables = {}; std::vector options = {}; std::vector options_one = {}; std::vector options_two = {}; std::vector options_three = {}; }; // do not ask what all these mean because I have no idea! // named from the client's CEverQuest::GetInnateDesc, they're missing some enum eInnateSkill { InnateEnabled = 0, InnateAwareness = 1, InnateBashDoor = 2, InnateBreathFire = 3, InnateHarmony = 4, InnateInfravision = 6, InnateLore = 8, InnateNoBash = 9, InnateRegen = 10, InnateSlam = 11, InnateSurprise = 12, InnateUltraVision = 13, InnateInspect = 14, InnateOpen = 15, InnateReveal = 16, InnateSkillMax = 25, // size of array in client InnateDisabled = 255 }; inline const std::string DIAWIND_RESPONSE_ONE_KEY = "diawind_npc_response_one"; inline const std::string DIAWIND_RESPONSE_TWO_KEY = "diawind_npc_response_two"; const uint32 POPUPID_DIAWIND_ONE = 99999; const uint32 POPUPID_DIAWIND_TWO = 100000; const uint32 POPUPID_UPDATE_SHOWSTATSWINDOW = 1000000; const uint32 POPUPID_REPLACE_SPELLWINDOW = 1000001; struct ClientReward { uint32 id; uint32 amount; }; struct ExpeditionInvite { uint32_t dz_id; std::string inviter_name; std::string swap_name; }; class Client : public Mob { public: //pull in opcode mappings: #include "client_packet.h" Client(EQStreamInterface * ieqs); Client(); // mocking / testing ~Client(); void ReconnectUCS(); void RecordStats(); void SetDisplayMobInfoWindow(bool display_mob_info_window); bool GetDisplayMobInfoWindow() const; bool IsDevToolsEnabled() const; void SetDevToolsEnabled(bool in_dev_tools_enabled); bool IsEXPEnabled() const; void SetEXPEnabled(bool is_exp_enabled); std::vector GetEXPModifiers(); void SetEXPModifiers(std::vector exp_modifiers); void SetPrimaryWeaponOrnamentation(uint32 model_id); void SetSecondaryWeaponOrnamentation(uint32 model_id); void SendChatLineBreak(uint16 color = Chat::White); bool GotoPlayer(const std::string& player_name); bool GotoPlayerGroup(const std::string& player_name); bool GotoPlayerRaid(const std::string& player_name); //abstract virtual function implementations required by base abstract class 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); 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 HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } virtual Raid* GetRaid() { return entity_list.GetRaidByClient(this); } virtual Group* GetGroup() { return entity_list.GetGroupByClient(this); } virtual inline bool IsBerserk() { return berserk; } virtual void SetAttackTimer(); int GetQuiverHaste(int delay); void DoAttackRounds(Mob *target, int hand, bool IsFromSpell = false); std::vector GetRaidOrGroupOrSelf(bool clients_only = false); bool CheckIfAlreadyDead(); void AI_Init(); void AI_Start(uint32 iMoveDelay = 0); void AI_Stop(); void AI_Process(); void AI_SpellCast(); void TraderShowItems(); void Trader_CustomerBrowsing(Client *Customer); void TraderEndTrader(); void TraderPriceUpdate(const EQApplicationPacket *app); void SendBazaarDone(uint32 trader_id); void SendBulkBazaarTraders(); void SendBulkBazaarBuyers(); void DoBazaarInspect(BazaarInspect_Struct &in); void SendBazaarDeliveryCosts(); static std::string DetermineMoneyString(uint64 copper); void SendTraderMode(BazaarTraderBarterActions status); void TraderStartTrader(const EQApplicationPacket *app); // void TraderPriceUpdate(const EQApplicationPacket *app); uint8 WithCustomer(uint16 NewCustomer); std::vector GetKeyRing() { return keyring; } void KeyRingLoad(); bool KeyRingAdd(uint32 item_id); bool KeyRingCheck(uint32 item_id); bool KeyRingClear(); bool KeyRingRemove(uint32 item_id); void KeyRingList(Client* c = nullptr); bool IsNameChangeAllowed(); void InvokeChangeNameWindow(bool immediate = true); bool ClearNameChange(); void GrantNameChange(); bool IsPetNameChangeAllowed(); void GrantPetNameChange(); void ClearPetNameChange(); void InvokeChangePetName(bool immediate = true); bool ChangePetName(std::string new_name); bool IsClient() const override { return true; } bool IsOfClientBot() const override { return true; } bool IsOfClientBotMerc() const override { return true; } void CompleteConnect(); bool TryStacking(EQ::ItemInstance* item, uint8 type = ItemPacketTrade, bool try_worn = true, bool try_cursor = true); void SendTraderPacket(Client* trader, uint32 Unknown72 = 51); void SendBuyerPacket(Client* Buyer); void SendBuyerToBarterWindow(Client* buyer, uint32 action); GetItems_Struct* GetTraderItems(); void SendBazaarWelcome(); void SendBarterWelcome(); void DyeArmor(EQ::TintProfile* dye); void DyeArmorBySlot(uint8 slot, uint8 red, uint8 green, uint8 blue, uint8 use_tint = 0x00); uint8 SlotConvert(uint8 slot,bool bracer=false); void MessageString(uint32 type, uint32 string_id, uint32 distance = 0); 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); void MessageString(const CZClientMessageString_Struct* msg); bool FilteredMessageCheck(Mob *sender, eqFilterType filter); void FilteredMessageString(Mob *sender, uint32 type, eqFilterType filter, uint32 string_id); 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 Tell_StringID(uint32 string_id, const char *who, const char *message); void SendColoredText(uint32 color, std::string message); void SendTraderItem(uint32 item_id,uint16 quantity, TraderRepository::Trader &trader); void DoBazaarSearch(BazaarSearchCriteria_Struct search_criteria); uint16 FindTraderItem(int32 SerialNumber,uint16 Quantity); uint32 FindTraderItemSerialNumber(int32 ItemID); EQ::ItemInstance* FindTraderItemBySerialNumber(int32 SerialNumber); void FindAndNukeTraderItem(int32 serial_number, int16 quantity, Client* customer, uint16 trader_slot); void NukeTraderItem(uint16 slot, int16 charges, int16 quantity, Client* customer, uint16 trader_slot, int32 serial_number, int32 item_id = 0); void ReturnTraderReq(const EQApplicationPacket* app,int16 traderitemcharges, uint32 itemid = 0); void TradeRequestFailed(const EQApplicationPacket* app); void BuyTraderItem(TraderBuy_Struct* tbs, Client* trader, const EQApplicationPacket* app); void BuyTraderItemOutsideBazaar(TraderBuy_Struct* tbs, const EQApplicationPacket* app); void FinishTrade( Mob *with, bool finalizer = false, void *event_entry = nullptr, std::list *event_details = nullptr ); void SendZonePoints(); void SendBulkParcels(); void DoParcelCancel(); void DoParcelSend(const Parcel_Struct *parcel_in); void DoParcelRetrieve(const ParcelRetrieve_Struct &parcel_in); void SendParcel(Parcel_Struct &parcel); void SendParcelStatus(); void SendParcelAck(); void SendParcelRetrieveAck(); void SendParcelDelete(const ParcelRetrieve_Struct &parcel_in); void SendParcelDeliveryToWorld(const Parcel_Struct &parcel); void SetParcelEnabled(bool status) { m_parcel_enabled = status; } bool GetParcelEnabled() { return m_parcel_enabled; } void SetParcelCount(uint32 count) { m_parcel_count = count; } int32 GetParcelCount() { return m_parcel_count; } bool GetEngagedWithParcelMerchant() { return m_parcel_merchant_engaged; } void SetEngagedWithParcelMerchant(bool status) { m_parcel_merchant_engaged = status; } Timer *GetParcelTimer() { return &parcel_timer; } bool DeleteParcel(uint32 parcel_id); void AddParcel(CharacterParcelsRepository::CharacterParcels &parcel); void LoadParcels(); std::map GetParcels() { return m_parcels; } int32 FindNextFreeParcelSlot(uint32 char_id); int32 FindNextFreeParcelSlotUsingMemory(); void SendParcelIconStatus(); void SendBecomeTraderToWorld(Client *trader, BazaarTraderBarterActions action); void SendBecomeTrader(BazaarTraderBarterActions action, uint32 trader_id); bool IsThereACustomer() const { return customer_id ? true : false; } uint32 GetCustomerID() { return customer_id; } void SetCustomerID(uint32 id) { customer_id = id; } void SetBuyerID(uint32 id) { m_buyer_id = id; } uint32 GetBuyerID() { return m_buyer_id; } bool IsBuyer() { return m_buyer_id != 0 ? true : false; } void SetBarterTime() { m_barter_time = time(nullptr); } uint32 GetBarterTime() { return m_barter_time; } void SetBuyerWelcomeMessage(const char* welcome_message); void SendBuyerGreeting(uint32 char_id); void SendSellerBrowsing(const std::string &browser); void SendBuyerMode(bool status); bool IsInBuyerSpace(); void SendBuyLineUpdate(const BuyerLineItems_Struct &buy_line); void CheckIfMovedItemIsPartOfBuyLines(uint32 item_id); void SendBuyerResults(BarterSearchRequest_Struct& bsr); void ShowBuyLines(const EQApplicationPacket *app); void SellToBuyer(const EQApplicationPacket *app); void ToggleBuyerMode(bool TurnOn); void ModifyBuyLine(const EQApplicationPacket *app); void CreateStartingBuyLines(const EQApplicationPacket *app); void BuyerItemSearch(const EQApplicationPacket *app); void SendWindowUpdatesToSellerAndBuyer(BuyerLineSellItem_Struct& blsi); void SendBarterBuyerClientMessage(BuyerLineSellItem_Struct& blsi, BarterBuyerActions action, BarterBuyerSubActions sub_action, BarterBuyerSubActions error_code); bool BuildBuyLineMap(std::map& item_map, BuyerBuyLines_Struct& bl); bool BuildBuyLineMapFromVector(std::map& item_map, std::vector& bl); void RemoveItemFromBuyLineMap(std::map& item_map, const BuyerLineItems_Struct& bl); bool ValidateBuyLineItems(std::map& item_map); int64 ValidateBuyLineCost(std::map& item_map); bool DoBarterBuyerChecks(BuyerLineSellItem_Struct& sell_line); bool DoBarterSellerChecks(BuyerLineSellItem_Struct& sell_line); void CancelBuyerTradeWindow(); void CancelTraderTradeWindow(); void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); bool ShouldISpawnFor(Client *c) { return !GMHideMe(c) && !IsHoveringForRespawn(); } virtual bool Process(); void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone); void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL); void ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname = nullptr, bool is_silent = false); void ChannelMessageSend(const char* from, const char* to, uint8 channel_id, uint8 language_id, uint8 language_skill, const char* message, ...); void Message(uint32 type, const char* message, ...); void FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, const char* message, ...); void VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber); void SendSound(); void LearnRecipe(uint32 recipe_id); int GetRecipeMadeCount(uint32 recipe_id); bool HasRecipeLearned(uint32 recipe_id); bool CanIncreaseTradeskill(EQ::skills::SkillType tradeskill); void ScribeRecipes(uint32_t item_id) const; bool GetRevoked() const { return revoked; } void SetRevoked(bool rev) { revoked = rev; } inline uint32 GetIP() const { return ip; } std::string GetIPString(); int GetIPExemption(); void SetIPExemption(int exemption_amount); inline bool GetHideMe() const { return gm_hide_me; } void SetHideMe(bool flag); inline uint16 GetPort() const { return port; } bool IsDead() const { return(dead); } bool IsUnconscious() const { return ((current_hp <= 0) ? true : false); } inline bool IsLFP() { return LFP; } void UpdateLFP(); virtual bool Save() { return Save(0); } bool Save(uint8 iCommitNow); // 0 = delayed, 1=async now, 2=sync now inline void SaveCharacterData() { database.SaveCharacterData(this, &m_pp, &m_epp); }; /* New PP Save Functions */ bool SaveCurrency(){ return database.SaveCharacterCurrency(this->CharacterID(), &m_pp); } bool SaveAA(); void RemoveExpendedAA(int aa_id); inline bool ClientDataLoaded() const { return client_data_loaded; } inline bool Connected() const { return (client_state == CLIENT_CONNECTED); } inline bool InZone() const { return (client_state == CLIENT_CONNECTED || client_state == CLIENT_LINKDEAD); } inline void Disconnect() { eqs->Close(); client_state = DISCONNECTED; } inline bool IsLD() const { return (bool) (client_state == CLIENT_LINKDEAD); } void Kick(const std::string &reason); void WorldKick(); inline uint8 GetAnon() const { return m_pp.anon; } inline uint8 GetAFK() const { return m_is_afk; } void SetAnon(uint8 anon_flag); inline Client* ResetAFKTimer() { if (!RuleB(Character, EnableAutoAFK)) { return this; } m_afk_reset = true; m_last_moved = std::chrono::steady_clock::now(); return this; }; void SetAFK(uint8 afk_flag); inline bool IsIdle() { return m_is_idle; } inline PlayerProfile_Struct& GetPP() { return m_pp; } inline ExtendedProfile_Struct& GetEPP() { return m_epp; } inline EQ::InventoryProfile& GetInv() { return m_inv; } inline const EQ::InventoryProfile& GetInv() const { return m_inv; } const std::vector& GetInventorySlots(); inline PetInfo* GetPetInfo(int pet_info_type) { return pet_info_type == PetInfoType::Suspended ? &m_suspendedminion : &m_petinfo; } inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; } inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; } void ReloadExpansionProfileSetting(); void SetPetCommandState(uint8 button, uint8 state); bool AutoAttackEnabled() const { return auto_attack; } bool AutoFireEnabled() const { return auto_fire; } bool ChangeFirstName(const std::string in_firstname,const std::string gmname); bool ChangeFirstName(const std::string in_firstname); void Duck(); void Stand(); void Sit(); virtual void SetMaxHP(); int32 LevelRegen(); void SetGM(bool toggle); void SetPVP(bool toggle, bool message = true); inline bool GetPVP(bool inc_temp = true) const { return m_pp.pvp != 0 || (inc_temp && temp_pvp); } inline bool GetGM() const { return m_pp.gm != 0; } inline void SetBaseClass(uint32 i) { m_pp.class_=i; } inline void SetBaseRace(uint32 i) { m_pp.race=i; } inline void SetBaseGender(uint32 i) { m_pp.gender=i; } inline void SetDeity(uint32 i) {m_pp.deity=i;deity=i;} void SetTrackingID(uint32 entity_id); inline uint8 GetLevel2() const { return m_pp.level2; } inline uint16 GetBaseRace() const { return m_pp.race; } inline uint16 GetBaseClass() const { return m_pp.class_; } inline uint8 GetBaseGender() const { return m_pp.gender; } inline uint8 GetBaseFace() const { return m_pp.face; } inline uint8 GetBaseHairColor() const { return m_pp.haircolor; } inline uint8 GetBaseBeardColor() const { return m_pp.beardcolor; } inline uint8 GetBaseEyeColor() const { return m_pp.eyecolor1; } inline uint8 GetBaseHairStyle() const { return m_pp.hairstyle; } inline uint8 GetBaseBeard() const { return m_pp.beard; } inline uint8 GetBaseHeritage() const { return m_pp.drakkin_heritage; } inline uint8 GetBaseTattoo() const { return m_pp.drakkin_tattoo; } inline uint8 GetBaseDetails() const { return m_pp.drakkin_details; } inline const float GetBindX(uint32 index = 0) const { return m_pp.binds[index].x; } inline const float GetBindY(uint32 index = 0) const { return m_pp.binds[index].y; } inline const float GetBindZ(uint32 index = 0) const { return m_pp.binds[index].z; } inline const float GetBindHeading(uint32 index = 0) const { return m_pp.binds[index].heading; } inline uint32 GetBindZoneID(uint32 index = 0) const { return m_pp.binds[index].zone_id; } inline uint32 GetBindInstanceID(uint32 index = 0) const { return m_pp.binds[index].instance_id; } int64 CalcMaxMana(); int64 CalcBaseMana(); const int64& SetMana(int64 amount); int64 CalcManaRegenCap() final; // guild pool regen shit. Sends a SpawnAppearance with a value that regens to value * 0.001 void EnableAreaHPRegen(int value); void DisableAreaHPRegen(); void EnableAreaManaRegen(int value); void DisableAreaManaRegen(); void EnableAreaEndRegen(int value); void DisableAreaEndRegen(); void EnableAreaRegens(int value); void DisableAreaRegens(); void ServerFilter(SetServerFilter_Struct* filter); void BulkSendTraderInventory(uint32 char_id); void SendSingleTraderItem(uint32 char_id, int serial_number); void BulkSendMerchantInventory(int merchant_id, int npcid); inline uint8 GetLanguageSkill(uint8 language_id) const { return m_pp.languages[language_id]; } void SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQ::ItemData* item = nullptr); inline const char* GetLastName() const { return lastname; } inline float ProximityX() const { return m_Proximity.x; } inline float ProximityY() const { return m_Proximity.y; } inline float ProximityZ() const { return m_Proximity.z; } inline void ClearAllProximities() { entity_list.ProcessMove(this, glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX)); m_Proximity = glm::vec3(FLT_MAX,FLT_MAX,FLT_MAX); } void CheckVirtualZoneLines(); /* Begin client modifiers */ virtual void CalcBonuses(); //these are all precalculated now inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; } inline virtual int GetHaste() const { return Haste; } int GetRawACNoShield(int &shield_ac) const; inline virtual int32 GetSTR() const { return STR; } inline virtual int32 GetSTA() const { return STA; } inline virtual int32 GetDEX() const { return DEX; } inline virtual int32 GetAGI() const { return AGI; } inline virtual int32 GetINT() const { return INT; } inline virtual int32 GetWIS() const { return WIS; } inline virtual int32 GetCHA() const { return CHA; } inline virtual int32 GetMR() const { return MR; } inline virtual int32 GetFR() const { return FR; } inline virtual int32 GetDR() const { return DR; } inline virtual int32 GetPR() const { return PR; } inline virtual int32 GetCR() const { return CR; } inline virtual int32 GetCorrup() const { return Corrup; } inline virtual int32 GetPhR() const { return PhR; } int32 GetMaxStat() const; int32 GetMaxResist() const; int32 GetMaxSTR() const; int32 GetMaxSTA() const; int32 GetMaxDEX() const; int32 GetMaxAGI() const; int32 GetMaxINT() const; int32 GetMaxWIS() const; int32 GetMaxCHA() const; int32 GetMaxMR() const; int32 GetMaxPR() const; int32 GetMaxDR() const; int32 GetMaxCR() const; int32 GetMaxFR() const; int32 GetMaxCorrup() const; inline uint8 GetBaseSTR() const { return m_pp.STR; } inline uint8 GetBaseSTA() const { return m_pp.STA; } inline uint8 GetBaseCHA() const { return m_pp.CHA; } inline uint8 GetBaseDEX() const { return m_pp.DEX; } inline uint8 GetBaseINT() const { return m_pp.INT; } inline uint8 GetBaseAGI() const { return m_pp.AGI; } inline uint8 GetBaseWIS() const { return m_pp.WIS; } inline uint8 GetBaseCorrup() const { return 15; } // Same for all inline uint8 GetBasePhR() const { return 0; } // Guessing at 0 as base inline virtual int32 GetHeroicSTR() const { return itembonuses.HeroicSTR; } inline virtual int32 GetHeroicSTA() const { return itembonuses.HeroicSTA; } inline virtual int32 GetHeroicDEX() const { return itembonuses.HeroicDEX; } inline virtual int32 GetHeroicAGI() const { return itembonuses.HeroicAGI; } inline virtual int32 GetHeroicINT() const { return itembonuses.HeroicINT; } inline virtual int32 GetHeroicWIS() const { return itembonuses.HeroicWIS; } inline virtual int32 GetHeroicCHA() const { return itembonuses.HeroicCHA; } inline virtual int32 GetHeroicMR() const { return itembonuses.HeroicMR; } inline virtual int32 GetHeroicFR() const { return itembonuses.HeroicFR; } inline virtual int32 GetHeroicDR() const { return itembonuses.HeroicDR; } inline virtual int32 GetHeroicPR() const { return itembonuses.HeroicPR; } inline virtual int32 GetHeroicCR() const { return itembonuses.HeroicCR; } inline virtual int32 GetHeroicCorrup() const { return itembonuses.HeroicCorrup; } inline virtual int32 GetHeroicPhR() const { return 0; } // Heroic PhR not implemented yet // Mod2 inline virtual int32 GetShielding() const { return itembonuses.MeleeMitigation; } inline virtual int32 GetSpellShield() const { return itembonuses.SpellShield; } inline virtual int32 GetDoTShield() const { return itembonuses.DoTShielding; } inline virtual int32 GetStunResist() const { return itembonuses.StunResist; } inline virtual int32 GetStrikeThrough() const { return itembonuses.StrikeThrough; } inline virtual int32 GetAvoidance() const { return itembonuses.AvoidMeleeChance; } inline virtual int32 GetAccuracy() const { return itembonuses.HitChance; } inline virtual int32 GetCombatEffects() const { return itembonuses.ProcChance; } inline virtual int32 GetDS() const { return itembonuses.DamageShield; } // Mod3 inline int32 GetHealAmt() const override { return itembonuses.HealAmt; } inline int32 GetSpellDmg() const final { return itembonuses.SpellDmg; } inline virtual int32 GetClair() const { return itembonuses.Clairvoyance; } inline virtual int32 GetDSMit() const { return itembonuses.DSMitigation; } inline virtual int32 GetSingMod() const { return itembonuses.singingMod; } inline virtual int32 GetBrassMod() const { return itembonuses.brassMod; } inline virtual int32 GetPercMod() const { return itembonuses.percussionMod; } inline virtual int32 GetStringMod() const { return itembonuses.stringedMod; } inline virtual int32 GetWindMod() const { return itembonuses.windMod; } inline virtual int32 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath + 11; } virtual bool CheckFizzle(uint16 spell_id); virtual int GetCurrentBuffSlots() const; virtual int GetCurrentSongSlots() const; virtual int GetCurrentDiscSlots() const { return 1; } virtual int GetMaxBuffSlots() const { return EQ::spells::LONG_BUFFS; } virtual int GetMaxSongSlots() const { return EQ::spells::SHORT_BUFFS; } virtual int GetMaxDiscSlots() const { return EQ::spells::DISC_BUFFS; } virtual int GetMaxTotalSlots() const { return EQ::spells::TOTAL_BUFFS; } virtual uint32 GetFirstBuffSlot(bool disc, bool song); virtual uint32 GetLastBuffSlot(bool disc, bool song); virtual void InitializeBuffSlots(); virtual void UninitializeBuffSlots(); inline const int32 GetBaseHP() const { return base_hp; } uint32 GetWeight() const { return(weight); } inline void RecalcWeight() { weight = CalcCurrentWeight(); } uint32 CalcCurrentWeight(); inline uint32 GetCopper() const { return m_pp.copper; } inline uint32 GetSilver() const { return m_pp.silver; } inline uint32 GetGold() const { return m_pp.gold; } inline uint32 GetPlatinum() const { return m_pp.platinum; } /*Endurance and such*/ void CalcMaxEndurance(); //This calculates the maximum endurance we can have int64 CalcBaseEndurance(); //Calculates Base End int64 CalcEnduranceRegen(bool bCombat = false); //Calculates endurance regen used in DoEnduranceRegen() int64 GetEndurance() const {return current_endurance;} //This gets our current endurance int64 GetMaxEndurance() const {return max_end;} //This gets our endurance from the last CalcMaxEndurance() call int64 CalcEnduranceRegenCap() final; int64 CalcHPRegenCap() final; inline uint8 GetEndurancePercent() { return (uint8)((float)current_endurance / (float)max_end * 100.0f); } void SetEndurance(int32 newEnd); //This sets the current endurance to the new value void DoEnduranceRegen(); //This Regenerates endurance void DoEnduranceUpkeep(); //does the endurance upkeep //This calculates total Attack Rating to match very close to what the client should show uint32 GetTotalATK(); uint32 GetATKRating(); //This gets the skill value of the item type equipped in the Primary Slot uint16 GetPrimarySkillValue(); bool Flurry(); bool Rampage(); inline uint32 GetEXP() const { return m_pp.exp; } float GetAAEXPModifier(uint32 zone_id, int16 instance_version = -1); float GetEXPModifier(uint32 zone_id, int16 instance_version = -1); void SetAAEXPModifier(uint32 zone_id, float aa_modifier, int16 instance_version = -1); void SetEXPModifier(uint32 zone_id, float exp_modifier, int16 instance_version = -1); void SetAAEXPPercentage(uint8 percentage); bool UpdateLDoNPoints(uint32 theme_id, int points); void SetLDoNPoints(uint32 theme_id, uint32 points); void SetPVPPoints(uint32 Points) { m_pp.PVPCurrentPoints = Points; } uint32 GetPVPPoints() { return m_pp.PVPCurrentPoints; } void AddPVPPoints(uint32 Points); void AddEbonCrystals(uint32 amount, bool is_reclaim = false); void AddRadiantCrystals(uint32 amount, bool is_reclaim = false); void RemoveEbonCrystals(uint32 amount, bool is_reclaim = false); void RemoveRadiantCrystals(uint32 amount, bool is_reclaim = false); uint32 GetRadiantCrystals() { return m_pp.currentRadCrystals; } void SetRadiantCrystals(uint32 value); uint32 GetEbonCrystals() { return m_pp.currentEbonCrystals; } void SetEbonCrystals(uint32 value); void SendCrystalCounts(); uint64 GetExperienceForKill(Mob *against); void AddEXP(ExpSource exp_source, uint64 in_add_exp, uint8 conlevel = 0xFF, bool resexp = false, NPC* npc = nullptr); uint64 CalcEXP(uint8 conlevel = 0xFF, bool ignore_mods = false); void CalculateNormalizedAAExp(uint64 &add_aaxp, uint8 conlevel, bool resexp); void CalculateStandardAAExp(uint64 &add_aaxp, uint8 conlevel, bool resexp); void CalculateLeadershipExp(uint64 &add_exp, uint8 conlevel); void CalculateExp(uint64 in_add_exp, uint64 &add_exp, uint64 &add_aaxp, uint8 conlevel, bool resexp); void SetEXP(ExpSource exp_source, uint64 set_exp, uint64 set_aaxp, bool resexp = false, NPC* npc = nullptr); void AddLevelBasedExp(ExpSource exp_source, uint8 exp_percentage, uint8 max_level = 0, bool ignore_mods = false); void SetLeadershipEXP(uint64 group_exp, uint64 raid_exp); void AddLeadershipEXP(uint64 group_exp, uint64 raid_exp); void SendLeadershipEXPUpdate(); bool IsLeadershipEXPOn(); inline int GetLeadershipAA(int AAID) { return m_pp.leader_abilities.ranks[AAID]; } inline LeadershipAA_Struct &GetLeadershipAA() { return m_pp.leader_abilities; } inline GroupLeadershipAA_Struct &GetGroupLeadershipAA() { return m_pp.leader_abilities.group; } inline RaidLeadershipAA_Struct &GetRaidLeadershipAA() { return m_pp.leader_abilities.raid; } int GroupLeadershipAAHealthEnhancement(); int GroupLeadershipAAManaEnhancement(); int GroupLeadershipAAHealthRegeneration(); int GroupLeadershipAAOffenseEnhancement(); void InspectBuffs(Client* Inspector, int Rank); uint32 GetRaidPoints() { return(m_pp.raid_leadership_points); } uint32 GetGroupPoints() { return(m_pp.group_leadership_points); } uint32 GetRaidEXP() { return(m_pp.raid_leadership_exp); } uint32 GetGroupEXP() { return(m_pp.group_leadership_exp); } uint32 GetTotalSecondsPlayed() { return(TotalSecondsPlayed); } virtual void SetLevel(uint8 set_level, bool command = false); void GoToBind(uint8 bindnum = 0); void GoToSafeCoords(uint16 zone_id, uint16 instance_id); void Gate(uint8 bindnum = 0); void SetBindPoint(int bind_num = 0, int to_zone = -1, int to_instance = 0, const glm::vec3& location = glm::vec3()); void SetBindPoint2(int bind_num = 0, int to_zone = -1, int to_instance = 0, const glm::vec4& location = glm::vec4()); void SetStartZone(uint32 zoneid, float x = 0.0f, float y =0.0f, float z = 0.0f, float heading = 0.0f); uint32 GetStartZone(void); void MovePC(const char* zonename, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited); void MovePC(uint32 zoneID, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited); void MovePC(float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited); void MovePC(uint32 zoneID, uint32 instanceID, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited); void MoveZone(const char *zone_short_name, const glm::vec4& location = glm::vec4(0.f)); void MoveZoneGroup(const char *zone_short_name, const glm::vec4& location = glm::vec4(0.f)); void MoveZoneRaid(const char *zone_short_name, const glm::vec4& location = glm::vec4(0.f)); void MoveZoneInstance(uint16 instance_id, const glm::vec4& location = glm::vec4(0.f)); void MoveZoneInstanceGroup(uint16 instance_id, const glm::vec4& location = glm::vec4(0.f)); void MoveZoneInstanceRaid(uint16 instance_id, const glm::vec4& location = glm::vec4(0.f)); void SendToGuildHall(); void SendToInstance(std::string instance_type, std::string zone_short_name, uint32 instance_version, float x, float y, float z, float heading, std::string instance_identifier, uint32 duration); void AssignToInstance(uint16 instance_id); void RemoveFromInstance(uint16 instance_id); void WhoAll(); bool CheckLoreConflict(const EQ::ItemData* item); void ChangeLastName(std::string last_name); void GetGroupAAs(GroupLeadershipAA_Struct *into) const; void GetRaidAAs(RaidLeadershipAA_Struct *into) const; void ClearGroupAAs(); void UpdateGroupAAs(int32 points, uint32 type); void SacrificeConfirm(Mob* caster); void Sacrifice(Mob* caster); void GoToDeath(); inline const int32 GetInstanceID() const { return zone->GetInstanceID(); } void SetZoning(bool in) { bZoning = in; } bool IsZoning() { return bZoning; } void ShowSpells(Client* c, ShowSpellType show_spell_type); FACTION_VALUE GetReverseFactionCon(Mob* iOther); FACTION_VALUE GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_race, uint32 p_class, uint32 p_deity, int32 pFaction, Mob* tnpc); bool ReloadCharacterFaction(Client *c, uint32 facid, uint32 charid); int32 GetCharacterFactionLevel(int32 faction_id); int32 GetModCharacterFactionLevel(int32 faction_id); void MerchantRejectMessage(Mob *merchant, int primaryfaction); void SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_before_hit, int32 totalvalue, uint8 temp, int32 this_faction_min, int32 this_faction_max); void UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction_id, int32 *current_value, int32 temp, int32 this_faction_min, int32 this_faction_max); void SetFactionLevel(uint32 char_id, uint32 npc_faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, bool quest = false); void SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value, uint8 temp); int32 GetRawItemAC(); inline uint32 LSAccountID() const { return lsaccountid; } inline uint32 GetWID() const { return WID; } inline void SetWID(uint32 iWID) { WID = iWID; } inline uint32 AccountID() const { return account_id; } inline const char* AccountName()const { return account_name; } inline int GetAccountCreation() const { return account_creation; } inline int16 Admin() const { return admin; } inline uint32 CharacterID() const { return character_id; } void UpdateAdmin(bool from_database = true); void UpdateWho(uint8 remove = 0); bool GMHideMe(Client* client = 0); inline bool IsInAGuild() const { return(guild_id != GUILD_NONE && guild_id != 0); } inline bool IsInGuild(uint32 in_gid) const { return(in_gid == guild_id && IsInAGuild()); } inline bool GetGuildListDirty() { return guild_dirty; } inline void SetGuildListDirty(bool state) { guild_dirty = state; } inline uint32 GuildID() const { return guild_id; } inline uint8 GuildRank() const { return guildrank; } inline bool GuildTributeOptIn() const { return guild_tribute_opt_in; } void SetGuildTributeOptIn(bool state); void SendGuildTributeDonateItemReply(GuildTributeDonateItemRequest_Struct* in, uint32 favor); void SendGuildTributeDonatePlatReply(GuildTributeDonatePlatRequest_Struct* in, uint32 favor); void SetGuildRank(uint32 rank); void SetGuildID(uint32 guild_id); void SendGuildMOTD(bool GetGuildMOTDReply = false); void SendGuildURL(); void SendGuildChannel(); void SendGuildSpawnAppearance(); void SendGuildRanks(); void SendGuildMembers(); void SendGuildList(); void SendGuildJoin(GuildJoin_Struct* gj); void RefreshGuildInfo(); void SendGuildRankNames(); void SendGuildTributeDetails(uint32 tribute_id, uint32 tier); void DoGuildTributeUpdate(); void SendGuildActiveTributes(uint32 guild_id); void SendGuildFavorAndTimer(uint32 guild_id); void SendGuildTributeOptInToggle(const GuildTributeMemberToggle* in); void RequestGuildActiveTributes(uint32 guild_id); void RequestGuildFavorAndTimer(uint32 guild_id); void SendGuildMembersList(); void SendGuildMemberAdd(uint32 guild_id, uint32 level, uint32 _class, uint32 rank, uint32 guild_show, uint32 zone_id, std::string player_name); void SendGuildMemberRename(uint32 guild_id, std::string player_name, std::string new_player_name); void SendGuildMemberDelete(uint32 guild_id, std::string player_name); void SendGuildMemberLevel(uint32 guild_id, uint32 level, std::string player_name); void SendGuildMemberRankAltBanker(uint32 guild_id, uint32 rank, std::string player_name, bool alt, bool banker); void SendGuildMemberPublicNote(uint32 guild_id, std::string player_name, std::string public_note); void SendGuildMemberDetails(uint32 guild_id, uint32 zone_id, uint32 offline_mode, std::string player_name); void SendGuildRenameGuild(uint32 guild_id, std::string new_guild_name); void SendGuildDeletePacket(uint32 guild_id); uint8 GetClientMaxLevel() const { return client_max_level; } void SetClientMaxLevel(uint8 max_level) { client_max_level = max_level; } void CheckManaEndUpdate(); void SendManaUpdate(); void SendEnduranceUpdate(); uint8 GetFace() const { return m_pp.face; } void WhoAll(Who_All_Struct* whom); void FriendsWho(char *FriendsString); void Stun(int duration); void UnStun(); void ReadBook(BookRequest_Struct *book); void ReadBookByName(std::string book_name, uint8 book_type); void QuestReadBook(const char* text, uint8 type); void SendMoneyUpdate(); bool TakeMoneyFromPP(uint64 copper, bool update_client = false); bool TakePlatinum(uint32 platinum, bool update_client = false); void AddMoneyToPP(uint64 copper, bool update_client = false); void AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool update_client = false); void AddPlatinum(uint32 platinu, bool update_client = false); bool HasMoney(uint64 copper); uint64 GetCarriedMoney(); uint32 GetCarriedPlatinum(); uint64 GetAllMoney(); uint32 GetMoney(uint8 type, uint8 subtype); int GetAccountAge(); void SendPath(Mob* target); bool IsDiscovered(uint32 itemid); void DiscoverItem(uint32 itemid); bool TGB() const { return tgb; } void OnDisconnect(bool hard_disconnect); uint16 GetSkillPoints() { return m_pp.points;} void SetSkillPoints(int inp) { m_pp.points = inp;} void IncreaseSkill(int skill_id, int value = 1) { if (skill_id <= EQ::skills::HIGHEST_SKILL) { m_pp.skills[skill_id] += value; } } void IncreaseLanguageSkill(uint8 language_id, uint8 increase = 1); virtual uint16 GetSkill(EQ::skills::SkillType skill_id) const; uint32 GetRawSkill(EQ::skills::SkillType skill_id) const { if (skill_id <= EQ::skills::HIGHEST_SKILL) { return(m_pp.skills[skill_id]); } return 0; } bool HasSkill(EQ::skills::SkillType skill_id) const; bool CanHaveSkill(EQ::skills::SkillType skill_id) const; void SetSkill(EQ::skills::SkillType skill_num, uint16 value); void AddSkill(EQ::skills::SkillType skillid, uint16 value); void CheckSpecializeIncrease(uint16 spell_id); void CheckSongSkillIncrease(uint16 spell_id); bool CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who, int chancemodi = 0); void CheckLanguageSkillIncrease(uint8 language_id, uint8 teacher_skill); void SetLanguageSkill(uint8 language_id, uint8 language_skill); void SetHoTT(uint32 mobid); void ShowSkillsWindow(); uint16 MaxSkill(EQ::skills::SkillType skill_id, uint8 class_id, uint8 level) const; inline uint16 MaxSkill(EQ::skills::SkillType skill_id) const { return MaxSkill(skill_id, GetClass(), GetLevel()); } uint8 GetSkillTrainLevel(EQ::skills::SkillType skill_id, uint8 class_id); void MaxSkills(); void SendTradeskillSearchResults(const std::string &query, unsigned long objtype, unsigned long someid); void SendTradeskillDetails(uint32 recipe_id); bool TradeskillExecute(DBTradeskillRecipe_Struct *spec); void CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float skillup_modifier, uint16 success_modifier, EQ::skills::SkillType tradeskill); bool CheckTradeskillLoreConflict(int32 recipe_id); void InitInnates(); void GMKill(); inline bool IsMedding() const {return medding;} inline uint32 GetDuelTarget() const { return duel_target; } inline bool IsDueling() const { return duelaccepted; } inline void SetDuelTarget(uint32 set_id) { duel_target = set_id; } inline void SetDueling(bool duel) { duelaccepted = duel; } // use this one instead void MemSpell(uint16 spell_id, int slot, bool update_client = true); void UnmemSpell(int slot, bool update_client = true); void UnmemSpellBySpellID(int32 spell_id); void UnmemSpellAll(bool update_client = true); int FindEmptyMemSlot(); uint16 FindMemmedSpellBySlot(int slot); int FindMemmedSpellBySpellID(uint16 spell_id); int MemmedCount(); std::vector GetLearnableDisciplines(uint8 min_level = 1, uint8 max_level = 0); std::vector GetLearnedDisciplines(); std::vector GetMemmedSpells(); std::vector GetScribeableSpells(uint8 min_level = 1, uint8 max_level = 0); std::vector GetScribedSpells(); // defer save used when bulk saving void ScribeSpell(uint16 spell_id, int slot, bool update_client = true, bool defer_save = false); void SaveSpells(); void SaveDisciplines(); // Bulk Scribe/Learn uint16 ScribeSpells(uint8 min_level, uint8 max_level); uint16 LearnDisciplines(uint8 min_level, uint8 max_level); // Configurable Tracking Skill uint16 GetClassTrackingDistanceMultiplier(uint16 class_); bool CanThisClassTrack(); // defer save used when bulk saving void UnscribeSpell(int slot, bool update_client = true, bool defer_save = false); void UnscribeSpellAll(bool update_client = true); void UnscribeSpellBySpellID(uint16 spell_id, bool update_client = true); void UntrainDisc(int slot, bool update_client = true, bool defer_save = false); void UntrainDiscAll(bool update_client = true); void UntrainDiscBySpellID(uint16 spell_id, bool update_client = true); bool SpellGlobalCheck(uint16 spell_id, uint32 char_id); bool SpellBucketCheck(uint16 spell_id, uint32 char_id); uint8 GetCharMaxLevelFromQGlobal(); uint8 GetCharMaxLevelFromBucket(); void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los = false, bool clip_through_walls = false, bool calculate_speed = false); inline bool IsStanding() const { return (playeraction == 0); } inline bool IsSitting() const override { return (playeraction == 1); } inline bool IsCrouching() const { return (playeraction == 2); } inline bool IsBecomeNPC() const { return npcflag; } inline uint8 GetBecomeNPCLevel() const { return npclevel; } inline void SetBecomeNPC(bool flag) { npcflag = flag; } inline void SetBecomeNPCLevel(uint8 level) { npclevel = level; } EQStreamInterface* Connection() { return eqs; } uint32 GetEquippedItemFromTextureSlot(uint8 material_slot) const; // returns item id uint32 GetEquipmentColor(uint8 material_slot) const; virtual void UpdateEquipmentLight() { m_Light.Type[EQ::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQ::lightsource::LightEquipment] = EQ::lightsource::TypeToLevel(m_Light.Type[EQ::lightsource::LightEquipment]); } inline bool AutoSplitEnabled() { return m_pp.autosplit != 0; } inline bool AutoConsentGroupEnabled() const { return m_pp.groupAutoconsent != 0; } inline bool AutoConsentRaidEnabled() const { return m_pp.raidAutoconsent != 0; } inline bool AutoConsentGuildEnabled() const { return m_pp.guildAutoconsent != 0; } void SummonHorse(uint16 spell_id); void SetHorseId(uint16 horseid_in); inline void SetControlledMobId(uint16 mob_id_in) { controlled_mob_id = mob_id_in; } uint16 GetControlledMobId() const{ return controlled_mob_id; } uint16 GetHorseId() const { return horseId; } bool CanMedOnHorse(); bool CanFastRegen() const { return ooc_regen; } void NPCSpawn(NPC *target_npc, const char *identifier, uint32 extra = 0); void Disarm(Client* disarmer, int chance); bool BindWound(Mob* bindmob, bool start, bool fail = false); void SetTradeskillObject(Object* object) { m_tradeskill_object = object; } Object* GetTradeskillObject() { return m_tradeskill_object; } void SendTributes(); void SendGuildTributes(); void DoTributeUpdate(); void SendTributeDetails(uint32 client_id, uint32 tribute_id); int32 TributeItem(uint32 slot, uint32 quantity); int32 TributeMoney(uint32 platinum); void AddTributePoints(int32 ammount); void ChangeTributeSettings(TributeInfo_Struct *t); void SendTributeTimer(); void ToggleTribute(bool enabled); std::map GetTributeList(); uint32 LookupTributeItemID(uint32 tribute_id, uint32 tier); void SendPathPacket(const std::vector &path); inline PTimerList &GetPTimers() { return(p_timers); } //New AA Methods void SendAlternateAdvancementRank(int aa_id, int level); void SendAlternateAdvancementTable(); void SendAlternateAdvancementStats(); void PurchaseAlternateAdvancementRank(int rank_id); bool GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost = false); void IncrementAlternateAdvancementRank(int rank_id); void ActivateAlternateAdvancementAbility(int rank_id, int target_id); void SendAlternateAdvancementPoints(); void SendAlternateAdvancementTimer(int ability, int begin, int end); void SendAlternateAdvancementTimers(); void ResetAlternateAdvancementTimer(int ability); void ResetAlternateAdvancementTimers(); void ResetOnDeathAlternateAdvancement(); void SetAAPoints(uint32 points); void AddAAPoints(uint32 points); bool RemoveAAPoints(uint32 points); int GetAAPoints() { return m_pp.aapoints; } int GetSpentAA() { return m_pp.aapoints_spent; } uint32 GetRequiredAAExperience(); void AutoGrantAAPoints(); void GrantAllAAPoints(uint8 unlock_level = 0, bool skip_grant_only = false); bool HasAlreadyPurchasedRank(AA::Rank* rank); void ListPurchasedAAs(Client *to, std::string search_criteria = std::string()); bool SendGMCommand(std::string message, bool ignore_status = false); void RegisterBug(BugReport_Struct* r); std::vector GetApplySpellList( ApplySpellType apply_type, bool allow_pets, bool is_raid_group_only, bool allow_bots ); void ApplySpell( int spell_id, int duration = 0, int level = -1, ApplySpellType apply_type = ApplySpellType::Solo, bool allow_pets = false, bool is_raid_group_only = true, bool allow_bots = false ); void SetSpellDuration( int spell_id, int duration = 0, int level = -1, ApplySpellType apply_type = ApplySpellType::Solo, bool allow_pets = false, bool is_raid_group_only = true, bool allow_bots = false ); //old AA methods that we still use void ResetAA(); void ResetLeadershipAA(); void RefundAA(); void SendClearLeadershipAA(); void SendClearPlayerAA(); inline uint32 GetAAXP() const { return m_pp.expAA; } inline uint32 GetAAPercent() const { return m_epp.perAA; } void SetAATitle(std::string title); void SetTitleSuffix(std::string suffix); void MemorizeSpell(uint32 slot, uint32 spell_id, uint32 scribing, uint32 reduction = 0); int GetAAEXPPercentage(); int GetEXPPercentage(); // Item methods void UseAugmentContainer(int container_slot); uint32 NukeItem(uint32 itemnum, uint8 where_to_check = (invWhereWorn | invWherePersonal | invWhereBank | invWhereSharedBank | invWhereTrading | invWhereCursor)); void SetTint(int16 slot_id, uint32 color); void SetTint(int16 slot_id, EQ::textures::Tint_Struct& color); void SetMaterial(int16 slot_id, uint32 item_id); void Undye(); int32 GetItemIDAt(int16 slot_id); int32 GetAugmentIDAt(int16 slot_id, uint8 augslot); bool PutItemInInventory(int16 slot_id, const EQ::ItemInstance& inst, bool client_update = false); bool PutItemInInventoryWithStacking(EQ::ItemInstance* inst); bool FindNumberOfFreeInventorySlotsWithSizeCheck(std::vector items); bool PushItemOnCursor(const EQ::ItemInstance& inst, bool client_update = false); void SendCursorBuffer(); void DeleteItemInInventory(int16 slot_id, int16 quantity = 0, bool client_update = false, bool update_db = true); uint32 CountItem(uint32 item_id); void ResetItemCooldown(uint32 item_id); void SetItemCooldown(uint32 item_id, bool use_saved_timer = false, uint32 in_seconds = 1); uint32 GetItemCooldown(uint32 item_id); void RemoveItem(uint32 item_id, uint32 quantity = 1); void RemoveItemBySerialNumber(uint32 serial_number, uint32 quantity = 1); bool SwapItem(MoveItem_Struct* move_in); void SwapItemResync(MoveItem_Struct* move_slots); void PutLootInInventory(int16 slot_id, const EQ::ItemInstance &inst, LootItem** bag_item_data = 0); bool AutoPutLootInInventory(EQ::ItemInstance& inst, bool try_worn = false, bool try_cursor = true, LootItem** bag_item_data = 0); bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = EQ::invslot::slotCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); void SummonItemIntoInventory(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool is_attuned = false); void SummonBaggedItems(uint32 bag_item_id, const std::vector& bag_items); void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id, bool recurse = true); bool HasItemOnCorpse(uint32 item_id); bool IsAugmentRestricted(uint8 item_type, uint32 augment_restriction); int GetItemLinkHash(const EQ::ItemInstance* inst); // move to ItemData..or make use of the pre-calculated database field void SendItemLink(const EQ::ItemInstance* inst, bool sendtoall=false); void SendLootItemInPacket(const EQ::ItemInstance* inst, int16 slot_id); void SendItemPacket(int16 slot_id, const EQ::ItemInstance* inst, ItemPacketType packet_type); bool IsValidSlot(uint32 slot); bool IsBankSlot(uint32 slot); bool IsTrader() const { return trader; } void SetTrader(bool status) { trader = status; } uint16 GetTraderID() { return trader_id; } void SetTraderID(uint16 id) { trader_id = id; } void SetTraderCount(uint32 no) { m_trader_count = no; } uint32 GetTraderCount() { return m_trader_count; } void IncrementTraderCount() { m_trader_count += 1; } void DecrementTraderCount() { m_trader_count > 0 ? m_trader_count -= 1 : m_trader_count = 0; } void SetTraderTransactionDate() { m_trader_transaction_date = time(nullptr); } time_t GetTraderTransactionDate() { return m_trader_transaction_date; } eqFilterMode GetFilter(eqFilterType filter_id) const { return ClientFilters[filter_id]; } void SetFilter(eqFilterType filter_id, eqFilterMode filter_mode) { ClientFilters[filter_id] = filter_mode; } void CancelSneakHide(); void BreakInvis(); void BreakSneakWhenCastOn(Mob* caster, bool IsResisted); void BreakFeignDeathWhenCastOn(bool IsResisted); void LeaveGroup(); bool Hungry() const {if (GetGM() || !RuleB(Character, EnableFoodRequirement)) return false; return m_pp.hunger_level <= 3000;} bool Thirsty() const {if (GetGM() || !RuleB(Character, EnableFoodRequirement)) return false; return m_pp.thirst_level <= 3000;} int32 GetHunger() const { return m_pp.hunger_level; } int32 GetThirst() const { return m_pp.thirst_level; } void SetHunger(int32 in_hunger); void SetThirst(int32 in_thirst); void SetConsumption(int32 in_hunger, int32 in_thirst); bool IsStarved() const { if (GetGM() || !RuleB(Character, EnableFoodRequirement) || !RuleB(Character, EnableHungerPenalties)) return false; return m_pp.hunger_level == 0 || m_pp.thirst_level == 0; } int32 GetIntoxication() const { return m_pp.intoxication; } bool CheckTradeLoreConflict(Client* other); bool CheckTradeNonDroppable(); void LinkDead(); bool CheckDoubleAttack(); bool CheckTripleAttack(); bool CheckDoubleRangedAttack(); bool CheckDualWield(); //remove charges/multiple objects from inventory: //bool DecreaseByType(uint32 type, uint8 amt); bool DecreaseByID(uint32 type, int16 quantity); uint8 SlotConvert2(uint8 slot); //Maybe not needed. void Escape(); //keep or quest function void DisenchantSummonedBags(bool client_update = true); void RemoveNoRent(bool client_update = true); void RemoveDuplicateLore(); void MoveSlotNotAllowed(bool client_update = true); virtual bool RangedAttack(Mob* other, bool CanDoubleAttack = false); virtual void ThrowingAttack(Mob* other, bool CanDoubleAttack = false); void DoClassAttacks(Mob *ca_target, uint16 skill = -1, bool IsRiposte=false); void ClearZoneFlag(uint32 zone_id); inline std::set GetZoneFlags() { return zone_flags; } ; bool HasZoneFlag(uint32 zone_id) const; void LoadZoneFlags(); void SendZoneFlagInfo(Client *to) const; void SetZoneFlag(uint32 zone_id); void ClearPEQZoneFlag(uint32 zone_id); inline std::set GetPEQZoneFlags() { return peqzone_flags; }; bool HasPEQZoneFlag(uint32 zone_id) const; void LoadPEQZoneFlags(); void SendPEQZoneFlagInfo(Client *to) const; void SetPEQZoneFlag(uint32 zone_id); bool CanFish(); void GoFish(bool guarantee = false, bool use_bait = true); void ForageItem(bool guarantee = false); //Calculate vendor price modifier based on CHA: (reverse==selling) float CalcClassicPriceMod(Mob* other = 0, bool reverse = false); float CalcNewPriceMod(Mob* other = 0, bool reverse = false); float CalcPriceMod(Mob* other = 0, bool reverse = false); void ResetTrade(); void DropInst(const EQ::ItemInstance* inst); bool TrainDiscipline(uint32 itemid); bool MemorizeSpellFromItem(uint32 item_id); void TrainDiscBySpellID(int32 spell_id); uint32 GetDisciplineTimer(uint32 timer_id); void ResetAllDisciplineTimers(); int GetDiscSlotBySpellID(int32 spellid); void ResetDisciplineTimer(uint32 timer_id); void SendDisciplineUpdate(); void SendDisciplineTimer(uint32 timer_id, uint32 duration); bool UseDiscipline(uint32 spell_id, uint32 target); bool HasDisciplineLearned(uint16 spell_id); void SetLinkedSpellReuseTimer(uint32 timer_id, uint32 duration); bool IsLinkedSpellReuseTimerReady(uint32 timer_id); void ResetCastbarCooldownBySlot(int slot); void ResetAllCastbarCooldowns(); void ResetCastbarCooldownBySpellID(uint32 spell_id); bool CheckTitle(int title_set); void EnableTitle(int title_set, bool insert = true); const std::vector& GetTitles() { return m_player_title_sets; }; void RemoveTitle(int title_set); void EnteringMessages(Client* client); void SendRules(); const bool GetGMSpeed() const { return (gmspeed > 0); } const bool GetGMInvul() const { return gminvul; } bool CanUseReport; const std::string GetAutoLoginCharacterName(); bool SetAutoLoginCharacterName(const std::string& character_name); //This is used to later set the buff duration of the spell, in slot to duration. //Doesn't appear to work directly after the client recieves an action packet. void SendBuffDurationPacket(Buffs_Struct &buff, int slot); void SendBuffNumHitPacket(Buffs_Struct &buff, int slot); void ProcessInspectRequest(Client* requestee, Client* requester); bool ClientFinishedLoading() { return (conn_state == ClientConnectFinished); } int FindSpellBookSlotBySpellID(uint16 spellid); uint32 GetSpellIDByBookSlot(int book_slot); int GetNextAvailableSpellBookSlot(int starting_slot = 0); int GetNextAvailableDisciplineSlot(int starting_slot = 0); inline uint32 GetSpellByBookSlot(int book_slot) { return m_pp.spell_book[book_slot]; } inline bool HasSpellScribed(int spellid) { return FindSpellBookSlotBySpellID(spellid) != -1; } uint32 GetHighestScribedSpellinSpellGroup(uint32 spell_group); std::unordered_map> LoadSpellGroupCache(uint8 min_level, uint8 max_level); uint16 GetMaxSkillAfterSpecializationRules(EQ::skills::SkillType skillid, uint16 maxSkill); void SendPopupToClient(const char *Title, const char *Text, uint32 PopupID = 0, uint32 Buttons = 0, uint32 Duration = 0); void SendFullPopup(const char *Title, const char *Text, uint32 PopupID = 0, uint32 NegativeID = 0, uint32 Buttons = 0, uint32 Duration = 0, const char *ButtonName0 = 0, const char *ButtonName1 = 0, uint32 SoundControls = 0); void SendWindow(uint32 button_one_id, uint32 button_two_id, uint32 button_type, const char* button_one_text, const char* button_two_text, uint32 duration, int title_type, Mob* target, const char* title, const char* text, ...); bool PendingTranslocate; time_t TranslocateTime; bool PendingSacrifice; uint16 sacrifice_caster_id; PendingTranslocate_Struct PendingTranslocateData; void SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID); // Help Window std::string SendBotCommandHelpWindow(const BotCommandHelpParams& params); std::string GetCommandHelpHeader(std::string msg, std::string color); std::string SplitCommandHelpText(std::vector msg, std::string color, uint16 max_length, std::string secondary_color = ""); void SendSpellTypePrompts(bool commanded_types = false, bool client_only_types = false); // Task System Methods inline void LoadClientSharedCompletedTasks() { std::string query = fmt::format(R"( SELECT cst.task_id FROM completed_shared_task_members cstm JOIN completed_shared_tasks cst ON cstm.shared_task_id = cst.id WHERE cstm.character_id = {} GROUP BY cst.task_id; )", CharacterID()); auto results = database.QueryDatabase(query); if (!results.Success()) { return; } m_completed_shared_tasks.clear(); for (auto row = results.begin(); row != results.end(); ++row) { m_completed_shared_tasks.push_back(std::stoi(row[0])); } }; inline std::vector GetCompletedSharedTasks() const { return m_completed_shared_tasks; }; void LoadClientTaskState(); void RemoveClientTaskState(); void SendTaskActivityComplete(int task_id, int activity_id, int task_index, TaskType task_type, int task_incomplete=1); void SendTaskFailed(int task_id, int task_index, TaskType task_type); void SendTaskComplete(int task_index); bool HasTaskRequestCooldownTimer(); void SendTaskRequestCooldownTimerMessage(); void StartTaskRequestCooldownTimer(); inline ClientTaskState *GetTaskState() const { return task_state; } inline bool HasTaskState() { if (task_state) { return true; } return false; } inline void CancelTask(int task_index, TaskType task_type) { if (task_state) { task_state->CancelTask( this, task_index, task_type ); } } inline bool SaveTaskState() { return TaskManager::Instance()->SaveClientState(this, task_state); } inline bool IsTaskStateLoaded() { return task_state != nullptr; } inline bool IsTaskActive(int task_id) { return task_state != nullptr && task_state->IsTaskActive(task_id); } inline bool IsTaskActivityActive(int task_id, int activity_id) { return task_state != nullptr && task_state->IsTaskActivityActive( task_id, activity_id ); } inline ActivityState GetTaskActivityState(TaskType task_type, int index, int activity_id) { return (task_state ? task_state->GetTaskActivityState(task_type, index, activity_id) : ActivityHidden); } inline void UpdateTaskActivity( int task_id, int activity_id, int count, bool ignore_quest_update = false ) { if (task_state) { task_state->UpdateTaskActivity(this, task_id, activity_id, count, ignore_quest_update); } } inline void RemoveTaskByTaskID(uint32 task_id) { if (task_state) { task_state->RemoveTaskByTaskID(this, task_id); } } inline void ResetTaskActivity(int task_id, int activity_id) { if (task_state) { task_state->ResetTaskActivity( this, task_id, activity_id ); } } inline void UpdateTasksForItem(TaskActivityType type, int item_id, int count = 1) { if (task_state) { task_state->UpdateTasksForItem(this, type, item_id, count); } } inline void UpdateTasksOnLoot(Corpse* corpse, int item_id, int count = 1) { if (task_state) { task_state->UpdateTasksOnLoot(this, corpse, item_id, count); } } inline void UpdateTasksOnExplore(const glm::vec4& pos) { if (task_state) { task_state->UpdateTasksOnExplore(this, pos); } } inline bool UpdateTasksOnSpeakWith(NPC* npc) { return task_state && task_state->UpdateTasksOnSpeakWith(this, npc); } inline bool UpdateTasksOnDeliver(std::vector& items, Trade& trade, NPC* npc) { return task_state && task_state->UpdateTasksOnDeliver(this, items, trade, npc); } void UpdateTasksOnTouchSwitch(int dz_switch_id) { if (task_state) { task_state->UpdateTasksOnTouch(this, dz_switch_id); } } inline void TaskSetSelector(Mob* mob, int task_set_id, bool ignore_cooldown) { if (task_state) { TaskManager::Instance()->TaskSetSelector(this, mob, task_set_id, ignore_cooldown); } } inline void TaskQuestSetSelector(Mob* mob, const std::vector& tasks, bool ignore_cooldown) { if (task_state) { TaskManager::Instance()->TaskQuestSetSelector(this, mob, tasks, ignore_cooldown); } } inline void EnableTask(int task_count, int *task_list) { if (task_state) { task_state->EnableTask( CharacterID(), task_count, task_list ); } } inline void DisableTask(int task_count, int *task_list) { if (task_state) { task_state->DisableTask( CharacterID(), task_count, task_list ); } } inline bool IsTaskEnabled(int task_id) { return task_state != nullptr && task_state->IsTaskEnabled(task_id); } inline void ProcessTaskProximities(float x, float y, float z) { if (task_state) { task_state->ProcessTaskProximities(this, x, y, z); } } inline void AssignTask( int task_id, int npc_id = 0, bool enforce_level_requirement = false ) { if (task_state) { task_state->AcceptNewTask(this, task_id, npc_id, std::time(nullptr), enforce_level_requirement); } } inline int ActiveSpeakTask(NPC* npc) { if (task_state) { return task_state->ActiveSpeakTask(this, npc); } else { return 0; } } inline int ActiveSpeakActivity(NPC* npc, int task_id) { if (task_state) { return task_state->ActiveSpeakActivity(this, npc, task_id); } else { return 0; } } inline bool CompleteTask(uint32 task_id) { return task_state ? task_state->CompleteTask(this, task_id) : false; } bool UncompleteTask(int task_id); inline void FailTask(int task_id) { if (task_state) { task_state->FailTask(this, task_id); }} inline int TaskTimeLeft(int task_id) { return (task_state ? task_state->TaskTimeLeft(task_id) : 0); } inline int EnabledTaskCount(int task_set_id) { return (task_state ? task_state->EnabledTaskCount(task_set_id) : -1); } inline bool IsTaskCompleted(int task_id) { return (task_state ? task_state->IsTaskCompleted(task_id, this) : false); } inline bool AreTasksCompleted(std::vector task_ids) { return (task_state ? task_state->AreTasksCompleted(task_ids) : false); } inline void ShowClientTasks(Client *client) { if (task_state) { task_state->ShowClientTasks(this, client); }} inline void CancelAllTasks() { if (task_state) { task_state->CancelAllTasks(this); }} inline int GetActiveTaskCount() { return (task_state ? task_state->GetActiveTaskCount() : 0); } inline int GetActiveTaskID(int index) { return (task_state ? task_state->GetActiveTaskID(index) : -1); } inline int GetTaskStartTime(TaskType task_type, int index) { return (task_state ? task_state->GetTaskStartTime( task_type, index ) : -1); } inline bool IsTaskActivityCompleted(TaskType task_type, int index, int activity_id) { return task_state != nullptr && task_state->IsTaskActivityCompleted(task_type, index, activity_id); } inline int GetTaskActivityDoneCount(TaskType task_type, int client_task_index, int activity_id) { return (task_state ? task_state->GetTaskActivityDoneCount(task_type, client_task_index, activity_id) : 0); } inline int GetTaskActivityDoneCountFromTaskID(int task_id, int activity_id) { return (task_state ? task_state->GetTaskActivityDoneCountFromTaskID(task_id, activity_id) : 0); } inline int ActiveTasksInSet(int task_set_id) { return (task_state ? task_state->ActiveTasksInSet(task_set_id) : 0); } inline int CompletedTasksInSet(int task_set_id) { return (task_state ? task_state->CompletedTasksInSet(task_set_id) : 0); } void PurgeTaskTimers(); void LockSharedTask(bool lock) { if (task_state) { task_state->LockSharedTask(this, lock); } } void EndSharedTask(bool fail = false) { if (task_state) { task_state->EndSharedTask(this, fail); } } // shared task shims / middleware // these variables are used as a shim to intercept normal localized task functionality // and pipe it into zone -> world and back to world -> zone // world is authoritative bool m_requesting_shared_task = false; bool m_shared_task_update = false; bool m_requested_shared_task_removal = false; std::vector GetPartyMembers(); inline const EQ::versions::ClientVersion ClientVersion() const { return m_ClientVersion; } inline const uint32 ClientVersionBit() const { return m_ClientVersionBit; } inline void SetClientVersion(EQ::versions::ClientVersion client_version) { m_ClientVersion = client_version; } /** Adventure Stuff **/ void SendAdventureError(const char *error); void SendAdventureDetails(); void SendAdventureCount(uint32 count, uint32 total); void NewAdventure(int id, int theme, const char *text, int member_count, const char *members); bool IsOnAdventure(); void LeaveAdventure(); void AdventureFinish(bool win, int theme, int points); void SetAdventureData(char *data) { adv_data = data; } void ClearAdventureData() { safe_delete(adv_data); } bool HasAdventureData() { return adv_data != nullptr; } void ClearCurrentAdventure(); void PendingAdventureRequest() { adventure_request_timer = new Timer(8000); } bool GetPendingAdventureRequest() const { return (adventure_request_timer != nullptr); } void ClearPendingAdventureRequest() { safe_delete(adventure_request_timer); } void PendingAdventureCreate() { adventure_create_timer = new Timer(8000); } bool GetPendingAdventureCreate() const { return (adventure_create_timer != nullptr); } void ClearPendingAdventureCreate() { safe_delete(adventure_create_timer); } void PendingAdventureLeave() { adventure_leave_timer = new Timer(8000); } bool GetPendingAdventureLeave() const { return (adventure_leave_timer != nullptr); } void ClearPendingAdventureLeave() { safe_delete(adventure_leave_timer); } void PendingAdventureDoorClick() { adventure_door_timer = new Timer(8000); } bool GetPendingAdventureDoorClick() const { return (adventure_door_timer != nullptr); } void ClearPendingAdventureDoorClick() { safe_delete(adventure_door_timer); } void ClearPendingAdventureData(); bool CanEnterZone(const std::string& zone_short_name = "", int16 instance_version = -1); uint32 GetAggroCount(); void IncrementAggroCount(bool raid_target = false); void DecrementAggroCount(); void SendPVPStats(); void SendDisciplineTimers(); void SendRespawnBinds(); uint32 GetLDoNWins() { return (m_pp.ldon_wins_guk + m_pp.ldon_wins_mir + m_pp.ldon_wins_mmc + m_pp.ldon_wins_ruj + m_pp.ldon_wins_tak); } uint32 GetLDoNLosses() { return (m_pp.ldon_losses_guk + m_pp.ldon_losses_mir + m_pp.ldon_losses_mmc + m_pp.ldon_losses_ruj + m_pp.ldon_losses_tak); } uint32 GetLDoNWinsTheme(uint32 t); uint32 GetLDoNLossesTheme(uint32 t); uint32 GetLDoNPointsTheme(uint32 t); void UpdateLDoNWinLoss(uint32 theme_id, bool win = false, bool remove = false); void CheckLDoNHail(NPC* n); void CheckEmoteHail(NPC* n, const char* message); void HandleLDoNOpen(NPC *target); void HandleLDoNSenseTraps(NPC *target, uint16 skill, uint8 type); void HandleLDoNDisarm(NPC *target, uint16 skill, uint8 type); void HandleLDoNPickLock(NPC *target, uint16 skill, uint8 type); int LDoNChest_SkillCheck(NPC *target, int skill); void MarkSingleCompassLoc(float in_x, float in_y, float in_z, uint8 count=1); // cross zone client messaging helpers (null client argument will fallback to messaging by name) static void SendCrossZoneMessage( Client* client, const std::string& client_name, uint16_t chat_type, const std::string& message); static void SendCrossZoneMessageString( Client* client, const std::string& client_name, uint16_t chat_type, uint32_t string_id, const std::initializer_list& arguments = {}); void AddDzLockout(const DzLockout& lockout, bool update_db = false); void AddDzLockout(const std::string& expedition, const std::string& event, uint32_t duration, std::string uuid = {}); void AddDzLockoutDuration(const DzLockout& lockout, int seconds, const std::string& uuid = {}, bool update_db = false); DynamicZone* CreateExpedition(DynamicZone& dz, bool silent = false); DynamicZone* CreateExpedition(uint32 zone_id, uint32 version, uint32 duration, const std::string& name, uint32 min_players, uint32 max_players, bool silent = false); DynamicZone* CreateExpeditionFromTemplate(uint32_t dz_template_id); DynamicZone* GetExpedition() const; uint32 GetExpeditionID() const; const DzLockout* GetDzLockout(const std::string& expedition, const std::string& event) const; const std::vector& GetDzLockouts() const { return m_dz_lockouts; }; std::vector GetDzLockouts(const std::string& expedition); uint32 GetPendingDzInviteID() const { return m_dz_invite.dz_id; } void SetPendingDzInvite(const ExpeditionInvite& invite) { m_dz_invite = invite; } void RequestPendingDzInvite() const; bool HasDzLockout(const std::string& expedition, const std::string& event) const; void RemoveDzLockouts(const std::string& expedition, bool update_db = false); void RemoveDzLockout(const std::string& expedition, const std::string& event, bool update_db = false); void SendDzLockoutTimers(); void DzListTimers(); void SetDzRemovalTimer(bool enable_timer); void SendDzCompassUpdate(); void GoToDzSafeReturnOrBind(const DynamicZone* dynamic_zone); void MovePCDynamicZone(uint32 zone_id, int zone_version = -1, bool msg_if_invalid = false); void MovePCDynamicZone(const std::string& zone_name, int zone_version = -1, bool msg_if_invalid = false); bool TryMovePCDynamicZoneSwitch(int dz_switch_id); std::vector GetDynamicZones(uint32_t zone_id = 0, int zone_version = -1); std::unique_ptr CreateDzSwitchListPacket(const std::vector& dzs); std::unique_ptr CreateCompassPacket(const std::vector& entries); void AddDynamicZoneID(uint32_t dz_id); void RemoveDynamicZoneID(uint32_t dz_id); void SendDynamicZoneUpdates(); void SetDynamicZoneMemberStatus(DynamicZoneMemberStatus status); void CreateTaskDynamicZone(int task_id, DynamicZone& dz_request); void CalcItemScale(); bool CalcItemScale(uint32 slot_x, uint32 slot_y); // behavior change: 'slot_y' is now [RANGE]_END and not [RANGE]_END + 1 void DoItemEnterZone(); bool DoItemEnterZone(uint32 slot_x, uint32 slot_y); // behavior change: 'slot_y' is now [RANGE]_END and not [RANGE]_END + 1 void SummonAndRezzAllCorpses(); void SummonAllCorpses(const glm::vec4& position); void DepopAllCorpses(); void DepopPlayerCorpse(uint32 dbid); void BuryPlayerCorpses(); int64 GetCorpseCount() { return database.GetCharacterCorpseCount(CharacterID()); } uint32 GetCorpseID(int corpse) { return database.GetCharacterCorpseID(CharacterID(), corpse); } uint32 GetCorpseItemAt(int corpse_id, int slot_id) { if (!corpse_id) { return 0; } return database.GetCharacterCorpseItemAt(corpse_id, slot_id); } void SuspendMinion(int value); void Doppelganger(uint16 spell_id, Mob *target, const char *name_override, int pet_count, int pet_duration); void NotifyNewTitlesAvailable(); void Signal(int signal_id); void SendPayload(int payload_id, std::string payload_value = std::string()); Mob *GetBindSightTarget() { return bind_sight_target; } void SetBindSightTarget(Mob *n) { bind_sight_target = n; } const uint16 GetBoatID() const { return controlling_boat_id; } void SendRewards(); bool TryReward(uint32 claim_id); QGlobalCache *GetQGlobals() { return qGlobals; } QGlobalCache *CreateQGlobals() { qGlobals = new QGlobalCache(); return qGlobals; } void GuildBankAck(); void GuildBankDepositAck(bool Fail, int8 action); inline bool IsGuildBanker() { return GuildBanker; } inline void SetGuildBanker(bool banker) { GuildBanker = banker; } void ClearGuildBank(); void SendGroupCreatePacket(); void SendGroupLeaderChangePacket(const char *LeaderName); void SendGroupJoinAcknowledge(); void DoTracking(); inline bool IsTracking() { return (TrackingID > 0); } inline void SetPendingGuildInvitation(bool inPendingGuildInvitation) { PendingGuildInvitation = inPendingGuildInvitation; } inline bool GetPendingGuildInvitation() { return PendingGuildInvitation; } void LocateCorpse(); void SendTargetCommand(uint32 EntityID); bool MoveItemToInventory(EQ::ItemInstance *BInst, bool UpdateClient = false); void HandleRespawnFromHover(uint32 Option); bool IsHoveringForRespawn() { return RespawnFromHoverTimer.Enabled(); } std::list respawn_options; void AddRespawnOption(std::string option_name, uint32 zoneid, uint16 instance_id, float x, float y, float z, float h = 0, bool initial_selection = false, int8 position = -1); bool RemoveRespawnOption(std::string option_name); bool RemoveRespawnOption(uint8 position); void ClearRespawnOptions() { respawn_options.clear(); } void SetPendingRezzData(int XP, uint32 DBID, uint16 SpellID, const char *CorpseName) { PendingRezzXP = XP; PendingRezzDBID = DBID; PendingRezzSpellID = SpellID; PendingRezzCorpseName = CorpseName; } bool IsRezzPending() { return PendingRezzSpellID > 0; } void ClearHover(); inline bool IsBlockedBuff(int32 SpellID) { return PlayerBlockedBuffs.find(SpellID) != PlayerBlockedBuffs.end(); } inline bool IsBlockedPetBuff(int32 SpellID) { return PetBlockedBuffs.find(SpellID) != PetBlockedBuffs.end(); } bool IsDraggingCorpse(uint16 CorpseID); inline bool IsDraggingCorpse() { return (DraggedCorpses.size() > 0); } void DragCorpses(); inline void ClearDraggedCorpses() { DraggedCorpses.clear(); } void ConsentCorpses(std::string consent_name, bool deny = false); void SendAltCurrencies(); void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount); int AddAlternateCurrencyValue(uint32 currency_id, int amount, bool is_scripted = false); bool RemoveAlternateCurrencyValue(uint32 currency_id, uint32 amount); void SendAlternateCurrencyValues(); void SendAlternateCurrencyValue(uint32 currency_id, bool send_if_null = true); uint32 GetAlternateCurrencyValue(uint32 currency_id) const; void ProcessAlternateCurrencyQueue(); void OpenLFGuildWindow(); void HandleLFGuildResponse(ServerPacket *pack); void SendLFGuildStatus(); void SendGuildLFGuildStatus(); inline bool XTargettingAvailable() const { return ((m_ClientVersionBit & EQ::versions::maskUFAndLater) && RuleB(Character, EnableXTargetting)); } inline uint8 GetMaxXTargets() const { return MaxXTargets; } void SetMaxXTargets(uint8 NewMax); bool IsXTarget(const Mob *m) const; bool IsClientXTarget(const Client *c) const; void UpdateClientXTarget(Client *c); void UpdateXTargetType(XTargetType Type, Mob *m, const char *Name = nullptr); void AddAutoXTarget(Mob *m, bool send = true); void RemoveXTarget(Mob *m, bool OnlyAutoSlots); void SendXTargetPacket(uint32 Slot, Mob *m); void SendXTargetUpdates(); void RemoveGroupXTargets(); void RemoveAutoXTargets(); void ShowXTargets(Client *c); inline XTargetAutoHaters *GetXTargetAutoMgr() { return m_activeautohatermgr; } // will be either raid or group or self inline void SetXTargetAutoMgr(XTargetAutoHaters *in) { if (in) m_activeautohatermgr = in; else m_activeautohatermgr = &m_autohatermgr; } inline void SetDirtyAutoHaters() { m_dirtyautohaters = true; } void ProcessXTargetAutoHaters(); // fixes up our auto haters void JoinGroupXTargets(Group *g); void LeaveGroupXTargets(Group *g); void LeaveRaidXTargets(Raid *r); void ClearXTargets(); bool GroupFollow(Client* inviter); inline bool GetRunMode() const { return runmode; } virtual bool CheckWaterAutoFireLoS(Mob* m); void SendReloadCommandMessages(); void SendItemRecastTimer(int32 recast_type, uint32 recast_delay = 0, bool in_ignore_casting_requirement = false); void SetItemRecastTimer(int32 spell_id, uint32 inventory_slot); void DeleteItemRecastTimer(uint32 item_id); bool HasItemRecastTimer(int32 spell_id, uint32 inventory_slot); inline bool AggroMeterAvailable() const { return ((m_ClientVersionBit & EQ::versions::maskRoF2AndLater)) && RuleB(Character, EnableAggroMeter); } // RoF untested inline void SetAggroMeterLock(int in) { m_aggrometer.set_lock_id(in); } void ProcessAggroMeter(); // builds packet and sends void InitializeMercInfo(); bool CheckCanSpawnMerc(uint32 template_id); bool CheckCanHireMerc(Mob* merchant, uint32 template_id); bool CheckCanRetainMerc(uint32 upkeep); bool CheckCanUnsuspendMerc(); bool DismissMerc(uint32 MercID); bool MercOnlyOrNoGroup(); inline uint32 GetMercenaryID() const { return mercid; } inline uint8 GetMercSlot() const { return mercSlot; } void SetMercID( uint32 newmercid) { mercid = newmercid; } void SetMercSlot( uint8 newmercslot) { mercSlot = newmercslot; } Merc* GetMerc(); MercInfo& GetMercInfo(uint8 slot) { return m_mercinfo[slot]; } MercInfo& GetMercInfo() { return m_mercinfo[mercSlot]; } uint8 GetNumberOfMercenaries(); void SetMerc(Merc* newmerc); void SendMercResponsePackets(uint32 ResponseType); void SendMercMerchantResponsePacket(int32 response_type); void SendMercenaryUnknownPacket(uint8 type); void SendMercenaryUnsuspendPacket(uint8 type); void SendMercTimer(Merc* merc = nullptr); void SendMercTimerPacket(int32 entity_id, int32 merc_state, int32 suspended_time, int32 update_interval = 900000, int32 unk01 = 180000); void SendMercSuspendResponsePacket(uint32 suspended_time); void SendMercAssignPacket(uint32 entityID, uint32 unk01, uint32 unk02); void SendMercPersonalInfo(); void SendClearMercInfo(); void SuspendMercCommand(); void SpawnMercOnZone(); void SpawnMerc(Merc* merc, bool setMaxStats); void UpdateMercTimer(); void UpdateMercLevel(); void CheckMercSuspendTimer(); Timer* GetMercTimer() { return &merc_timer; }; Timer* GetPickLockTimer() { return &pick_lock_timer; }; void SendWebLink(const char* website); void SendMarqueeMessage(uint32 type, std::string message, uint32 duration = 3000); void SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message); void SendSpellAnim(uint16 targetid, uint16 spell_id); void DuplicateLoreMessage(uint32 ItemID); void GarbleMessage(char *, uint8); void ItemTimerCheck(); void TryItemTimer(int slot); void SendItemScale(EQ::ItemInstance *inst); int32 GetActSTR() { return( std::min(GetMaxSTR(), GetSTR()) ); } int32 GetActSTA() { return( std::min(GetMaxSTA(), GetSTA()) ); } int32 GetActDEX() { return( std::min(GetMaxDEX(), GetDEX()) ); } int32 GetActAGI() { return( std::min(GetMaxAGI(), GetAGI()) ); } int32 GetActINT() { return( std::min(GetMaxINT(), GetINT()) ); } int32 GetActWIS() { return( std::min(GetMaxWIS(), GetWIS()) ); } int32 GetActCHA() { return( std::min(GetMaxCHA(), GetCHA()) ); } void LoadAccountFlags(); void ClearAccountFlag(const std::string& flag); void SetAccountFlag(const std::string& flag, const std::string& value); std::string GetAccountFlag(const std::string& flag); std::vector GetAccountFlags(); void SetGMStatus(int new_status); void Consume(const EQ::ItemData *item, uint8 type, int16 slot, bool auto_consume); void PlayMP3(const char* fname); void ExpeditionSay(const char *str, int ExpID); inline int32 GetEnvironmentDamageModifier() const { return environment_damage_modifier; } void SetEnvironmentDamageModifier(int32 val) { environment_damage_modifier = val; } inline bool GetInvulnerableEnvironmentDamage() const { return invulnerable_environment_damage; } void SetInvulnerableEnvironmentDamage(bool val) { invulnerable_environment_damage = val; } void SetIntoxication(int32 in_intoxication); void ApplyWeaponsStance(); void TogglePassiveAlternativeAdvancement(const AA::Rank &rank, uint32 ability_id); bool UseTogglePassiveHotkey(const AA::Rank &rank); void TogglePurchaseAlternativeAdvancementRank(int rank_id); void ResetAlternateAdvancementRank(uint32 aa_id); bool IsEffectinAlternateAdvancementRankEffects(const AA::Rank &rank, int effect_id); void TripInterrogateInvState() { interrogateinv_flag = true; } bool GetInterrogateInvState() { return interrogateinv_flag; } bool InterrogateInventory(Client* requester, bool log, bool silent, bool allowtrip, bool& error, bool autolog = true); void SetNextInvSnapshot(uint32 interval_in_min) { m_epp.last_invsnapshot_time = time(nullptr); m_epp.next_invsnapshot_time = m_epp.last_invsnapshot_time + (interval_in_min * 60); } uint32 GetLastInvSnapshotTime() { return m_epp.last_invsnapshot_time; } uint32 GetNextInvSnapshotTime() { return m_epp.next_invsnapshot_time; } void QuestReward(Mob* target, uint32 copper = 0, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0, uint32 itemid = 0, uint32 exp = 0, bool faction = false); void QuestReward(Mob* target, const QuestReward_Struct &reward, bool faction = false); void CashReward(uint32 copper, uint32 silver, uint32 gold, uint32 platinum); void RewardFaction(int id, int amount); void ResetHPUpdateTimer() { hpupdate_timer.Start(); } void SendHPUpdateMarquee(); void CheckRegionTypeChanges(); WaterRegionType GetLastRegion() { return last_region_type; } int32 CalcATK(); uint32 trapid; //ID of trap player has triggered. This is cleared when the player leaves the trap's radius, or it despawns. void SendMerchantEnd(); void CheckItemDiscoverability(uint32 item_id); Raid *p_raid_instance; inline uint32 GetPotionBeltItemIcon(uint8 slot_id) { return EQ::ValueWithin( slot_id, 0, EQ::profile::POTION_BELT_SIZE - 1 ) ? m_pp.potionbelt.Items[slot_id].Icon : 0; }; inline uint32 GetPotionBeltItemID(uint8 slot_id) { return EQ::ValueWithin(slot_id, 0, EQ::profile::POTION_BELT_SIZE - 1) ? m_pp.potionbelt.Items[slot_id].ID : 0; }; inline std::string GetPotionBeltItemName(uint8 slot_id) { return EQ::ValueWithin( slot_id, 0, EQ::profile::POTION_BELT_SIZE - 1 ) ? m_pp.potionbelt.Items[slot_id].Name : 0; }; void ShowDevToolsMenu(); CheatManager cheat_manager; // rate limit Timer m_list_task_timers_rate_limit = {}; std::string GetGuildPublicNote(); PlayerEvent::PlayerEvent GetPlayerEvent(); void RecordKilledNPCEvent(NPC *n); uint32 GetEXPForLevel(uint16 check_level); // Evolving Item Info void ProcessEvolvingItem(const uint64 exp, const Mob* mob); void SendEvolvingPacket(int8 action, const CharacterEvolvingItemsRepository::CharacterEvolvingItems &item); void DoEvolveItemToggle(const EQApplicationPacket* app); void DoEvolveItemDisplayFinalResult(const EQApplicationPacket* app); bool DoEvolveCheckProgression(EQ::ItemInstance &inst); void SendEvolveXPWindowDetails(const EQApplicationPacket* app); void DoEvolveTransferXP(const EQApplicationPacket* app); void SendEvolveXPTransferWindow(); void SendEvolveTransferResults(const EQ::ItemInstance &inst_from, const EQ::ItemInstance &inst_to, const EQ::ItemInstance &inst_from_new, const EQ::ItemInstance &inst_to_new, const uint32 compatibility, const uint32 max_transfer_level); // Account buckets std::string GetAccountBucket(std::string bucket_name); void SetAccountBucket(std::string bucket_name, std::string bucket_value, std::string expiration = ""); void DeleteAccountBucket(std::string bucket_name); std::string GetAccountBucketExpires(std::string bucket_name); std::string GetAccountBucketRemaining(std::string bucket_name); std::string GetBandolierName(uint8 bandolier_slot); uint32 GetBandolierItemIcon(uint8 bandolier_slot, uint8 slot_id); uint32 GetBandolierItemID(uint8 bandolier_slot, uint8 slot_id); std::string GetBandolierItemName(uint8 bandolier_slot, uint8 slot_id); // External handin tracking // this is used to prevent things like quest::givecash and AddMoneyToPP // from double giving money back to players in scripts when return_items // also gives money back to players struct ExternalHandinMoneyReturned { uint64 copper; uint64 silver; uint64 gold; uint64 platinum; std::string return_source; }; private: ExternalHandinMoneyReturned m_external_handin_money_returned = {}; std::vector m_external_handin_items_returned = {}; public: ExternalHandinMoneyReturned GetExternalHandinMoneyReturned() { return m_external_handin_money_returned; } std::vector GetExternalHandinItemsReturned() { return m_external_handin_items_returned; } // used only for testing inline void SetCharacterId(uint32_t id) { character_id = id; } protected: friend class Mob; void CalcEdibleBonuses(StatBonuses* newbon); void MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message = true); bool client_data_loaded; void FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost, bool send_message_and_save); Mob* bind_sight_target; glm::vec4 m_AutoAttackPosition; glm::vec3 m_AutoAttackTargetLocation; Mob *aa_los_them_mob; bool los_status; bool los_status_facing; QGlobalCache *qGlobals; /** Adventure Variables **/ Timer *adventure_request_timer; Timer *adventure_create_timer; Timer *adventure_leave_timer; Timer *adventure_door_timer; Timer *adventure_stats_timer; Timer *adventure_leaderboard_timer; int adv_requested_theme; int adv_requested_id; char *adv_requested_data; int adv_requested_member_count; char *adv_data; private: eqFilterMode ClientFilters[_FilterCount]; int32 HandlePacket(const EQApplicationPacket *app); void OPTGB(const EQApplicationPacket *app); void OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 InstanceID, float x, float y, float z); void OPMemorizeSpell(const EQApplicationPacket *app); void OPMoveCoin(const EQApplicationPacket* app); void MoveItemCharges(EQ::ItemInstance &from, int16 to_slot, uint8 type); void OPGMTraining(const EQApplicationPacket *app); void OPGMEndTraining(const EQApplicationPacket *app); void OPGMTrainSkill(const EQApplicationPacket *app); void OPGMSummon(const EQApplicationPacket *app); void OPCombatAbility(const CombatAbility_Struct *ca_atk); // Bandolier Methods void CreateBandolier(const EQApplicationPacket *app); void RemoveBandolier(const EQApplicationPacket *app); void SetBandolier(const EQApplicationPacket *app); int32 CalcItemATKCap() final; int32 CalcHaste(); int32 CalcAlcoholPhysicalEffect(); int32 CalcSTR(); int32 CalcSTA(); int32 CalcDEX(); int32 CalcAGI(); int32 CalcINT(); int32 CalcWIS(); int32 CalcCHA(); int32 CalcMR(); int32 CalcFR(); int32 CalcDR(); int32 CalcPR(); int32 CalcCR(); int32 CalcCorrup(); int64 CalcMaxHP(); int64 CalcBaseHP(); int64 CalcHPRegen(bool bCombat = false); int64 CalcManaRegen(bool bCombat = false); int64 CalcBaseManaRegen(); void DoHPRegen(); void DoManaRegen(); void DoStaminaHungerUpdate(); void CalcRestState(); // if they have aggro (AggroCount != 0) their timer is saved in m_pp.RestTimer, else we need to get current timer inline uint32 GetRestTimer() const { return AggroCount ? m_pp.RestTimer : rest_timer.GetRemainingTime() / 1000; } void UpdateRestTimer(uint32 new_timer); uint8 playeraction; EQStreamInterface* eqs; uint32 ip; uint16 port; CLIENT_CONN_STATUS client_state; uint32 character_id; uint32 WID; uint32 account_id; char account_name[30]; char loginserver[64]; uint32 lsaccountid; char lskey[30]; int16 admin; uint32 guild_id; uint8 guildrank; // player's rank in the guild, 1- Leader 8 Recruit bool guild_tribute_opt_in; bool guild_dirty{ true }; //used to control add/delete opcodes due to client bug in Ti thru RoF2 bool GuildBanker; uint16 duel_target; bool duelaccepted; std::vector keyring; bool tellsoff; // GM /toggle bool gm_hide_me; bool LFG; bool LFP; uint8 LFGFromLevel; uint8 LFGToLevel; bool LFGMatchFilter; char LFGComments[64]; bool m_is_afk = false; bool m_is_manual_afk = false; bool auto_attack; bool auto_fire; bool runmode; uint8 gmspeed; bool gminvul; bool medding; uint16 horseId; bool revoked; uint16 pClientSideTarget; uint32 weight; bool berserk; bool dead; uint16 controlling_boat_id; uint16 controlled_mob_id; uint16 TrackingID; bool trader; uint16 trader_id; uint16 customer_id; uint32 account_creation; bool first_login; bool ingame; uint32 mercid; // current merc uint8 mercSlot; // selected merc slot time_t m_trader_transaction_date; uint32 m_trader_count{}; uint32 m_buyer_id; uint32 m_barter_time; int32 m_parcel_platinum; int32 m_parcel_gold; int32 m_parcel_silver; int32 m_parcel_copper; int32 m_parcel_count; bool m_parcel_enabled; bool m_parcel_merchant_engaged; std::map m_parcels{}; int Haste; //precalced value uint32 tmSitting; // time stamp started sitting, used for HP regen bonus added on MAY 5, 2004 int32 environment_damage_modifier; bool invulnerable_environment_damage; // dev tools bool display_mob_info_window; bool dev_tools_enabled; uint16 m_door_tool_entity_id; uint16 m_object_tool_entity_id; public: uint16 GetDoorToolEntityId() const; void SetDoorToolEntityId(uint16 door_tool_entity_id); uint16 GetObjectToolEntityId() const; void SetObjectToolEntityId(uint16 object_tool_entity_id); private: int32 max_end; int32 current_endurance; // https://github.com/EQEmu/Server/pull/2479 bool m_lock_save_position = false; public: bool IsLockSavePosition() const; void SetLockSavePosition(bool lock_save_position); private: PlayerProfile_Struct m_pp; ExtendedProfile_Struct m_epp; EQ::InventoryProfile m_inv; Object* m_tradeskill_object; PetInfo m_petinfo; // current pet data, used while loading from and saving to DB PetInfo m_suspendedminion; // pet data for our suspended minion. MercInfo m_mercinfo[MAXMERCS]; // current mercenary InspectMessage_Struct m_inspect_message; bool temp_pvp; void NPCSpawn(const Seperator* sep); void SendLogoutPackets(); void SendZoneInPackets(); bool AddPacket(const EQApplicationPacket *, bool); bool AddPacket(EQApplicationPacket**, bool); bool SendAllPackets(); std::deque> clientpackets; //Zoning related stuff void SendZoneCancel(ZoneChange_Struct *zc); void SendZoneError(ZoneChange_Struct *zc, int8 err); void DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instance_id, float dest_x, float dest_y, float dest_z, float dest_h, int8 ignore_r); void ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z, float heading, uint8 ignorerestrictions, ZoneMode zm); void ProcessMovePC(uint32 zoneID, uint32 instance_id, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited); void SendTopLevelInventory(); glm::vec4 m_ZoneSummonLocation; uint16 zonesummon_id; uint8 zonesummon_ignorerestrictions; ZoneMode zone_mode; WaterRegionType last_region_type; PTimerList p_timers; //persistent timers Timer hpupdate_timer; Timer camp_timer; Timer bot_camp_timer; Timer process_timer; Timer consume_food_timer; Timer zoneinpacket_timer; Timer linkdead_timer; Timer dead_timer; Timer global_channel_timer; Timer fishing_timer; Timer endupkeep_timer; Timer autosave_timer; Timer tribute_timer; Timer proximity_timer; Timer TaskPeriodic_Timer; Timer charm_update_timer; Timer rest_timer; Timer charm_class_attacks_timer; Timer charm_cast_timer; Timer qglobal_purge_timer; Timer TrackingTimer; Timer RespawnFromHoverTimer; Timer merc_timer; Timer anon_toggle_timer; Timer afk_toggle_timer; Timer helm_toggle_timer; Timer aggro_meter_timer; Timer consent_throttle_timer; Timer dynamiczone_removal_timer; Timer task_request_timer; Timer pick_lock_timer; Timer parcel_timer; //Used to limit the number of parcels to one every 30 seconds (default). Changable via rule. Timer lazy_load_bank_check_timer; Timer bandolier_throttle_timer; bool m_lazy_load_bank = false; int m_lazy_load_sent_bank_slots = 0; glm::vec3 m_Proximity; // client aggro Timer m_client_npc_aggro_scan_timer; void CheckClientToNpcAggroTimer(); void ClientToNpcAggroProcess(); void BroadcastPositionUpdate(); // bulk position updates glm::vec4 m_last_position_before_bulk_update; Timer m_client_bulk_npc_pos_update_timer; Timer m_position_update_timer; void CheckSendBulkNpcPositions(bool force = false); // afk bool m_is_idle = false; bool m_afk_reset = false; // used to trigger next-tic afk reset std::chrono::steady_clock::time_point m_last_moved = std::chrono::steady_clock::now(); void BulkSendInventoryItems(); faction_map factionvalues; uint32 tribute_master_id; bool npcflag; uint8 npclevel; bool bZoning; bool tgb; bool instalog; int32 last_reported_mana; int32 last_reported_endurance; int8 last_reported_mana_percent; int8 last_reported_endurance_percent; uint32 AggroCount; // How many mobs are aggro on us. bool ooc_regen; float AreaHPRegen; float AreaManaRegen; float AreaEndRegen; std::set zone_flags; std::set peqzone_flags; ClientTaskState *task_state; int TotalSecondsPlayed; // we use this very sparingly at the zone level // used for keeping clients in donecount sync before world sends absolute confirmations of state int64 m_shared_task_id = 0; public: void SetSharedTaskId(int64 shared_task_id); int64 GetSharedTaskId() const; struct XTarget_Struct XTargets[XTARGET_HARDCAP]; private: bool m_exp_enabled; std::vector m_exp_modifiers; std::vector m_player_title_sets; //Anti Spam Stuff Timer *KarmaUpdateTimer; uint32 TotalKarma; Timer *GlobalChatLimiterTimer; //60 seconds uint32 AttemptedMessages; EQ::versions::ClientVersion m_ClientVersion; uint32 m_ClientVersionBit; int XPRate; bool alternate_currency_loaded; std::map alternate_currency; std::queue> alternate_currency_queued_operations; //Connecting debug code. enum { //connecting states, used for debugging only NoPacketsReceived, //havent gotten anything //this is the point where the client changes to the loading screen ReceivedZoneEntry, //got the first packet, loading up PP PlayerProfileLoaded, //our DB work is done, sending it ZoneInfoSent, //includes PP, tributes, tasks, spawns, time and weather //this is the point where the client shows a status bar zoning in NewZoneRequested, //received and sent new zone request ClientSpawnRequested, //client sent ReqClientSpawn ZoneContentsSent, //objects, doors, zone points ClientReadyReceived, //client told us its ready, send them a bunch of crap like guild MOTD, etc //this is the point where the client releases the mouse ClientConnectFinished //client finally moved to finished state, were done here } conn_state; void ReportConnectingState(); uint8 HideCorpseMode; bool PendingGuildInvitation; int PendingRezzXP; uint32 PendingRezzDBID; uint16 PendingRezzSpellID; // Only used for resurrect while hovering. std::string PendingRezzCorpseName; // Only used for resurrect while hovering. std::set PlayerBlockedBuffs; std::set PetBlockedBuffs; std::list > DraggedCorpses; uint8 MaxXTargets; bool XTargetAutoAddHaters; bool m_dirtyautohaters; XTargetAutoHaters m_autohatermgr; XTargetAutoHaters *m_activeautohatermgr; AggroMeter m_aggrometer; Timer ItemQuestTimer; std::map accountflags; uint8 initial_respawn_selection; bool interrogateinv_flag; // used to minimize log spamming by players void InterrogateInventory_(bool errorcheck, Client* requester, int16 head, int16 index, const EQ::ItemInstance* inst, const EQ::ItemInstance* parent, bool log, bool silent, bool &error, int depth); bool InterrogateInventory_error(int16 head, int16 index, const EQ::ItemInstance* inst, const EQ::ItemInstance* parent, int depth); uint8 client_max_level; ExpeditionInvite m_dz_invite = {}; std::vector m_dz_lockouts; glm::vec3 m_quest_compass; bool m_has_quest_compass = false; std::vector m_dynamic_zone_ids; std::vector m_completed_shared_tasks; public: enum BotOwnerOption : size_t { booDeathMarquee, booStatsUpdate, booSpawnMessageSay, booSpawnMessageTell, booSpawnMessageClassSpecific, booUnused, booAutoDefend, booBuffCounter, booMonkWuMessage, _booCount }; bool GetBotOption(BotOwnerOption boo) const; void SetBotOption(BotOwnerOption boo, bool flag = true); bool GetBotPulling() { return m_bot_pulling; } void SetBotPulling(bool flag = true) { m_bot_pulling = flag; } uint32 GetAssistee() { return bot_assistee; } void SetAssistee(uint32 id = 0) { bot_assistee = id; } bool GetBotPrecombat() { return m_bot_precombat; } void SetBotPrecombat(bool flag = true) { m_bot_precombat = flag; } int GetBotRequiredLevel(uint8 class_id = Class::None); uint32 GetBotCreationLimit(uint8 class_id = Class::None); int GetBotSpawnLimit(uint8 class_id = Class::None); void SetBotCreationLimit(uint32 new_creation_limit, uint8 class_id = Class::None); void SetBotRequiredLevel(int new_required_level, uint8 class_id = Class::None); void SetBotSpawnLimit(int new_spawn_limit, uint8 class_id = Class::None); void CampAllBots(uint8 class_id = Class::None); void SpawnRaidBotsOnConnect(Raid* raid); void LoadDefaultBotSettings(); int GetDefaultBotSettings(uint8 setting_type, uint16 bot_setting); int GetBotSetting(uint8 setting_type, uint16 bot_setting); void SetBotSetting(uint8 setting_type, uint16 bot_setting, uint32 setting_value); uint16 GetDefaultSpellTypeDelay(uint16 spell_type); uint8 GetDefaultSpellTypeMinThreshold(uint16 spell_type); uint8 GetDefaultSpellTypeMaxThreshold(uint16 spell_type); inline uint16 GetSpellTypeDelay(uint16 spell_type) const { return m_bot_spell_settings[spell_type].delay; } inline void SetSpellTypeDelay(uint16 spell_type, uint16 delay_value) { m_bot_spell_settings[spell_type].delay = delay_value; } inline uint8 GetSpellTypeMinThreshold(uint16 spell_type) const { return m_bot_spell_settings[spell_type].min_threshold; } inline void SetSpellTypeMinThreshold(uint16 spell_type, uint8 threshold_value) { m_bot_spell_settings[spell_type].min_threshold = threshold_value; } inline uint8 GetSpellTypeMaxThreshold(uint16 spell_type) const { return m_bot_spell_settings[spell_type].max_threshold; } inline void SetSpellTypeMaxThreshold(uint16 spell_type, uint8 threshold_value) { m_bot_spell_settings[spell_type].max_threshold = threshold_value; } inline bool SpellTypeRecastCheck(uint16 spellType) { return !m_bot_spell_settings[spellType].recast_timer.GetRemainingTime(); } void SetSpellTypeRecastTimer(uint16 spell_type, uint32 recast_time) { m_bot_spell_settings[spell_type].recast_timer.Start(recast_time); } void SetIllusionBlock(bool value) { _illusion_block = value; } bool GetIllusionBlock() const override { return _illusion_block; } private: bool bot_owner_options[_booCount]; bool m_bot_pulling; bool m_bot_precombat; uint32 bot_assistee; std::vector m_bot_spell_settings; bool _illusion_block; bool CanTradeFVNoDropItem(); void SendMobPositions(); void PlayerTradeEventLog(Trade *t, Trade *t2); // full and partial mail key cache std::string m_mail_key_full; std::string m_mail_key; public: const std::string &GetMailKeyFull() const; const std::string &GetMailKey() const; void ShowZoneShardMenu(); void Handle_OP_ChangePetName(const EQApplicationPacket *app); bool IsFilteredAFKPacket(const EQApplicationPacket *p); void CheckAutoIdleAFK(PlayerPositionUpdateClient_Struct *p); void SyncWorldPositionsToClient(bool ignore_idle = false); };