[Bot/Merc] Cleanup methods, and virtual overrides. (#2734)

* [Bot] Cleanup methods, and virtual overrides.

* Remove Bot::CheckAggroAmount & Bot::CheckHealAggroAmount

* formatting
This commit is contained in:
Aeadoin 2023-01-14 23:32:19 -05:00 committed by GitHub
parent a422484307
commit 403c54362e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 145 additions and 480 deletions

View File

@ -80,7 +80,7 @@ void Aura::ProcessOnAllFriendlies(Mob *owner)
if (!mob) {
continue;
}
if (mob->IsClient() || mob->IsPetOwnerClient() || mob->IsMerc()) {
if (mob->IsClient() || mob->IsPetOwnerClient() || mob->IsMerc() || mob->IsBot()) {
auto it = casted_on.find(mob->GetID());
if (it != casted_on.end()) { // we are already on the list, let's check for removal

View File

@ -5320,11 +5320,6 @@ void Bot::Damage(Mob *from, int64 damage, uint16 spell_id, EQ::skills::SkillType
}
}
//void Bot::AddToHateList(Mob* other, int64 hate = 0, int64 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false)
void Bot::AddToHateList(Mob* other, int64 hate, int64 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic, bool pet_command) {
Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic, pet_command);
}
bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) {
if (!other) {
SetTarget(nullptr);
@ -6134,20 +6129,6 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
classattack_timer.Start(reuse / HasteModifier);
}
int32 Bot::CheckAggroAmount(uint16 spellid) {
int32 AggroAmount = Mob::CheckAggroAmount(spellid, nullptr);
int64 focusAggro = GetFocusEffect(focusSpellHateMod, spellid);
AggroAmount = (AggroAmount * (100 + focusAggro) / 100);
return AggroAmount;
}
int32 Bot::CheckHealAggroAmount(uint16 spellid, Mob *target, uint32 heal_possible) {
int32 AggroAmount = Mob::CheckHealAggroAmount(spellid, target, heal_possible);
int64 focusAggro = GetFocusEffect(focusSpellHateMod, spellid);
AggroAmount = (AggroAmount * (100 + focusAggro) / 100);
return AggroAmount;
}
void Bot::MakePet(uint16 spell_id, const char* pettype, const char *petname) {
Mob::MakePet(spell_id, pettype, petname);
}
@ -6415,276 +6396,6 @@ void Bot::SetAttackTimer() {
}
}
int64 Bot::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target) {
if (target == nullptr)
target = this;
int64 base_value = value;
int16 critical_chance = 0;
int8 critical_modifier = 1;
if (spells[spell_id].buff_duration < 1) {
critical_chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance;
if (spellbonuses.CriticalHealDecay) {
critical_chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
}
}
else {
critical_chance = itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime;
if (spellbonuses.CriticalRegenDecay) {
critical_chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay);
}
}
if (critical_chance) {
if (spells[spell_id].override_crit_chance > 0 && critical_chance > spells[spell_id].override_crit_chance) {
critical_chance = spells[spell_id].override_crit_chance;
}
if (zone->random.Roll(critical_chance)) {
critical_modifier = 2; //At present time no critical heal amount modifier SPA exists.
}
}
if (GetClass() == CLERIC) {
value += int(base_value*RuleI(Spells, ClericInnateHealFocus) / 100); //confirmed on live parsing clerics get an innate 5 pct heal focus
}
value += int(base_value*GetFocusEffect(focusImprovedHeal, spell_id) / 100);
value += int(base_value*GetFocusEffect(focusFcAmplifyMod, spell_id) / 100);
// Instant Heals
if (spells[spell_id].buff_duration < 1) {
/* Mob::GetFocusEffect is not accessible from this context. This focus effect was not accounted for in previous version of this method at all, either
if (target) {
value += int(base_value * target->GetFocusEffect(focusFcHealPctIncoming, spell_id, this)/100,nullptr); //SPA 393 Add before critical
value += int(base_value * target->GetFocusEffect(focusFcHealPctCritIncoming, spell_id, this)/100,nullptr); //SPA 395 Add before critical (?)
}
*/
value += GetFocusEffect(focusFcHealAmtCrit, spell_id); //SPA 396 Add before critical
//Using IgnoreSpellDmgLvlRestriction to also allow healing to scale
if ((RuleB(Spells, IgnoreSpellDmgLvlRestriction) || spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.HealAmt) {
value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, base_value);//Item Heal Amt Add before critical
}
if (target) {
value += value * target->GetHealRate() / 100; //SPA 120 modifies value after Focus Applied but before critical
}
/*
Apply critical hit modifier
*/
value *= critical_modifier;
value += GetFocusEffect(focusFcHealAmt, spell_id); //SPA 392 Add after critical
value += GetFocusEffect(focusFcAmplifyAmt, spell_id); //SPA 508 ? Add after critical
if (critical_modifier > 1) {
entity_list.MessageCloseString(
this, true, 100, Chat::SpellCrit,
OTHER_CRIT_HEAL, GetName(), itoa(value));
}
return value;
}
//Heal over time spells. [Heal Rate and Additional Healing effects do not increase this value]
else {
//Using IgnoreSpellDmgLvlRestriction to also allow healing to scale
if (RuleB(Spells, HOTsScaleWithHealAmt)) {
int duration = CalcBuffDuration(this, target, spell_id);
int32 extra_heal = 0;
if ((RuleB(Spells, IgnoreSpellDmgLvlRestriction) || spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.HealAmt) {
extra_heal += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, base_value);
}
if (duration > 0 && extra_heal > 0) {
extra_heal /= duration;
value += extra_heal;
}
}
if (critical_chance && zone->random.Roll(critical_chance))
value *= critical_modifier;
}
return value;
}
int32 Bot::GetActSpellCasttime(uint16 spell_id, int32 casttime) {
int64 cast_reducer = GetFocusEffect(focusSpellHaste, spell_id);
auto min_cap = casttime / 2;
uint8 botlevel = GetLevel();
uint8 botclass = GetClass();
if (botlevel >= 51 && casttime >= 3000 && !spells[spell_id].good_effect &&
(botclass == SHADOWKNIGHT || botclass == RANGER || botclass == PALADIN || botclass == BEASTLORD)) {
int level_mod = std::min(15, botlevel - 50);
cast_reducer += level_mod * 3;
}
if((casttime >= 4000) && BeneficialSpell(spell_id) && IsBuffSpell(spell_id)) {
switch (GetAA(aaSpellCastingDeftness)) {
case 1:
cast_reducer += 5;
break;
case 2:
cast_reducer += 10;
break;
case 3:
cast_reducer += 25;
break;
}
switch (GetAA(aaQuickBuff)) {
case 1:
cast_reducer += 10;
break;
case 2:
cast_reducer += 25;
break;
case 3:
cast_reducer += 50;
break;
}
}
if(IsSummonSpell(spell_id)) {
switch (GetAA(aaQuickSummoning)) {
case 1:
cast_reducer += 10;
break;
case 2:
cast_reducer += 25;
break;
case 3:
cast_reducer += 50;
break;
}
}
if(IsEvacSpell(spell_id)) {
switch (GetAA(aaQuickEvacuation)) {
case 1:
cast_reducer += 10;
break;
case 2:
cast_reducer += 25;
break;
case 3:
cast_reducer += 50;
break;
}
}
if(IsDamageSpell(spell_id) && spells[spell_id].cast_time >= 4000) {
switch (GetAA(aaQuickDamage)) {
case 1:
cast_reducer += 2;
break;
case 2:
cast_reducer += 5;
break;
case 3:
cast_reducer += 10;
break;
}
}
casttime = casttime * (100 - cast_reducer) / 100;
return std::max(casttime, min_cap);
}
int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) {
if(itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) {
int32 mana_back = (itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100);
if(mana_back > cost)
mana_back = cost;
cost -= mana_back;
}
float PercentManaReduction = 0;
float SpecializeSkill = GetSpecializeSkillValue(spell_id);
int SuccessChance = zone->random.Int(0, 100);
float bonus = 1.0;
switch(GetAA(aaSpellCastingMastery)) {
case 1:
bonus += 0.05;
break;
case 2:
bonus += 0.15;
break;
case 3:
bonus += 0.30;
break;
}
bonus += (0.05 * GetAA(aaAdvancedSpellCastingMastery));
if(SuccessChance <= (SpecializeSkill * 0.3 * bonus)) {
PercentManaReduction = (1 + 0.05 * SpecializeSkill);
switch(GetAA(aaSpellCastingMastery)) {
case 1:
PercentManaReduction += 2.5;
break;
case 2:
PercentManaReduction += 5.0;
break;
case 3:
PercentManaReduction += 10.0;
break;
}
switch(GetAA(aaAdvancedSpellCastingMastery)) {
case 1:
PercentManaReduction += 2.5;
break;
case 2:
PercentManaReduction += 5.0;
break;
case 3:
PercentManaReduction += 10.0;
break;
}
}
int64 focus_redux = GetFocusEffect(focusManaCost, spell_id);
if(focus_redux > 0)
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
cost -= (cost * (PercentManaReduction / 100));
if(focus_redux >= 100) {
uint32 buff_max = GetMaxTotalSlots();
for (int buffSlot = 0; buffSlot < buff_max; buffSlot++) {
if (buffs[buffSlot].spellid == 0 || buffs[buffSlot].spellid >= SPDAT_RECORDS)
continue;
if(IsEffectInSpell(buffs[buffSlot].spellid, SE_ReduceManaCost)) {
if(CalcFocusEffect(focusManaCost, buffs[buffSlot].spellid, spell_id) == 100)
cost = 1;
}
}
}
if(cost < 0)
cost = 0;
return cost;
}
float Bot::GetActSpellRange(uint16 spell_id, float range) {
float extrange = 100;
extrange += GetFocusEffect(focusRange, spell_id);
return ((range * extrange) / 100);
}
int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) {
int increase = 100;
increase += GetFocusEffect(focusSpellDuration, spell_id);

View File

@ -144,15 +144,17 @@ public:
Bot(NPCType *npcTypeData, Client* botOwner);
Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData);
//abstract virtual function implementations requird by base abstract class
virtual bool Death(Mob* killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill);
virtual void Damage(Mob* from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None);
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 (GetRaid() ? true : false); }
virtual bool HasGroup() { return (GetGroup() ? true : false); }
virtual Raid* GetRaid() { return entity_list.GetRaidByMob(this); }
virtual Group* GetGroup() { return entity_list.GetGroupByMob(this); }
//abstract virtual override function implementations requird by base abstract class
bool Death(Mob* killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill) 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 Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false,
ExtraAttackOptions *opts = nullptr) override;
bool HasRaid() override { return (GetRaid() ? true : false); }
bool HasGroup() override { return (GetGroup() ? true : false); }
Raid* GetRaid() override { return entity_list.GetRaidByMob(this); }
Group* GetGroup() override { return entity_list.GetGroupByMob(this); }
// Common, but informal "interfaces" with Client object
uint32 CharacterID() { return GetBotID(); } // Just returns the Bot Id
@ -167,71 +169,68 @@ public:
bool IsValidName();
static bool IsValidName(std::string& name);
bool Spawn(Client* botCharacterOwner);
virtual void SetLevel(uint8 in_level, bool command = false);
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
virtual bool Process();
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);
virtual bool Save();
virtual void Depop();
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; }
virtual float GetProcChances(float ProcBonus, uint16 hand);
virtual int GetHandToHandDamage(void);
virtual bool TryFinishingBlow(Mob *defender, int64 &damage);
virtual void DoRiposte(Mob* defender);
inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(EQ::skills::SkillOffense)) * 9 / 10); }
inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
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() const override { 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) const { return MaxSkill(skillid, GetClass(), GetLevel()); }
virtual int GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target = nullptr);
virtual 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);
virtual void TryBackstab(Mob *other,int ReuseTime = 10);
virtual void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10);
virtual void RogueAssassinate(Mob* other);
virtual void DoClassAttacks(Mob *target, bool IsRiposte=false);
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 TryBackstab(Mob *other,int ReuseTime = 10) override;
void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10) override;
void RogueAssassinate(Mob* other) override;
void DoClassAttacks(Mob *target, bool IsRiposte=false);
bool CanDoSpecialAttack(Mob *other);
virtual int32 CheckAggroAmount(uint16 spellid);
virtual void CalcBonuses();
void CalcBonuses() override;
void CalcItemBonuses(StatBonuses* newbon);
void AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0);
int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat);
virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr);
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther);
inline virtual bool IsPet() { return false; }
virtual bool IsNPC() const { return false; }
virtual Mob* GetOwner();
virtual Mob* GetOwnerOrSelf();
inline virtual bool HasOwner() { return (GetBotOwner() ? true : false); }
virtual int32 CheckHealAggroAmount(uint16 spellid, Mob *target, uint32 heal_possible = 0);
virtual int64 CalcMaxMana();
virtual void SetAttackTimer();
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() ? true : false); }
int64 CalcMaxMana() override;
void SetAttackTimer() override;
uint64 GetClassHPFactor();
virtual int64 CalcMaxHP();
int64 CalcMaxHP() override;
bool DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQ::spells::CastingSlot slot, bool &stopLogic);
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 SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color);
void Camp(bool save_to_database = true);
virtual void AddToHateList(Mob* other, int64 hate = 0, int64 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false, bool pet_command = false);
virtual void SetTarget(Mob* mob);
virtual void Zone();
void SetTarget(Mob* mob) override;
void Zone();
bool IsArcheryRange(Mob* target);
void ChangeBotArcherWeapons(bool isArcher);
void Sit();
void Stand();
bool IsSitting();
bool IsStanding();
virtual int GetWalkspeed() const { return (int)((float)_GetWalkSpeed() * 1.785714285f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143
virtual int GetRunspeed() const { return (int)((float)_GetRunSpeed() * 1.785714285f); }
virtual void WalkTo(float x, float y, float z);
virtual void RunTo(float x, float y, float z);
virtual void StopMoving();
virtual void StopMoving(float new_heading);
int GetWalkspeed() const override { return (int)((float)_GetWalkSpeed() * 1.785714285f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143
int GetRunspeed() const override { return (int)((float)_GetRunSpeed() * 1.785714285f); }
void WalkTo(float x, float y, float z) override;
void RunTo(float x, float y, float z) override;
void StopMoving() override;
void StopMoving(float new_heading) override;
//bool GetCombatJitterFlag() { return m_combat_jitter_flag; }
bool GetGuardFlag() { return m_guard_flag; }
void SetGuardFlag(bool flag = true) { m_guard_flag = flag; }
@ -342,10 +341,10 @@ public:
void AI_Bot_Event_SpellCastFinished(bool iCastSucceeded, uint16 slot);
// AI Methods
virtual bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes);
virtual bool AI_EngagedCastCheck();
virtual bool AI_PursueCastCheck();
virtual bool AI_IdleCastCheck();
bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes);
bool AI_EngagedCastCheck() override;
bool AI_PursueCastCheck() override;
bool AI_IdleCastCheck() override;
bool AIHealRotation(Mob* tar, bool useFastHeals);
bool GetPauseAI() { return _pauseAI; }
void SetPauseAI(bool pause_flag) { _pauseAI = pause_flag; }
@ -359,25 +358,22 @@ public:
void AI_Bot_Start(uint32 iMoveDelay = 0);
// Mob AI Virtual Override Methods
virtual void AI_Process();
virtual void AI_Stop();
void AI_Process() override;
void AI_Stop() override;
// Mob Spell Virtual Override Methods
virtual void SpellProcess();
virtual int64 GetActSpellHealing(uint16 spell_id, int64 value, Mob* target = nullptr);
virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
virtual int32 GetActSpellCost(uint16 spell_id, int32 cost);
virtual float GetActSpellRange(uint16 spell_id, float range);
virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration);
virtual float GetAOERange(uint16 spell_id);
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);
virtual void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr);
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);
uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr, uint32 aa_id = 0);
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar);
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
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 = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0);
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 = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0);
bool GetBotOwnerDataBuckets();
bool GetBotDataBuckets();
@ -387,7 +383,7 @@ public:
void BotTradeAddItem(const EQ::ItemInstance* inst, uint16 slot_id, std::string* error_message, bool save_to_database = true);
void EquipBot(std::string* error_message);
bool CheckLoreConflict(const EQ::ItemData* item);
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]); }
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() { return m_inv; }
// Static Class Methods
@ -464,12 +460,12 @@ public:
Mob* GetBotOwner() { return this->_botOwner; }
uint32 GetBotArcheryRange();
EQ::ItemInstance* GetBotItem(uint16 slot_id);
virtual bool GetSpawnStatus() { return _spawnStatus; }
bool GetSpawnStatus() { return _spawnStatus; }
uint8 GetPetChooserID() { return _petChooserID; }
bool IsPetChooser() { return _petChooser; }
bool IsBotArcher() { return m_bot_archery_setting; }
bool IsBotCharmer() { return _botCharmer; }
virtual bool IsBot() const { return true; }
bool IsBot() const override { return true; }
bool GetRangerAutoWeaponSelect() { return _rangerAutoWeaponSelect; }
BotRoleType GetBotRole() { return _botRole; }
EQ::constants::StanceType GetBotStance() { return _botStance; }
@ -524,32 +520,32 @@ public:
bool GetAltOutOfCombatBehavior() { return _altoutofcombatbehavior;}
bool GetShowHelm() { return _showhelm; }
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 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 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 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; }
@ -593,7 +589,7 @@ public:
// "SET" Class Methods
void SetBotSpellID(uint32 newSpellID);
virtual void SetSpawnStatus(bool spawnStatus) { _spawnStatus = spawnStatus; }
void SetSpawnStatus(bool spawnStatus) { _spawnStatus = spawnStatus; }
void SetPetChooserID(uint8 id) { _petChooserID = id; }
void SetBotArcherySetting(bool bot_archer_setting, bool save = false);
void SetBotCharmer(bool c) { _botCharmer = c; }
@ -645,10 +641,10 @@ public:
std::string CreateSayLink(Client* botOwner, const char* message, const char* name);
// Class Destructors
virtual ~Bot();
~Bot() override;
// Publicized protected functions
virtual void BotRangedAttack(Mob* other);
void BotRangedAttack(Mob* other);
// Publicized private functions
static NPCType *FillNPCTypeStruct(
@ -734,11 +730,11 @@ public:
void OwnerMessage(std::string message);
protected:
virtual void PetAIProcess();
virtual void BotMeditate(bool isSitting);
virtual bool CheckBotDoubleAttack(bool Triple = false);
virtual void PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* client);
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
void PetAIProcess();
void BotMeditate(bool isSitting);
bool CheckBotDoubleAttack(bool Triple = false);
void PerformTradeWithClient(int16 begin_slot_id, int16 end_slot_id, Client* client);
bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0) override;
BotCastingRoles& GetCastingRoles() { return m_CastingRoles; }
void SetGroupHealer(bool flag = true) { m_CastingRoles.GroupHealer = flag; }

