eqemu-server/zone/client.h
Knightly 7ab909ee47 Standardize Licensing
- License was intended to be GPLv3 per earlier commit of GPLv3 LICENSE FILE
- This is confirmed by the inclusion of libraries that are incompatible with GPLv2
- This is also confirmed by KLS and the agreement of KLS's predecessors
- Added GPLv3 license headers to the compilable source files
- Removed Folly licensing in strings.h since the string functions do not match the Folly functions and are standard functions - this must have been left over from previous implementations
- Removed individual contributor license headers since the project has been under the "developer" mantle for many years
- Removed comments on files that were previously automatically generated since they've been manually modified multiple times and there are no automatic scripts referencing them (removed in 2023)
2026-04-01 17:09:57 -07:00

2425 lines
101 KiB
C++

/* 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 <http://www.gnu.org/licenses/>.
*/
#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 <cfloat>
#include <set>
#include <algorithm>
#include <memory>
#include <deque>
#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.
typedef enum {
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
} ZoneMode;
// translate above enum to a string
std::string GetZoneModeString(ZoneMode mode);
enum {
HideCorpseNone = 0,
HideCorpseAll = 1,
HideCorpseAllButGroup = 2,
HideCorpseLooted = 3,
HideCorpseNPC = 5
};
typedef enum
{
Disciplines,
Spells
} ShowSpellType;
typedef enum
{
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
} XTargetType;
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<std::string> description = {};
std::vector<std::string> notes = {};
std::vector<std::string> example_format = {};
std::vector<std::string> examples_one = {};
std::vector<std::string> examples_two = {};
std::vector<std::string> examples_three = {};
std::vector<std::string> actionables = {};
std::vector<std::string> options = {};
std::vector<std::string> options_one = {};
std::vector<std::string> options_two = {};
std::vector<std::string> 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<EXPModifier> GetEXPModifiers();
void SetEXPModifiers(std::vector<EXPModifier> 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<Mob*> 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<uint32> 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<void *> *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<uint32, CharacterParcelsRepository::CharacterParcels> 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<uint32, BuylineItemDetails_Struct>& item_map, BuyerBuyLines_Struct& bl);
bool BuildBuyLineMapFromVector(std::map<uint32, BuylineItemDetails_Struct>& item_map, std::vector<BuyerLineItems_Struct>& bl);
void RemoveItemFromBuyLineMap(std::map<uint32, BuylineItemDetails_Struct>& item_map, const BuyerLineItems_Struct& bl);
bool ValidateBuyLineItems(std::map<uint32, BuylineItemDetails_Struct>& item_map);
int64 ValidateBuyLineCost(std::map<uint32, BuylineItemDetails_Struct>& 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<int16>& 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<int> GetLearnableDisciplines(uint8 min_level = 1, uint8 max_level = 0);
std::vector<int> GetLearnedDisciplines();
std::vector<int> GetMemmedSpells();
std::vector<int> GetScribeableSpells(uint8 min_level = 1, uint8 max_level = 0);
std::vector<int> 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<uint32, TributeData> GetTributeList();
uint32 LookupTributeItemID(uint32 tribute_id, uint32 tier);
void SendPathPacket(const std::vector<FindPerson_Point> &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<Mob*> 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<BuyerLineTradeItems_Struct> 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<LootItem>& 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<uint32> 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<uint32> 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<PlayerTitlesetsRepository::PlayerTitlesets>& 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<uint32, std::vector<uint16>> 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<std::string> 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<uint32_t> 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<EQ::ItemInstance*>& 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<int>& 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<int> 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<Client*> 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<std::string>& 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<DzLockout>& GetDzLockouts() const { return m_dz_lockouts; };
std::vector<DzLockout> 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<DynamicZone*> GetDynamicZones(uint32_t zone_id = 0, int zone_version = -1);
std::unique_ptr<EQApplicationPacket> CreateDzSwitchListPacket(const std::vector<DynamicZone*>& dzs);
std::unique_ptr<EQApplicationPacket> CreateCompassPacket(const std::vector<DynamicZoneCompassEntry_Struct>& 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<RespawnOption> 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<std::string> 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<uint32_t> m_external_handin_items_returned = {};
public:
ExternalHandinMoneyReturned GetExternalHandinMoneyReturned() { return m_external_handin_money_returned; }
std::vector<uint32_t> 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<uint32> 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<uint32, CharacterParcelsRepository::CharacterParcels> 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<std::unique_ptr<CLIENTPACKET>> 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<uint32> zone_flags;
std::set<uint32> 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<EXPModifier> m_exp_modifiers;
std::vector<PlayerTitlesetsRepository::PlayerTitlesets> 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<uint32, uint32> alternate_currency;
std::queue<std::pair<uint32, int32>> 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<uint32> PlayerBlockedBuffs;
std::set<uint32> PetBlockedBuffs;
std::list<std::pair<std::string, uint16> > DraggedCorpses;
uint8 MaxXTargets;
bool XTargetAutoAddHaters;
bool m_dirtyautohaters;
XTargetAutoHaters m_autohatermgr;
XTargetAutoHaters *m_activeautohatermgr;
AggroMeter m_aggrometer;
Timer ItemQuestTimer;
std::map<std::string,std::string> 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<DzLockout> m_dz_lockouts;
glm::vec3 m_quest_compass;
bool m_has_quest_compass = false;
std::vector<uint32_t> m_dynamic_zone_ids;
std::vector<uint32_t> 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<BotSpellSettings> 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);
};