mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 22:01:30 +00:00
Need to increase from int16 to int32 when calculating focus due it causing issues with returning spell ids for some effects which can easily be over the int16 limit. CalcAAFocus and CalcFocusEffect were doing all math in int16 also, no reason not to increase to int32.
394 lines
16 KiB
C++
394 lines
16 KiB
C++
#ifndef MERC_H
|
|
#define MERC_H
|
|
|
|
#include "npc.h"
|
|
|
|
class Client;
|
|
class Corpse;
|
|
class Group;
|
|
class Mob;
|
|
class Raid;
|
|
struct MercTemplate;
|
|
struct NPCType;
|
|
struct NewSpawn_Struct;
|
|
|
|
namespace EQ
|
|
{
|
|
struct ItemData;
|
|
}
|
|
|
|
#define MAXMERCS 1
|
|
#define TANK 1
|
|
#define HEALER 2
|
|
#define MELEEDPS 9
|
|
#define CASTERDPS 12
|
|
|
|
#define NO_MERC_ID 0
|
|
#define MERC_STATE_NORMAL 5
|
|
#define MERC_STATE_SUSPENDED 1
|
|
#define NOT_SUSPENDED_TIME 0
|
|
|
|
const int MercAISpellRange = 100; // TODO: Write a method that calcs what the merc's spell range is based on spell, equipment, AA, whatever and replace this
|
|
|
|
struct MercSpell {
|
|
uint16 spellid; // <= 0 = no spell
|
|
uint32 type; // 0 = never, must be one (and only one) of the defined values
|
|
int16 stance; // 0 = all, + = only this stance, - = all except this stance
|
|
int16 slot;
|
|
uint16 proc_chance;
|
|
uint32 time_cancast; // when we can cast this spell next
|
|
};
|
|
|
|
struct MercTimer {
|
|
uint16 timerid; // EndurTimerIndex
|
|
uint8 timertype; // 1 = spell, 2 = disc
|
|
uint16 spellid; // <= 0 = no spell
|
|
uint32 time_cancast; // when we can cast this spell next
|
|
};
|
|
|
|
class Merc : public NPC {
|
|
public:
|
|
Merc(const NPCType* d, float x, float y, float z, float heading);
|
|
virtual ~Merc();
|
|
|
|
//abstract virtual function implementations requird by base abstract class
|
|
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQ::skills::SkillType attack_skill);
|
|
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None);
|
|
virtual bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
|
|
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr);
|
|
virtual bool HasRaid() { return false; }
|
|
virtual bool HasGroup() { return (GetGroup() ? true : false); }
|
|
virtual Raid* GetRaid() { return 0; }
|
|
virtual Group* GetGroup() { return entity_list.GetGroupByMob(this); }
|
|
|
|
// Mob AI Virtual Override Methods
|
|
virtual void AI_Start(int32 iMoveDelay = 0);
|
|
virtual void AI_Stop();
|
|
virtual void AI_Process();
|
|
|
|
//virtual bool AICastSpell(Mob* tar, int8 iChance, uint32 iSpellTypes);
|
|
virtual bool AICastSpell(int8 iChance, uint32 iSpellTypes);
|
|
virtual bool AIDoSpellCast(uint16 spellid, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
|
|
virtual bool AI_EngagedCastCheck();
|
|
//virtual bool AI_PursueCastCheck();
|
|
virtual bool AI_IdleCastCheck();
|
|
|
|
virtual bool Process();
|
|
|
|
// Static Merc Group Methods
|
|
static bool AddMercToGroup(Merc* merc, Group* group);
|
|
static bool RemoveMercFromGroup(Merc* merc, Group* group);
|
|
void ProcessClientZoneChange(Client* mercOwner);
|
|
static void MercGroupSay(Mob *speaker, const char *msg, ...);
|
|
Corpse* GetGroupMemberCorpse();
|
|
|
|
// Merc Spell Casting Methods
|
|
virtual int32 GetActSpellCost(uint16 spell_id, int32 cost);
|
|
int8 GetChanceToCastBySpellType(uint32 spellType);
|
|
void SetSpellRecastTimer(uint16 timer_id, uint16 spellid, uint32 recast_delay);
|
|
void SetDisciplineRecastTimer(uint16 timer_id, uint16 spellid, uint32 recast_delay);
|
|
void SetSpellTimeCanCast(uint16 spellid, uint32 recast_delay);
|
|
static int32 GetSpellRecastTimer(Merc *caster, uint16 timer_id);
|
|
static bool CheckSpellRecastTimers(Merc *caster, uint16 spellid);
|
|
static int32 GetDisciplineRecastTimer(Merc *caster, uint16 timer_id);
|
|
static bool CheckDisciplineRecastTimers(Merc *caster, uint16 spell_id, uint16 timer_id);
|
|
static int32 GetDisciplineRemainingTime(Merc *caster, uint16 timer_id);
|
|
static std::list<MercSpell> GetMercSpellsForSpellEffect(Merc* caster, int spellEffect);
|
|
static std::list<MercSpell> GetMercSpellsForSpellEffectAndTargetType(Merc* caster, int spellEffect, SpellTargetType targetType);
|
|
static std::list<MercSpell> GetMercSpellsBySpellType(Merc* caster, uint32 spellType);
|
|
static MercSpell GetFirstMercSpellBySpellType(Merc* caster, uint32 spellType);
|
|
static MercSpell GetFirstMercSpellForSingleTargetHeal(Merc* caster);
|
|
static MercSpell GetMercSpellBySpellID(Merc* caster, uint16 spellid);
|
|
static MercSpell GetBestMercSpellForVeryFastHeal(Merc* caster);
|
|
static MercSpell GetBestMercSpellForFastHeal(Merc* caster);
|
|
static MercSpell GetBestMercSpellForHealOverTime(Merc* caster);
|
|
static MercSpell GetBestMercSpellForPercentageHeal(Merc* caster);
|
|
static MercSpell GetBestMercSpellForRegularSingleTargetHeal(Merc* caster);
|
|
static MercSpell GetBestMercSpellForGroupHealOverTime(Merc* caster);
|
|
static MercSpell GetBestMercSpellForGroupCompleteHeal(Merc* caster);
|
|
static MercSpell GetBestMercSpellForGroupHeal(Merc* caster);
|
|
static MercSpell GetBestMercSpellForAETaunt(Merc* caster);
|
|
static MercSpell GetBestMercSpellForTaunt(Merc* caster);
|
|
static MercSpell GetBestMercSpellForHate(Merc* caster);
|
|
static MercSpell GetBestMercSpellForCure(Merc* caster, Mob* target);
|
|
static MercSpell GetBestMercSpellForStun(Merc* caster);
|
|
static MercSpell GetBestMercSpellForAENuke(Merc* caster, Mob* target);
|
|
static MercSpell GetBestMercSpellForTargetedAENuke(Merc* caster, Mob* target);
|
|
static MercSpell GetBestMercSpellForPBAENuke(Merc* caster, Mob* target);
|
|
static MercSpell GetBestMercSpellForAERainNuke(Merc* caster, Mob* target);
|
|
static MercSpell GetBestMercSpellForNuke(Merc* caster);
|
|
static MercSpell GetBestMercSpellForNukeByTargetResists(Merc* caster, Mob* target);
|
|
static bool CheckAENuke(Merc* caster, Mob* tar, uint16 spell_id, uint8 &numTargets);
|
|
static bool GetNeedsCured(Mob *tar);
|
|
bool HasOrMayGetAggro();
|
|
bool UseDiscipline(int32 spell_id, int32 target);
|
|
|
|
virtual bool IsMerc() const { return true; }
|
|
|
|
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
|
|
static Merc* LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, bool updateFromDB = false);
|
|
void UpdateMercInfo(Client *c);
|
|
void UpdateMercStats(Client *c, bool setmax = false);
|
|
void UpdateMercAppearance();
|
|
virtual void UpdateEquipmentLight();
|
|
void AddItem(uint8 slot, uint32 item_id);
|
|
static const char *GetRandomName();
|
|
bool Spawn(Client *owner);
|
|
bool Suspend();
|
|
bool Unsuspend(bool setMaxStats);
|
|
bool MercJoinClientGroup();
|
|
void Zone();
|
|
virtual void Depop();
|
|
virtual bool Save();
|
|
bool GetDepop() { return p_depop; }
|
|
|
|
bool IsDead() { return GetHP() < 0;};
|
|
bool IsMedding() { return _medding; };
|
|
bool IsSuspended() { return _suspended; };
|
|
|
|
static uint32 CalcPurchaseCost( uint32 templateID , uint8 level, uint8 currency_type = 0);
|
|
static uint32 CalcUpkeepCost( uint32 templateID , uint8 level, uint8 currency_type = 0);
|
|
|
|
// "GET" Class Methods
|
|
virtual Mob* GetOwner();
|
|
Client* GetMercOwner();
|
|
virtual Mob* GetOwnerOrSelf();
|
|
uint32 GetMercID() { return _MercID; }
|
|
uint32 GetMercCharacterID( ) { return owner_char_id; }
|
|
uint32 GetMercTemplateID() { return _MercTemplateID; }
|
|
uint32 GetMercType() { return _MercType; }
|
|
uint32 GetMercSubType() { return _MercSubType; }
|
|
uint8 GetProficiencyID() { return _ProficiencyID; }
|
|
uint8 GetTierID() { return _TierID; }
|
|
uint32 GetCostFormula() { return _CostFormula; }
|
|
uint32 GetMercNameType() { return _NameType; }
|
|
EQ::constants::StanceType GetStance() { return _currentStance; }
|
|
int GetHatedCount() { return _hatedCount; }
|
|
|
|
inline const uint8 GetClientVersion() const { return _OwnerClientVersion; }
|
|
|
|
virtual void SetTarget(Mob* mob);
|
|
bool HasSkill(EQ::skills::SkillType skill_id) const;
|
|
bool CanHaveSkill(EQ::skills::SkillType skill_id) const;
|
|
uint16 MaxSkill(EQ::skills::SkillType skillid, uint16 class_, uint16 level) const;
|
|
inline uint16 MaxSkill(EQ::skills::SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); }
|
|
virtual void DoClassAttacks(Mob *target);
|
|
void CheckHateList();
|
|
bool CheckTaunt();
|
|
bool CheckAETaunt();
|
|
bool CheckConfidence();
|
|
bool TryHide();
|
|
|
|
// stat functions
|
|
virtual void ScaleStats(int scalepercent, bool setmax = false);
|
|
virtual void CalcBonuses();
|
|
int32 GetEndurance() const {return cur_end;} //This gets our current endurance
|
|
inline uint8 GetEndurancePercent() { return (uint8)((float)cur_end / (float)max_end * 100.0f); }
|
|
inline virtual int32 GetATK() const { return ATK; }
|
|
inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
|
|
int32 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 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; }
|
|
// 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 virtual int32 GetHealAmt() const { return itembonuses.HealAmt; }
|
|
inline virtual int32 GetSpellDmg() const { 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; }
|
|
|
|
// "SET" Class Methods
|
|
void SetMercData (uint32 templateID );
|
|
void SetMercID( uint32 mercID ) { _MercID = mercID; }
|
|
void SetMercCharacterID( uint32 ownerID ) { owner_char_id = ownerID; }
|
|
void SetMercTemplateID( uint32 templateID ) { _MercTemplateID = templateID; }
|
|
void SetMercType( uint32 type ) { _MercType = type; }
|
|
void SetMercSubType( uint32 subtype ) { _MercSubType = subtype; }
|
|
void SetProficiencyID( uint8 proficiency_id ) { _ProficiencyID = proficiency_id; }
|
|
void SetTierID( uint8 tier_id ) { _TierID = tier_id; }
|
|
void SetCostFormula( uint8 costformula ) { _CostFormula = costformula; }
|
|
void SetMercNameType( uint8 nametype ) { _NameType = nametype; }
|
|
void SetClientVersion(uint8 clientVersion) { _OwnerClientVersion = clientVersion; }
|
|
void SetSuspended(bool suspended) { _suspended = suspended; }
|
|
void SetStance( EQ::constants::StanceType stance ) { _currentStance = stance; }
|
|
void SetHatedCount( int count ) { _hatedCount = count; }
|
|
|
|
void Sit();
|
|
void Stand();
|
|
bool IsSitting();
|
|
bool IsStanding();
|
|
|
|
// Merc-specific functions
|
|
bool IsMercCaster() { return (GetClass() == HEALER || GetClass() == CASTERDPS); }
|
|
bool IsMercCasterCombatRange(Mob *target);
|
|
virtual float GetMaxMeleeRangeToTarget(Mob* target);
|
|
virtual void MercMeditate(bool isSitting);
|
|
bool FindTarget();
|
|
|
|
protected:
|
|
void CalcItemBonuses(StatBonuses* newbon);
|
|
void AddItemBonuses(const EQ::ItemData *item, StatBonuses* newbon);
|
|
int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat);
|
|
|
|
int32 GetFocusEffect(focusType type, uint16 spell_id);
|
|
|
|
std::vector<MercSpell> merc_spells;
|
|
std::map<uint32,MercTimer> timers;
|
|
|
|
Timer evade_timer; // can be moved to pTimers at some point
|
|
|
|
uint16 skills[EQ::skills::HIGHEST_SKILL + 1];
|
|
uint32 equipment[EQ::invslot::EQUIPMENT_COUNT]; //this is an array of item IDs
|
|
uint16 d_melee_texture1; //this is an item Material value
|
|
uint16 d_melee_texture2; //this is an item Material value (offhand)
|
|
uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation
|
|
uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation
|
|
|
|
private:
|
|
|
|
int32 CalcAC();
|
|
int32 GetACMit();
|
|
int32 GetACAvoid();
|
|
int32 acmod();
|
|
int32 CalcATK();
|
|
//int CalcHaste();
|
|
|
|
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();
|
|
int32 CalcMaxHP();
|
|
int32 CalcBaseHP();
|
|
int32 GetClassHPFactor();
|
|
int32 CalcHPRegen();
|
|
int32 CalcHPRegenCap();
|
|
int32 CalcMaxMana();
|
|
int32 CalcBaseMana();
|
|
int32 CalcManaRegen();
|
|
int32 CalcBaseManaRegen();
|
|
int32 CalcManaRegenCap();
|
|
void CalcMaxEndurance(); //This calculates the maximum endurance we can have
|
|
int32 CalcBaseEndurance(); //Calculates Base End
|
|
int32 GetMaxEndurance() const {return max_end;} //This gets our endurance from the last CalcMaxEndurance() call
|
|
int32 CalcEnduranceRegen(); //Calculates endurance regen used in DoEnduranceRegen()
|
|
int32 CalcEnduranceRegenCap();
|
|
void SetEndurance(int32 newEnd); //This sets the current endurance to the new value
|
|
void DoEnduranceUpkeep(); //does the endurance upkeep
|
|
void CalcRestState();
|
|
|
|
int GroupLeadershipAAHealthEnhancement();
|
|
int GroupLeadershipAAManaEnhancement();
|
|
int GroupLeadershipAAHealthRegeneration();
|
|
int GroupLeadershipAAOffenseEnhancement();
|
|
|
|
float GetDefaultSize();
|
|
|
|
bool LoadMercSpells();
|
|
bool CheckStance(int16 stance);
|
|
std::vector<MercSpell> GetMercSpells() { return merc_spells; }
|
|
|
|
// Private "base stats" Members
|
|
int32 base_mana;
|
|
int32 base_end;
|
|
int32 _baseAC;
|
|
uint32 _baseSTR;
|
|
uint32 _baseSTA;
|
|
uint32 _baseDEX;
|
|
uint32 _baseAGI;
|
|
uint32 _baseINT;
|
|
uint32 _baseWIS;
|
|
uint32 _baseCHA;
|
|
uint32 _baseATK;
|
|
uint32 _baseRace; // Necessary to preserve the race otherwise mercs get their race updated in the db when they get an illusion.
|
|
uint8 _baseGender; // Merc gender. Necessary to preserve the original value otherwise it can be changed by illusions.
|
|
uint32 _baseMR;
|
|
uint32 _baseCR;
|
|
uint32 _baseDR;
|
|
uint32 _baseFR;
|
|
uint32 _basePR;
|
|
uint32 _baseCorrup;
|
|
uint32 RestRegenHP;
|
|
uint32 RestRegenMana;
|
|
uint32 RestRegenEndurance;
|
|
|
|
uint32 _MercID;
|
|
uint32 _MercTemplateID;
|
|
uint32 _MercType;
|
|
uint32 _MercSubType;
|
|
uint8 _ProficiencyID;
|
|
uint8 _TierID;
|
|
uint8 _CostFormula;
|
|
uint8 _NameType;
|
|
uint8 _OwnerClientVersion;
|
|
EQ::constants::StanceType _currentStance;
|
|
|
|
EQ::InventoryProfile m_inv;
|
|
int32 max_end;
|
|
int32 cur_end;
|
|
bool _medding;
|
|
bool _suspended;
|
|
bool p_depop;
|
|
bool _check_confidence;
|
|
bool _lost_confidence;
|
|
int _hatedCount;
|
|
uint32 owner_char_id;
|
|
Timer endupkeep_timer;
|
|
Timer rest_timer;
|
|
Timer confidence_timer;
|
|
Timer check_target_timer;
|
|
};
|
|
|
|
#endif // MERC_H
|