View File

@ -559,7 +559,6 @@ public:
inline virtual int32 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath + 11; }
int32 GetActSpellCost(uint16 spell_id, int32);
virtual bool CheckFizzle(uint16 spell_id);
virtual bool CheckSpellLevelRestriction(uint16 spell_id);
virtual int GetCurrentBuffSlots() const;

View File

@ -31,7 +31,7 @@
#include "../common/zone_store.h"
#include "position.h"
float Mob::GetActSpellRange(uint16 spell_id, float range, bool IsBard)
float Mob::GetActSpellRange(uint16 spell_id, float range)
{
float extrange = 100;
@ -317,7 +317,9 @@ int64 Mob::GetExtraSpellAmt(uint16 spell_id, int64 extra_spell_amt, int64 base_s
}
int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool from_buff_tic) {
if (target == nullptr && IsBot()) {
target = this;
}
if (IsNPC()) {
value += value * CastToNPC()->GetSpellFocusHeal() / 100;
@ -443,7 +445,7 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr
}
int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
int32 Mob::GetActSpellCost(uint16 spell_id, int32 cost)
{
//FrenziedDevastation doubles mana cost of all DD spells
int16 FrenziedDevastation = itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation;

View File

@ -2706,53 +2706,6 @@ int64 Merc::GetFocusEffect(focusType type, uint16 spell_id, bool from_buff_tic)
return realTotal + realTotal2 + realTotal3;
}
int32 Merc::GetActSpellCost(uint16 spell_id, int32 cost)
{
// Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell
if(itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5)
{
int mana_back = itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100;
// Doesnt generate mana, so best case is a free spell
if(mana_back > cost)
mana_back = cost;
cost -= mana_back;
}
// This formula was derived from the following resource:
// http://www.eqsummoners.com/eq1/specialization-library.html
// WildcardX
float PercentManaReduction = 0;
int16 focus_redux = GetFocusEffect(focusManaCost, spell_id);
if(focus_redux > 0)
{
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
}
cost -= (cost * (PercentManaReduction / 100));
// Gift of Mana - reduces spell cost to 1 mana
if(focus_redux >= 100) {
uint32 buff_max = GetMaxTotalSlots();
for (int buffSlot = 0; buffSlot < buff_max; buffSlot++) {
if (buffs[buffSlot].spellid == 0 || buffs[buffSlot].spellid >= SPDAT_RECORDS)
continue;
if(IsEffectInSpell(buffs[buffSlot].spellid, SE_ReduceManaCost)) {
if(CalcFocusEffect(focusManaCost, buffs[buffSlot].spellid, spell_id) == 100)
cost = 1;
}
}
}
if(cost < 0)
cost = 0;
return cost;
}
int8 Merc::GetChanceToCastBySpellType(uint32 spellType) {
int mercStance = (int)GetStance();
int8 mercClass = GetClass();

View File

@ -83,7 +83,6 @@ public:
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);

View File

@ -322,13 +322,13 @@ public:
bool IsAISpellEffect = false, uint16 effect_id = 0, int32 se_base = 0, int32 se_limit = 0, int32 se_max = 0);
void NegateSpellEffectBonuses(uint16 spell_id);
bool NegateSpellEffect(uint16 spell_id, int effect_id);
virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false);
virtual int64 GetActSpellDamage(uint16 spell_id, int64 value, Mob* target = nullptr);
virtual int64 GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_buff_tic = true);
virtual int64 GetActSpellHealing(uint16 spell_id, int64 value, Mob* target = nullptr, bool from_buff_tic = false);
virtual int32 GetActSpellCost(uint16 spell_id, int32 cost){ return cost;}
float GetActSpellRange(uint16 spell_id, float range);
int64 GetActSpellDamage(uint16 spell_id, int64 value, Mob* target = nullptr);
int64 GetActDoTDamage(uint16 spell_id, int64 value, Mob* target, bool from_buff_tic = true);
int64 GetActSpellHealing(uint16 spell_id, int64 value, Mob* target = nullptr, bool from_buff_tic = false);
int32 GetActSpellCost(uint16 spell_id, int32 cost);
virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration);
virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
virtual int64 GetActReflectedSpellDamage(int32 spell_id, int64 value, int effectiveness);
float ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override = false,
int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false,
@ -710,7 +710,7 @@ public:
//AI
static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel);
inline uint32 GetLevelCon(uint8 iOtherLevel) const { return GetLevelCon(GetLevel(), iOtherLevel); }
virtual void AddToHateList(Mob* other, int64 hate = 0, int64 damage = 0, bool iYellForHelp = true,
void AddToHateList(Mob* other, int64 hate = 0, int64 damage = 0, bool iYellForHelp = true,
bool bFrenzy = false, bool iBuffTic = false, uint16 spell_id = SPELL_UNKNOWN, bool pet_comand = false);
bool RemoveFromHateList(Mob* mob);
void SetHateAmountOnEnt(Mob* other, int64 hate = 0, int64 damage = 0) { hate_list.SetHateAmountOnEnt(other,hate,damage);}
@ -1601,7 +1601,7 @@ protected:
virtual
#endif
int GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target = nullptr);
int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false);
virtual int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false);
virtual EQ::InventoryProfile& GetInv() { return m_inv; }
void CalculateNewFearpoint();
float FindGroundZ(float new_x, float new_y, float z_offset=0.0);

