mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-29 01:31:30 +00:00
[Spells] Added constant labeling to all StatBonuses that use as arrays. (#1485)
* constexpr labels added * more updates * more updates * completed * Update common.h * Namespace constants, few minor spelling tweaks Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
parent
72056ffba3
commit
38beb804a3
210
zone/attack.cpp
210
zone/attack.cpp
@ -87,7 +87,7 @@ EQ::skills::SkillType Mob::AttackAnimation(int Hand, const EQ::ItemInstance* wea
|
||||
break;
|
||||
case EQ::item::ItemType2HBlunt: // 2H Blunt
|
||||
skillinuse = EQ::skills::Skill2HBlunt;
|
||||
type = RuleB(Combat, Classic2HBAnimation) ? anim2HWeapon : anim2HSlashing;
|
||||
type = RuleB(Combat, Classic2HBAnimation) ? anim2HWeapon : anim2HSlashing;
|
||||
break;
|
||||
case EQ::item::ItemType2HPiercing: // 2H Piercing
|
||||
if (IsClient() && CastToClient()->ClientVersion() < EQ::versions::ClientVersion::RoF2)
|
||||
@ -265,7 +265,7 @@ int Mob::GetTotalDefense()
|
||||
auto evasion_bonus = spellbonuses.AvoidMeleeChanceEffect; // we check this first since it has a special case
|
||||
if (evasion_bonus >= 10000)
|
||||
return -1;
|
||||
|
||||
|
||||
// 515 SE_AC_Avoidance_Max_Percent
|
||||
auto ac_aviodance_bonus = itembonuses.AC_Avoidance_Max_Percent + aabonuses.AC_Avoidance_Max_Percent + spellbonuses.AC_Avoidance_Max_Percent;
|
||||
if (ac_aviodance_bonus)
|
||||
@ -870,7 +870,7 @@ int Mob::GetBestMeleeSkill()
|
||||
{ EQ::skills::Skill1HBlunt,
|
||||
EQ::skills::Skill1HSlashing,
|
||||
EQ::skills::Skill2HBlunt,
|
||||
EQ::skills::Skill2HSlashing,
|
||||
EQ::skills::Skill2HSlashing,
|
||||
EQ::skills::SkillHandtoHand,
|
||||
EQ::skills::Skill1HPiercing,
|
||||
EQ::skills::Skill2HPiercing,
|
||||
@ -1547,12 +1547,12 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
///////////////////////////////////////////////////////////
|
||||
////// Send Attack Damage
|
||||
///////////////////////////////////////////////////////////
|
||||
if (my_hit.damage_done > 0 && aabonuses.SkillAttackProc[0] && aabonuses.SkillAttackProc[1] == my_hit.skill &&
|
||||
IsValidSpell(aabonuses.SkillAttackProc[2])) {
|
||||
float chance = aabonuses.SkillAttackProc[0] / 1000.0f;
|
||||
if (my_hit.damage_done > 0 && aabonuses.SkillAttackProc[SBIndex::SKILLPROC_CHANCE] && aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SKILL] == my_hit.skill &&
|
||||
IsValidSpell(aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID])) {
|
||||
float chance = aabonuses.SkillAttackProc[SBIndex::SKILLPROC_CHANCE] / 1000.0f;
|
||||
if (zone->random.Roll(chance))
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], other, EQ::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[2]].ResistDiff);
|
||||
SpellFinished(aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID], other, EQ::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID]].ResistDiff);
|
||||
}
|
||||
other->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, my_hit.skill, true, -1, false, m_specialattacks);
|
||||
|
||||
@ -2746,9 +2746,9 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
if (damage > GetHP())
|
||||
damage = GetHP();
|
||||
|
||||
if (spellbonuses.ImprovedTaunt[1] && (GetLevel() < spellbonuses.ImprovedTaunt[0])
|
||||
&& other && (buffs[spellbonuses.ImprovedTaunt[2]].casterid != other->GetID()))
|
||||
hate = (hate*spellbonuses.ImprovedTaunt[1]) / 100;
|
||||
if (spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_AGGRO_MOD] && (GetLevel() < spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_MAX_LVL])
|
||||
&& other && (buffs[spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_BUFFSLOT]].casterid != other->GetID()))
|
||||
hate = (hate*spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_AGGRO_MOD]) / 100;
|
||||
|
||||
hate_list.AddEntToHateList(other, hate, damage, bFrenzy, !iBuffTic);
|
||||
|
||||
@ -2806,7 +2806,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
// owner must get on list, but he's not actually gained any hate yet
|
||||
if (
|
||||
!owner->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||
!(this->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && owner->IsClient()) &&
|
||||
!(this->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && owner->IsClient()) &&
|
||||
!(this->GetSpecialAbility(IMMUNE_AGGRO_NPC) && owner->IsNPC())
|
||||
) {
|
||||
if (owner->IsClient() && !CheckAggro(owner))
|
||||
@ -2818,9 +2818,9 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
|
||||
if (mypet && !mypet->IsHeld() && !mypet->IsPetStop()) { // I have a pet, add other to it
|
||||
if (
|
||||
!mypet->IsFamiliar() &&
|
||||
!mypet->IsFamiliar() &&
|
||||
!mypet->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||
!(mypet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && this->IsClient()) &&
|
||||
!(mypet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && this->IsClient()) &&
|
||||
!(mypet->GetSpecialAbility(IMMUNE_AGGRO_NPC) && this->IsNPC())
|
||||
) {
|
||||
mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
||||
@ -2828,9 +2828,9 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
}
|
||||
else if (myowner) { // I am a pet, add other to owner if it's NPC/LD
|
||||
if (
|
||||
myowner->IsAIControlled() &&
|
||||
myowner->IsAIControlled() &&
|
||||
!myowner->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||
!(this->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && myowner->IsClient()) &&
|
||||
!(this->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && myowner->IsClient()) &&
|
||||
!(this->GetSpecialAbility(IMMUNE_AGGRO_NPC) && myowner->IsNPC())
|
||||
) {
|
||||
myowner->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
||||
@ -2907,7 +2907,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) {
|
||||
int ds_mitigation = attacker->itembonuses.DSMitigation;
|
||||
// Subtract mitigations because DS_Mitigation_Percentage is a negative value when reducing total, thus final value will be positive
|
||||
ds_mitigation -= attacker->aabonuses.DS_Mitigation_Percentage + attacker->itembonuses.DS_Mitigation_Percentage + attacker->spellbonuses.DS_Mitigation_Percentage; //Negative value to reduce
|
||||
|
||||
|
||||
DS -= DS * ds_mitigation / 100;
|
||||
}
|
||||
attacker->Damage(this, -DS, spellid, EQ::skills::SkillAbjuration/*hackish*/, false);
|
||||
@ -3122,8 +3122,8 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
int32 slot = -1;
|
||||
bool DisableMeleeRune = false;
|
||||
|
||||
if (spellbonuses.NegateAttacks[0]) {
|
||||
slot = spellbonuses.NegateAttacks[1];
|
||||
if (spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_EXISTS]) {
|
||||
slot = spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_BUFFSLOT];
|
||||
if (slot >= 0) {
|
||||
if (--buffs[slot].numhits == 0) {
|
||||
|
||||
@ -3131,21 +3131,21 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
BuffFadeBySlot(slot, true);
|
||||
}
|
||||
|
||||
if (spellbonuses.NegateAttacks[2] && (damage > spellbonuses.NegateAttacks[2]))
|
||||
damage -= spellbonuses.NegateAttacks[2];
|
||||
if (spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_MAX_DMG_ABSORB_PER_HIT] && (damage > spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_MAX_DMG_ABSORB_PER_HIT]))
|
||||
damage -= spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_MAX_DMG_ABSORB_PER_HIT];
|
||||
else
|
||||
return DMG_RUNE;
|
||||
}
|
||||
}
|
||||
|
||||
//Only mitigate if damage is above the minimium specified.
|
||||
if (spellbonuses.MeleeThresholdGuard[0]) {
|
||||
slot = spellbonuses.MeleeThresholdGuard[1];
|
||||
if (spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT]) {
|
||||
slot = spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_BUFFSLOT];
|
||||
|
||||
if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2]))
|
||||
if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_MIN_DMG_TO_TRIGGER]))
|
||||
{
|
||||
DisableMeleeRune = true;
|
||||
int damage_to_reduce = damage * spellbonuses.MeleeThresholdGuard[0] / 100;
|
||||
int damage_to_reduce = damage * spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT] / 100;
|
||||
if (damage_to_reduce >= buffs[slot].melee_rune)
|
||||
{
|
||||
LogSpells("Mob::ReduceDamage SE_MeleeThresholdGuard [{}] damage negated, [{}] damage remaining, fading buff", damage_to_reduce, buffs[slot].melee_rune);
|
||||
@ -3162,16 +3162,16 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
}
|
||||
}
|
||||
|
||||
if (spellbonuses.MitigateMeleeRune[0] && !DisableMeleeRune) {
|
||||
slot = spellbonuses.MitigateMeleeRune[1];
|
||||
if (spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_PERCENT] && !DisableMeleeRune) {
|
||||
slot = spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_BUFFSLOT];
|
||||
if (slot >= 0)
|
||||
{
|
||||
int damage_to_reduce = damage * spellbonuses.MitigateMeleeRune[0] / 100;
|
||||
int damage_to_reduce = damage * spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_PERCENT] / 100;
|
||||
|
||||
if (spellbonuses.MitigateMeleeRune[2] && (damage_to_reduce > spellbonuses.MitigateMeleeRune[2]))
|
||||
damage_to_reduce = spellbonuses.MitigateMeleeRune[2];
|
||||
if (spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_MAX_DMG_ABSORB_PER_HIT] && (damage_to_reduce > spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_MAX_DMG_ABSORB_PER_HIT]))
|
||||
damage_to_reduce = spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_MAX_DMG_ABSORB_PER_HIT];
|
||||
|
||||
if (spellbonuses.MitigateMeleeRune[3] && (damage_to_reduce >= buffs[slot].melee_rune))
|
||||
if (spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_MAX_HP_AMT] && (damage_to_reduce >= buffs[slot].melee_rune))
|
||||
{
|
||||
LogSpells("Mob::ReduceDamage SE_MitigateMeleeDamage [{}] damage negated, [{}] damage remaining, fading buff", damage_to_reduce, buffs[slot].melee_rune);
|
||||
damage -= buffs[slot].melee_rune;
|
||||
@ -3182,7 +3182,7 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
{
|
||||
LogSpells("Mob::ReduceDamage SE_MitigateMeleeDamage [{}] damage negated, [{}] damage remaining", damage_to_reduce, buffs[slot].melee_rune);
|
||||
|
||||
if (spellbonuses.MitigateMeleeRune[3])
|
||||
if (spellbonuses.MitigateMeleeRune[SBIndex::MITIGATION_RUNE_MAX_HP_AMT])
|
||||
buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce);
|
||||
|
||||
damage -= damage_to_reduce;
|
||||
@ -3193,7 +3193,7 @@ int32 Mob::ReduceDamage(int32 damage)
|
||||
if (damage < 1)
|
||||
return DMG_RUNE;
|
||||
|
||||
if (spellbonuses.MeleeRune[0] && spellbonuses.MeleeRune[1] >= 0)
|
||||
if (spellbonuses.MeleeRune[SBIndex::RUNE_AMOUNT] && spellbonuses.MeleeRune[SBIndex::POSITIONAL_DAMAGE_MOD] >= 0)
|
||||
damage = RuneAbsorb(damage, SE_Rune);
|
||||
|
||||
if (damage < 1)
|
||||
@ -3211,8 +3211,8 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
int32 slot = -1;
|
||||
|
||||
// See if we block the spell outright first
|
||||
if (!iBuffTic && spellbonuses.NegateAttacks[0]) {
|
||||
slot = spellbonuses.NegateAttacks[1];
|
||||
if (!iBuffTic && spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_EXISTS]) {
|
||||
slot = spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_BUFFSLOT];
|
||||
if (slot >= 0) {
|
||||
if (--buffs[slot].numhits == 0) {
|
||||
|
||||
@ -3220,8 +3220,8 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
BuffFadeBySlot(slot, true);
|
||||
}
|
||||
|
||||
if (spellbonuses.NegateAttacks[2] && (damage > spellbonuses.NegateAttacks[2]))
|
||||
damage -= spellbonuses.NegateAttacks[2];
|
||||
if (spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_MAX_DMG_ABSORB_PER_HIT] && (damage > spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_MAX_DMG_ABSORB_PER_HIT]))
|
||||
damage -= spellbonuses.NegateAttacks[SBIndex::NEGATE_ATK_MAX_DMG_ABSORB_PER_HIT];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
@ -3231,16 +3231,16 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
if (iBuffTic) {
|
||||
damage -= (damage * itembonuses.DoTShielding / 100);
|
||||
|
||||
if (spellbonuses.MitigateDotRune[0]) {
|
||||
slot = spellbonuses.MitigateDotRune[1];
|
||||
if (spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT]) {
|
||||
slot = spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_BUFFSLOT];
|
||||
if (slot >= 0)
|
||||
{
|
||||
int damage_to_reduce = damage * spellbonuses.MitigateDotRune[0] / 100;
|
||||
int damage_to_reduce = damage * spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_PERCENT] / 100;
|
||||
|
||||
if (spellbonuses.MitigateDotRune[2] && (damage_to_reduce > spellbonuses.MitigateDotRune[2]))
|
||||
damage_to_reduce = spellbonuses.MitigateDotRune[2];
|
||||
if (spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_MAX_DMG_ABSORB_PER_HIT] && (damage_to_reduce > spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_MAX_DMG_ABSORB_PER_HIT]))
|
||||
damage_to_reduce = spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_MAX_DMG_ABSORB_PER_HIT];
|
||||
|
||||
if (spellbonuses.MitigateDotRune[3] && (damage_to_reduce >= buffs[slot].dot_rune))
|
||||
if (spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_MAX_HP_AMT] && (damage_to_reduce >= buffs[slot].dot_rune))
|
||||
{
|
||||
damage -= buffs[slot].dot_rune;
|
||||
if (!TryFadeEffect(slot))
|
||||
@ -3248,7 +3248,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spellbonuses.MitigateDotRune[3])
|
||||
if (spellbonuses.MitigateDotRune[SBIndex::MITIGATION_RUNE_MAX_HP_AMT])
|
||||
buffs[slot].dot_rune = (buffs[slot].dot_rune - damage_to_reduce);
|
||||
|
||||
damage -= damage_to_reduce;
|
||||
@ -3264,13 +3264,13 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
damage -= (damage * itembonuses.SpellShield / 100);
|
||||
|
||||
//Only mitigate if damage is above the minimium specified.
|
||||
if (spellbonuses.SpellThresholdGuard[0]) {
|
||||
slot = spellbonuses.SpellThresholdGuard[1];
|
||||
if (spellbonuses.SpellThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT]) {
|
||||
slot = spellbonuses.SpellThresholdGuard[SBIndex::THRESHOLDGUARD_BUFFSLOT];
|
||||
|
||||
if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2]))
|
||||
if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[SBIndex::THRESHOLDGUARD_MIN_DMG_TO_TRIGGER]))
|
||||
{
|
||||
DisableSpellRune = true;
|
||||
int damage_to_reduce = damage * spellbonuses.SpellThresholdGuard[0] / 100;
|
||||
int damage_to_reduce = damage * spellbonuses.SpellThresholdGuard[SBIndex::THRESHOLDGUARD_MITIGATION_PERCENT] / 100;
|
||||
if (damage_to_reduce >= buffs[slot].magic_rune)
|
||||
{
|
||||
damage -= buffs[slot].magic_rune;
|
||||
@ -3286,16 +3286,16 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
}
|
||||
|
||||
// Do runes now.
|
||||
if (spellbonuses.MitigateSpellRune[0] && !DisableSpellRune) {
|
||||
slot = spellbonuses.MitigateSpellRune[1];
|
||||
if (spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_PERCENT] && !DisableSpellRune) {
|
||||
slot = spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_BUFFSLOT];
|
||||
if (slot >= 0)
|
||||
{
|
||||
int damage_to_reduce = damage * spellbonuses.MitigateSpellRune[0] / 100;
|
||||
int damage_to_reduce = damage * spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_PERCENT] / 100;
|
||||
|
||||
if (spellbonuses.MitigateSpellRune[2] && (damage_to_reduce > spellbonuses.MitigateSpellRune[2]))
|
||||
damage_to_reduce = spellbonuses.MitigateSpellRune[2];
|
||||
if (spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_MAX_DMG_ABSORB_PER_HIT] && (damage_to_reduce > spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_MAX_DMG_ABSORB_PER_HIT]))
|
||||
damage_to_reduce = spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_MAX_DMG_ABSORB_PER_HIT];
|
||||
|
||||
if (spellbonuses.MitigateSpellRune[3] && (damage_to_reduce >= buffs[slot].magic_rune))
|
||||
if (spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_MAX_HP_AMT] && (damage_to_reduce >= buffs[slot].magic_rune))
|
||||
{
|
||||
LogSpells("Mob::ReduceDamage SE_MitigateSpellDamage [{}] damage negated, [{}] damage remaining, fading buff", damage_to_reduce, buffs[slot].magic_rune);
|
||||
damage -= buffs[slot].magic_rune;
|
||||
@ -3306,7 +3306,7 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
{
|
||||
LogSpells("Mob::ReduceDamage SE_MitigateMeleeDamage [{}] damage negated, [{}] damage remaining", damage_to_reduce, buffs[slot].magic_rune);
|
||||
|
||||
if (spellbonuses.MitigateSpellRune[3])
|
||||
if (spellbonuses.MitigateSpellRune[SBIndex::MITIGATION_RUNE_MAX_HP_AMT])
|
||||
buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce);
|
||||
|
||||
damage -= damage_to_reduce;
|
||||
@ -3318,10 +3318,10 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi
|
||||
return 0;
|
||||
|
||||
//Regular runes absorb spell damage (except dots) - Confirmed on live.
|
||||
if (spellbonuses.MeleeRune[0] && spellbonuses.MeleeRune[1] >= 0)
|
||||
if (spellbonuses.MeleeRune[SBIndex::RUNE_AMOUNT] && spellbonuses.MeleeRune[SBIndex::POSITIONAL_DAMAGE_MOD] >= 0)
|
||||
damage = RuneAbsorb(damage, SE_Rune);
|
||||
|
||||
if (spellbonuses.AbsorbMagicAtt[0] && spellbonuses.AbsorbMagicAtt[1] >= 0)
|
||||
if (spellbonuses.AbsorbMagicAtt[SBIndex::RUNE_AMOUNT] && spellbonuses.AbsorbMagicAtt[SBIndex::POSITIONAL_DAMAGE_MOD] >= 0)
|
||||
damage = RuneAbsorb(damage, SE_AbsorbMagicAtt);
|
||||
|
||||
if (damage < 1)
|
||||
@ -3344,9 +3344,9 @@ int32 Mob::ReduceAllDamage(int32 damage)
|
||||
}
|
||||
}
|
||||
|
||||
if (spellbonuses.EnduranceAbsorbPercentDamage[0]) {
|
||||
int32 damage_reduced = damage * spellbonuses.EnduranceAbsorbPercentDamage[0] / 10000; //If hit for 1000, at 10% then lower damage by 100;
|
||||
int32 endurance_drain = damage_reduced * spellbonuses.EnduranceAbsorbPercentDamage[1] / 10000; //Reduce endurance by 0.05% per HP loss
|
||||
if (spellbonuses.EnduranceAbsorbPercentDamage[SBIndex::ENDURANCE_ABSORD_MITIGIATION]) {
|
||||
int32 damage_reduced = damage * spellbonuses.EnduranceAbsorbPercentDamage[SBIndex::ENDURANCE_ABSORD_MITIGIATION] / 10000; //If hit for 1000, at 10% then lower damage by 100;
|
||||
int32 endurance_drain = damage_reduced * spellbonuses.EnduranceAbsorbPercentDamage[SBIndex::ENDURANCE_ABSORD_DRAIN_PER_HP] / 10000; //Reduce endurance by 0.05% per HP loss
|
||||
if (endurance_drain < 1)
|
||||
endurance_drain = 1;
|
||||
|
||||
@ -3529,7 +3529,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
||||
// emote goes with every one ... even npcs
|
||||
entity_list.MessageClose(this, true, RuleI(Range, SpellMessages), Chat::Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName());
|
||||
}
|
||||
|
||||
|
||||
// If a client pet is damaged while sitting, stand, fix sit button,
|
||||
// and remove sitting regen. Removes bug where client clicks sit
|
||||
// during battle and gains pet hp-regen and bugs the sit button.
|
||||
@ -3542,7 +3542,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
||||
// fix GUI sit button to be unpressed and stop sitting regen
|
||||
owner->CastToClient()->SetPetCommandState(PET_BUTTON_SIT, 0);
|
||||
SetAppearance(eaStanding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} //end `if there is some damage being done and theres anattacker person involved`
|
||||
@ -3552,16 +3552,16 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
||||
// pets that have Hold and no Focus will add NPCs if they're engaged
|
||||
// pets that have Hold and Focus will not add NPCs
|
||||
if (
|
||||
pet &&
|
||||
!pet->IsFamiliar() &&
|
||||
!pet->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||
!pet->IsEngaged() &&
|
||||
attacker &&
|
||||
!(pet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && attacker->IsClient()) &&
|
||||
!(pet->GetSpecialAbility(IMMUNE_AGGRO_NPC) && attacker->IsNPC()) &&
|
||||
attacker != this &&
|
||||
!attacker->IsCorpse() &&
|
||||
!pet->IsGHeld() &&
|
||||
pet &&
|
||||
!pet->IsFamiliar() &&
|
||||
!pet->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||
!pet->IsEngaged() &&
|
||||
attacker &&
|
||||
!(pet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && attacker->IsClient()) &&
|
||||
!(pet->GetSpecialAbility(IMMUNE_AGGRO_NPC) && attacker->IsNPC()) &&
|
||||
attacker != this &&
|
||||
!attacker->IsCorpse() &&
|
||||
!pet->IsGHeld() &&
|
||||
!attacker->IsTrap()
|
||||
) {
|
||||
if (!pet->IsHeld()) {
|
||||
@ -4384,12 +4384,12 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
|
||||
// 1: Try Slay Undead
|
||||
if (defender->GetBodyType() == BT_Undead || defender->GetBodyType() == BT_SummonedUndead ||
|
||||
defender->GetBodyType() == BT_Vampire) {
|
||||
int SlayRateBonus = aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0];
|
||||
int SlayRateBonus = aabonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] + itembonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD] + spellbonuses.SlayUndead[SBIndex::SLAYUNDEAD_RATE_MOD];
|
||||
if (SlayRateBonus) {
|
||||
float slayChance = static_cast<float>(SlayRateBonus) / 10000.0f;
|
||||
if (zone->random.Roll(slayChance)) {
|
||||
int SlayDmgBonus = std::max(
|
||||
{ aabonuses.SlayUndead[1], itembonuses.SlayUndead[1], spellbonuses.SlayUndead[1] });
|
||||
{aabonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD], itembonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD], spellbonuses.SlayUndead[SBIndex::SLAYUNDEAD_DMG_MOD] });
|
||||
hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5;
|
||||
hit.damage_done = (hit.damage_done * SlayDmgBonus) / 100;
|
||||
|
||||
@ -4560,18 +4560,18 @@ bool Mob::TryFinishingBlow(Mob *defender, int &damage)
|
||||
if (defender && !defender->IsClient() && defender->GetHPRatio() < 10) {
|
||||
|
||||
uint32 FB_Dmg =
|
||||
aabonuses.FinishingBlow[1] + spellbonuses.FinishingBlow[1] + itembonuses.FinishingBlow[1];
|
||||
aabonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] + spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG] + itembonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_DMG];
|
||||
|
||||
uint32 FB_Level = 0;
|
||||
FB_Level = aabonuses.FinishingBlowLvl[0];
|
||||
if (FB_Level < spellbonuses.FinishingBlowLvl[0])
|
||||
FB_Level = spellbonuses.FinishingBlowLvl[0];
|
||||
else if (FB_Level < itembonuses.FinishingBlowLvl[0])
|
||||
FB_Level = itembonuses.FinishingBlowLvl[0];
|
||||
FB_Level = aabonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX];
|
||||
if (FB_Level < spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX])
|
||||
FB_Level = spellbonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX];
|
||||
else if (FB_Level < itembonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX])
|
||||
FB_Level = itembonuses.FinishingBlowLvl[SBIndex::FINISHING_EFFECT_LEVEL_MAX];
|
||||
|
||||
// modern AA description says rank 1 (500) is 50% chance
|
||||
int ProcChance =
|
||||
aabonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0];
|
||||
aabonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] + spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE] + spellbonuses.FinishingBlow[SBIndex::FINISHING_EFFECT_PROC_CHANCE];
|
||||
|
||||
if (FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) &&
|
||||
(ProcChance >= zone->random.Int(1, 1000))) {
|
||||
@ -4622,8 +4622,8 @@ void Mob::DoRiposte(Mob *defender)
|
||||
return;
|
||||
}
|
||||
|
||||
DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[0] + defender->spellbonuses.GiveDoubleRiposte[0] +
|
||||
defender->itembonuses.GiveDoubleRiposte[0];
|
||||
DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[SBIndex::DOUBLE_RIPOSTE_CHANCE] + defender->spellbonuses.GiveDoubleRiposte[SBIndex::DOUBLE_RIPOSTE_CHANCE] +
|
||||
defender->itembonuses.GiveDoubleRiposte[SBIndex::DOUBLE_RIPOSTE_CHANCE];
|
||||
|
||||
// Live AA - Double Riposte
|
||||
if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
|
||||
@ -4636,15 +4636,15 @@ void Mob::DoRiposte(Mob *defender)
|
||||
// Double Riposte effect, allows for a chance to do RIPOSTE with a skill specific special attack (ie Return Kick).
|
||||
// Coded narrowly: Limit to one per client. Limit AA only. [1 = Skill Attack Chance, 2 = Skill]
|
||||
|
||||
DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[1];
|
||||
DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[SBIndex::DOUBLE_RIPOSTE_SKILL_ATK_CHANCE];
|
||||
|
||||
if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
|
||||
LogCombat("Preforming a return SPECIAL ATTACK ([{}] percent chance)", DoubleRipChance);
|
||||
|
||||
if (defender->GetClass() == MONK)
|
||||
defender->MonkSpecialAttack(this, defender->aabonuses.GiveDoubleRiposte[2]);
|
||||
defender->MonkSpecialAttack(this, defender->aabonuses.GiveDoubleRiposte[SBIndex::DOUBLE_RIPOSTE_SKILL]);
|
||||
else if (defender->IsClient()) // so yeah, even if you don't have the skill you can still do the attack :P (and we don't crash anymore)
|
||||
defender->CastToClient()->DoClassAttacks(this, defender->aabonuses.GiveDoubleRiposte[2], true);
|
||||
defender->CastToClient()->DoClassAttacks(this, defender->aabonuses.GiveDoubleRiposte[SBIndex::DOUBLE_RIPOSTE_SKILL], true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5067,13 +5067,13 @@ bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
|
||||
- Root break chance values obtained from live parses.
|
||||
*/
|
||||
|
||||
if (!attacker || !spellbonuses.Root[0] || spellbonuses.Root[1] < 0)
|
||||
if (!attacker || !spellbonuses.Root[SBIndex::ROOT_EXISTS] || spellbonuses.Root[SBIndex::ROOT_BUFFSLOT] < 0)
|
||||
return false;
|
||||
|
||||
if (IsDetrimentalSpell(spellbonuses.Root[1]) && spellbonuses.Root[1] != buffslot) {
|
||||
if (IsDetrimentalSpell(spellbonuses.Root[SBIndex::ROOT_BUFFSLOT]) && spellbonuses.Root[SBIndex::ROOT_BUFFSLOT] != buffslot) {
|
||||
int BreakChance = RuleI(Spells, RootBreakFromSpells);
|
||||
|
||||
BreakChance -= BreakChance*buffs[spellbonuses.Root[1]].RootBreakChance / 100;
|
||||
BreakChance -= BreakChance * buffs[spellbonuses.Root[SBIndex::ROOT_BUFFSLOT]].RootBreakChance / 100;
|
||||
int level_diff = attacker->GetLevel() - GetLevel();
|
||||
|
||||
//Use baseline if level difference <= 1 (ie. If target is (1) level less than you, or equal or greater level)
|
||||
@ -5092,8 +5092,8 @@ bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
|
||||
|
||||
if (zone->random.Roll(BreakChance)) {
|
||||
|
||||
if (!TryFadeEffect(spellbonuses.Root[1])) {
|
||||
BuffFadeBySlot(spellbonuses.Root[1]);
|
||||
if (!TryFadeEffect(spellbonuses.Root[SBIndex::ROOT_BUFFSLOT])) {
|
||||
BuffFadeBySlot(spellbonuses.Root[SBIndex::ROOT_BUFFSLOT]);
|
||||
LogCombat("Spell broke root! BreakChance percent chance");
|
||||
return true;
|
||||
}
|
||||
@ -5109,7 +5109,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type)
|
||||
uint32 buff_max = GetMaxTotalSlots();
|
||||
if (type == SE_Rune) {
|
||||
for (uint32 slot = 0; slot < buff_max; slot++) {
|
||||
if (slot == spellbonuses.MeleeRune[1] && spellbonuses.MeleeRune[0] && buffs[slot].melee_rune && IsValidSpell(buffs[slot].spellid)) {
|
||||
if (slot == spellbonuses.MeleeRune[SBIndex::POSITIONAL_DAMAGE_MOD] && spellbonuses.MeleeRune[SBIndex::RUNE_AMOUNT] && buffs[slot].melee_rune && IsValidSpell(buffs[slot].spellid)) {
|
||||
int melee_rune_left = buffs[slot].melee_rune;
|
||||
|
||||
if (melee_rune_left > damage)
|
||||
@ -5133,7 +5133,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type)
|
||||
|
||||
else {
|
||||
for (uint32 slot = 0; slot < buff_max; slot++) {
|
||||
if (slot == spellbonuses.AbsorbMagicAtt[1] && spellbonuses.AbsorbMagicAtt[0] && buffs[slot].magic_rune && IsValidSpell(buffs[slot].spellid)) {
|
||||
if (slot == spellbonuses.AbsorbMagicAtt[SBIndex::POSITIONAL_DAMAGE_MOD] && spellbonuses.AbsorbMagicAtt[SBIndex::RUNE_AMOUNT] && buffs[slot].magic_rune && IsValidSpell(buffs[slot].spellid)) {
|
||||
int magic_rune_left = buffs[slot].magic_rune;
|
||||
if (magic_rune_left > damage)
|
||||
{
|
||||
@ -5255,7 +5255,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
||||
spec_mod = mod;
|
||||
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
||||
//SE_PC_Pet_Rampage SPA 464 on pet, damage modifier
|
||||
int spell_mod = spellbonuses.PC_Pet_Rampage[1] + itembonuses.PC_Pet_Rampage[1] + aabonuses.PC_Pet_Rampage[1];
|
||||
int spell_mod = spellbonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] + itembonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] + aabonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD];
|
||||
if (spell_mod > spec_mod)
|
||||
spec_mod = spell_mod;
|
||||
}
|
||||
@ -5266,7 +5266,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
||||
spec_mod = mod;
|
||||
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
||||
//SE_PC_Pet_AE_Rampage SPA 465 on pet, damage modifier
|
||||
int spell_mod = spellbonuses.PC_Pet_AE_Rampage[1] + itembonuses.PC_Pet_AE_Rampage[1] + aabonuses.PC_Pet_AE_Rampage[1];
|
||||
int spell_mod = spellbonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] + itembonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD] + aabonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_DMG_MOD];
|
||||
if (spell_mod > spec_mod)
|
||||
spec_mod = spell_mod;
|
||||
}
|
||||
@ -5483,24 +5483,24 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell)
|
||||
CheckIncreaseSkill(EQ::skills::SkillDoubleAttack, target, -10);
|
||||
if (CheckDoubleAttack()) {
|
||||
Attack(target, hand, false, false, IsFromSpell);
|
||||
|
||||
|
||||
if (hand == EQ::invslot::slotPrimary) {
|
||||
|
||||
if (HasTwoHanderEquipped()) {
|
||||
auto extraattackchance = aabonuses.ExtraAttackChance[0] + spellbonuses.ExtraAttackChance[0] +
|
||||
itembonuses.ExtraAttackChance[0];
|
||||
auto extraattackchance = aabonuses.ExtraAttackChance[SBIndex::EXTRA_ATTACK_CHANCE] + spellbonuses.ExtraAttackChance[SBIndex::EXTRA_ATTACK_CHANCE] +
|
||||
itembonuses.ExtraAttackChance[SBIndex::EXTRA_ATTACK_CHANCE];
|
||||
if (extraattackchance && zone->random.Roll(extraattackchance)) {
|
||||
auto extraattackamt = std::max({ aabonuses.ExtraAttackChance[1], spellbonuses.ExtraAttackChance[1], itembonuses.ExtraAttackChance[1] });
|
||||
auto extraattackamt = std::max({aabonuses.ExtraAttackChance[SBIndex::EXTRA_ATTACK_NUM_ATKS], spellbonuses.ExtraAttackChance[SBIndex::EXTRA_ATTACK_NUM_ATKS], itembonuses.ExtraAttackChance[SBIndex::EXTRA_ATTACK_NUM_ATKS] });
|
||||
for (int i = 0; i < extraattackamt; i++) {
|
||||
Attack(target, hand, false, false, IsFromSpell);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto extraattackchance_primary = aabonuses.ExtraAttackChancePrimary[0] + spellbonuses.ExtraAttackChancePrimary[0] +
|
||||
itembonuses.ExtraAttackChancePrimary[0];
|
||||
auto extraattackchance_primary = aabonuses.ExtraAttackChancePrimary[SBIndex::EXTRA_ATTACK_CHANCE] + spellbonuses.ExtraAttackChancePrimary[SBIndex::EXTRA_ATTACK_CHANCE] +
|
||||
itembonuses.ExtraAttackChancePrimary[SBIndex::EXTRA_ATTACK_CHANCE];
|
||||
if (extraattackchance_primary && zone->random.Roll(extraattackchance_primary)) {
|
||||
auto extraattackamt_primary = std::max({ aabonuses.ExtraAttackChancePrimary[1], spellbonuses.ExtraAttackChancePrimary[1], itembonuses.ExtraAttackChancePrimary[1] });
|
||||
auto extraattackamt_primary = std::max({aabonuses.ExtraAttackChancePrimary[SBIndex::EXTRA_ATTACK_NUM_ATKS], spellbonuses.ExtraAttackChancePrimary[SBIndex::EXTRA_ATTACK_NUM_ATKS], itembonuses.ExtraAttackChancePrimary[SBIndex::EXTRA_ATTACK_NUM_ATKS] });
|
||||
for (int i = 0; i < extraattackamt_primary; i++) {
|
||||
Attack(target, hand, false, false, IsFromSpell);
|
||||
}
|
||||
@ -5509,10 +5509,10 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell)
|
||||
}
|
||||
|
||||
if (hand == EQ::invslot::slotSecondary) {
|
||||
auto extraattackchance_secondary = aabonuses.ExtraAttackChanceSecondary[0] + spellbonuses.ExtraAttackChanceSecondary[0] +
|
||||
itembonuses.ExtraAttackChanceSecondary[0];
|
||||
auto extraattackchance_secondary = aabonuses.ExtraAttackChanceSecondary[SBIndex::EXTRA_ATTACK_CHANCE] + spellbonuses.ExtraAttackChanceSecondary[SBIndex::EXTRA_ATTACK_CHANCE] +
|
||||
itembonuses.ExtraAttackChanceSecondary[SBIndex::EXTRA_ATTACK_CHANCE];
|
||||
if (extraattackchance_secondary && zone->random.Roll(extraattackchance_secondary)) {
|
||||
auto extraattackamt_secondary = std::max({ aabonuses.ExtraAttackChanceSecondary[1], spellbonuses.ExtraAttackChanceSecondary[1], itembonuses.ExtraAttackChanceSecondary[1] });
|
||||
auto extraattackamt_secondary = std::max({aabonuses.ExtraAttackChanceSecondary[SBIndex::EXTRA_ATTACK_NUM_ATKS], spellbonuses.ExtraAttackChanceSecondary[SBIndex::EXTRA_ATTACK_NUM_ATKS], itembonuses.ExtraAttackChanceSecondary[SBIndex::EXTRA_ATTACK_NUM_ATKS] });
|
||||
for (int i = 0; i < extraattackamt_secondary; i++) {
|
||||
Attack(target, hand, false, false, IsFromSpell);
|
||||
}
|
||||
|
||||
588
zone/bonuses.cpp
588
zone/bonuses.cpp
File diff suppressed because it is too large
Load Diff
@ -328,10 +328,10 @@ int32 Client::CalcMaxHP()
|
||||
if (current_hp > max_hp) {
|
||||
current_hp = max_hp;
|
||||
}
|
||||
int hp_perc_cap = spellbonuses.HPPercCap[0];
|
||||
int hp_perc_cap = spellbonuses.HPPercCap[SBIndex::RESOURCE_PERCENT_CAP];
|
||||
if (hp_perc_cap) {
|
||||
int curHP_cap = (max_hp * hp_perc_cap) / 100;
|
||||
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[1] && current_hp > spellbonuses.HPPercCap[1])) {
|
||||
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP] && current_hp > spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP])) {
|
||||
|
||||
current_hp = curHP_cap;
|
||||
}
|
||||
@ -591,10 +591,10 @@ int32 Client::CalcMaxMana()
|
||||
if (current_mana > max_mana) {
|
||||
current_mana = max_mana;
|
||||
}
|
||||
int mana_perc_cap = spellbonuses.ManaPercCap[0];
|
||||
int mana_perc_cap = spellbonuses.ManaPercCap[SBIndex::RESOURCE_PERCENT_CAP];
|
||||
if (mana_perc_cap) {
|
||||
int curMana_cap = (max_mana * mana_perc_cap) / 100;
|
||||
if (current_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && current_mana > spellbonuses.ManaPercCap[1])) {
|
||||
if (current_mana > curMana_cap || (spellbonuses.ManaPercCap[SBIndex::RESOURCE_AMOUNT_CAP] && current_mana > spellbonuses.ManaPercCap[SBIndex::RESOURCE_AMOUNT_CAP])) {
|
||||
current_mana = curMana_cap;
|
||||
}
|
||||
}
|
||||
@ -1614,10 +1614,10 @@ void Client::CalcMaxEndurance()
|
||||
if (current_endurance > max_end) {
|
||||
current_endurance = max_end;
|
||||
}
|
||||
int end_perc_cap = spellbonuses.EndPercCap[0];
|
||||
int end_perc_cap = spellbonuses.EndPercCap[SBIndex::RESOURCE_PERCENT_CAP];
|
||||
if (end_perc_cap) {
|
||||
int curEnd_cap = (max_end * end_perc_cap) / 100;
|
||||
if (current_endurance > curEnd_cap || (spellbonuses.EndPercCap[1] && current_endurance > spellbonuses.EndPercCap[1])) {
|
||||
if (current_endurance > curEnd_cap || (spellbonuses.EndPercCap[SBIndex::RESOURCE_AMOUNT_CAP] && current_endurance > spellbonuses.EndPercCap[SBIndex::RESOURCE_AMOUNT_CAP])) {
|
||||
current_endurance = curEnd_cap;
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,8 +503,8 @@ struct StatBonuses {
|
||||
uint32 MitigateDotRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per tick 3 = Rune Amt
|
||||
bool TriggerMeleeThreshold; // Has Melee Threshhold
|
||||
bool TriggerSpellThreshold; // Has Spell Threshhold
|
||||
uint32 ManaAbsorbPercentDamage; // 0 = Mitigation value
|
||||
int32 EnduranceAbsorbPercentDamage[2]; // 0 = Mitigation value 1 = Percent Endurance drain per HP lost
|
||||
uint32 ManaAbsorbPercentDamage; // 0 = Mitigation value
|
||||
int32 EnduranceAbsorbPercentDamage[2]; // 0 = Mitigation value 1 = Percent Endurance drain per HP lost
|
||||
int32 ShieldBlock; // Chance to Shield Block
|
||||
int32 BlockBehind; // Chance to Block Behind (with our without shield)
|
||||
bool CriticalRegenDecay; // increase critical regen chance, decays based on spell level cast
|
||||
@ -512,7 +512,7 @@ struct StatBonuses {
|
||||
bool CriticalDotDecay; // increase critical dot chance, decays based on spell level cast
|
||||
bool DivineAura; // invulnerability
|
||||
bool DistanceRemoval; // Check if Cancle if Moved effect is present
|
||||
int32 ImprovedTaunt[3]; // 0 = Max Level 1 = Aggro modifier 2 = buffid
|
||||
int32 ImprovedTaunt[3]; // 0 = Max Level 1 = Aggro modifier 2 = buff slot
|
||||
int8 Root[2]; // The lowest buff slot a root can be found. [0] = Bool if has root [1] = buff slot
|
||||
int32 FrenziedDevastation; // base1= AArank(used) base2= chance increase spell criticals + all DD spells 2x mana.
|
||||
uint32 AbsorbMagicAtt[2]; // 0 = magic rune value 1 = buff slot
|
||||
@ -616,6 +616,58 @@ struct StatBonuses {
|
||||
bool hunger; // Song of Sustenance -- min caps to 3500
|
||||
};
|
||||
|
||||
// StatBonus Indexes
|
||||
namespace SBIndex {
|
||||
constexpr uint16 BUFFSTACKER_EXISTS = 0; // SPA 446-449
|
||||
constexpr uint16 BUFFSTACKER_VALUE = 1; // SPA 446-449
|
||||
constexpr uint16 EXTRA_ATTACK_CHANCE = 0; // SPA 266,498,499
|
||||
constexpr uint16 EXTRA_ATTACK_NUM_ATKS = 1; // SPA 266,498,499
|
||||
constexpr uint16 DIVINE_SAVE_CHANCE = 0; // SPA 232
|
||||
constexpr uint16 DIVINE_SAVE_SPELL_TRIGGER_ID = 1; // SPA 232
|
||||
constexpr uint16 DEATH_SAVE_TYPE = 0; // SPA 150
|
||||
constexpr uint16 DEATH_SAVE_BUFFSLOT = 1; // SPA 150
|
||||
constexpr uint16 DEATH_SAVE_MIN_LEVEL_FOR_HEAL = 2; // SPA 150
|
||||
constexpr uint16 DEATH_SAVE_HEAL_AMT = 3; // SPA 150
|
||||
constexpr uint16 RESOURCE_PERCENT_CAP = 0; // SPA 408-410
|
||||
constexpr uint16 RESOURCE_AMOUNT_CAP = 1; // SPA 408-419
|
||||
constexpr uint16 NEGATE_ATK_EXISTS = 0; // SPA 163
|
||||
constexpr uint16 NEGATE_ATK_BUFFSLOT = 1; // SPA 163
|
||||
constexpr uint16 NEGATE_ATK_MAX_DMG_ABSORB_PER_HIT = 2; // SPA 163
|
||||
constexpr uint16 MITIGATION_RUNE_PERCENT = 0; // SPA 161,162,450
|
||||
constexpr uint16 MITIGATION_RUNE_BUFFSLOT = 1; // SPA 161,162,450
|
||||
constexpr uint16 MITIGATION_RUNE_MAX_DMG_ABSORB_PER_HIT = 2; // SPA 161,162,450
|
||||
constexpr uint16 MITIGATION_RUNE_MAX_HP_AMT = 3; // SPA 161,162,450
|
||||
constexpr uint16 THRESHOLDGUARD_MITIGATION_PERCENT = 0; // SPA 451,452
|
||||
constexpr uint16 THRESHOLDGUARD_BUFFSLOT = 1; // SPA 451,452
|
||||
constexpr uint16 THRESHOLDGUARD_MIN_DMG_TO_TRIGGER = 2; // SPA 451,452
|
||||
constexpr uint16 ENDURANCE_ABSORD_MITIGIATION = 0; // SPA 521
|
||||
constexpr uint16 ENDURANCE_ABSORD_DRAIN_PER_HP = 1; // SPA 521
|
||||
constexpr uint16 IMPROVED_TAUNT_MAX_LVL = 0; // SPA 444
|
||||
constexpr uint16 IMPROVED_TAUNT_AGGRO_MOD = 1; // SPA 444
|
||||
constexpr uint16 IMPROVED_TAUNT_BUFFSLOT = 2; // SPA 444
|
||||
constexpr uint16 ROOT_EXISTS = 0; // SPA 99
|
||||
constexpr uint16 ROOT_BUFFSLOT = 1; // SPA 99
|
||||
constexpr uint16 RUNE_AMOUNT = 0; // SPA 55
|
||||
constexpr uint16 RUNE_BUFFSLOT = 1; // SPA 78
|
||||
constexpr uint16 POSITIONAL_DAMAGE_MOD = 0; // SPA 503-506
|
||||
constexpr uint16 POSITIONAL_LOCATION = 1; // SPA 503-506
|
||||
constexpr uint16 PET_RAMPAGE_CHANCE = 0; // SPA 464,465
|
||||
constexpr uint16 PET_RAMPAGE_DMG_MOD = 1; // SPA 465,465
|
||||
constexpr uint16 SKILLPROC_CHANCE = 0; // SPA 427
|
||||
constexpr uint16 SKILLPROC_SKILL = 1; // SPA 427
|
||||
constexpr uint16 SKILLPROC_SPELL_ID = 2; // SPA 427
|
||||
constexpr uint16 SLAYUNDEAD_RATE_MOD = 0; // SPA 219
|
||||
constexpr uint16 SLAYUNDEAD_DMG_MOD = 1; // SPA 219
|
||||
constexpr uint16 DOUBLE_RIPOSTE_CHANCE = 0; // SPA 223
|
||||
constexpr uint16 DOUBLE_RIPOSTE_SKILL_ATK_CHANCE = 1; // SPA 223
|
||||
constexpr uint16 DOUBLE_RIPOSTE_SKILL = 2; // SPA 223
|
||||
constexpr uint16 FINISHING_EFFECT_PROC_CHANCE = 0; // SPA 278, 439, 217
|
||||
constexpr uint16 FINISHING_EFFECT_DMG = 1; // SPA 278, 439, 217
|
||||
constexpr uint16 FINISHING_EFFECT_LEVEL_MAX = 0; // SPA 440, 345, 346
|
||||
constexpr uint16 FINISHING_EFFECT_LEVEL_CHANCE_BONUS = 1; // SPA 440, 345, 346
|
||||
};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16 spellID;
|
||||
|
||||
@ -862,10 +862,10 @@ int32 Merc::CalcMaxHP() {
|
||||
if (current_hp > max_hp)
|
||||
current_hp = max_hp;
|
||||
|
||||
int hp_perc_cap = spellbonuses.HPPercCap[0];
|
||||
int hp_perc_cap = spellbonuses.HPPercCap[SBIndex::RESOURCE_PERCENT_CAP];
|
||||
if(hp_perc_cap) {
|
||||
int curHP_cap = (max_hp * hp_perc_cap) / 100;
|
||||
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[1] && current_hp > spellbonuses.HPPercCap[1]))
|
||||
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP] && current_hp > spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP]))
|
||||
current_hp = curHP_cap;
|
||||
}
|
||||
|
||||
@ -904,10 +904,10 @@ int32 Merc::CalcMaxMana()
|
||||
current_mana = max_mana;
|
||||
}
|
||||
|
||||
int mana_perc_cap = spellbonuses.ManaPercCap[0];
|
||||
int mana_perc_cap = spellbonuses.ManaPercCap[SBIndex::RESOURCE_PERCENT_CAP];
|
||||
if(mana_perc_cap) {
|
||||
int curMana_cap = (max_mana * mana_perc_cap) / 100;
|
||||
if (current_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && current_mana > spellbonuses.ManaPercCap[1]))
|
||||
if (current_mana > curMana_cap || (spellbonuses.ManaPercCap[SBIndex::RESOURCE_AMOUNT_CAP] && current_mana > spellbonuses.ManaPercCap[SBIndex::RESOURCE_AMOUNT_CAP]))
|
||||
current_mana = curMana_cap;
|
||||
}
|
||||
|
||||
@ -999,10 +999,10 @@ void Merc::CalcMaxEndurance()
|
||||
cur_end = max_end;
|
||||
}
|
||||
|
||||
int end_perc_cap = spellbonuses.EndPercCap[0];
|
||||
int end_perc_cap = spellbonuses.EndPercCap[SBIndex::RESOURCE_PERCENT_CAP];
|
||||
if(end_perc_cap) {
|
||||
int curEnd_cap = (max_end * end_perc_cap) / 100;
|
||||
if (cur_end > curEnd_cap || (spellbonuses.EndPercCap[1] && cur_end > spellbonuses.EndPercCap[1]))
|
||||
if (cur_end > curEnd_cap || (spellbonuses.EndPercCap[SBIndex::RESOURCE_AMOUNT_CAP] && cur_end > spellbonuses.EndPercCap[SBIndex::RESOURCE_AMOUNT_CAP]))
|
||||
cur_end = curEnd_cap;
|
||||
}
|
||||
}
|
||||
@ -1624,7 +1624,7 @@ void Merc::AI_Process() {
|
||||
}
|
||||
}
|
||||
|
||||
int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance[0] + itembonuses.ExtraAttackChance[0] + aabonuses.ExtraAttackChance[0];
|
||||
int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance[SBIndex::EXTRA_ATTACK_CHANCE] + itembonuses.ExtraAttackChance[SBIndex::EXTRA_ATTACK_CHANCE] + aabonuses.ExtraAttackChance[SBIndex::EXTRA_ATTACK_CHANCE];
|
||||
|
||||
if (GetTarget() && ExtraAttackChanceBonus) {
|
||||
if(zone->random.Roll(ExtraAttackChanceBonus))
|
||||
|
||||
22
zone/mob.cpp
22
zone/mob.cpp
@ -3547,9 +3547,9 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect)
|
||||
return false;
|
||||
|
||||
/*The effects SE_SpellTrigger (SPA 340) and SE_Chance_Best_in_Spell_Grp (SPA 469) work as follows, you typically will have 2-3 different spells each with their own
|
||||
chance to be triggered with all chances equaling up to 100 pct, with only 1 spell out of the group being ultimately cast.
|
||||
(ie Effect1 trigger spellA with 30% chance, Effect2 triggers spellB with 20% chance, Effect3 triggers spellC with 50% chance).
|
||||
The following function ensures a stastically accurate chance for each spell to be cast based on their chance values. These effects are also used in spells where there
|
||||
chance to be triggered with all chances equaling up to 100 pct, with only 1 spell out of the group being ultimately cast.
|
||||
(ie Effect1 trigger spellA with 30% chance, Effect2 triggers spellB with 20% chance, Effect3 triggers spellC with 50% chance).
|
||||
The following function ensures a stastically accurate chance for each spell to be cast based on their chance values. These effects are also used in spells where there
|
||||
is only 1 effect using the trigger effect. In those situations we simply roll a chance for that spell to be cast once.
|
||||
Note: Both SPA 340 and 469 can be in same spell and both cummulative add up to 100 pct chances. SPA469 only difference being the spell cast will
|
||||
be "best in spell group", instead of a defined spell_id.*/
|
||||
@ -3558,7 +3558,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect)
|
||||
int total_chance = 0;
|
||||
int effect_slot = effect;
|
||||
bool CastSpell = false;
|
||||
|
||||
|
||||
for (int i = 0; i < EFFECT_COUNT; i++)
|
||||
{
|
||||
if (spells[spell_id].effectid[i] == SE_SpellTrigger || spells[spell_id].effectid[i] == SE_Chance_Best_in_Spell_Grp)
|
||||
@ -3743,7 +3743,7 @@ void Mob::TryOnSpellFinished(Mob *caster, Mob *target, uint16 spell_id)
|
||||
if (!IsValidSpell(spell_id))
|
||||
return;
|
||||
|
||||
/*Apply damage from Lifeburn type effects on caster at end of spell cast.
|
||||
/*Apply damage from Lifeburn type effects on caster at end of spell cast.
|
||||
This allows for the AE spells to function without repeatedly killing caster
|
||||
Damage or heal portion can be found as regular single use spell effect
|
||||
*/
|
||||
@ -3766,7 +3766,7 @@ void Mob::TryOnSpellFinished(Mob *caster, Mob *target, uint16 spell_id)
|
||||
int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining)
|
||||
{
|
||||
/*
|
||||
Modifies incoming spell damage by percent, to increase or decrease damage, can be limited to specific resists.
|
||||
Modifies incoming spell damage by percent, to increase or decrease damage, can be limited to specific resists.
|
||||
Can be applied through quest function, spell focus or npc_spells_effects table. This function is run on the target of the spell.
|
||||
*/
|
||||
|
||||
@ -3789,7 +3789,7 @@ int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining)
|
||||
innate_mod = Vulnerability_Mod[HIGHEST_RESIST+1];
|
||||
|
||||
//[Apply spell derived vulnerabilities] Step 1: Check this focus effect exists on the mob.
|
||||
if (spellbonuses.FocusEffects[focusSpellVulnerability]){
|
||||
if (spellbonuses.FocusEffects[focusSpellVulnerability]){
|
||||
|
||||
int32 tmp_focus = 0;
|
||||
int tmp_buffslot = -1;
|
||||
@ -3903,8 +3903,8 @@ int32 Mob::GetPositionalDmgTaken(Mob *attacker)
|
||||
int back_arc = 0;
|
||||
int total_mod = 0;
|
||||
|
||||
back_arc += itembonuses.Damage_Taken_Position_Mod[0] + aabonuses.Damage_Taken_Position_Mod[0] + spellbonuses.Damage_Taken_Position_Mod[0];
|
||||
front_arc += itembonuses.Damage_Taken_Position_Mod[1] + aabonuses.Damage_Taken_Position_Mod[1] + spellbonuses.Damage_Taken_Position_Mod[1];
|
||||
back_arc += itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] + aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] + spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD];
|
||||
front_arc += itembonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_LOCATION] + aabonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_LOCATION] + spellbonuses.Damage_Taken_Position_Mod[SBIndex::POSITIONAL_LOCATION];
|
||||
|
||||
if (back_arc || front_arc) { //Do they have this bonus?
|
||||
if (attacker->BehindMob(this, attacker->GetX(), attacker->GetY()))//Check if attacker is striking from behind
|
||||
@ -4897,8 +4897,8 @@ int16 Mob::GetMeleeDmgPositionMod(Mob* defender)
|
||||
int back_arc = 0;
|
||||
int total_mod = 0;
|
||||
|
||||
back_arc += itembonuses.Melee_Damage_Position_Mod[0] + aabonuses.Melee_Damage_Position_Mod[0] + spellbonuses.Melee_Damage_Position_Mod[0];
|
||||
front_arc += itembonuses.Melee_Damage_Position_Mod[1] + aabonuses.Melee_Damage_Position_Mod[1] + spellbonuses.Melee_Damage_Position_Mod[1];
|
||||
back_arc += itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] + aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD] + spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_DAMAGE_MOD];
|
||||
front_arc += itembonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_LOCATION] + aabonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_LOCATION] + spellbonuses.Melee_Damage_Position_Mod[SBIndex::POSITIONAL_LOCATION];
|
||||
|
||||
if (back_arc || front_arc) { //Do they have this bonus?
|
||||
if (BehindMob(defender, GetX(), GetY()))//Check if attacker is striking from behind
|
||||
|
||||
@ -1224,12 +1224,12 @@ void Mob::AI_Process() {
|
||||
|
||||
//SE_PC_Pet_Rampage SPA 464 on pet, chance modifier
|
||||
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
||||
int chance = spellbonuses.PC_Pet_Rampage[0] + itembonuses.PC_Pet_Rampage[0] + aabonuses.PC_Pet_Rampage[0];
|
||||
int chance = spellbonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE] + itembonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE] + aabonuses.PC_Pet_Rampage[SBIndex::PET_RAMPAGE_CHANCE];
|
||||
if (chance && zone->random.Roll(chance)) {
|
||||
Rampage(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (GetSpecialAbility(SPECATK_RAMPAGE) && !specialed) {
|
||||
int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0);
|
||||
@ -1267,7 +1267,7 @@ void Mob::AI_Process() {
|
||||
|
||||
//SE_PC_Pet_Rampage SPA 465 on pet, chance modifier
|
||||
if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) {
|
||||
int chance = spellbonuses.PC_Pet_AE_Rampage[0] + itembonuses.PC_Pet_AE_Rampage[0] + aabonuses.PC_Pet_AE_Rampage[0];
|
||||
int chance = spellbonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_CHANCE] + itembonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_CHANCE] + aabonuses.PC_Pet_AE_Rampage[SBIndex::PET_RAMPAGE_CHANCE];
|
||||
if (chance && zone->random.Roll(chance)) {
|
||||
Rampage(nullptr);
|
||||
}
|
||||
|
||||
@ -193,12 +193,12 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 bas
|
||||
DoAttack(who, my_hit);
|
||||
|
||||
who->AddToHateList(this, hate, 0);
|
||||
if (my_hit.damage_done > 0 && aabonuses.SkillAttackProc[0] && aabonuses.SkillAttackProc[1] == skill &&
|
||||
IsValidSpell(aabonuses.SkillAttackProc[2])) {
|
||||
float chance = aabonuses.SkillAttackProc[0] / 1000.0f;
|
||||
if (my_hit.damage_done > 0 && aabonuses.SkillAttackProc[SBIndex::SKILLPROC_CHANCE] && aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SKILL] == skill &&
|
||||
IsValidSpell(aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID])) {
|
||||
float chance = aabonuses.SkillAttackProc[SBIndex::SKILLPROC_CHANCE] / 1000.0f;
|
||||
if (zone->random.Roll(chance))
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], who, EQ::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[2]].ResistDiff);
|
||||
SpellFinished(aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID], who, EQ::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID]].ResistDiff);
|
||||
}
|
||||
|
||||
who->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, skill, false);
|
||||
@ -996,21 +996,21 @@ void Mob::ProjectileAttack()
|
||||
disable = false;
|
||||
Mob *target = entity_list.GetMobID(ProjectileAtk[i].target_id);
|
||||
|
||||
if (target && target->IsMoving()) {
|
||||
if (target && target->IsMoving()) {
|
||||
/*
|
||||
Only recalculate hit increment if target is moving.
|
||||
Due to frequency that we need to check increment the targets position variables may not be
|
||||
Due to frequency that we need to check increment the targets position variables may not be
|
||||
updated even if moving. Do a simple check before calculating distance.
|
||||
*/
|
||||
if (ProjectileAtk[i].tlast_x != target->GetX() || ProjectileAtk[i].tlast_y != target->GetY()) {
|
||||
|
||||
|
||||
ProjectileAtk[i].tlast_x = target->GetX();
|
||||
ProjectileAtk[i].tlast_y = target->GetY();
|
||||
|
||||
//Recalculate from the original location the projectile was fired in relation to the current targets location.
|
||||
float distance = target->CalculateDistance(ProjectileAtk[i].origin_x, ProjectileAtk[i].origin_y, ProjectileAtk[i].origin_z);
|
||||
float distance_mod = 0.0f;
|
||||
|
||||
|
||||
if (distance <= 125.0f) {
|
||||
distance_mod = (ProjectileAtk[i].speed_mod - 4.0f) * -20.0f;
|
||||
distance += distance * distance_mod / 100.0f;
|
||||
@ -1022,14 +1022,14 @@ void Mob::ProjectileAttack()
|
||||
distance = distance * 1.30f; //Add 30% to base distance if over 200 range to tighten up hit timing.
|
||||
distance = 3.14f * (distance / 2.0f); //Get distance of arc to better reflect projectile path length
|
||||
}
|
||||
|
||||
|
||||
float hit = 1200.0f + (10 * distance / ProjectileAtk[i].speed_mod);
|
||||
|
||||
ProjectileAtk[i].hit_increment = static_cast<uint16>(hit);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we hit.
|
||||
// Check if we hit.
|
||||
if (ProjectileAtk[i].hit_increment <= ProjectileAtk[i].increment) {
|
||||
if (target) {
|
||||
if (IsNPC()) {
|
||||
@ -2061,9 +2061,9 @@ int Mob::TryHeadShot(Mob *defender, EQ::skills::SkillType skillInUse)
|
||||
// Only works on YOUR target.
|
||||
if (defender && defender->GetBodyType() == BT_Humanoid && !defender->IsClient() &&
|
||||
skillInUse == EQ::skills::SkillArchery && GetTarget() == defender) {
|
||||
uint32 HeadShot_Dmg = aabonuses.HeadShot[1] + spellbonuses.HeadShot[1] + itembonuses.HeadShot[1];
|
||||
uint32 HeadShot_Dmg = aabonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] + spellbonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG] + itembonuses.HeadShot[SBIndex::FINISHING_EFFECT_DMG];
|
||||
uint8 HeadShot_Level = 0; // Get Highest Headshot Level
|
||||
HeadShot_Level = std::max({aabonuses.HSLevel[0], spellbonuses.HSLevel[0], itembonuses.HSLevel[0]});
|
||||
HeadShot_Level = std::max({aabonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX], spellbonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX], itembonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX]});
|
||||
|
||||
if (HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)) {
|
||||
int chance = GetDEX();
|
||||
@ -2071,10 +2071,10 @@ int Mob::TryHeadShot(Mob *defender, EQ::skills::SkillType skillInUse)
|
||||
if (IsClient())
|
||||
chance += CastToClient()->GetHeroicDEX() / 25;
|
||||
chance *= 10;
|
||||
int norm = aabonuses.HSLevel[1];
|
||||
int norm = aabonuses.HSLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS];
|
||||
if (norm > 0)
|
||||
chance = chance * norm / 100;
|
||||
chance += aabonuses.HeadShot[0] + spellbonuses.HeadShot[0] + itembonuses.HeadShot[0];
|
||||
chance += aabonuses.HeadShot[SBIndex::FINISHING_EFFECT_PROC_CHANCE] + spellbonuses.HeadShot[SBIndex::FINISHING_EFFECT_PROC_CHANCE] + itembonuses.HeadShot[SBIndex::FINISHING_EFFECT_PROC_CHANCE];
|
||||
if (zone->random.Int(1, 1000) <= chance) {
|
||||
entity_list.MessageCloseString(
|
||||
this, false, 200, Chat::MeleeCrit, FATAL_BOW_SHOT,
|
||||
@ -2097,7 +2097,7 @@ int Mob::TryAssassinate(Mob *defender, EQ::skills::SkillType skillInUse)
|
||||
if (IsClient())
|
||||
chance += CastToClient()->GetHeroicDEX();
|
||||
chance *= 10;
|
||||
int norm = aabonuses.AssassinateLevel[1];
|
||||
int norm = aabonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_CHANCE_BONUS];
|
||||
if (norm > 0)
|
||||
chance = chance * norm / 100;
|
||||
} else if (skillInUse == EQ::skills::SkillThrowing) {
|
||||
@ -2107,14 +2107,14 @@ int Mob::TryAssassinate(Mob *defender, EQ::skills::SkillType skillInUse)
|
||||
chance += 5;
|
||||
}
|
||||
|
||||
chance += aabonuses.Assassinate[0] + spellbonuses.Assassinate[0] + itembonuses.Assassinate[0];
|
||||
chance += aabonuses.Assassinate[SBIndex::FINISHING_EFFECT_PROC_CHANCE] + spellbonuses.Assassinate[SBIndex::FINISHING_EFFECT_PROC_CHANCE] + itembonuses.Assassinate[SBIndex::FINISHING_EFFECT_PROC_CHANCE];
|
||||
|
||||
uint32 Assassinate_Dmg =
|
||||
aabonuses.Assassinate[1] + spellbonuses.Assassinate[1] + itembonuses.Assassinate[1];
|
||||
aabonuses.Assassinate[SBIndex::FINISHING_EFFECT_DMG] + spellbonuses.Assassinate[SBIndex::FINISHING_EFFECT_DMG] + itembonuses.Assassinate[SBIndex::FINISHING_EFFECT_DMG];
|
||||
|
||||
uint8 Assassinate_Level = 0; // Get Highest Headshot Level
|
||||
Assassinate_Level = std::max(
|
||||
{aabonuses.AssassinateLevel[0], spellbonuses.AssassinateLevel[0], itembonuses.AssassinateLevel[0]});
|
||||
{aabonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX], spellbonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX], itembonuses.AssassinateLevel[SBIndex::FINISHING_EFFECT_LEVEL_MAX]});
|
||||
|
||||
// revamped AAs require AA line I believe?
|
||||
if (!Assassinate_Level)
|
||||
@ -2198,12 +2198,12 @@ void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQ::skills::Sk
|
||||
}
|
||||
|
||||
other->AddToHateList(this, hate, 0);
|
||||
if (damage > 0 && aabonuses.SkillAttackProc[0] && aabonuses.SkillAttackProc[1] == skillinuse &&
|
||||
IsValidSpell(aabonuses.SkillAttackProc[2])) {
|
||||
float chance = aabonuses.SkillAttackProc[0] / 1000.0f;
|
||||
if (damage > 0 && aabonuses.SkillAttackProc[SBIndex::SKILLPROC_CHANCE] && aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SKILL] == skillinuse &&
|
||||
IsValidSpell(aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID])) {
|
||||
float chance = aabonuses.SkillAttackProc[SBIndex::SKILLPROC_CHANCE] / 1000.0f;
|
||||
if (zone->random.Roll(chance))
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], other, EQ::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[2]].ResistDiff);
|
||||
SpellFinished(aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID], other, EQ::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID]].ResistDiff);
|
||||
}
|
||||
|
||||
other->Damage(this, damage, SPELL_UNKNOWN, skillinuse);
|
||||
|
||||
@ -2903,10 +2903,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
|
||||
if (zone->random.Roll(spells[spell_id].base[i]) && IsValidSpell(spells[spell_id].base2[i]))
|
||||
caster->SpellFinished(spells[spell_id].base2[i], this, EQ::spells::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case SE_Hatelist_To_Tail_Index: {
|
||||
if (caster && zone->random.Roll(spells[spell_id].base[i]))
|
||||
caster->SetBottomRampageList();
|
||||
@ -2940,7 +2940,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
else
|
||||
Stun(spells[spell_id].base[i]);
|
||||
}
|
||||
else
|
||||
else
|
||||
caster->MessageString(Chat::SpellFailure, FEAR_TOO_HIGH);
|
||||
break;
|
||||
}
|
||||
@ -2949,7 +2949,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
buffs[buffslot].focusproclimit_procamt = spells[spell_id].base[i]; //Set max amount of procs before lockout timer
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case SE_PersistentEffect:
|
||||
MakeAura(spell_id);
|
||||
break;
|
||||
@ -3928,11 +3928,11 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
|
||||
int32 amt = abs(GetMaxHP() * effect_value / 100);
|
||||
if (spells[buff.spellid].max[i] && amt > spells[buff.spellid].max[i])
|
||||
amt = spells[buff.spellid].max[i];
|
||||
|
||||
if (effect_value < 0) {
|
||||
|
||||
if (effect_value < 0) {
|
||||
Damage(this, amt, 0, EQ::skills::SkillEvocation, false);
|
||||
}
|
||||
else {
|
||||
else {
|
||||
HealDamage(amt);
|
||||
}
|
||||
break;
|
||||
@ -3945,7 +3945,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
|
||||
amt = spells[buff.spellid].max[i];
|
||||
|
||||
if (effect_value < 0) {
|
||||
|
||||
|
||||
SetMana(GetMana() - amt);
|
||||
}
|
||||
else {
|
||||
@ -6192,16 +6192,16 @@ bool Mob::TryDivineSave()
|
||||
-If desired, additional spells can be triggered from the AA/item/spell effect, generally a heal.
|
||||
*/
|
||||
|
||||
int32 SuccessChance = aabonuses.DivineSaveChance[0] + itembonuses.DivineSaveChance[0] + spellbonuses.DivineSaveChance[0];
|
||||
int32 SuccessChance = aabonuses.DivineSaveChance[SBIndex::DIVINE_SAVE_CHANCE] + itembonuses.DivineSaveChance[SBIndex::DIVINE_SAVE_CHANCE] + spellbonuses.DivineSaveChance[SBIndex::DIVINE_SAVE_CHANCE];
|
||||
if (SuccessChance && zone->random.Roll(SuccessChance))
|
||||
{
|
||||
SetHP(1);
|
||||
|
||||
int32 EffectsToTry[] =
|
||||
{
|
||||
aabonuses.DivineSaveChance[1],
|
||||
itembonuses.DivineSaveChance[1],
|
||||
spellbonuses.DivineSaveChance[1]
|
||||
aabonuses.DivineSaveChance[SBIndex::DIVINE_SAVE_SPELL_TRIGGER_ID],
|
||||
itembonuses.DivineSaveChance[SBIndex::DIVINE_SAVE_SPELL_TRIGGER_ID],
|
||||
spellbonuses.DivineSaveChance[SBIndex::DIVINE_SAVE_SPELL_TRIGGER_ID]
|
||||
};
|
||||
//Fade the divine save effect here after saving the old effects off.
|
||||
//That way, if desired, the effect could apply SE_DivineSave again.
|
||||
@ -6236,10 +6236,10 @@ bool Mob::TryDeathSave() {
|
||||
-In later expansions this SE_DeathSave was given a level limit and a heal value in its effect data.
|
||||
*/
|
||||
|
||||
if (spellbonuses.DeathSave[0]){
|
||||
if (spellbonuses.DeathSave[SBIndex::DEATH_SAVE_TYPE]){
|
||||
|
||||
int SuccessChance = 0;
|
||||
int buffSlot = spellbonuses.DeathSave[1];
|
||||
int buffSlot = spellbonuses.DeathSave[SBIndex::DEATH_SAVE_BUFFSLOT];
|
||||
int32 UD_HealMod = 0;
|
||||
int HealAmt = 300; //Death Pact max Heal
|
||||
|
||||
@ -6254,12 +6254,12 @@ bool Mob::TryDeathSave() {
|
||||
|
||||
if(zone->random.Roll(SuccessChance)) {
|
||||
|
||||
if(spellbonuses.DeathSave[0] == 2)
|
||||
if(spellbonuses.DeathSave[SBIndex::DEATH_SAVE_TYPE] == 2)
|
||||
HealAmt = RuleI(Spells, DivineInterventionHeal); //8000HP is how much LIVE Divine Intervention max heals
|
||||
|
||||
//Check if bonus Heal amount can be applied ([3] Bonus Heal [2] Level limit)
|
||||
if (spellbonuses.DeathSave[3] && (GetLevel() >= spellbonuses.DeathSave[2]))
|
||||
HealAmt += spellbonuses.DeathSave[3];
|
||||
if (spellbonuses.DeathSave[SBIndex::DEATH_SAVE_HEAL_AMT] && (GetLevel() >= spellbonuses.DeathSave[SBIndex::DEATH_SAVE_MIN_LEVEL_FOR_HEAL]))
|
||||
HealAmt += spellbonuses.DeathSave[SBIndex::DEATH_SAVE_HEAL_AMT];
|
||||
|
||||
if ((GetMaxHP() - GetHP()) < HealAmt)
|
||||
HealAmt = GetMaxHP() - GetHP();
|
||||
@ -6267,7 +6267,7 @@ bool Mob::TryDeathSave() {
|
||||
SetHP((GetHP()+HealAmt));
|
||||
Message(263, "The gods have healed you for %i points of damage.", HealAmt);
|
||||
|
||||
if(spellbonuses.DeathSave[0] == 2)
|
||||
if(spellbonuses.DeathSave[SBIndex::DEATH_SAVE_TYPE] == 2)
|
||||
entity_list.MessageCloseString(
|
||||
this,
|
||||
false,
|
||||
@ -6291,12 +6291,12 @@ bool Mob::TryDeathSave() {
|
||||
|
||||
if(zone->random.Roll(SuccessChance)) {
|
||||
|
||||
if(spellbonuses.DeathSave[0] == 2)
|
||||
if(spellbonuses.DeathSave[SBIndex::DEATH_SAVE_TYPE] == 2)
|
||||
HealAmt = RuleI(Spells, DivineInterventionHeal);
|
||||
|
||||
//Check if bonus Heal amount can be applied ([3] Bonus Heal [2] Level limit)
|
||||
if (spellbonuses.DeathSave[3] && (GetLevel() >= spellbonuses.DeathSave[2]))
|
||||
HealAmt += spellbonuses.DeathSave[3];
|
||||
if (spellbonuses.DeathSave[SBIndex::DEATH_SAVE_HEAL_AMT] && (GetLevel() >= spellbonuses.DeathSave[SBIndex::DEATH_SAVE_MIN_LEVEL_FOR_HEAL]))
|
||||
HealAmt += spellbonuses.DeathSave[SBIndex::DEATH_SAVE_HEAL_AMT];
|
||||
|
||||
HealAmt = HealAmt*UD_HealMod/100;
|
||||
|
||||
@ -6306,7 +6306,7 @@ bool Mob::TryDeathSave() {
|
||||
SetHP((GetHP()+HealAmt));
|
||||
Message(263, "The gods have healed you for %i points of damage.", HealAmt);
|
||||
|
||||
if(spellbonuses.DeathSave[0] == 2)
|
||||
if(spellbonuses.DeathSave[SBIndex::DEATH_SAVE_TYPE] == 2)
|
||||
entity_list.MessageCloseString(
|
||||
this,
|
||||
false,
|
||||
@ -6645,22 +6645,22 @@ bool Mob::TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier){
|
||||
|
||||
bool Mob::ImprovedTaunt(){
|
||||
|
||||
if (spellbonuses.ImprovedTaunt[0]){
|
||||
if (spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_MAX_LVL]){
|
||||
|
||||
if (GetLevel() > spellbonuses.ImprovedTaunt[0])
|
||||
if (GetLevel() > spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_MAX_LVL])
|
||||
return false;
|
||||
|
||||
if (spellbonuses.ImprovedTaunt[2] >= 0){
|
||||
if (spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_BUFFSLOT] >= 0){
|
||||
|
||||
target = entity_list.GetMob(buffs[spellbonuses.ImprovedTaunt[2]].casterid);
|
||||
target = entity_list.GetMob(buffs[spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_BUFFSLOT]].casterid);
|
||||
|
||||
if (target){
|
||||
SetTarget(target);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if(!TryFadeEffect(spellbonuses.ImprovedTaunt[2]))
|
||||
BuffFadeBySlot(spellbonuses.ImprovedTaunt[2], true); //If caster killed removed effect.
|
||||
if(!TryFadeEffect(spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_BUFFSLOT]))
|
||||
BuffFadeBySlot(spellbonuses.ImprovedTaunt[SBIndex::IMPROVED_TAUNT_BUFFSLOT], true); //If caster killed removed effect.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7187,7 +7187,7 @@ void Mob::CastSpellOnLand(Mob* caster, int32 spell_id)
|
||||
the CalcFocusEffect function if not 100pct.
|
||||
ApplyFocusProcLimiter() function checks for SE_Proc_Timer_Modifier which allows for limiting how often a spell from effect can be triggered
|
||||
for example, if set to base=1 and base2= 1500, then for everyone 1 successful trigger, you will be unable to trigger again for 1.5 seconds.
|
||||
|
||||
|
||||
Live only has this focus in buffs/debuffs that can be placed on a target. TODO: Will consider adding support for it as AA and Item.
|
||||
*/
|
||||
if (!caster)
|
||||
@ -7221,7 +7221,7 @@ void Mob::CastSpellOnLand(Mob* caster, int32 spell_id)
|
||||
SpellFinished(trigger_spell_id, current_target, EQ::spells::CastingSlot::Item, 0, -1, spells[trigger_spell_id].ResistDiff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (i >= 0)
|
||||
CheckNumHitsRemaining(NumHit::MatchingSpells, i);
|
||||
}
|
||||
@ -7237,13 +7237,13 @@ bool Mob::ApplyFocusProcLimiter(int32 spell_id, int buffslot)
|
||||
|
||||
//Do not allow spell cast if timer is active.
|
||||
if (buffs[buffslot].focusproclimit_time > 0)
|
||||
return false;
|
||||
return false;
|
||||
|
||||
/*
|
||||
SE_Proc_Timer_Modifier
|
||||
SE_Proc_Timer_Modifier
|
||||
base1= amount of total procs allowed until lock out timer is triggered, should be set to at least 1 in any spell for the effect to function.
|
||||
base2= lock out timer, which prevents any more procs set in ms 1500 = 1.5 seconds
|
||||
This system allows easy scaling for multiple different buffs with same effects each having seperate active individual timer checks. Ie.
|
||||
This system allows easy scaling for multiple different buffs with same effects each having seperate active individual timer checks. Ie.
|
||||
*/
|
||||
|
||||
if (IsValidSpell(spell_id)) {
|
||||
@ -7270,7 +7270,7 @@ bool Mob::ApplyFocusProcLimiter(int32 spell_id, int buffslot)
|
||||
if (!focus_proc_limit_timer.Enabled()) {
|
||||
focus_proc_limit_timer.Start(250);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2945,31 +2945,33 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
|
||||
}
|
||||
}
|
||||
|
||||
/*Buff stacking prevention spell effects (446 - 449) works as follows... If B prevent A, if C prevent B, if D prevent C.
|
||||
If checking same type ie A vs A, which ever effect base value is higher will take hold.
|
||||
Special check is added to make sure the buffs stack properly when applied from fade on duration effect, since the buff
|
||||
is not fully removed at the time of the trgger*/
|
||||
if (spellbonuses.AStacker[0]) {
|
||||
if ((effect2 == SE_AStacker) && (sp2.effectid[i] <= spellbonuses.AStacker[1]))
|
||||
/*
|
||||
Buff stacking prevention spell effects (446 - 449) works as follows... If B prevent A, if C prevent B, if D prevent C.
|
||||
If checking same type ie A vs A, which ever effect base value is higher will take hold.
|
||||
Special check is added to make sure the buffs stack properly when applied from fade on duration effect, since the buff
|
||||
is not fully removed at the time of the trigger
|
||||
*/
|
||||
if (spellbonuses.AStacker[SBIndex::BUFFSTACKER_EXISTS]) {
|
||||
if ((effect2 == SE_AStacker) && (sp2.effectid[i] <= spellbonuses.AStacker[SBIndex::BUFFSTACKER_VALUE]))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spellbonuses.BStacker[0]) {
|
||||
if ((effect2 == SE_BStacker) && (sp2.effectid[i] <= spellbonuses.BStacker[1]))
|
||||
if (spellbonuses.BStacker[SBIndex::BUFFSTACKER_EXISTS]) {
|
||||
if ((effect2 == SE_BStacker) && (sp2.effectid[i] <= spellbonuses.BStacker[SBIndex::BUFFSTACKER_VALUE]))
|
||||
return -1;
|
||||
if ((effect2 == SE_AStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_BStacker)))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spellbonuses.CStacker[0]) {
|
||||
if ((effect2 == SE_CStacker) && (sp2.effectid[i] <= spellbonuses.CStacker[1]))
|
||||
if (spellbonuses.CStacker[SBIndex::BUFFSTACKER_EXISTS]) {
|
||||
if ((effect2 == SE_CStacker) && (sp2.effectid[i] <= spellbonuses.CStacker[SBIndex::BUFFSTACKER_VALUE]))
|
||||
return -1;
|
||||
if ((effect2 == SE_BStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_CStacker)))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spellbonuses.DStacker[0]) {
|
||||
if ((effect2 == SE_DStacker) && (sp2.effectid[i] <= spellbonuses.DStacker[1]))
|
||||
if (spellbonuses.DStacker[SBIndex::BUFFSTACKER_EXISTS]) {
|
||||
if ((effect2 == SE_DStacker) && (sp2.effectid[i] <= spellbonuses.DStacker[SBIndex::BUFFSTACKER_VALUE]))
|
||||
return -1;
|
||||
if ((effect2 == SE_CStacker) && (!IsCastonFadeDurationSpell(spellid1) && buffs[buffslot].ticsremaining != 1 && IsEffectInSpell(spellid1, SE_DStacker)))
|
||||
return -1;
|
||||
@ -3786,7 +3788,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
||||
MessageString(Chat::SpellFailure, SPELL_NO_EFFECT);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Block next spell effect should be used up first(since its blocking the next spell)
|
||||
if(CanBlockSpell()) {
|
||||
int buff_count = GetMaxTotalSlots();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user