mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
1273 lines
58 KiB
C++
1273 lines
58 KiB
C++
/* EQEMu: Everquest Server Emulator
|
|
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org)
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
|
are required to give you total support for your newly bought product;
|
|
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#ifndef BOT_H
|
|
#define BOT_H
|
|
|
|
#include "bot_structs.h"
|
|
#include "mob.h"
|
|
#include "client.h"
|
|
#include "pets.h"
|
|
#include "heal_rotation.h"
|
|
#include "groups.h"
|
|
#include "corpse.h"
|
|
#include "zonedb.h"
|
|
#include "../common/zone_store.h"
|
|
#include "string_ids.h"
|
|
#include "../common/misc_functions.h"
|
|
#include "../common/global_define.h"
|
|
#include "guild_mgr.h"
|
|
#include "worldserver.h"
|
|
#include "raids.h"
|
|
|
|
#include <sstream>
|
|
|
|
constexpr uint32 BOT_KEEP_ALIVE_INTERVAL = 5000; // 5 seconds
|
|
|
|
constexpr uint32 BOT_COMBAT_JITTER_INTERVAL_MIN = 1500; // 1.5 seconds
|
|
constexpr uint32 BOT_COMBAT_JITTER_INTERVAL_MAX = 3000; // 3 seconds
|
|
|
|
constexpr uint32 MAG_EPIC_1_0 = 28034;
|
|
|
|
extern WorldServer worldserver;
|
|
|
|
constexpr int NegativeItemReuse = -1; // Unlinked timer for items
|
|
|
|
constexpr uint8 SumWater = 1;
|
|
constexpr uint8 SumFire = 2;
|
|
constexpr uint8 SumAir = 3;
|
|
constexpr uint8 SumEarth = 4;
|
|
constexpr uint8 MonsterSum = 5;
|
|
constexpr uint8 SumMageMultiElement = 6;
|
|
|
|
// nHSND negative Healer/Slower/Nuker/Doter
|
|
// pH positive Healer
|
|
// pS positive Slower
|
|
// pHS positive Healer/Slower
|
|
// pN positive Nuker
|
|
// pHN positive Healer/Nuker
|
|
// pSN positive Slower/Nuker
|
|
// pHSN positive Healer/Slower/Nuker
|
|
// pD positive Doter
|
|
// pHD positive Healer/Doter
|
|
// pSD positive Slower/Doter
|
|
// pHSD positive Healer/Slower/Doter
|
|
// pND positive Nuker/Doter
|
|
// pHND positive Healer/Nuker/Doter
|
|
// pSND positive Slower/Nuker/Doter
|
|
// pHSND positive Healer/Slower/Nuker/Doter
|
|
// cntHSND count Healer/Slower/Nuker/Doter
|
|
enum BotCastingChanceConditional : uint8
|
|
{
|
|
nHSND = 0,
|
|
pH,
|
|
pS,
|
|
pHS,
|
|
pN,
|
|
pHN,
|
|
pSN,
|
|
pHSN,
|
|
pD,
|
|
pHD,
|
|
pSD,
|
|
pHSD,
|
|
pND,
|
|
pHND,
|
|
pSND,
|
|
pHSND,
|
|
cntHSND = 16
|
|
};
|
|
|
|
namespace BotSettingCategories { // Update GetBotSpellCategoryName as needed
|
|
constexpr uint8 BaseSetting = 0;
|
|
constexpr uint8 SpellHold = 1;
|
|
constexpr uint8 SpellDelay = 2;
|
|
constexpr uint8 SpellMinThreshold = 3;
|
|
constexpr uint8 SpellMaxThreshold = 4;
|
|
constexpr uint8 SpellTypeResistLimit = 5;
|
|
constexpr uint8 SpellTypeAggroCheck = 6;
|
|
constexpr uint8 SpellTypeMinManaPct = 7;
|
|
constexpr uint8 SpellTypeMaxManaPct = 8;
|
|
constexpr uint8 SpellTypeMinHPPct = 9;
|
|
constexpr uint8 SpellTypeMaxHPPct = 10;
|
|
constexpr uint8 SpellTypeIdlePriority = 11;
|
|
constexpr uint8 SpellTypeEngagedPriority = 12;
|
|
constexpr uint8 SpellTypePursuePriority = 13;
|
|
constexpr uint8 SpellTypeAEOrGroupTargetCount = 14;
|
|
constexpr uint8 SpellTypeAnnounceCast = 15;
|
|
|
|
constexpr uint16 START = BotSettingCategories::BaseSetting;
|
|
constexpr uint16 START_NO_BASE = BotSettingCategories::SpellHold;
|
|
constexpr uint16 START_CLIENT = BotSettingCategories::SpellDelay;
|
|
constexpr uint16 END_CLIENT = BotSettingCategories::SpellMaxThreshold;
|
|
constexpr uint16 END = BotSettingCategories::SpellTypeAnnounceCast;
|
|
};
|
|
|
|
static std::map<uint8, std::string> botSpellCategory_names = {
|
|
{ BotSettingCategories::BaseSetting, "BaseSetting" },
|
|
{ BotSettingCategories::SpellHold, "SpellHolds" },
|
|
{ BotSettingCategories::SpellDelay, "SpellDelays" },
|
|
{ BotSettingCategories::SpellMinThreshold, "SpellMinThresholds" },
|
|
{ BotSettingCategories::SpellMaxThreshold, "SpellMaxThresholds" },
|
|
{ BotSettingCategories::SpellTypeResistLimit, "SpellResistLimit" },
|
|
{ BotSettingCategories::SpellTypeAggroCheck, "SpellAggroChecks" },
|
|
{ BotSettingCategories::SpellTypeMinManaPct, "SpellMinManaPct" },
|
|
{ BotSettingCategories::SpellTypeMaxManaPct, "SpellMaxManaPct" },
|
|
{ BotSettingCategories::SpellTypeMinHPPct, "SpellMinHPPct" },
|
|
{ BotSettingCategories::SpellTypeMaxHPPct, "SpellMaxHPPct" },
|
|
{ BotSettingCategories::SpellTypeIdlePriority, "SpellIdlePriority" },
|
|
{ BotSettingCategories::SpellTypeEngagedPriority, "SpellEngagedPriority" },
|
|
{ BotSettingCategories::SpellTypePursuePriority, "SpellPursuePriority" },
|
|
{ BotSettingCategories::SpellTypeAEOrGroupTargetCount, "SpellTargetCounts" },
|
|
{ BotSettingCategories::SpellTypeAnnounceCast, "SpellAnnounceCasts" }
|
|
};
|
|
|
|
namespace BotPriorityCategories { // Update GetBotSpellCategoryName as needed
|
|
constexpr uint8 Idle = 0;
|
|
constexpr uint8 Engaged = 1;
|
|
constexpr uint8 Pursue = 2;
|
|
|
|
constexpr uint16 START = BotPriorityCategories::Idle;
|
|
constexpr uint16 END = BotPriorityCategories::Pursue; // Increment as needed
|
|
};
|
|
|
|
namespace BotBaseSettings {
|
|
constexpr uint16 ExpansionBitmask = 0;
|
|
constexpr uint16 ShowHelm = 1;
|
|
constexpr uint16 FollowDistance = 2;
|
|
constexpr uint16 StopMeleeLevel = 3;
|
|
constexpr uint16 EnforceSpellSettings = 4;
|
|
constexpr uint16 RangedSetting = 5;
|
|
constexpr uint16 PetSetTypeSetting = 6;
|
|
constexpr uint16 BehindMob = 7;
|
|
constexpr uint16 DistanceRanged = 8;
|
|
constexpr uint16 IllusionBlock = 9;
|
|
constexpr uint16 MaxMeleeRange = 10;
|
|
constexpr uint16 MedInCombat = 11;
|
|
constexpr uint16 SitHPPct = 12;
|
|
constexpr uint16 SitManaPct = 13;
|
|
|
|
constexpr uint16 START_ALL = ExpansionBitmask;
|
|
constexpr uint16 START = BotBaseSettings::ShowHelm; // Everything above this cannot be copied, changed or viewed by players
|
|
constexpr uint16 END = BotBaseSettings::SitManaPct; // Increment as needed
|
|
};
|
|
|
|
static std::map<uint16, std::string> botBaseSettings_names = {
|
|
{ BotBaseSettings::ExpansionBitmask, "ExpansionBitmask" },
|
|
{ BotBaseSettings::ShowHelm, "ShowHelm" },
|
|
{ BotBaseSettings::FollowDistance, "FollowDistance" },
|
|
{ BotBaseSettings::StopMeleeLevel, "StopMeleeLevel" },
|
|
{ BotBaseSettings::EnforceSpellSettings, "EnforceSpellSettings" },
|
|
{ BotBaseSettings::RangedSetting, "RangedSetting" },
|
|
{ BotBaseSettings::PetSetTypeSetting, "PetSetTypeSetting" },
|
|
{ BotBaseSettings::BehindMob, "BehindMob" },
|
|
{ BotBaseSettings::DistanceRanged, "DistanceRanged" },
|
|
{ BotBaseSettings::IllusionBlock, "IllusionBlock" },
|
|
{ BotBaseSettings::MaxMeleeRange, "MaxMeleeRange" },
|
|
{ BotBaseSettings::MedInCombat, "MedInCombat" },
|
|
{ BotBaseSettings::SitHPPct, "SitHPPct" },
|
|
{ BotBaseSettings::SitManaPct, "SitManaPct" }
|
|
};
|
|
|
|
namespace CommandedSubTypes {
|
|
constexpr uint16 SingleTarget = 1;
|
|
constexpr uint16 GroupTarget = 2;
|
|
constexpr uint16 AETarget = 3;
|
|
constexpr uint16 SeeInvis = 4;
|
|
constexpr uint16 Invis = 5;
|
|
constexpr uint16 InvisUndead = 6;
|
|
constexpr uint16 InvisAnimals = 7;
|
|
constexpr uint16 Shrink = 8;
|
|
constexpr uint16 Grow = 9;
|
|
constexpr uint16 Selo = 10;
|
|
|
|
constexpr uint16 START = CommandedSubTypes::SingleTarget;
|
|
constexpr uint16 END = CommandedSubTypes::Selo;
|
|
};
|
|
|
|
static std::map<uint16, std::string> botSubType_names = {
|
|
{ CommandedSubTypes::SingleTarget, "SingleTarget" },
|
|
{ CommandedSubTypes::GroupTarget, "GroupTarget" },
|
|
{ CommandedSubTypes::AETarget, "AETarget" },
|
|
{ CommandedSubTypes::SeeInvis, "SeeInvis" },
|
|
{ CommandedSubTypes::Invis, "Invis" },
|
|
{ CommandedSubTypes::InvisUndead, "InvisUndead" },
|
|
{ CommandedSubTypes::InvisAnimals, "InvisAnimals" },
|
|
{ CommandedSubTypes::Shrink, "Shrink" },
|
|
{ CommandedSubTypes::Grow, "Grow" },
|
|
{ CommandedSubTypes::Selo, "Selo" }
|
|
};
|
|
|
|
struct CombatRangeInput {
|
|
Mob* target;
|
|
float target_distance;
|
|
bool behind_mob;
|
|
uint8 stop_melee_level;
|
|
const EQ::ItemInstance* p_item;
|
|
const EQ::ItemInstance* s_item;
|
|
};
|
|
|
|
struct CombatRangeOutput {
|
|
bool at_combat_range = false;
|
|
float melee_distance_min = 0.0f;
|
|
float melee_distance = 0.0f;
|
|
float melee_distance_max = 0.0f;
|
|
};
|
|
|
|
class Bot : public NPC {
|
|
friend class Mob;
|
|
public:
|
|
// Class enums
|
|
enum BotTradeType { // types of trades a bot can do
|
|
BotTradeClientNormal,
|
|
BotTradeClientNoDropNoTrade
|
|
};
|
|
|
|
enum SpellTypeIndex : uint32 {
|
|
spellTypeIndexNuke,
|
|
spellTypeIndexHeal,
|
|
spellTypeIndexRoot,
|
|
spellTypeIndexBuff,
|
|
spellTypeIndexEscape,
|
|
spellTypeIndexPet,
|
|
spellTypeIndexLifetap,
|
|
spellTypeIndexSnare,
|
|
spellTypeIndexDot,
|
|
spellTypeIndexDispel,
|
|
spellTypeIndexInCombatBuff,
|
|
spellTypeIndexMez,
|
|
spellTypeIndexCharm,
|
|
spellTypeIndexSlow,
|
|
spellTypeIndexDebuff,
|
|
spellTypeIndexCure,
|
|
spellTypeIndexResurrect,
|
|
spellTypeIndexHateRedux,
|
|
spellTypeIndexInCombatBuffSong,
|
|
spellTypeIndexOutOfCombatBuffSong,
|
|
spellTypeIndexPreCombatBuff,
|
|
spellTypeIndexPreCombatBuffSong
|
|
};
|
|
|
|
static const uint32 SPELL_TYPE_FIRST = spellTypeIndexNuke;
|
|
static const uint32 SPELL_TYPE_LAST = spellTypeIndexPreCombatBuffSong;
|
|
static const uint32 SPELL_TYPE_COUNT = SPELL_TYPE_LAST + 1;
|
|
|
|
// Class Constructors
|
|
Bot(NPCType *npcTypeData, Client* botOwner);
|
|
Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData);
|
|
|
|
//abstract virtual override function implementations requird by base abstract class
|
|
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) override;
|
|
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) override;
|
|
|
|
bool HasRaid() final { return GetRaid() != nullptr; }
|
|
bool HasGroup() final { return GetGroup() != nullptr; }
|
|
Raid* GetRaid() final { return entity_list.GetRaidByBot(this); }
|
|
Group* GetGroup() final { return entity_list.GetGroupByMob(this); }
|
|
Group* GetGroupByLeaderName() { return entity_list.GetGroupByLeaderName(GetName()); }
|
|
|
|
// Common, but informal "interfaces" with Client object
|
|
uint32 CharacterID() const { return GetBotID(); }
|
|
inline bool IsInAGuild() const { return (_guildId != GUILD_NONE && _guildId != 0); }
|
|
inline bool IsInGuild(uint32 in_gid) const { return (in_gid == _guildId && IsInAGuild()); }
|
|
inline uint32 GuildID() const { return _guildId; }
|
|
inline uint8 GuildRank() const { return _guildRank; }
|
|
|
|
// Class Methods
|
|
bool IsValidRaceClassCombo();
|
|
static bool IsValidRaceClassCombo(uint16 r, uint8 c);
|
|
bool IsValidName();
|
|
static bool IsValidName(std::string& name);
|
|
bool Spawn(Client* botCharacterOwner);
|
|
void SetLevel(uint8 in_level, bool command = false) override;
|
|
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) override;
|
|
bool Process() override;
|
|
void FinishTrade(Client* client, BotTradeType trade_type, int16 chosen_slot = INVALID_INDEX);
|
|
bool Save() override;
|
|
void Depop();
|
|
void CalcBotStats(bool showtext = true);
|
|
uint16 BotGetSpells(int spellslot) { return AIBot_spells[spellslot].spellid; }
|
|
uint32 BotGetSpellType(int spellslot) { return AIBot_spells[spellslot].type; }
|
|
uint16 BotGetSpellPriority(int spellslot) { return AIBot_spells[spellslot].priority; }
|
|
const std::vector<BotSpells_wIndex>& BotGetSpellsByType(uint16 spell_type) const;
|
|
float GetProcChances(float ProcBonus, uint16 hand) override;
|
|
int GetHandToHandDamage(void) override;
|
|
bool TryFinishingBlow(Mob *defender, int64 &damage) override;
|
|
void DoRiposte(Mob* defender) override;
|
|
inline int32 GetATK() { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(EQ::skills::SkillOffense)) * 9 / 10); }
|
|
inline int32 GetATKBonus() const override { return itembonuses.ATK + spellbonuses.ATK; }
|
|
uint32 GetTotalATK();
|
|
uint32 GetATKRating();
|
|
uint16 GetPrimarySkillValue();
|
|
uint16 MaxSkill(EQ::skills::SkillType skillid, uint16 class_, uint16 level) const;
|
|
inline uint16 MaxSkill(EQ::skills::SkillType skillid) { return MaxSkill(skillid, GetClass(), GetLevel()); }
|
|
int GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target = nullptr) override;
|
|
void DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance = false);
|
|
void DoClassAttacks(Mob *target, bool IsRiposte=false);
|
|
void CalcBonuses() override;
|
|
|
|
void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr) override;
|
|
FACTION_VALUE GetReverseFactionCon(Mob* iOther) override;
|
|
inline bool IsPet() override { return false; }
|
|
bool IsNPC() const override { return false; }
|
|
Mob* GetOwner() override;
|
|
Mob* GetOwnerOrSelf() override;
|
|
inline bool HasOwner() override { return GetBotOwner() != nullptr; }
|
|
int64 CalcMaxMana() override;
|
|
void SetAttackTimer() override;
|
|
uint64 GetClassHPFactor();
|
|
int64 CalcMaxHP() override;
|
|
bool DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool &stopLogic);
|
|
bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool &stopLogic);
|
|
void Camp(bool save_to_database = true);
|
|
void SetTarget(Mob* mob) override;
|
|
void Zone();
|
|
bool IsAtRange(Mob* target);
|
|
void ChangeBotRangedWeapons(bool is_ranged);
|
|
void Sit();
|
|
void Stand();
|
|
bool IsSitting() const override;
|
|
bool IsStanding();
|
|
int GetWalkspeed() { return (int)((float)_GetWalkSpeed() * 1.785714285f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143
|
|
int GetRunspeed() { return (int)((float)_GetRunSpeed() * 1.785714285f); }
|
|
void WalkTo(float x, float y, float z) override;
|
|
void RunTo(float x, float y, float z) override;
|
|
|
|
bool GetGuardFlag() const { return m_guard_flag; }
|
|
void SetGuardFlag(bool flag = true) { m_guard_flag = flag; }
|
|
bool GetHoldFlag() const { return m_hold_flag; }
|
|
void SetHoldFlag(bool flag = true) { m_hold_flag = flag; }
|
|
bool GetAttackFlag() const { return m_attack_flag; }
|
|
void SetAttackFlag(bool flag = true) { m_attack_flag = flag; }
|
|
bool GetCombatRoundForAlerts() const { return m_combat_round_alert_flag; }
|
|
bool GetAttackingFlag() const { return m_attacking_flag; }
|
|
bool GetPullFlag() const { return m_pull_flag; }
|
|
void SetPullFlag(bool flag = true) { m_pull_flag = flag; }
|
|
bool GetPullingFlag() const { return m_pulling_flag; }
|
|
bool GetReturningFlag() const { return m_returning_flag; }
|
|
bool GetIsUsingItemClick() { return is_using_item_click; }
|
|
void SetIsUsingItemClick(bool flag = true) { is_using_item_click = flag; }
|
|
bool UseDiscipline(uint32 spell_id, uint32 target);
|
|
uint8 GetNumberNeedingHealedInGroup(Mob* tar, uint16 spell_type, uint16 spell_id, float range);
|
|
bool GetNeedsCured(Mob *tar);
|
|
bool GetNeedsHateRedux(Mob *tar);
|
|
bool HasOrMayGetAggro(bool SitAggro, uint32 spell_id = 0);
|
|
void SetDefaultBotStance();
|
|
void SetSurname(std::string_view bot_surname);
|
|
void SetTitle(std::string_view bot_title);
|
|
void SetSuffix(std::string_view bot_suffix);
|
|
std::string GetSurname() const { return _surname; }
|
|
std::string GetTitle() const { return _title; }
|
|
std::string GetSuffix() const { return _suffix; }
|
|
inline virtual int32 GetMaxStat();
|
|
inline virtual int32 GetMaxResist();
|
|
inline virtual int32 GetMaxSTR();
|
|
inline virtual int32 GetMaxSTA();
|
|
inline virtual int32 GetMaxDEX();
|
|
inline virtual int32 GetMaxAGI();
|
|
inline virtual int32 GetMaxINT();
|
|
inline virtual int32 GetMaxWIS();
|
|
inline virtual int32 GetMaxCHA();
|
|
inline virtual int32 GetMaxMR();
|
|
inline virtual int32 GetMaxPR();
|
|
inline virtual int32 GetMaxDR();
|
|
inline virtual int32 GetMaxCR();
|
|
inline virtual int32 GetMaxFR();
|
|
inline virtual int32 GetMaxCorrup();
|
|
int32 CalcATK();
|
|
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 CalcHPRegenCap() final;
|
|
int64 CalcManaRegenCap() final;
|
|
int32 LevelRegen();
|
|
int64 CalcHPRegen();
|
|
int64 CalcManaRegen();
|
|
uint32 CalcCurrentWeight();
|
|
int GroupLeadershipAAHealthEnhancement();
|
|
int GroupLeadershipAAManaEnhancement();
|
|
int GroupLeadershipAAHealthRegeneration();
|
|
int GroupLeadershipAAOffenseEnhancement();
|
|
void CalcRestState();
|
|
|
|
int64 CalcMaxEndurance();
|
|
int64 CalcBaseEndurance();
|
|
int64 CalcEnduranceRegen();
|
|
int64 GetEndurance() const override {return cur_end;}
|
|
int64 GetMaxEndurance() const override {return max_end;}
|
|
int64 CalcEnduranceRegenCap();
|
|
inline uint8 GetEndurancePercent() override { return (uint8)((float)cur_end / (float)max_end * 100.0f); }
|
|
void SetEndurance(int32 newEnd) override;
|
|
void DoEnduranceUpkeep();
|
|
|
|
void TryItemClick(uint16 slot_id);
|
|
EQ::ItemInstance* GetClickItem(uint16 slot_id);
|
|
void DoItemClick(const EQ::ItemData* inst, uint16 slot_id);
|
|
|
|
bool AI_AddBotSpells(uint32 bot_spell_id);
|
|
void AddSpellToBotList(
|
|
int16 iPriority,
|
|
uint16 iSpellID,
|
|
uint32 iType,
|
|
int16 iManaCost,
|
|
int32 iRecastDelay,
|
|
int16 iResistAdjust,
|
|
uint8 min_level,
|
|
uint8 max_level,
|
|
int8 min_hp,
|
|
int8 max_hp,
|
|
std::string bucket_name,
|
|
std::string bucket_value,
|
|
uint8 bucket_comparison
|
|
);
|
|
|
|
void AddSpellToBotEnforceList(
|
|
int16 iPriority,
|
|
uint16 iSpellID,
|
|
uint32 iType,
|
|
int16 iManaCost,
|
|
int32 iRecastDelay,
|
|
int16 iResistAdjust,
|
|
uint8 min_level,
|
|
uint8 max_level,
|
|
int8 min_hp,
|
|
int8 max_hp,
|
|
std::string bucket_name,
|
|
std::string bucket_value,
|
|
uint8 bucket_comparison
|
|
);
|
|
|
|
void AI_Bot_Event_SpellCastFinished(bool iCastSucceeded, uint16 slot);
|
|
|
|
// AI Methods
|
|
bool AICastSpell(Mob* tar, uint8 chance, uint16 spell_type, uint16 sub_target_type = UINT16_MAX, uint16 sub_type = UINT16_MAX);
|
|
bool AttemptAICastSpell(uint16 spell_type, Mob* tar = nullptr);
|
|
bool AttemptAACastSpell(Mob* tar, uint16 spell_id, AA::Rank* rank);
|
|
bool AttemptForcedCastSpell(Mob* tar, uint16 spell_id, bool is_disc = false);
|
|
bool AttemptCloseBeneficialSpells(uint16 spell_type);
|
|
bool AI_EngagedCastCheck() override;
|
|
bool AI_PursueCastCheck() override;
|
|
bool AI_IdleCastCheck() override;
|
|
bool AIHealRotation(Mob* tar, bool useFastHeals);
|
|
bool GetPauseAI() const { return _pauseAI; }
|
|
void SetPauseAI(bool pause_flag) { _pauseAI = pause_flag; }
|
|
bool IsCommandedSpell() const { return _commandedSpell; }
|
|
void SetCommandedSpell(bool value) { _commandedSpell = value; }
|
|
bool IsPullingSpell() const { return _pullingSpell; }
|
|
void SetPullingSpell(bool value) { _pullingSpell = value; }
|
|
|
|
void SetGuardMode();
|
|
void SetHoldMode();
|
|
|
|
bool IsValidSpellRange(uint16 spell_id, Mob* tar);
|
|
|
|
// Bot AI Methods
|
|
void AI_Bot_Init();
|
|
void AI_Bot_Start(uint32 iMoveDelay = 0);
|
|
|
|
// Mob AI Virtual Override Methods
|
|
void AI_Process() final;
|
|
void AI_Stop() final;
|
|
|
|
// Mob Spell Virtual Override Methods
|
|
void SpellProcess() override;
|
|
int32 GetActSpellDuration(uint16 spell_id, int32 duration) override;
|
|
float GetAOERange(uint16 spell_id) override;
|
|
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100);
|
|
void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr) override;
|
|
virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0,
|
|
uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr, uint32 aa_id = 0);
|
|
bool SpellOnTarget(
|
|
uint16 spell_id,
|
|
Mob* spelltar,
|
|
int reflect_effectiveness = 0,
|
|
bool use_resist_adjust = false,
|
|
int16 resist_adjust = 0,
|
|
bool isproc = false,
|
|
int level_override = -1,
|
|
int duration_override = 0,
|
|
bool disable_buff_overwrite = false
|
|
) final;
|
|
bool IsImmuneToSpell(uint16 spell_id, Mob *caster) override;
|
|
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQ::spells::CastingSlot slot);
|
|
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1,
|
|
uint32* oSpellWillFinish = nullptr, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0);
|
|
inline int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false) override
|
|
{ return Mob::GetFocusEffect(type, spell_id, caster, from_buff_tic); }
|
|
inline bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
|
|
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) override
|
|
{ return Mob::Attack(other, Hand, FromRiposte, IsStrikethrough, IsFromSpell, opts); }
|
|
void DoAttackRounds(Mob* target, int hand);
|
|
|
|
bool BotPassiveCheck();
|
|
bool ValidStateCheck(Mob* other, bool same_raid_group = false);
|
|
Raid* GetStoredRaid() { return _storedRaid; }
|
|
void SetStoredRaid(Raid* stored_raid) { _storedRaid = stored_raid; }
|
|
bool GetVerifiedRaid() { return _verifiedRaid; }
|
|
void SetVerifiedRaid(bool status) { _verifiedRaid = status; }
|
|
uint16 GetTempSpellType() { return _tempSpellType; }
|
|
void SetTempSpellType(uint16 spell_type) { _tempSpellType = spell_type; }
|
|
bool IsMobEngagedByAnyone(Mob* tar);
|
|
void SetBotTimers(std::vector<BotTimer> timers) { bot_timers = timers; }
|
|
|
|
// Targeting
|
|
std::vector<Mob*> GatherSpellTargets(bool entireRaid = false, Mob* target = nullptr, bool no_clients = false, bool no_bots = false);
|
|
bool HasValidAETarget(Bot* caster, uint16 spell_id, uint16 spell_type, Mob* tar);
|
|
void SetHasLoS(bool has_los) { _hasLoS = has_los; }
|
|
bool HasLoS() const { return _hasLoS; }
|
|
bool IsValidMezTarget(Mob* owner, Mob* npc, uint16 spell_id);
|
|
|
|
// Cast checks
|
|
bool PrecastChecks(Mob* tar, uint16 spell_type);
|
|
bool CastChecks(uint16 spell_id, Mob* tar, uint16 spell_type, bool prechecks = false, bool ae_check = false);
|
|
bool IsImmuneToBotSpell(uint16 spell_id, Mob* caster);
|
|
bool CanCastSpellType(uint16 spell_type, uint16 spell_id, Mob* tar);
|
|
bool BotHasEnoughMana(uint16 spell_id);
|
|
bool IsTargetAlreadyReceivingSpell(Mob* tar, uint16 spell_id);
|
|
bool DoResistCheck(Mob* target, uint16 spell_id, int32 resist_limit);
|
|
bool DoResistCheckBySpellType(Mob* tar, uint16 spell_id, uint16 spell_type);
|
|
bool IsValidTargetType(uint16 spell_id, int target_type, uint8 body_type);
|
|
|
|
// Spell checks
|
|
static bool IsValidBotSpellType(uint16 spell_type);
|
|
uint16 GetPetBotSpellType(uint16 spell_type);
|
|
|
|
// Movement checks
|
|
bool PlotBotPositionAroundTarget(Mob* target, float& x_dest, float& y_dest, float& z_dest, float min_distance, float max_distance, bool behind_only = false, bool front_only = false, bool bypass_los = false);
|
|
std::vector<Mob*> GetSpellTargetList(bool entire_raid = false);
|
|
void SetSpellTargetList(std::vector<Mob*> spell_target_list) { _spell_target_list = spell_target_list; }
|
|
std::vector<Mob*> GetGroupSpellTargetList() { return _group_spell_target_list; }
|
|
void SetGroupSpellTargetList(std::vector<Mob*> spell_target_list) { _group_spell_target_list = spell_target_list; }
|
|
std::vector<Mob*> GetBuffTargets(Mob* spellTarget);
|
|
|
|
// Bot settings
|
|
void LoadDefaultBotSettings();
|
|
int GetDefaultSetting(uint16 setting_category, uint16 setting_type, uint8 stance = Stance::Balanced);
|
|
int GetDefaultBotBaseSetting(uint16 bot_setting, uint8 stance = Stance::Balanced);
|
|
bool GetDefaultSpellTypeHold(uint16 spell_type, uint8 stance = Stance::Balanced);
|
|
uint16 GetDefaultSpellTypePriority(uint16 spell_type, uint8 priority_type, uint8 bot_class, uint8 stance = Stance::Balanced);
|
|
uint16 GetDefaultSpellTypeIdlePriority(uint16 spell_type, uint8 bot_class, uint8 stance = Stance::Balanced);
|
|
uint16 GetDefaultSpellTypeEngagedPriority(uint16 spell_type, uint8 bot_class, uint8 stance = Stance::Balanced);
|
|
uint16 GetDefaultSpellTypePursuePriority(uint16 spell_type, uint8 bot_class, uint8 stance = Stance::Balanced);
|
|
uint16 GetDefaultSpellTypeResistLimit(uint16 spell_type, uint8 stance = Stance::Balanced);
|
|
bool GetDefaultSpellTypeAggroCheck(uint16 spell_type, uint8 stance = Stance::Balanced);
|
|
uint8 GetDefaultSpellTypeMinManaLimit(uint16 spell_type, uint8 stance = Stance::Balanced);
|
|
uint8 GetDefaultSpellTypeMaxManaLimit(uint16 spell_type, uint8 stance = Stance::Balanced);
|
|
uint8 GetDefaultSpellTypeMinHPLimit(uint16 spell_type, uint8 stance = Stance::Balanced);
|
|
uint8 GetDefaultSpellTypeMaxHPLimit(uint16 spell_type, uint8 stance = Stance::Balanced);
|
|
uint16 GetDefaultSpellTypeAnnounceCast(uint16 spell_type, uint8 stance = Stance::Balanced);
|
|
uint16 GetDefaultSpellTypeAEOrGroupTargetCount(uint16 spell_type, uint8 stance = Stance::Balanced);
|
|
|
|
static bool IsValidBotBaseSetting(uint16 setting_type);
|
|
static std::string GetBotSettingCategoryName(uint16 setting_type);
|
|
uint16 GetBaseSettingIDByShortName(std::string setting_string);
|
|
int GetBotBaseSetting(uint16 bot_setting);
|
|
void SetBotBaseSetting(uint16 bot_setting, int setting_value);
|
|
int GetSetting(uint16 setting_category, uint16 setting_type);
|
|
void SetBotSetting(uint8 setting_type, uint16 bot_setting, int setting_value);
|
|
void CopySettings(Bot* to, uint8 setting_type, uint16 spell_type = UINT16_MAX);
|
|
void CopyBotSpellSettings(Bot* to);
|
|
void ResetBotSpellSettings();
|
|
|
|
void CopyBotBlockedBuffs(Bot* to);
|
|
void CopyBotBlockedPetBuffs(Bot* to);
|
|
void CleanBotBlockedBuffs();
|
|
void ClearBotBlockedBuffs() { bot_blocked_buffs.clear(); }
|
|
bool IsBlockedBuff(int32 spell_id) override;
|
|
bool IsBlockedPetBuff(int32 spell_id) override;
|
|
void SetBotBlockedBuff(uint16 spell_id, bool block);
|
|
void SetBotBlockedPetBuff(uint16 spell_id, bool block);
|
|
std::vector<BotBlockedBuffs> GetBotBlockedBuffs() { return bot_blocked_buffs; }
|
|
void SetBotBlockedBuffs(std::vector<BotBlockedBuffs> blocked_buffs) { bot_blocked_buffs = blocked_buffs; }
|
|
|
|
void SetBotSpellRecastTimer(uint16 spell_type, Mob* spelltar, bool pre_cast = false);
|
|
uint16 GetSpellTypePriority(uint16 spell_type, uint8 priority_type);
|
|
void SetSpellTypePriority(uint16 spell_type, uint8 priority_type, uint16 priority);
|
|
inline uint16 GetSpellTypeResistLimit(uint16 spell_type) const { return m_bot_spell_settings[spell_type].resist_limit; }
|
|
inline void SetSpellTypeResistLimit(uint16 spell_type, uint16 value) { m_bot_spell_settings[spell_type].resist_limit = value; }
|
|
inline bool GetSpellTypeAggroCheck(uint16 spell_type) const { return m_bot_spell_settings[spell_type].aggro_check; }
|
|
inline void SetSpellTypeAggroCheck(uint16 spell_type, bool value) { m_bot_spell_settings[spell_type].aggro_check = value; }
|
|
uint8 GetHPRatioForSpellType(uint16 spell_type, Mob* tar);
|
|
inline uint8 GetSpellTypeMinManaLimit(uint16 spell_type) const { return m_bot_spell_settings[spell_type].min_mana_pct; }
|
|
inline uint8 GetSpellTypeMaxManaLimit(uint16 spell_type) const { return m_bot_spell_settings[spell_type].max_mana_pct; }
|
|
inline void SetSpellTypeMinManaLimit(uint16 spell_type, uint8 value) { m_bot_spell_settings[spell_type].min_mana_pct = value; }
|
|
inline void SetSpellTypeMaxManaLimit(uint16 spell_type, uint8 value) { m_bot_spell_settings[spell_type].max_mana_pct = value; }
|
|
inline uint8 GetSpellTypeMinHPLimit(uint16 spell_type) const { return m_bot_spell_settings[spell_type].min_hp_pct; }
|
|
inline uint8 GetSpellTypeMaxHPLimit(uint16 spell_type) const { return m_bot_spell_settings[spell_type].max_hp_pct; }
|
|
inline void SetSpellTypeMinHPLimit(uint16 spell_type, uint8 value) { m_bot_spell_settings[spell_type].min_hp_pct = value; }
|
|
inline void SetSpellTypeMaxHPLimit(uint16 spell_type, uint8 value) { m_bot_spell_settings[spell_type].max_hp_pct = value; }
|
|
inline uint16 GetSpellTypeAEOrGroupTargetCount(uint16 spell_type) const { return m_bot_spell_settings[spell_type].ae_or_group_target_count; }
|
|
inline void SetSpellTypeAEOrGroupTargetCount(uint16 spell_type, uint16 value) { m_bot_spell_settings[spell_type].ae_or_group_target_count = value; }
|
|
inline uint16 GetSpellTypeAnnounceCast(uint16 spell_type) const { return m_bot_spell_settings[spell_type].announce_cast; }
|
|
inline void SetSpellTypeAnnounceCast(uint16 spell_type, uint16 value) { m_bot_spell_settings[spell_type].announce_cast = value; }
|
|
inline bool GetSpellTypeHold(uint16 spell_type) const { return m_bot_spell_settings[spell_type].hold; }
|
|
inline void SetSpellTypeHold(uint16 spell_type, bool value) { m_bot_spell_settings[spell_type].hold = value; }
|
|
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); }
|
|
inline bool SpellTypeAIDelayCheck(uint16 spellType) { return !m_bot_spell_settings[spellType].ai_delay.GetRemainingTime(); }
|
|
void SetSpellTypeAITimer(uint16 spell_type, uint32 recast_time) { m_bot_spell_settings[spell_type].ai_delay.Start(recast_time); }
|
|
bool GetUltimateSpellTypeHold(uint16 spell_type, Mob* tar);
|
|
uint16 GetDefaultSpellTypeDelay(uint16 spell_type, uint8 stance = Stance::Balanced);
|
|
uint8 GetDefaultSpellTypeMinThreshold(uint16 spell_type, uint8 stance = Stance::Balanced);
|
|
uint8 GetDefaultSpellTypeMaxThreshold(uint16 spell_type, uint8 stance = Stance::Balanced);
|
|
uint16 GetUltimateSpellTypeDelay(uint16 spell_type, Mob* tar);
|
|
bool GetUltimateSpellTypeDelayCheck(uint16 spell_type, Mob* tar);
|
|
uint8 GetUltimateSpellTypeMinThreshold(uint16 spell_type, Mob* tar);
|
|
uint8 GetUltimateSpellTypeMaxThreshold(uint16 spell_type, Mob* tar);
|
|
void SetIllusionBlock(bool value) { _illusionBlock = value; }
|
|
bool GetIllusionBlock() const override { return _illusionBlock; }
|
|
bool GetShowHelm() const { return _showHelm; }
|
|
void SetShowHelm(bool show_helm) { _showHelm = show_helm; }
|
|
bool GetBehindMob() const { return _behindMobStatus; }
|
|
void SetBehindMob(bool value) { _behindMobStatus = value; }
|
|
bool GetMaxMeleeRange() const { return _maxMeleeRangeStatus; }
|
|
void SetMaxMeleeRange(bool value) { _maxMeleeRangeStatus = value; }
|
|
uint8 GetStopMeleeLevel() const { return _stopMeleeLevel; }
|
|
void SetStopMeleeLevel(uint8 level) { _stopMeleeLevel = level; }
|
|
uint32 GetBotDistanceRanged() const { return _distanceRanged; }
|
|
void SetBotDistanceRanged(uint32 distance) { _distanceRanged = distance; }
|
|
bool GetMedInCombat() const { return _medInCombat; }
|
|
void SetMedInCombat(bool value) { _medInCombat = value; }
|
|
uint8 GetSitHPPct() const { return _SitHPPct; }
|
|
void SetSitHPPct(uint8 value) { _SitHPPct = value; }
|
|
uint8 GetSitManaPct() const { return _SitManaPct; }
|
|
void SetSitManaPct(uint8 value) { _SitManaPct = value; }
|
|
|
|
// Spell lists
|
|
void CheckBotSpells();
|
|
void MapSpellTypeLevels();
|
|
const std::map<int32_t, std::map<int32_t, BotSpellTypesByClass>>& GetCommandedSpellTypesMinLevels() { return commanded_spells_min_level; }
|
|
std::list<BotSpellTypeOrder> GetSpellTypesPrioritized(uint8 priority_type);
|
|
static uint16 GetParentSpellType(uint16 spell_type);
|
|
bool IsValidSpellTypeBySpellID(uint16 spell_type, uint16 spell_id);
|
|
inline uint16 GetCastedSpellType() const { return _castedSpellType; }
|
|
void SetCastedSpellType(uint16 spell_type);
|
|
bool IsValidSpellTypeSubType(uint16 spell_type, uint16 sub_type, uint16 spell_id);
|
|
static bool IsValidBotSpellCategory(uint8 setting_type);
|
|
static std::string GetBotSpellCategoryName(uint8 setting_type);
|
|
static uint16 GetBotSpellCategoryIDByShortName(std::string setting_string);
|
|
void AssignBotSpellsToTypes(std::vector<BotSpells>& AIBot_spells, std::unordered_map<uint16, std::vector<BotSpells_wIndex>>& AIBot_spells_by_type);
|
|
uint16 GetSpellByAA(int id, AA::Rank*& rank);
|
|
|
|
// Spell Type
|
|
static uint16 GetSpellTypeIDByShortName(std::string spellType_string);
|
|
static std::string GetSpellTypeNameByID(uint16 spell_type);
|
|
static std::string GetSpellTypeShortNameByID(uint16 spell_type);
|
|
bool IsValidSubType(uint16 sub_type);
|
|
static std::string GetSubTypeNameByID(uint16 sub_type);
|
|
|
|
[[nodiscard]] int GetMaxBuffSlots() const final { return EQ::spells::LONG_BUFFS; }
|
|
[[nodiscard]] int GetMaxSongSlots() const final { return EQ::spells::SHORT_BUFFS; }
|
|
[[nodiscard]] int GetMaxDiscSlots() const final { return EQ::spells::DISC_BUFFS; }
|
|
[[nodiscard]] int GetMaxTotalSlots() const final { return EQ::spells::TOTAL_BUFFS; }
|
|
|
|
bool CheckDataBucket(std::string bucket_name, const std::string& bucket_value, uint8 bucket_comparison);
|
|
|
|
// Bot Equipment & Inventory Class Methods
|
|
void BotTradeAddItem(const EQ::ItemInstance* inst, uint16 slot_id, bool save_to_database = true);
|
|
void EquipBot();
|
|
bool CheckLoreConflict(const EQ::ItemData* item);
|
|
void UpdateEquipmentLight() override
|
|
{
|
|
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 EQ::InventoryProfile& GetInv() override { return m_inv; }
|
|
|
|
// Static Class Methods
|
|
static Bot* LoadBot(uint32 botID);
|
|
static uint32 SpawnedBotCount(const uint32 owner_id, uint8 class_id = Class::None);
|
|
static void LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp);
|
|
|
|
static bool IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined);
|
|
static Bot* GetBotByBotClientOwnerAndBotName(Client* c, const std::string& botName);
|
|
static void ProcessBotGroupInvite(Client* c, std::string const& botName);
|
|
static void ProcessBotGroupDisband(Client* c, const std::string& botName);
|
|
static void BotOrderCampAll(Client* c, uint8 class_id = Class::None);
|
|
static void ProcessBotInspectionRequest(Bot* inspectedBot, Client* client);
|
|
static void LoadAndSpawnAllZonedBots(Client* bot_owner);
|
|
static bool GroupHasBot(Group* group);
|
|
static Bot* GetFirstBotInGroup(Group* group);
|
|
static void ProcessClientZoneChange(Client* botOwner);
|
|
static void ProcessBotOwnerRefDelete(Mob* botOwner); // Removes a Client* reference when the Client object is destroyed
|
|
|
|
//Raid methods
|
|
static void ProcessRaidInvite(Mob* invitee, Client* invitor, bool group_invite = false);
|
|
static void RemoveBotFromRaid(Bot* bot);
|
|
inline void SetDirtyAutoHaters() { m_dirtyautohaters = true; }
|
|
static void CreateBotRaid(Mob* invitee, Client* invitor, bool group_invite, Raid* raid);
|
|
static void
|
|
ProcessBotGroupAdd(Group* group, Raid* raid, Client* client = nullptr, bool new_raid = false, bool initial = false);
|
|
|
|
|
|
static std::list<BotSpell> GetBotSpellsForSpellEffect(Bot* caster, uint16 spell_type, int spell_effect);
|
|
static std::list<BotSpell> GetBotSpellsForSpellEffectAndTargetType(Bot* caster, uint16 spell_type, int spell_effect, SpellTargetType target_type);
|
|
static std::list<BotSpell> GetBotSpellsBySpellType(Bot* caster, uint16 spell_type);
|
|
static std::vector<BotSpell_wPriority> GetPrioritizedBotSpellsBySpellType(Bot* caster, uint16 spell_type, Mob* tar, bool AE = false, uint16 sub_target_type = UINT16_MAX, uint16 sub_type = UINT16_MAX);
|
|
|
|
static BotSpell GetFirstBotSpellBySpellType(Bot* caster, uint16 spell_type);
|
|
BotSpell GetSpellByHealType(uint16 spell_type, Mob* tar);
|
|
static BotSpell GetBestBotSpellForVeryFastHeal(Bot* caster, Mob* tar, uint16 spell_type = BotSpellTypes::RegularHeal);
|
|
static BotSpell GetBestBotSpellForFastHeal(Bot* caster, Mob* tar, uint16 spell_type = BotSpellTypes::RegularHeal);
|
|
static BotSpell GetBestBotSpellForHealOverTime(Bot* caster, Mob* tar, uint16 spell_type = BotSpellTypes::RegularHeal);
|
|
static BotSpell GetBestBotSpellForPercentageHeal(Bot* caster, Mob* tar, uint16 spell_type = BotSpellTypes::RegularHeal);
|
|
static BotSpell GetBestBotSpellForRegularSingleTargetHeal(Bot* caster, Mob* tar, uint16 spell_type = BotSpellTypes::RegularHeal);
|
|
static BotSpell GetFirstBotSpellForSingleTargetHeal(Bot* caster, Mob* tar, uint16 spell_type = BotSpellTypes::RegularHeal);
|
|
static BotSpell GetBestBotSpellForGroupHealOverTime(Bot* caster, Mob* tar, uint16 spell_type = BotSpellTypes::RegularHeal);
|
|
static BotSpell GetBestBotSpellForGroupCompleteHeal(Bot* caster, Mob* tar, uint16 spell_type = BotSpellTypes::RegularHeal);
|
|
static BotSpell GetBestBotSpellForGroupHeal(Bot* caster, Mob* tar, uint16 spell_type = BotSpellTypes::RegularHeal);
|
|
|
|
static Mob* GetFirstIncomingMobToMez(Bot* caster, int16 spell_id, uint16 spell_type, bool AE);
|
|
static BotSpell GetBestBotSpellForMez(Bot* caster, uint16 spell_type = BotSpellTypes::Mez);
|
|
static BotSpell GetBestBotMagicianPetSpell(Bot* caster, uint16 spell_type = BotSpellTypes::Pet);
|
|
static std::string GetBotMagicianPetType(Bot* caster);
|
|
static BotSpell GetBestBotSpellForNukeByTargetType(Bot* caster, SpellTargetType target_type, uint16 spell_type, bool AE = false, Mob* tar = nullptr);
|
|
static BotSpell GetBestBotSpellForStunByTargetType(Bot* caster, SpellTargetType target_type, uint16 spell_type, bool AE = false, Mob* tar = nullptr);
|
|
static BotSpell GetBestBotWizardNukeSpellByTargetResists(Bot* caster, Mob* target, uint16 spell_type);
|
|
static BotSpell GetDebuffBotSpell(Bot* caster, Mob* target, uint16 spell_type);
|
|
static BotSpell GetBestBotSpellForCure(Bot* caster, Mob* target, uint16 spell_type);
|
|
static BotSpell GetBestBotSpellForResistDebuff(Bot* caster, Mob* target, uint16 spell_type);
|
|
static BotSpell GetBestBotSpellForNukeByBodyType(Bot* caster, uint8 body_type, uint16 spell_type, bool AE = false, Mob* tar = nullptr);
|
|
static BotSpell GetBestBotSpellForRez(Bot* caster, Mob* target, uint16 spell_type);
|
|
static BotSpell GetBestBotSpellForCharm(Bot* caster, Mob* target, uint16 spell_type);
|
|
|
|
static NPCType *CreateDefaultNPCTypeStructForBot(
|
|
const std::string& botName,
|
|
const std::string& botLastName,
|
|
uint8 botLevel,
|
|
uint16 botRace,
|
|
uint8 botClass,
|
|
uint8 gender
|
|
);
|
|
|
|
void AddBotStartingItems(uint16 race_id, uint8 class_id);
|
|
|
|
// Static Bot Group Methods
|
|
static bool AddBotToGroup(Bot* bot, Group* group);
|
|
static bool RemoveBotFromGroup(Bot* bot, Group* group);
|
|
void RaidGroupSay(const char *msg, ...);
|
|
|
|
// "GET" Class Methods
|
|
uint32 GetBotID() const { return _botID; }
|
|
uint32 GetBotOwnerCharacterID() const { return _botOwnerCharacterID; }
|
|
uint32 GetBotSpellID() const { return npc_spells_id; }
|
|
Mob* GetBotOwner() { return this->_botOwner; }
|
|
uint32 GetBotRangedValue();
|
|
EQ::ItemInstance* GetBotItem(uint16 slot_id);
|
|
bool GetSpawnStatus() { return _spawnStatus; }
|
|
uint8 GetPetChooserID() { return _petChooserID; }
|
|
bool IsBotRanged() { return _botRangedSetting; }
|
|
bool IsBotCharmer() { return _botCharmer; }
|
|
bool IsBot() const override { return true; }
|
|
bool IsOfClientBot() const override { return true; }
|
|
bool IsOfClientBotMerc() const override { return true; }
|
|
|
|
bool GetRangerAutoWeaponSelect() { return _rangerAutoWeaponSelect; }
|
|
uint8 GetBotStance() { return _botStance; }
|
|
uint8 GetChanceToCastBySpellType(uint16 spell_type);
|
|
bool IsGroupHealer() const { return m_CastingRoles.GroupHealer; }
|
|
bool IsGroupSlower() const { return m_CastingRoles.GroupSlower; }
|
|
bool IsGroupNuker() const { return m_CastingRoles.GroupNuker; }
|
|
bool IsGroupDoter() const { return m_CastingRoles.GroupDoter; }
|
|
static void UpdateGroupCastingRoles(const Group* group, bool disband = false);
|
|
|
|
bool IsBotCaster() { return IsCasterClass(GetClass()); }
|
|
bool IsBotHybrid() { return IsHybridClass(GetClass()); }
|
|
bool IsBotINTCaster() { return IsINTCasterClass(GetClass()); }
|
|
bool IsBotWISCaster() { return IsWISCasterClass(GetClass()); }
|
|
bool IsBotSpellFighter() { return IsSpellFighterClass(GetClass()); }
|
|
bool IsBotFighter() { return IsFighterClass(GetClass()); }
|
|
bool IsBotNonSpellFighter() { return (GetClass() == Class::Bard ? false : IsNonSpellFighterClass(GetClass())); }
|
|
uint8 GetBotClass() { return GetClass(); }
|
|
int GetRawACNoShield(int &shield_ac);
|
|
|
|
// new heal rotation code
|
|
bool CreateHealRotation(uint32 cycle_duration_ms = 5000, bool fast_heals = false, bool adaptive_targeting = false, bool casting_override = false);
|
|
bool DestroyHealRotation();
|
|
bool JoinHealRotationMemberPool(std::shared_ptr<HealRotation>* heal_rotation);
|
|
bool LeaveHealRotationMemberPool();
|
|
|
|
bool IsHealRotationMember() { return (m_member_of_heal_rotation.use_count() && m_member_of_heal_rotation.get()); }
|
|
bool UseHealRotationFastHeals();
|
|
bool UseHealRotationAdaptiveTargeting();
|
|
|
|
bool IsHealRotationActive();
|
|
bool IsHealRotationReady();
|
|
bool IsHealRotationCaster();
|
|
bool HealRotationPokeTarget();
|
|
Mob* HealRotationTarget();
|
|
bool AdvanceHealRotation(bool use_interval = true);
|
|
|
|
bool IsMyHealRotationSet();
|
|
bool AmICastingForHealRotation();
|
|
void SetMyCastingForHealRotation(bool flag = true);
|
|
|
|
std::shared_ptr<HealRotation>* MemberOfHealRotation() { return &m_member_of_heal_rotation; }
|
|
|
|
inline int32 GetSTR() const override { return STR; }
|
|
inline int32 GetSTA() const override { return STA; }
|
|
inline int32 GetDEX() const override { return DEX; }
|
|
inline int32 GetAGI() const override { return AGI; }
|
|
inline int32 GetINT() const override { return INT; }
|
|
inline int32 GetWIS() const override { return WIS; }
|
|
inline int32 GetCHA() const override { return CHA; }
|
|
inline int32 GetMR() const override { return MR; }
|
|
inline int32 GetFR() const override { return FR; }
|
|
inline int32 GetDR() const override { return DR; }
|
|
inline int32 GetPR() const override { return PR; }
|
|
inline int32 GetCR() const override { return CR; }
|
|
inline int32 GetCorrup() const override { return Corrup; }
|
|
//Heroic
|
|
inline int32 GetHeroicSTR() const override { return itembonuses.HeroicSTR; }
|
|
inline int32 GetHeroicSTA() const override { return itembonuses.HeroicSTA; }
|
|
inline int32 GetHeroicDEX() const override { return itembonuses.HeroicDEX; }
|
|
inline int32 GetHeroicAGI() const override { return itembonuses.HeroicAGI; }
|
|
inline int32 GetHeroicINT() const override { return itembonuses.HeroicINT; }
|
|
inline int32 GetHeroicWIS() const override { return itembonuses.HeroicWIS; }
|
|
inline int32 GetHeroicCHA() const override { return itembonuses.HeroicCHA; }
|
|
inline int32 GetHeroicMR() const override { return itembonuses.HeroicMR; }
|
|
inline int32 GetHeroicFR() const override { return itembonuses.HeroicFR; }
|
|
inline int32 GetHeroicDR() const override { return itembonuses.HeroicDR; }
|
|
inline int32 GetHeroicPR() const override { return itembonuses.HeroicPR; }
|
|
inline int32 GetHeroicCR() const override { return itembonuses.HeroicCR; }
|
|
inline virtual int32 GetHeroicCorrup() const { return itembonuses.HeroicCorrup; }
|
|
// 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 override { 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; }
|
|
|
|
inline InspectMessage_Struct& GetInspectMessage() { return _botInspectMessage; }
|
|
inline const InspectMessage_Struct& GetInspectMessage() const { return _botInspectMessage; }
|
|
|
|
// "Quest API" Methods
|
|
bool HasBotSpellEntry(uint16 spell_id);
|
|
bool CanUseBotSpell(uint16 spell_id);
|
|
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);
|
|
void BreakInvis();
|
|
void Escape();
|
|
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);
|
|
std::vector<Mob*> GetApplySpellList(ApplySpellType apply_type, bool allow_pets, bool is_raid_group_only);
|
|
int32 GetItemIDAt(int16 slot_id);
|
|
int32 GetAugmentIDAt(int16 slot_id, uint8 augslot);
|
|
int32 GetRawItemAC();
|
|
void SendSpellAnim(uint16 targetid, uint16 spell_id);
|
|
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);
|
|
|
|
// "SET" Class Methods
|
|
void SetBotSpellID(uint32 newSpellID);
|
|
void SetSpawnStatus(bool spawnStatus) { _spawnStatus = spawnStatus; }
|
|
void SetPetChooserID(uint8 id) { _petChooserID = id; }
|
|
void SetBotRangedSetting(bool value) { _botRangedSetting = value; }
|
|
void SetBotCharmer(bool c) { _botCharmer = c; }
|
|
void SetBotOwner(Mob* botOwner) { this->_botOwner = botOwner; }
|
|
void SetRangerAutoWeaponSelect(bool enable) { GetClass() == Class::Ranger ? _rangerAutoWeaponSelect = enable : _rangerAutoWeaponSelect = false; }
|
|
void SetBotStance(uint8 stance_id) { _botStance = Stance::IsValid(stance_id) ? stance_id : Stance::Passive; }
|
|
uint32 GetSpellRecastTimer(uint16 spell_id = 0);
|
|
bool CheckSpellRecastTimer(uint16 spell_id = 0);
|
|
uint32 GetSpellRecastRemainingTime(uint16 spell_id = 0);
|
|
void SetSpellRecastTimer(uint16 spell_id, int32 recast_delay = 0);
|
|
uint32 CalcSpellRecastTimer(uint16 spell_id);
|
|
uint32 GetDisciplineReuseTimer(uint16 spell_id = 0);
|
|
bool CheckDisciplineReuseTimer(uint16 spell_id = 0);
|
|
uint32 GetDisciplineReuseRemainingTime(uint16 spell_id = 0);
|
|
void SetDisciplineReuseTimer(uint16 spell_id, int32 reuse_timer = 0);
|
|
uint32 GetItemReuseTimer(uint32 item_id = 0);
|
|
bool CheckItemReuseTimer(uint32 item_id = 0);
|
|
void SetItemReuseTimer(uint32 item_id, uint32 reuse_timer = 0);
|
|
void ClearDisciplineReuseTimer(uint16 spell_id = 0);
|
|
void ClearItemReuseTimer(uint32 item_id = 0);
|
|
void ClearSpellRecastTimer(uint16 spell_id = 0);
|
|
uint32 GetItemReuseRemainingTime(uint32 item_id = 0);
|
|
void ClearExpiredTimers();
|
|
void SetBeardColor(uint8 value) { beardcolor = value; }
|
|
void SetBeard(uint8 value) { beard = value; }
|
|
void SetEyeColor1(uint8 value) { eyecolor1 = value; }
|
|
void SetEyeColor2(uint8 value) { eyecolor2 = value; }
|
|
void SetLuclinFace(uint8 value) { luclinface = value; }
|
|
void SetHairColor(uint8 value) { haircolor = value; }
|
|
void SetHairStyle(uint8 value) { hairstyle = value; }
|
|
void SetDrakkinDetails(uint32 value) { drakkin_details = value; }
|
|
void SetDrakkinHeritage(uint32 value) { drakkin_heritage = value; }
|
|
void SetDrakkinTattoo(uint32 value) { drakkin_tattoo = value; }
|
|
bool DyeArmor(int16 slot_id, uint32 rgb, bool all_flag = false, bool save_flag = true);
|
|
|
|
int GetExpansionBitmask();
|
|
void SetExpansionBitmask(int expansionBitmask);
|
|
|
|
void ListBotSpells(uint8 min_level);
|
|
|
|
std::string GetHPString(int8 min_hp, int8 max_hp);
|
|
|
|
bool AddBotSpellSetting(uint16 spell_id, BotSpellSetting* bs);
|
|
bool DeleteBotSpellSetting(uint16 spell_id);
|
|
BotSpellSetting* GetBotSpellSetting(uint16 spell_id);
|
|
void ListBotSpellSettings();
|
|
void LoadBotSpellSettings();
|
|
bool UpdateBotSpellSetting(uint16 spell_id, BotSpellSetting* bs);
|
|
void SetBotEnforceSpellSetting(bool enforceSpellSettings);
|
|
bool GetBotEnforceSpellSetting() { return _enforceSpellSettings; }
|
|
|
|
// Class Destructors
|
|
~Bot() override;
|
|
|
|
// Publicized private functions
|
|
static NPCType *FillNPCTypeStruct(
|
|
uint32 botSpellsID,
|
|
const std::string& botName,
|
|
const std::string& botLastName,
|
|
uint8 botLevel,
|
|
uint16 botRace,
|
|
uint8 botClass,
|
|
uint8 gender,
|
|
float size,
|
|
uint32 face,
|
|
uint32 hairStyle,
|
|
uint32 hairColor,
|
|
uint32 eyeColor,
|
|
uint32 eyeColor2,
|
|
uint32 beard,
|
|
uint32 beardColor,
|
|
uint32 drakkinHeritage,
|
|
uint32 drakkinTattoo,
|
|
uint32 drakkinDetails,
|
|
int32 hp,
|
|
int32 mana,
|
|
int32 mr,
|
|
int32 cr,
|
|
int32 dr,
|
|
int32 fr,
|
|
int32 pr,
|
|
int32 corrup,
|
|
int32 ac,
|
|
uint32 str,
|
|
uint32 sta,
|
|
uint32 dex,
|
|
uint32 agi,
|
|
uint32 _int,
|
|
uint32 wis,
|
|
uint32 cha,
|
|
uint32 attack
|
|
);
|
|
void BotRemoveEquipItem(uint16 slot_id);
|
|
void RemoveBotItemBySlot(uint16 slot_id
|
|
);
|
|
void AddBotItem(
|
|
uint16 slot_id,
|
|
uint32 item_id,
|
|
int16 charges = -1,
|
|
bool attuned = false,
|
|
uint32 augment_one = 0,
|
|
uint32 augment_two = 0,
|
|
uint32 augment_three = 0,
|
|
uint32 augment_four = 0,
|
|
uint32 augment_five = 0,
|
|
uint32 augment_six = 0
|
|
);
|
|
uint32 CountBotItem(uint32 item_id);
|
|
std::map<uint16, uint32> GetBotItemSlots();
|
|
uint32 GetBotItemBySlot(uint16 slot_id);
|
|
int16 HasBotItem(uint32 item_id);
|
|
void RemoveBotItem(uint32 item_id);
|
|
uint32 GetTotalPlayTime();
|
|
|
|
// New accessors for BotDatabase access
|
|
bool DeleteBot();
|
|
std::vector<BotTimer> GetBotTimers() { return bot_timers; }
|
|
uint32 GetLastZoneID() const { return _lastZoneId; }
|
|
int32 GetBaseAC() const { return _baseAC; }
|
|
int32 GetBaseATK() const { return _baseATK; }
|
|
int32 GetBaseSTR() const { return _baseSTR; }
|
|
int32 GetBaseSTA() const { return _baseSTA; }
|
|
int32 GetBaseCHA() const { return _baseCHA; }
|
|
int32 GetBaseDEX() const { return _baseDEX; }
|
|
int32 GetBaseINT() const { return _baseINT; }
|
|
int32 GetBaseAGI() const { return _baseAGI; }
|
|
int32 GetBaseWIS() const { return _baseWIS; }
|
|
int32 GetBaseFR() const { return _baseFR; }
|
|
int32 GetBaseCR() const { return _baseCR; }
|
|
int32 GetBaseMR() const { return _baseMR; }
|
|
int32 GetBasePR() const { return _basePR; }
|
|
int32 GetBaseDR() const { return _baseDR; }
|
|
int32 GetBaseCorrup() const { return _baseCorrup; }
|
|
|
|
void Signal(int signal_id);
|
|
void SendPayload(int payload_id, std::string payload_value = std::string());
|
|
void OwnerMessage(const std::string& message);
|
|
|
|
//Raid additions
|
|
Raid* p_raid_instance;
|
|
|
|
static uint8 spell_casting_chances[SPELL_TYPE_COUNT][Class::PLAYER_CLASS_COUNT][Stance::AEBurn][cntHSND];
|
|
|
|
bool BotCastMez(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spell_type);
|
|
bool BotCastHeal(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spell_type);
|
|
bool BotCastNuke(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spell_type);
|
|
bool BotCastPet(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spell_type);
|
|
bool BotCastCure(Mob* tar, uint8 bot_class, BotSpell& bot_spell, uint16 spell_type);
|
|
|
|
bool CheckIfIncapacitated();
|
|
bool IsAIProcessValid(const Client* bot_owner, const Group* bot_group, const Raid* raid);
|
|
|
|
Client* SetLeashOwner(Client* bot_owner, Group* bot_group, Raid* raid, uint32 r_group) const;
|
|
Mob* SetFollowMob(Client* leash_owner);
|
|
|
|
Mob* GetBotTarget(Client* bot_owner);
|
|
void SetOwnerTarget(Client* bot_owner);
|
|
bool IsValidTarget(
|
|
Client* bot_owner,
|
|
Client* leash_owner,
|
|
float lo_distance,
|
|
float leash_distance,
|
|
Mob* tar,
|
|
float tar_distance
|
|
);
|
|
bool TargetValidation(Mob* other);
|
|
|
|
bool PullingFlagChecks(Client* bot_owner);
|
|
bool ReturningFlagChecks(Client* bot_owner, Mob* leash_owner, float fm_distance);
|
|
void BotPullerProcess(Client* bot_owner, Raid* raid);
|
|
|
|
// Combat Checks
|
|
CombatRangeOutput EvaluateCombatRange(const CombatRangeInput& input);
|
|
|
|
void SetBerserkState();
|
|
bool CheckIfCasting(float fm_distance);
|
|
void HealRotationChecks();
|
|
|
|
bool GetCombatJitterFlag() { return m_combat_jitter_flag; }
|
|
void SetCombatJitterFlag(bool flag = true) { m_combat_jitter_flag = flag; }
|
|
bool GetCombatOutOfRangeJitterFlag() { return m_combat_out_of_range_jitter_flag; }
|
|
void SetCombatOutOfRangeJitterFlag(bool flag = true) { m_combat_out_of_range_jitter_flag = flag; }
|
|
void SetCombatJitter();
|
|
void SetCombatOutOfRangeJitter();
|
|
void DoCombatPositioning(Mob* tar, glm::vec3 Goal, bool stop_melee_level, float tar_distance, float melee_distance_min, float melee_distance, float melee_distance_max, bool behind_mob, bool front_mob);
|
|
void DoFaceCheckWithJitter(Mob* tar);
|
|
void DoFaceCheckNoJitter(Mob* tar);
|
|
void RunToGoalWithJitter(glm::vec3 Goal);
|
|
bool RequiresLoSForPositioning();
|
|
bool HasRequiredLoSForPositioning(Mob* tar);
|
|
|
|
// Try Combat Methods
|
|
bool TryEvade(Mob* tar);
|
|
bool TryFacingTarget(Mob* tar);
|
|
bool TryPursueTarget(float leash_distance, glm::vec3& Goal);
|
|
bool TryMeditate();
|
|
bool TryAutoDefend(Client* bot_owner, float leash_distance);
|
|
bool TryIdleChecks(float fm_distance);
|
|
bool TryNonCombatMovementChecks(Client* bot_owner, const Mob* follow_mob, glm::vec3& Goal);
|
|
bool TryBardMovementCasts();
|
|
bool BotRangedAttack(Mob* other, bool can_double_attack = false);
|
|
bool CheckDoubleRangedAttack();
|
|
|
|
// Public "Refactor" Methods
|
|
static bool CheckCampSpawnConditions(Client* c);
|
|
|
|
protected:
|
|
void BotMeditate(bool is_sitting);
|
|
bool CheckBotDoubleAttack(bool triple_attack = false);
|
|
bool CheckTripleAttack();
|
|
void PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* client, int16 chosen_slot = INVALID_INDEX);
|
|
bool AIDoSpellCast(int32 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = nullptr) override;
|
|
|
|
BotCastingRoles& GetCastingRoles() { return m_CastingRoles; }
|
|
void SetGroupHealer(bool flag = true) { m_CastingRoles.GroupHealer = flag; }
|
|
void SetGroupSlower(bool flag = true) { m_CastingRoles.GroupSlower = flag; }
|
|
void SetGroupNuker(bool flag = true) { m_CastingRoles.GroupNuker = flag; }
|
|
void SetGroupDoter(bool flag = true) { m_CastingRoles.GroupDoter = flag; }
|
|
std::deque<int> bot_signal_q;
|
|
|
|
std::vector<BotSpells> AIBot_spells;
|
|
std::vector<BotSpells> AIBot_spells_enforced;
|
|
std::unordered_map<uint16, std::vector<BotSpells_wIndex>> AIBot_spells_by_type;
|
|
|
|
std::map<int32_t, std::map<int32_t, BotSpellTypesByClass>> commanded_spells_min_level;
|
|
|
|
std::vector<BotTimer> bot_timers;
|
|
std::vector<BotBlockedBuffs> bot_blocked_buffs;
|
|
|
|
private:
|
|
// Class Members
|
|
uint32 _botID;
|
|
uint32 _botOwnerCharacterID;
|
|
bool _spawnStatus;
|
|
Mob* _botOwner;
|
|
bool _botCharmer;
|
|
uint8 _petChooserID;
|
|
bool berserk;
|
|
EQ::InventoryProfile m_inv;
|
|
double _lastTotalPlayTime;
|
|
time_t _startTotalPlayTime;
|
|
uint32 _guildId;
|
|
uint8 _guildRank;
|
|
std::string _guildName;
|
|
std::string _surname;
|
|
std::string _title;
|
|
std::string _suffix;
|
|
uint32 _lastZoneId;
|
|
bool _rangerAutoWeaponSelect;
|
|
uint8 _botStance;
|
|
unsigned int RestRegenHP;
|
|
unsigned int RestRegenMana;
|
|
unsigned int RestRegenEndurance;
|
|
Timer rest_timer;
|
|
Timer m_ping_timer;
|
|
int32 base_end;
|
|
int32 cur_end;
|
|
int32 max_end;
|
|
int32 end_regen;
|
|
|
|
Timer m_rogue_evade_timer; // Rogue evade timer
|
|
Timer m_monk_evade_timer; // Monk evade FD timer
|
|
Timer m_auto_defend_timer;
|
|
Timer m_auto_save_timer;
|
|
|
|
Timer m_combat_jitter_timer;
|
|
bool m_combat_jitter_flag;
|
|
bool m_combat_out_of_range_jitter_flag;
|
|
|
|
bool m_dirtyautohaters;
|
|
bool m_guard_flag;
|
|
bool m_hold_flag;
|
|
bool m_attack_flag;
|
|
bool m_combat_round_alert_flag;
|
|
bool m_attacking_flag;
|
|
bool m_pull_flag;
|
|
bool m_pulling_flag;
|
|
bool m_returning_flag;
|
|
bool is_using_item_click;
|
|
|
|
BotCastingRoles m_CastingRoles;
|
|
|
|
std::map<uint16, BotSpellSetting> bot_spell_settings;
|
|
|
|
std::shared_ptr<HealRotation> m_member_of_heal_rotation;
|
|
|
|
InspectMessage_Struct _botInspectMessage;
|
|
bool _pauseAI;
|
|
|
|
int _expansionBitmask;
|
|
bool _enforceSpellSettings;
|
|
bool _showHelm;
|
|
bool _botRangedSetting;
|
|
uint8 _stopMeleeLevel;
|
|
uint32 _distanceRanged;
|
|
bool _behindMobStatus;
|
|
bool _maxMeleeRangeStatus;
|
|
bool _medInCombat;
|
|
uint8 _SitHPPct;
|
|
uint8 _SitManaPct;
|
|
uint16 _castedSpellType;
|
|
bool _hasLoS;
|
|
bool _commandedSpell;
|
|
bool _pullingSpell;
|
|
|
|
bool _illusionBlock;
|
|
std::vector<BotSpellSettings> m_bot_spell_settings;
|
|
std::vector<Mob*> _spell_target_list;
|
|
std::vector<Mob*> _group_spell_target_list;
|
|
Raid* _storedRaid;
|
|
bool _verifiedRaid;
|
|
uint16 _tempSpellType; // this is used to check the spell type being cast against ^spellannouncecasts status
|
|
|
|
// Private "base stats" Members
|
|
int32 _baseMR;
|
|
int32 _baseCR;
|
|
int32 _baseDR;
|
|
int32 _baseFR;
|
|
int32 _basePR;
|
|
int32 _baseCorrup;
|
|
int32 _baseAC;
|
|
int32 _baseSTR;
|
|
int32 _baseSTA;
|
|
int32 _baseDEX;
|
|
int32 _baseAGI;
|
|
int32 _baseINT;
|
|
int32 _baseWIS;
|
|
int32 _baseCHA;
|
|
int32 _baseATK;
|
|
uint16 _baseRace; // Necessary to preserve the race otherwise bots get their race updated in the db when they get an illusion.
|
|
uint8 _baseGender; // Bots gender. Necessary to preserve the original value otherwise it can be changed by illusions.
|
|
|
|
// Class Methods
|
|
void LoadAAs();
|
|
void GenerateBaseStats();
|
|
void GenerateAppearance();
|
|
int32 GenerateBaseHitPoints();
|
|
int32 GenerateBaseManaPoints();
|
|
void GenerateSpecialAttacks();
|
|
void SetBotID(uint32 botID);
|
|
void SetCombatRoundForAlerts(bool flag = true) { m_combat_round_alert_flag = flag; }
|
|
void SetAttackingFlag(bool flag = true) { m_attacking_flag = flag; }
|
|
void SetPullingFlag(bool flag = true) { m_pulling_flag = flag; }
|
|
void SetReturningFlag(bool flag = true) { m_returning_flag = flag; }
|
|
|
|
// Private "Inventory" Methods
|
|
void GetBotItems(EQ::InventoryProfile &inv);
|
|
void BotAddEquipItem(uint16 slot_id, uint32 item_id);
|
|
|
|
// Private "Pet" Methods
|
|
bool LoadPet(); // Load and spawn bot pet if there is one
|
|
bool SavePet(); // Save and depop bot pet if there is one
|
|
bool DeletePet();
|
|
|
|
public:
|
|
|
|
int32 CalcItemATKCap() final;
|
|
};
|
|
|
|
bool IsSpellInBotList(DBbotspells_Struct* spell_list, uint16 spell_id);
|
|
|
|
#endif // BOT_H
|