View File

@ -580,7 +580,7 @@ protected:
virtual bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes, bool bInnates = false);
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
AISpellsVar_Struct AISpellVar;
int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false);
int64 GetFocusEffect(focusType type, uint16 spell_id, Mob *caster = nullptr, bool from_buff_tic = false) override;
uint16 innate_proc_spell_id;
uint32 npc_spells_effects_id;

View File

@ -6373,8 +6373,8 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro
rand_effectiveness = true;
}
//Check if item focus effect exists for the client.
if (itembonuses.FocusEffects[type]){
//Check if item focus effect exists for the mob.
if (itembonuses.FocusEffects[type]) {
const EQ::ItemData* TempItem = nullptr;
const EQ::ItemData* UsedItem = nullptr;
@ -6384,12 +6384,13 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro
int32 focus_max_real = 0;
//item focus
for (int x = EQ::invslot::EQUIPMENT_BEGIN; x <= EQ::invslot::EQUIPMENT_END; x++)
{
for (int x = EQ::invslot::EQUIPMENT_BEGIN; x <= EQ::invslot::EQUIPMENT_END; x++) {
TempItem = nullptr;
EQ::ItemInstance* ins = GetInv().GetItem(x);
if (!ins)
if (!ins) {
continue;
}
TempItem = ins->GetItem();
if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) {
if(rand_effectiveness) {
@ -6418,12 +6419,10 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro
}
}
for (int y = EQ::invaug::SOCKET_BEGIN; y <= EQ::invaug::SOCKET_END; ++y)
{
for (int y = EQ::invaug::SOCKET_BEGIN; y <= EQ::invaug::SOCKET_END; ++y) {
EQ::ItemInstance *aug = nullptr;
aug = ins->GetAugment(y);
if(aug)
{
if (aug) {
const EQ::ItemData* TempItemAug = aug->GetItem();
if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) {
if(rand_effectiveness) {
@ -6456,16 +6455,17 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro
}
if (IsClient()) {
//Tribute Focus
for (int x = EQ::invslot::TRIBUTE_BEGIN; x <= EQ::invslot::TRIBUTE_END; ++x)
{
//Client Tribute Focus
for (int x = EQ::invslot::TRIBUTE_BEGIN; x <= EQ::invslot::TRIBUTE_END; ++x) {
TempItem = nullptr;
EQ::ItemInstance* ins = GetInv().GetItem(x);
if (!ins)
if (!ins) {
continue;
}
TempItem = ins->GetItem();
if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) {
if(rand_effectiveness) {
if (rand_effectiveness) {
focus_max = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id, true);
if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) {
focus_max_real = focus_max;
@ -6494,8 +6494,9 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro
}
}
if(UsedItem && rand_effectiveness && focus_max_real != 0)
if (UsedItem && rand_effectiveness && focus_max_real != 0) {
realTotal = CalcFocusEffect(type, UsedFocusID, spell_id);
}
if ((rand_effectiveness && UsedItem) || (realTotal != 0 && UsedItem)) {
// there are a crap ton more of these, I was able to verify these ones though
@ -6540,8 +6541,8 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro
}
}
//Check if spell focus effect exists for the client.
if (spellbonuses.FocusEffects[type]){
//Check if spell focus effect exists for the mob.
if (spellbonuses.FocusEffects[type]) {
//Spell Focus
int32 Total2 = 0;
@ -6555,10 +6556,11 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro
int buff_max = GetMaxTotalSlots();
for (buff_slot = 0; buff_slot < buff_max; buff_slot++) {
focusspellid = buffs[buff_slot].spellid;
if (focusspellid == 0 || focusspellid >= SPDAT_RECORDS)
if (focusspellid == 0 || focusspellid >= SPDAT_RECORDS) {
continue;
}
if(rand_effectiveness) {
if (rand_effectiveness) {
focus_max2 = CalcFocusEffect(type, focusspellid, spell_id, true, buffs[buff_slot].casterid, caster);
if (focus_max2 > 0 && focus_max_real2 >= 0 && focus_max2 > focus_max_real2) {
focus_max_real2 = focus_max2;
@ -6589,16 +6591,17 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro
original_caster_id = buffs[buff_tracker].casterid;
}
if(focusspell_tracker && rand_effectiveness && focus_max_real2 != 0)
if (focusspell_tracker && rand_effectiveness && focus_max_real2 != 0) {
realTotal2 = CalcFocusEffect(type, focusspell_tracker, spell_id, false, original_caster_id, caster);
}
if(!from_buff_tic && buff_tracker >= 0 && buffs[buff_tracker].hit_number > 0) {
if (!from_buff_tic && buff_tracker >= 0 && buffs[buff_tracker].hit_number > 0) {
CheckNumHitsRemaining(NumHit::MatchingSpells, buff_tracker);
}
}
// AA Focus
if (aabonuses.FocusEffects[type]){
if (aabonuses.FocusEffects[type]) {
int32 Total3 = 0;
@ -6607,12 +6610,13 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro
auto ability = ability_rank.first;
auto rank = ability_rank.second;
if(!ability) {
if (!ability) {
continue;
}
if (rank->effects.empty())
if (rank->effects.empty()) {
continue;
}
Total3 = CalcAAFocus(type, *rank, spell_id);
if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) {
@ -6624,15 +6628,17 @@ int64 Mob::GetFocusEffect(focusType type, uint16 spell_id, Mob *caster, bool fro
}
}
if(type == focusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id)))
if (type == focusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id))) {
return 0;
}
//Summon Spells that require reagents are typically imbue type spells, enchant metal, sacrifice and shouldn't be affected
//by reagent conservation for obvious reasons.
//Non-Live like feature to allow for an additive focus bonus to be applied from foci that are placed in worn slot. (No limit checks)
int32 worneffect_bonus = 0;
if (RuleB(Spells, UseAdditiveFocusFromWornSlot))
if (RuleB(Spells, UseAdditiveFocusFromWornSlot)) {
worneffect_bonus = itembonuses.FocusEffectsWorn[type];
}
return realTotal + realTotal2 + realTotal3 + worneffect_bonus;
}

View File

@ -739,8 +739,7 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp
ignore_if_npc_or_gm = true;
}
if (check_on_casting){
if (check_on_casting) {
if (spells[spell_id].target_type == ST_AEClientV1 ||
spells[spell_id].target_type == ST_AECaster ||
spells[spell_id].target_type == ST_Ring ||