diff --git a/common/spdat.cpp b/common/spdat.cpp index b81b8167c..edd670928 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1609,19 +1609,19 @@ uint32 GetProcLimitTimer(int32 spell_id, int proc_type) { bool use_next_timer = false; for (int i = 0; i < EFFECT_COUNT; ++i) { - if (proc_type == SE_WeaponProc) { + if (proc_type == ProcType::MELEE_PROC) { if (spells[spell_id].effect_id[i] == SE_WeaponProc || spells[spell_id].effect_id[i] == SE_AddMeleeProc) { use_next_timer = true; } } - if (proc_type == SE_RangedProc) { + if (proc_type == ProcType::RANGED_PROC) { if (spells[spell_id].effect_id[i] == SE_RangedProc) { use_next_timer = true; } } - if (proc_type == SE_DefensiveProc) { + if (proc_type == ProcType::DEFENSIVE_PROC) { if (spells[spell_id].effect_id[i] == SE_DefensiveProc) { use_next_timer = true; } diff --git a/common/spdat.h b/common/spdat.h index 1e4cb49cd..cf7f7b21e 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -533,6 +533,15 @@ enum ReflectSpellType RELFECT_ALL_SINGLE_TARGET_SPELLS = 3, REFLECT_ALL_SPELLS = 4, }; +//For better organizing in proc effects, not used in spells. +enum ProcType +{ + MELEE_PROC = 1, + RANGED_PROC = 2, + DEFENSIVE_PROC = 3, + SKILL_PROC = 4, + SKILL_PROC_SUCCESS = 5, +}; enum SpellTypes : uint32 { @@ -1134,8 +1143,8 @@ typedef enum { #define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace //#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626) #define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window -#define SE_SkillProc 427 // implemented - chance to proc when using a skill(ie taunt) -#define SE_LimitToSkill 428 // implemented - limits what skills will effect a skill proc +#define SE_SkillProcAttempt 427 // implemented - chance to proc when using a skill(ie taunt) +#define SE_LimitToSkill 428 // implemented, @Procs, limits what combat skills will effect a skill proc, base: skill value, limit: none, max: none #define SE_SkillProcSuccess 429 // implemented - chance to proc when tje skill in use successfully fires. //#define SE_PostEffect 430 // *not implemented - Fear of the Dark(27641) - Alters vision //#define SE_PostEffectData 431 // *not implemented - Fear of the Dark(27641) - Alters vision diff --git a/zone/attack.cpp b/zone/attack.cpp index 403528430..da4394d91 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1603,12 +1603,12 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b /////////////////////////////////////////////////////////// ////// Send Attack Damage /////////////////////////////////////////////////////////// - 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 (my_hit.damage_done > 0 && aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] && aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SKILL] == my_hit.skill && + IsValidSpell(aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID])) { + float chance = aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] / 1000.0f; if (zone->random.Roll(chance)) - SpellFinished(aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID], other, EQ::spells::CastingSlot::Item, 0, -1, - spells[aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID]].resist_difficulty); + SpellFinished(aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID], other, EQ::spells::CastingSlot::Item, 0, -1, + spells[aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID]].resist_difficulty); } other->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, my_hit.skill, true, -1, false, m_specialattacks); @@ -1616,9 +1616,6 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b MeleeLifeTap(my_hit.damage_done); - if (my_hit.damage_done > 0 && HasSkillProcSuccess() && other && other->GetHP() > 0) - TrySkillProc(other, my_hit.skill, 0, true, Hand); - CommonBreakInvisibleFromCombat(); if (GetTarget()) @@ -3471,7 +3468,6 @@ bool Mob::HasDefensiveProcs() const bool Mob::HasSkillProcs() const { - for (int i = 0; i < MAX_SKILL_PROCS; i++) { if (spellbonuses.SkillProc[i] || itembonuses.SkillProc[i] || aabonuses.SkillProc[i]) return true; @@ -4164,12 +4160,12 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) { //Spell Procs and Quest added procs for (int i = 0; i < MAX_PROCS; i++) { if (IsValidSpell(DefensiveProcs[i].spellID)) { - if (!IsProcLimitTimerActive(DefensiveProcs[i].base_spellID, DefensiveProcs[i].proc_reuse_time, SE_DefensiveProc)) { + if (!IsProcLimitTimerActive(DefensiveProcs[i].base_spellID, DefensiveProcs[i].proc_reuse_time, ProcType::DEFENSIVE_PROC)) { float chance = ProcChance * (static_cast(DefensiveProcs[i].chance) / 100.0f); if (zone->random.Roll(chance)) { ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on); CheckNumHitsRemaining(NumHit::DefensiveSpellProcs, 0, DefensiveProcs[i].base_spellID); - SetProcLimitTimer(DefensiveProcs[i].base_spellID, DefensiveProcs[i].proc_reuse_time, SE_DefensiveProc); + SetProcLimitTimer(DefensiveProcs[i].base_spellID, DefensiveProcs[i].proc_reuse_time, ProcType::DEFENSIVE_PROC); } } } @@ -4178,17 +4174,17 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) { //AA Procs if (IsClient()){ for (int i = 0; i < MAX_AA_PROCS; i += 4) { - int32 aa_rank_id = aabonuses.DefensiveProc[i]; - int32 aa_spell_id = aabonuses.DefensiveProc[i + 1]; - int32 aa_proc_chance = 100 + aabonuses.DefensiveProc[i + 2]; - uint32 aa_proc_reuse_timer = aabonuses.DefensiveProc[i + 3]; + int32 aa_rank_id = aabonuses.DefensiveProc[i + +SBIndex::COMBAT_PROC_ORIGIN_ID]; + int32 aa_spell_id = aabonuses.DefensiveProc[i + SBIndex::COMBAT_PROC_SPELL_ID]; + int32 aa_proc_chance = 100 + aabonuses.DefensiveProc[i + SBIndex::COMBAT_PROC_RATE_MOD]; + uint32 aa_proc_reuse_timer = aabonuses.DefensiveProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER]; if (aa_rank_id) { - if (!IsProcLimitTimerActive(-aa_rank_id, aa_proc_reuse_timer, SE_DefensiveProc)) { + if (!IsProcLimitTimerActive(-aa_rank_id, aa_proc_reuse_timer, ProcType::DEFENSIVE_PROC)) { float chance = ProcChance * (static_cast(aa_proc_chance) / 100.0f); if (zone->random.Roll(chance) && IsValidSpell(aa_spell_id)) { ExecWeaponProc(nullptr, aa_spell_id, on); - SetProcLimitTimer(-aa_rank_id, aa_proc_reuse_timer, SE_DefensiveProc); + SetProcLimitTimer(-aa_rank_id, aa_proc_reuse_timer, ProcType::DEFENSIVE_PROC); } } } @@ -4197,7 +4193,8 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) { } } -void Mob::TryWeaponProc(const EQ::ItemInstance* weapon_g, Mob *on, uint16 hand) { +void Mob::TryCombatProcs(const EQ::ItemInstance* weapon_g, Mob *on, uint16 hand, const EQ::ItemData* weapon_data) { + if (!on) { SetTarget(nullptr); LogError("A null Mob object was passed to Mob::TryWeaponProc for evaluation!"); @@ -4214,6 +4211,13 @@ void Mob::TryWeaponProc(const EQ::ItemInstance* weapon_g, Mob *on, uint16 hand) return; } + //used for special case when checking last ammo item on projectile hit. + if (!weapon_g && weapon_data) { + TryWeaponProc(nullptr, weapon_data, on, hand); + TrySpellProc(nullptr, weapon_data, on, hand); + return; + } + if (!weapon_g) { TrySpellProc(nullptr, (const EQ::ItemData*)nullptr, on); return; @@ -4253,7 +4257,7 @@ void Mob::TryWeaponProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon // Try innate proc on weapon // We can proc once here, either weapon or one aug bool proced = false; // silly bool to prevent augs from going if weapon does - skillinuse = GetSkillByItemType(weapon->ItemType); + if (weapon->Proc.Type == EQ::item::ItemEffectCombatProc && IsValidSpell(weapon->Proc.Effect)) { float WPC = ProcChance * (100.0f + // Proc chance for this weapon static_cast(weapon->ProcRate)) / 100.0f; @@ -4330,8 +4334,16 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, float ProcChance = 0.0f; ProcChance = GetProcChances(ProcBonus, hand); - if (hand == EQ::invslot::slotSecondary) + bool passed_skill_limit_check = true; + EQ::skills::SkillType skillinuse = EQ::skills::SkillHandtoHand; + + if (weapon){ + skillinuse = GetSkillByItemType(weapon->ItemType); + } + + if (hand == EQ::invslot::slotSecondary) { ProcChance /= 2; + } bool rangedattk = false; if (weapon && hand == EQ::invslot::slotRange) { @@ -4343,8 +4355,9 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, } } - if (!weapon && hand == EQ::invslot::slotRange && GetSpecialAbility(SPECATK_RANGED_ATK)) + if (!weapon && hand == EQ::invslot::slotRange && GetSpecialAbility(SPECATK_RANGED_ATK)) { rangedattk = true; + } int16 poison_slot=-1; @@ -4353,8 +4366,9 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, continue; // If pets ever can proc from off hand, this will need to change if (SpellProcs[i].base_spellID == POISON_PROC && - (!weapon || weapon->ItemType != EQ::item::ItemType1HPiercing)) + (!weapon || weapon->ItemType != EQ::item::ItemType1HPiercing)) { continue; // Old school poison will only proc with 1HP equipped. + } // Not ranged if (!rangedattk) { @@ -4375,14 +4389,16 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, poison_slot=i; continue; // Process the poison proc last per @mackal } - - if (!IsProcLimitTimerActive(SpellProcs[i].base_spellID, SpellProcs[i].proc_reuse_time, SE_WeaponProc)) { + + passed_skill_limit_check = PassLimitToSkill(skillinuse, SpellProcs[i].base_spellID, ProcType::MELEE_PROC); + + if (passed_skill_limit_check && !IsProcLimitTimerActive(SpellProcs[i].base_spellID, SpellProcs[i].proc_reuse_time, ProcType::MELEE_PROC)) { float chance = ProcChance * (static_cast(SpellProcs[i].chance) / 100.0f); if (zone->random.Roll(chance)) { LogCombat("Spell proc [{}] procing spell [{}] ([{}] percent chance)", i, SpellProcs[i].spellID, chance); SendBeginCast(SpellProcs[i].spellID, 0); ExecWeaponProc(nullptr, SpellProcs[i].spellID, on, SpellProcs[i].level_override); - SetProcLimitTimer(SpellProcs[i].base_spellID, SpellProcs[i].proc_reuse_time, SE_WeaponProc); + SetProcLimitTimer(SpellProcs[i].base_spellID, SpellProcs[i].proc_reuse_time, ProcType::MELEE_PROC); CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0, SpellProcs[i].base_spellID); } else { @@ -4395,13 +4411,15 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, // ranged spell procs (buffs) if (RangedProcs[i].spellID != SPELL_UNKNOWN) { - if (!IsProcLimitTimerActive(RangedProcs[i].base_spellID, RangedProcs[i].proc_reuse_time, SE_RangedProc)) { + passed_skill_limit_check = PassLimitToSkill(skillinuse, RangedProcs[i].base_spellID, ProcType::RANGED_PROC); + + if (passed_skill_limit_check && !IsProcLimitTimerActive(RangedProcs[i].base_spellID, RangedProcs[i].proc_reuse_time, ProcType::RANGED_PROC)) { float chance = ProcChance * (static_cast(RangedProcs[i].chance) / 100.0f); if (zone->random.Roll(chance)) { LogCombat("Ranged proc [{}] procing spell [{}] ([{}] percent chance)", i, RangedProcs[i].spellID, chance); ExecWeaponProc(nullptr, RangedProcs[i].spellID, on); CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0, RangedProcs[i].base_spellID); - SetProcLimitTimer(RangedProcs[i].base_spellID, RangedProcs[i].proc_reuse_time, SE_RangedProc); + SetProcLimitTimer(RangedProcs[i].base_spellID, RangedProcs[i].proc_reuse_time, ProcType::RANGED_PROC); } else { LogCombat("Ranged proc [{}] failed to proc [{}] ([{}] percent chance)", i, RangedProcs[i].spellID, chance); @@ -4411,7 +4429,7 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, } } - //AA Procs + //AA Melee and Ranged Procs if (IsClient()) { for (int i = 0; i < MAX_AA_PROCS; i += 4) { @@ -4423,22 +4441,25 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, if (!rangedattk) { - aa_rank_id = aabonuses.SpellProc[i]; - aa_spell_id = aabonuses.SpellProc[i + 1]; - aa_proc_chance += aabonuses.SpellProc[i + 2]; - aa_proc_reuse_timer = aabonuses.SpellProc[i + 3]; - proc_type = SE_WeaponProc; + aa_rank_id = aabonuses.SpellProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID]; + aa_spell_id = aabonuses.SpellProc[i + SBIndex::COMBAT_PROC_SPELL_ID]; + aa_proc_chance += aabonuses.SpellProc[i + SBIndex::COMBAT_PROC_RATE_MOD]; + aa_proc_reuse_timer = aabonuses.SpellProc[i + SBIndex::COMBAT_PROC_RATE_MOD]; + proc_type = ProcType::MELEE_PROC; } else { - aa_rank_id = aabonuses.RangedProc[i]; - aa_spell_id = aabonuses.RangedProc[i + 1]; - aa_proc_chance += aabonuses.RangedProc[i + 2]; - aa_proc_reuse_timer = aabonuses.RangedProc[i + 3]; - proc_type = SE_RangedProc; + aa_rank_id = aabonuses.RangedProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID]; + aa_spell_id = aabonuses.RangedProc[i + SBIndex::COMBAT_PROC_SPELL_ID]; + aa_proc_chance += aabonuses.RangedProc[i + SBIndex::COMBAT_PROC_RATE_MOD]; + aa_proc_reuse_timer = aabonuses.RangedProc[i + SBIndex::COMBAT_PROC_RATE_MOD]; + proc_type = ProcType::RANGED_PROC; } if (aa_rank_id) { - if (!IsProcLimitTimerActive(-aa_rank_id, aa_proc_reuse_timer, proc_type)) { + + passed_skill_limit_check = PassLimitToSkill(skillinuse, 0, proc_type, aa_rank_id); + + if (passed_skill_limit_check && !IsProcLimitTimerActive(-aa_rank_id, aa_proc_reuse_timer, proc_type)) { float chance = ProcChance * (static_cast(aa_proc_chance) / 100.0f); if (zone->random.Roll(chance) && IsValidSpell(aa_spell_id)) { LogCombat("AA proc [{}] procing spell [{}] ([{}] percent chance)", aa_rank_id, aa_spell_id, chance); @@ -4469,13 +4490,12 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, } if (HasSkillProcs() && hand != EQ::invslot::slotRange) { //We check ranged skill procs within the attack functions. - uint16 skillinuse = 28; - if (weapon) - skillinuse = GetSkillByItemType(weapon->ItemType); - TrySkillProc(on, skillinuse, 0, false, hand); } + if (HasSkillProcSuccess() && hand != EQ::invslot::slotRange) { //We check ranged skill procs within the attack functions. + TrySkillProc(on, skillinuse, 0, true, hand); + } return; } @@ -5040,7 +5060,7 @@ void Mob::ApplyDamageTable(DamageHitInfo &hit) Log(Logs::Detail, Logs::Attack, "Damage table applied %d (max %d)", percent, damage_table.max_extra); } -void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, uint16 hand, bool IsDefensive) +void Mob::TrySkillProc(Mob *on, EQ::skills::SkillType skill, uint16 ReuseTime, bool Success, uint16 hand, bool IsDefensive) { if (!on) { @@ -5049,12 +5069,19 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui return; } - if (!spellbonuses.LimitToSkill[skill] && !itembonuses.LimitToSkill[skill] && !aabonuses.LimitToSkill[skill]) + if (on->HasDied()) { return; + } - /*Allow one proc from each (Spell/Item/AA) - Kayen: Due to limited avialability of effects on live it is too difficult - to confirm how they stack at this time, will adjust formula when more data is avialablle to test.*/ + if (!spellbonuses.LimitToSkill[skill] && !itembonuses.LimitToSkill[skill] && !aabonuses.LimitToSkill[skill]) { + return; + } + + /* + Allow one proc from each (Spell/Item/AA) + Kayen: Due to limited avialability of effects on live it is too difficult + to confirm how they stack at this time, will adjust formula when more data is avialablle to test. + */ bool CanProc = true; uint16 base_spell_id = 0; @@ -5069,22 +5096,24 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui if (spellbonuses.LimitToSkill[skill]) { - for (int e = 0; e < MAX_SKILL_PROCS; e++) { + for (int i = 0; i < MAX_SKILL_PROCS; i++) { if (CanProc && - ((!Success && spellbonuses.SkillProc[e] && IsValidSpell(spellbonuses.SkillProc[e])) - || (Success && spellbonuses.SkillProcSuccess[e] && IsValidSpell(spellbonuses.SkillProcSuccess[e])))) { + ((!Success && spellbonuses.SkillProc[i] && IsValidSpell(spellbonuses.SkillProc[i])) + || (Success && spellbonuses.SkillProcSuccess[i] && IsValidSpell(spellbonuses.SkillProcSuccess[i])))) { - if (Success) - base_spell_id = spellbonuses.SkillProcSuccess[e]; - else - base_spell_id = spellbonuses.SkillProc[e]; + if (Success) { + base_spell_id = spellbonuses.SkillProcSuccess[i]; + } + else { + base_spell_id = spellbonuses.SkillProc[i]; + } proc_spell_id = 0; ProcMod = 0; for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[base_spell_id].effect_id[i] == SE_SkillProc || spells[base_spell_id].effect_id[i] == SE_SkillProcSuccess) { + if (spells[base_spell_id].effect_id[i] == SE_SkillProcAttempt || spells[base_spell_id].effect_id[i] == SE_SkillProcSuccess) { proc_spell_id = spells[base_spell_id].base_value[i]; ProcMod = static_cast(spells[base_spell_id].limit_value[i]); } @@ -5095,8 +5124,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui float final_chance = chance * (ProcMod / 100.0f); if (zone->random.Roll(final_chance)) { ExecWeaponProc(nullptr, proc_spell_id, on); - CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0, - base_spell_id); + CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0, base_spell_id); CanProc = false; break; } @@ -5114,21 +5142,23 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui if (itembonuses.LimitToSkill[skill]) { CanProc = true; - for (int e = 0; e < MAX_SKILL_PROCS; e++) { + for (int i = 0; i < MAX_SKILL_PROCS; i++) { if (CanProc && - ((!Success && itembonuses.SkillProc[e] && IsValidSpell(itembonuses.SkillProc[e])) - || (Success && itembonuses.SkillProcSuccess[e] && IsValidSpell(itembonuses.SkillProcSuccess[e])))) { + ((!Success && itembonuses.SkillProc[i] && IsValidSpell(itembonuses.SkillProc[i])) + || (Success && itembonuses.SkillProcSuccess[i] && IsValidSpell(itembonuses.SkillProcSuccess[i])))) { - if (Success) - base_spell_id = itembonuses.SkillProcSuccess[e]; - else - base_spell_id = itembonuses.SkillProc[e]; + if (Success) { + base_spell_id = itembonuses.SkillProcSuccess[i]; + } + else { + base_spell_id = itembonuses.SkillProc[i]; + } proc_spell_id = 0; ProcMod = 0; for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[base_spell_id].effect_id[i] == SE_SkillProc || spells[base_spell_id].effect_id[i] == SE_SkillProcSuccess) { + if (spells[base_spell_id].effect_id[i] == SE_SkillProcAttempt || spells[base_spell_id].effect_id[i] == SE_SkillProcSuccess) { proc_spell_id = spells[base_spell_id].base_value[i]; ProcMod = static_cast(spells[base_spell_id].limit_value[i]); } @@ -5161,16 +5191,16 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui int32 limit_value = 0; uint32 slot = 0; - for (int e = 0; e < MAX_SKILL_PROCS; e++) { + for (int i = 0; i < MAX_SKILL_PROCS; i++) { if (CanProc && - ((!Success && aabonuses.SkillProc[e]) - || (Success && aabonuses.SkillProcSuccess[e]))) { + ((!Success && aabonuses.SkillProc[i]) + || (Success && aabonuses.SkillProcSuccess[i]))) { int aaid = 0; if (Success) - base_spell_id = aabonuses.SkillProcSuccess[e]; + base_spell_id = aabonuses.SkillProcSuccess[i]; else - base_spell_id = aabonuses.SkillProc[e]; + base_spell_id = aabonuses.SkillProc[i]; proc_spell_id = 0; ProcMod = 0; @@ -5190,7 +5220,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui limit_value = effect.limit_value; slot = effect.slot; - if (effect_id == SE_SkillProc || effect_id == SE_SkillProcSuccess) { + if (effect_id == SE_SkillProcAttempt || effect_id == SE_SkillProcSuccess) { proc_spell_id = base_value; ProcMod = static_cast(limit_value); } @@ -5225,12 +5255,14 @@ float Mob::GetSkillProcChances(uint16 ReuseTime, uint16 hand) { if (!ReuseTime && hand) { weapon_speed = GetWeaponSpeedbyHand(hand); ProcChance = static_cast(weapon_speed) * (RuleR(Combat, AvgProcsPerMinute) / 60000.0f); - if (hand == EQ::invslot::slotSecondary) + if (hand == EQ::invslot::slotSecondary) { ProcChance /= 2; + } } - else + else { ProcChance = static_cast(ReuseTime) * (RuleR(Combat, AvgProcsPerMinute) / 60000.0f); + } return ProcChance; } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index bf4c5cfb9..28b98d655 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1074,11 +1074,11 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_WeaponProc: case SE_AddMeleeProc: for (int i = 0; i < MAX_AA_PROCS; i += 4) { - if (!newbon->SpellProc[i]) { - newbon->SpellProc[i] = rank.id; //aa rank id - newbon->SpellProc[i + 1] = base_value; //proc spell id - newbon->SpellProc[i + 2] = limit_value; //proc rate modifer - newbon->SpellProc[i + 3] = 0; //Lock out Timer + if (!newbon->SpellProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID]) { + newbon->SpellProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] = rank.id; //aa rank id + newbon->SpellProc[i + SBIndex::COMBAT_PROC_SPELL_ID] = base_value; //proc spell id + newbon->SpellProc[i + SBIndex::COMBAT_PROC_RATE_MOD] = limit_value; //proc rate modifer + newbon->SpellProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER] = 0; //Lock out Timer break; } } @@ -1086,11 +1086,11 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_RangedProc: for (int i = 0; i < MAX_AA_PROCS; i += 4) { - if (!newbon->RangedProc[i]) { - newbon->RangedProc[i] = rank.id; //aa rank id - newbon->RangedProc[i + 1] = base_value; //proc spell id - newbon->RangedProc[i + 2] = limit_value; //proc rate modifer - newbon->RangedProc[i + 3] = 0; //Lock out Timer + if (!newbon->RangedProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID]) { + newbon->RangedProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] = rank.id; //aa rank id + newbon->RangedProc[i + SBIndex::COMBAT_PROC_SPELL_ID] = base_value; //proc spell id + newbon->RangedProc[i + SBIndex::COMBAT_PROC_RATE_MOD] = limit_value; //proc rate modifer + newbon->RangedProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER] = 0; //Lock out Timer break; } } @@ -1098,11 +1098,11 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_DefensiveProc: for (int i = 0; i < MAX_AA_PROCS; i += 4) { - if (!newbon->DefensiveProc[i]) { - newbon->DefensiveProc[i] = rank.id; //aa rank id - newbon->DefensiveProc[i + 1] = base_value; //proc spell id - newbon->DefensiveProc[i + 2] = limit_value; //proc rate modifer - newbon->DefensiveProc[i + 3] = 0; //Lock out Timer + if (!newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID]) { + newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] = rank.id; //aa rank id + newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_SPELL_ID] = base_value; //proc spell id + newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_RATE_MOD] = limit_value; //proc rate modifer + newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER] = 0; //Lock out Timer break; } } @@ -1118,23 +1118,23 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->Proc_Timer_Modifier = true; for (int i = 0; i < MAX_AA_PROCS; i += 4) { - if (newbon->SpellProc[i] == rank.id) { - if (!newbon->SpellProc[i + 3]) { - newbon->SpellProc[i + 3] = limit_value;//Lock out Timer + if (newbon->SpellProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] == rank.id) { + if (!newbon->SpellProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER]) { + newbon->SpellProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER] = limit_value;//Lock out Timer break; } } - if (newbon->RangedProc[i] == rank.id) { - if (!newbon->RangedProc[i + 3]) { - newbon->RangedProc[i + 3] = limit_value;//Lock out Timer + if (newbon->RangedProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] == rank.id) { + if (!newbon->RangedProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER]) { + newbon->RangedProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER] = limit_value;//Lock out Timer break; } } - if (newbon->DefensiveProc[i] == rank.id) { - if (!newbon->DefensiveProc[i + 3]) { - newbon->DefensiveProc[i + 3] = limit_value;//Lock out Timer + if (newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_ORIGIN_ID] == rank.id) { + if (!newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER]) { + newbon->DefensiveProc[i + SBIndex::COMBAT_PROC_REUSE_TIMER] = limit_value;//Lock out Timer break; } } @@ -1208,9 +1208,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_SkillAttackProc: { // You can only have one of these per client. [AA Dragon Punch] - newbon->SkillAttackProc[SBIndex::SKILLPROC_CHANCE] = base_value; // Chance base 1000 = 100% proc rate - newbon->SkillAttackProc[SBIndex::SKILLPROC_SKILL] = limit_value; // Skill to Proc Off - newbon->SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID] = rank.spell; // spell to proc + newbon->SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] = base_value; // Chance base 1000 = 100% proc rate + newbon->SkillAttackProc[SBIndex::SKILLATK_PROC_SKILL] = limit_value; // Skill to Proc Off + newbon->SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID] = rank.spell; // spell to proc break; } @@ -1458,15 +1458,19 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; case SE_LimitToSkill: { + // Bad data or unsupported new skill - if (limit_value > EQ::skills::HIGHEST_SKILL) + if (base_value > EQ::skills::HIGHEST_SKILL) { break; - if (base_value <= EQ::skills::HIGHEST_SKILL) + } + if (base_value <= EQ::skills::HIGHEST_SKILL) { newbon->LimitToSkill[base_value] = true; + newbon->LimitToSkill[EQ::skills::HIGHEST_SKILL + 3] = true; //Used as a general exists check + } break; } - case SE_SkillProc: { + case SE_SkillProcAttempt: { for (int e = 0; e < MAX_SKILL_PROCS; e++) { if (newbon->SkillProc[e] && newbon->SkillProc[e] == rank.id) break; // Do not use the same aa id more than once. @@ -3535,15 +3539,17 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_LimitToSkill:{ // Bad data or unsupported new skill - if (limit_value > EQ::skills::HIGHEST_SKILL) + if (effect_value > EQ::skills::HIGHEST_SKILL) { break; + } if (effect_value <= EQ::skills::HIGHEST_SKILL){ new_bonus->LimitToSkill[effect_value] = true; + new_bonus->LimitToSkill[EQ::skills::HIGHEST_SKILL + 3] = true; //Used as a general exists check } break; } - case SE_SkillProc:{ + case SE_SkillProcAttempt:{ for(int e = 0; e < MAX_SKILL_PROCS; e++) { @@ -5528,7 +5534,7 @@ void Mob::NegateSpellEffectBonuses(uint16 spell_id) } } - case SE_SkillProc: { + case SE_SkillProcAttempt: { for (int e = 0; e < MAX_SKILL_PROCS; e++) { if (negate_spellbonus) { spellbonuses.SkillProc[e] = effect_value; } diff --git a/zone/bot.cpp b/zone/bot.cpp index 5de3bc7e9..031282051 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3248,7 +3248,7 @@ void Bot::AI_Process() TriggerDefensiveProcs(tar, EQ::invslot::slotPrimary, false); TEST_COMBATANTS(); - TryWeaponProc(p_item, tar, EQ::invslot::slotPrimary); + TryCombatProcs(p_item, tar, EQ::invslot::slotPrimary); // bool tripleSuccess = false; @@ -3337,7 +3337,7 @@ void Bot::AI_Process() Attack(tar, EQ::invslot::slotSecondary); // Single attack with offhand TEST_COMBATANTS(); - TryWeaponProc(s_item, tar, EQ::invslot::slotSecondary); + TryCombatProcs(s_item, tar, EQ::invslot::slotSecondary); TEST_COMBATANTS(); if (CanThisClassDoubleAttack() && CheckBotDoubleAttack()) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e23bebe65..b7b44277e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -721,17 +721,17 @@ void Client::CompleteConnect() case SE_AddMeleeProc: case SE_WeaponProc: { - AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetProcLimitTimer(buffs[j1].spellid, SE_WeaponProc)); + AddProcToWeapon(GetProcID(buffs[j1].spellid, x1), false, 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC)); break; } case SE_DefensiveProc: { - AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, SE_DefensiveProc)); + AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC)); break; } case SE_RangedProc: { - AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, SE_RangedProc)); + AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC)); break; } } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index b363292e8..e96e2ac02 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -414,7 +414,7 @@ bool Client::Process() { else if (auto_attack_target->GetHP() > -10) // -10 so we can watch people bleed in PvP { EQ::ItemInstance *wpn = GetInv().GetItem(EQ::invslot::slotPrimary); - TryWeaponProc(wpn, auto_attack_target, EQ::invslot::slotPrimary); + TryCombatProcs(wpn, auto_attack_target, EQ::invslot::slotPrimary); TriggerDefensiveProcs(auto_attack_target, EQ::invslot::slotPrimary, false); DoAttackRounds(auto_attack_target, EQ::invslot::slotPrimary); @@ -460,7 +460,7 @@ bool Client::Process() { CheckIncreaseSkill(EQ::skills::SkillDualWield, auto_attack_target, -10); if (CheckDualWield()) { EQ::ItemInstance *wpn = GetInv().GetItem(EQ::invslot::slotSecondary); - TryWeaponProc(wpn, auto_attack_target, EQ::invslot::slotSecondary); + TryCombatProcs(wpn, auto_attack_target, EQ::invslot::slotSecondary); DoAttackRounds(auto_attack_target, EQ::invslot::slotSecondary); } diff --git a/zone/common.h b/zone/common.h index cd7d072be..4998d3889 100644 --- a/zone/common.h +++ b/zone/common.h @@ -533,7 +533,7 @@ struct StatBonuses { int32 Metabolism; // Food/drink consumption rates. bool Sanctuary; // Sanctuary effect, lowers place on hate list until cast on others. int32 FactionModPct; // Modifies amount of faction gained. - bool LimitToSkill[EQ::skills::HIGHEST_SKILL + 2]; // Determines if we need to search for a skill proc. + bool LimitToSkill[EQ::skills::HIGHEST_SKILL + 3]; // Determines if we need to search for a skill proc. uint32 SkillProc[MAX_SKILL_PROCS]; // Max number of spells containing skill_procs. uint32 SkillProcSuccess[MAX_SKILL_PROCS]; // Max number of spells containing skill_procs_success. int32 SpellProc[MAX_AA_PROCS]; // Max number of spells containing melee spell procs. @@ -671,9 +671,9 @@ namespace SBIndex { constexpr uint16 POSITION_FRONT = 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 SKILLATK_PROC_CHANCE = 0; // SPA 427 + constexpr uint16 SKILLATK_PROC_SKILL = 1; // SPA 427 + constexpr uint16 SKILLATK_PROC_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 @@ -688,14 +688,18 @@ namespace SBIndex { constexpr uint16 REFLECT_CHANCE = 0; // SPA 158 constexpr uint16 REFLECT_RESISTANCE_MOD = 1; // SPA 158 constexpr uint16 REFLECT_DMG_EFFECTIVENESS = 2; // SPA 158 + constexpr uint16 COMBAT_PROC_ORIGIN_ID = 0; // SPA + constexpr uint16 COMBAT_PROC_SPELL_ID = 1; // SPA + constexpr uint16 COMBAT_PROC_RATE_MOD = 2; // SPA + constexpr uint16 COMBAT_PROC_REUSE_TIMER = 3; // SPA }; typedef struct { - uint16 spellID; + int32 spellID; uint16 chance; - uint16 base_spellID; + int32 base_spellID; int level_override; uint32 proc_reuse_time; } tProc; diff --git a/zone/mob.cpp b/zone/mob.cpp index c2e09c121..f4e4582be 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4213,15 +4213,17 @@ int Mob::GetSnaredAmount() void Mob::TriggerDefensiveProcs(Mob *on, uint16 hand, bool FromSkillProc, int damage) { - if (!on) + if (!on) { return; + } - if (!FromSkillProc) + if (!FromSkillProc) { on->TryDefensiveProc(this, hand); + } //Defensive Skill Procs if (damage < 0 && damage >= -4) { - uint16 skillinuse = 0; + EQ::skills::SkillType skillinuse = EQ::skills::SkillBlock; switch (damage) { case (-1): skillinuse = EQ::skills::SkillBlock; @@ -4240,11 +4242,13 @@ void Mob::TriggerDefensiveProcs(Mob *on, uint16 hand, bool FromSkillProc, int da break; } - if (on->HasSkillProcs()) + if (on->HasSkillProcs()) { on->TrySkillProc(this, skillinuse, 0, false, hand, true); + } - if (on->HasSkillProcSuccess()) + if (on && on->HasSkillProcSuccess()) { on->TrySkillProc(this, skillinuse, 0, true, hand, true); + } } } @@ -5617,7 +5621,7 @@ void Mob::SlowMitigation(Mob* caster) } } -uint16 Mob::GetSkillByItemType(int ItemType) +EQ::skills::SkillType Mob::GetSkillByItemType(int ItemType) { switch (ItemType) { case EQ::item::ItemType1HSlash: @@ -5673,22 +5677,6 @@ uint8 Mob::GetItemTypeBySkill(EQ::skills::SkillType skill) } } - -bool Mob::PassLimitToSkill(uint16 spell_id, uint16 skill) { - - if (!IsValidSpell(spell_id)) - return false; - - for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[spell_id].effect_id[i] == SE_LimitToSkill){ - if (spells[spell_id].base_value[i] == skill){ - return true; - } - } - } - return false; -} - uint16 Mob::GetWeaponSpeedbyHand(uint16 hand) { uint16 weapon_speed = 0; diff --git a/zone/mob.h b/zone/mob.h index 07c5c4382..0ee5a76c2 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -701,7 +701,7 @@ public: static uint32 RandomTimer(int min, int max); static uint8 GetDefaultGender(uint16 in_race, uint8 in_gender = 0xFF); static bool IsPlayerRace(uint16 in_race); - uint16 GetSkillByItemType(int ItemType); + EQ::skills::SkillType GetSkillByItemType(int ItemType); uint8 GetItemTypeBySkill(EQ::skills::SkillType skill); virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr); virtual void MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, const char *petname = nullptr, float in_size = 0.0f); @@ -864,6 +864,7 @@ public: bool IsTargetedFocusEffect(int focus_type); bool HasPersistDeathIllusion(int32 spell_id); + bool TryDoubleMeleeRoundEffect(); bool GetUseDoubleMeleeRoundDmgBonus() const { return use_double_melee_round_dmg_bonus; } inline void SetUseDoubleMeleeRoundDmgBonus(bool val) { use_double_melee_round_dmg_bonus = val; } @@ -1446,13 +1447,13 @@ protected: bool spawned; void CalcSpellBonuses(StatBonuses* newbon); virtual void CalcBonuses(); - void TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); // hand = SlotCharm? - bool PassLimitToSkill(uint16 spell_id, uint16 skill); + void TrySkillProc(Mob *on, EQ::skills::SkillType skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); // hand = SlotCharm? + bool PassLimitToSkill(EQ::skills::SkillType skill, int32 spell_id, int proc_type, int aa_id=0); bool PassLimitClass(uint32 Classes_, uint16 Class_); void TryDefensiveProc(Mob *on, uint16 hand = EQ::invslot::slotPrimary); void TryWeaponProc(const EQ::ItemInstance* inst, const EQ::ItemData* weapon, Mob *on, uint16 hand = EQ::invslot::slotPrimary); void TrySpellProc(const EQ::ItemInstance* inst, const EQ::ItemData* weapon, Mob *on, uint16 hand = EQ::invslot::slotPrimary); - void TryWeaponProc(const EQ::ItemInstance* weapon, Mob *on, uint16 hand = EQ::invslot::slotPrimary); + void TryCombatProcs(const EQ::ItemInstance* weapon, Mob *on, uint16 hand = EQ::invslot::slotPrimary, const EQ::ItemData* weapon_data = nullptr); void ExecWeaponProc(const EQ::ItemInstance* weapon, uint16 spell_id, Mob *on, int level_override = -1); virtual float GetProcChances(float ProcBonus, uint16 hand = EQ::invslot::slotPrimary); virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = EQ::invslot::slotPrimary, Mob *on = nullptr); diff --git a/zone/pets.cpp b/zone/pets.cpp index 8aeb1f5f2..d14989f73 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -580,13 +580,13 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { case SE_WeaponProc: // We need to reapply buff based procs // We need to do this here so suspended pets also regain their procs. - AddProcToWeapon(GetProcID(buffs[j1].spellid,x1), false, 100+spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetProcLimitTimer(buffs[j1].spellid, SE_WeaponProc)); + AddProcToWeapon(GetProcID(buffs[j1].spellid,x1), false, 100+spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC)); break; case SE_DefensiveProc: - AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, SE_DefensiveProc)); + AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC)); break; case SE_RangedProc: - AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, SE_RangedProc)); + AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC)); break; case SE_Charm: case SE_Rune: diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index f6003a8d2..a8c6f932d 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -196,12 +196,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[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 (my_hit.damage_done > 0 && aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] && aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SKILL] == skill && + IsValidSpell(aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID])) { + float chance = aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] / 1000.0f; if (zone->random.Roll(chance)) - SpellFinished(aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID], who, EQ::spells::CastingSlot::Item, 0, -1, - spells[aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID]].resist_difficulty); + SpellFinished(aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID], who, EQ::spells::CastingSlot::Item, 0, -1, + spells[aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID]].resist_difficulty); } who->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, skill, false); @@ -212,11 +212,12 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 bas if (HasDied()) return; - if (HasSkillProcs()) + if (HasSkillProcs()) { TrySkillProc(who, skill, ReuseTime * 1000); - - if (my_hit.damage_done > 0 && HasSkillProcSuccess()) + } + if (my_hit.damage_done > 0 && HasSkillProcSuccess()) { TrySkillProc(who, skill, ReuseTime * 1000, true); + } } // We should probably refactor this to take the struct not the packet @@ -798,7 +799,7 @@ void Mob::DoArcheryAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, co const EQ::ItemInstance *_RangeWeapon = nullptr; const EQ::ItemInstance *_Ammo = nullptr; - const EQ::ItemData *ammo_lost = nullptr; + const EQ::ItemData *last_ammo_used = nullptr; /* If LaunchProjectile is false this function will do archery damage on target, @@ -822,7 +823,7 @@ void Mob::DoArcheryAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, co if (!RangeWeapon && !Ammo && range_id && ammo_id) { if (IsClient()) { _RangeWeapon = CastToClient()->m_inv[EQ::invslot::slotRange]; - if (_RangeWeapon && _RangeWeapon->GetItem() && + if (_RangeWeapon && _RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id) RangeWeapon = _RangeWeapon; @@ -830,7 +831,7 @@ void Mob::DoArcheryAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, co if (_Ammo && _Ammo->GetItem() && _Ammo->GetItem()->ID == ammo_id) Ammo = _Ammo; else - ammo_lost = database.GetItem(ammo_id); + last_ammo_used = database.GetItem(ammo_id); } } } @@ -900,34 +901,39 @@ void Mob::DoArcheryAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, co other->Damage(this, TotalDmg, SPELL_UNKNOWN, EQ::skills::SkillArchery); - // Skill Proc Success - if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()) { - if (ReuseTime) - TrySkillProc(other, EQ::skills::SkillArchery, ReuseTime); - else - TrySkillProc(other, EQ::skills::SkillArchery, 0, true, EQ::invslot::slotRange); - } - // end of old fuck - if (LaunchProjectile) - return; // Shouldn't reach this point durring initial launch phase, but just in case. // Weapon Proc - if (RangeWeapon && other && !other->HasDied()) - TryWeaponProc(RangeWeapon, other, EQ::invslot::slotRange); + if (RangeWeapon && other && !other->HasDied()) { + TryCombatProcs(RangeWeapon, other, EQ::invslot::slotRange); + } - // Ammo Proc - if (ammo_lost) - TryWeaponProc(nullptr, ammo_lost, other, EQ::invslot::slotRange); - else if (Ammo && other && !other->HasDied()) - TryWeaponProc(Ammo, other, EQ::invslot::slotRange); + // Ammo Proc, do not try spell procs if from ammo. + if (last_ammo_used) { + TryWeaponProc(nullptr, last_ammo_used, other, EQ::invslot::slotRange); + } + else if (Ammo && other && !other->HasDied()) { + TryWeaponProc(Ammo, Ammo->GetItem(), other, EQ::invslot::slotRange); + } - // Skill Proc + // Skill Proc Attempt if (HasSkillProcs() && other && !other->HasDied()) { - if (ReuseTime) + if (ReuseTime) { TrySkillProc(other, EQ::skills::SkillArchery, ReuseTime); - else + } + else { TrySkillProc(other, EQ::skills::SkillArchery, 0, false, EQ::invslot::slotRange); + } + } + + // Skill Proc Success ... can proc off hits OR misses + if (HasSkillProcSuccess() && other && !other->HasDied()) { + if (ReuseTime) { + TrySkillProc(other, EQ::skills::SkillArchery, ReuseTime, true); + } + else { + TrySkillProc(other, EQ::skills::SkillArchery, 0, true, EQ::invslot::slotRange); + } } } @@ -991,7 +997,7 @@ bool Mob::TryProjectileAttack(Mob *other, const EQ::ItemData *item, EQ::skills:: if (Ammo && Ammo->GetItem()) ProjectileAtk[slot].ammo_id = Ammo->GetItem()->ID; - ProjectileAtk[slot].ammo_slot = 0; + ProjectileAtk[slot].ammo_slot = AmmoSlot; ProjectileAtk[slot].skill = skillInUse; ProjectileAtk[slot].speed_mod = speed; @@ -1268,15 +1274,18 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha other->Damage(this, TotalDmg, SPELL_UNKNOWN, skillInUse); - if (TotalDmg > 0 && HasSkillProcSuccess() && !other->HasDied()) - TrySkillProc(other, skillInUse, 0, true, EQ::invslot::slotRange); - //try proc on hits and misses - if(other && !other->HasDied()) + if (other && !other->HasDied()) { TrySpellProc(nullptr, (const EQ::ItemData*)nullptr, other, EQ::invslot::slotRange); + } - if (HasSkillProcs() && other && !other->HasDied()) + if (HasSkillProcs() && other && !other->HasDied()) { TrySkillProc(other, skillInUse, 0, false, EQ::invslot::slotRange); + } + + if (HasSkillProcSuccess() && other && !other->HasDied()) { + TrySkillProc(other, skillInUse, 0, true, EQ::invslot::slotRange); + } } void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 @@ -1294,7 +1303,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 int ammo_slot = EQ::invslot::slotRange; const EQ::ItemInstance* RangeWeapon = m_inv[EQ::invslot::slotRange]; - + if (!RangeWeapon || !RangeWeapon->IsClassCommon()) { LogCombat("Ranged attack canceled. Missing or invalid ranged weapon ([{}]) in slot [{}]", GetItemIDAt(EQ::invslot::slotRange), EQ::invslot::slotRange); Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing to throw!", GetItemIDAt(EQ::invslot::slotRange)); @@ -1355,7 +1364,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 return; } - DoThrowingAttackDmg(other, RangeWeapon, item); + DoThrowingAttackDmg(other, RangeWeapon, item, 0, 0, 0, 0, 0,ammo_slot); // Consume Ammo, unless Ammo Consumption is disabled if (RuleB(Combat, ThrowingConsumesAmmo)) { @@ -1378,8 +1387,8 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, c return; } - const EQ::ItemInstance *_RangeWeapon = nullptr; - const EQ::ItemData *ammo_lost = nullptr; + const EQ::ItemInstance *m_RangeWeapon = nullptr;//throwing weapon + const EQ::ItemData *last_ammo_used = nullptr; /* If LaunchProjectile is false this function will do archery damage on target, @@ -1394,12 +1403,14 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, c } else { if (!RangeWeapon && range_id) { if (IsClient()) { - _RangeWeapon = CastToClient()->m_inv[AmmoSlot]; - if (_RangeWeapon && _RangeWeapon->GetItem() && - _RangeWeapon->GetItem()->ID != range_id) - RangeWeapon = _RangeWeapon; - else - ammo_lost = database.GetItem(range_id); + m_RangeWeapon = CastToClient()->m_inv[AmmoSlot]; + + if (m_RangeWeapon && m_RangeWeapon->GetItem() && m_RangeWeapon->GetItem()->ID == range_id) { + RangeWeapon = m_RangeWeapon; + } + else { + last_ammo_used = database.GetItem(range_id); + } } } } @@ -1412,10 +1423,12 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, c int WDmg = 0; if (!weapon_damage) { - if (IsClient() && RangeWeapon) + if (IsClient() && RangeWeapon) { WDmg = GetWeaponDamage(other, RangeWeapon); - else if (AmmoItem) + } + else if (AmmoItem) { WDmg = GetWeaponDamage(other, AmmoItem); + } if (LaunchProjectile) { TryProjectileAttack(other, AmmoItem, EQ::skills::SkillThrowing, WDmg, RangeWeapon, @@ -1426,8 +1439,9 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, c WDmg = weapon_damage; } - if (focus) // From FcBaseEffects + if (focus) { // no longer used, keep for quests WDmg += WDmg * focus / 100; + } int TotalDmg = 0; @@ -1455,29 +1469,28 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQ::ItemInstance *RangeWeapon, c other->Damage(this, TotalDmg, SPELL_UNKNOWN, EQ::skills::SkillThrowing); - if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()) { - if (ReuseTime) - TrySkillProc(other, EQ::skills::SkillThrowing, ReuseTime); - else - TrySkillProc(other, EQ::skills::SkillThrowing, 0, true, EQ::invslot::slotRange); + if (other && !other->HasDied()) { + TryCombatProcs(RangeWeapon, other, EQ::invslot::slotRange, last_ammo_used); } - // end old shit - - if (LaunchProjectile) - return; - - // Throwing item Proc - if (ammo_lost) - TryWeaponProc(nullptr, ammo_lost, other, EQ::invslot::slotRange); - else if (RangeWeapon && other && !other->HasDied()) - TryWeaponProc(RangeWeapon, other, EQ::invslot::slotRange); if (HasSkillProcs() && other && !other->HasDied()) { - if (ReuseTime) + if (ReuseTime) { TrySkillProc(other, EQ::skills::SkillThrowing, ReuseTime); - else + } + else { TrySkillProc(other, EQ::skills::SkillThrowing, 0, false, EQ::invslot::slotRange); + } } + + if (HasSkillProcSuccess() && other && !other->HasDied()) { + if (ReuseTime) { + TrySkillProc(other, EQ::skills::SkillThrowing, ReuseTime, true); + } + else { + TrySkillProc(other, EQ::skills::SkillThrowing, 0, true, EQ::invslot::slotRange); + } + } + if (IsClient()) { CastToClient()->CheckIncreaseSkill(EQ::skills::SkillThrowing, GetTarget()); } @@ -1965,7 +1978,7 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell, Mob *hate_top = who->GetHateMost(); int level_difference = GetLevel() - who->GetLevel(); - bool Success = false; + bool success = false; // Support for how taunt worked pre 2000 on LIVE - Can not taunt NPC over your level. if ((RuleB(Combat, TauntOverLevel) == false) && (level_difference < 0) || @@ -1978,7 +1991,7 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell, if ((hate_top && hate_top->GetHPRatio() >= 20) || hate_top == nullptr || chance_bonus) { // SE_Taunt this is flat chance if (chance_bonus) { - Success = zone->random.Roll(chance_bonus); + success = zone->random.Roll(chance_bonus); } else { float tauntchance = 50.0f; @@ -2012,14 +2025,14 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell, tauntchance /= 100.0f; - Success = tauntchance > zone->random.Real(0, 1); + success = tauntchance > zone->random.Real(0, 1); } - if (Success) { + if (success) { if (hate_top && hate_top != this) { int newhate = (who->GetNPCHate(hate_top) - who->GetNPCHate(this)) + 1 + bonus_hate; who->CastToNPC()->AddToHateList(this, newhate); - Success = true; + success = true; } else { who->CastToNPC()->AddToHateList(this, 12); } @@ -2033,11 +2046,13 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell, MessageString(Chat::SpellFailure, FAILED_TAUNT); } - if (HasSkillProcs()) + if (HasSkillProcs()) { TrySkillProc(who, EQ::skills::SkillTaunt, TauntReuseTime * 1000); + } - if (Success && HasSkillProcSuccess()) + if (success && HasSkillProcSuccess()) { TrySkillProc(who, EQ::skills::SkillTaunt, TauntReuseTime * 1000, true); + } } void Mob::InstillDoubt(Mob *who) { @@ -2061,6 +2076,7 @@ void Mob::InstillDoubt(Mob *who) { //I think this formula needs work int value = 0; + bool success = false; //user's bonus value += GetSkill(EQ::skills::SkillIntimidation) + GetCHA() / 4; @@ -2073,6 +2089,7 @@ void Mob::InstillDoubt(Mob *who) { //cast fear on them... should prolly be a different spell //and should be un-resistable. SpellOnTarget(229, who, 0, true, -2000); + success = true; //is there a success message? } else { MessageString(Chat::LightBlue,NOT_SCARING); @@ -2083,6 +2100,14 @@ void Mob::InstillDoubt(Mob *who) { entity_list.AEAttack(target, 50); }*/ } + + if (HasSkillProcs()) { + TrySkillProc(who, EQ::skills::SkillIntimidation, InstillDoubtReuseTime * 1000); + } + + if (success && HasSkillProcSuccess()) { + TrySkillProc(who, EQ::skills::SkillIntimidation, InstillDoubtReuseTime * 1000, true); + } } int Mob::TryHeadShot(Mob *defender, EQ::skills::SkillType skillInUse) @@ -2228,12 +2253,12 @@ void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQ::skills::Sk } other->AddToHateList(this, hate, 0); - 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 (damage > 0 && aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] && aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SKILL] == skillinuse && + IsValidSpell(aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID])) { + float chance = aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_CHANCE] / 1000.0f; if (zone->random.Roll(chance)) - SpellFinished(aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID], other, EQ::spells::CastingSlot::Item, 0, -1, - spells[aabonuses.SkillAttackProc[SBIndex::SKILLPROC_SPELL_ID]].resist_difficulty); + SpellFinished(aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID], other, EQ::spells::CastingSlot::Item, 0, -1, + spells[aabonuses.SkillAttackProc[SBIndex::SKILLATK_PROC_SPELL_ID]].resist_difficulty); } other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); @@ -2241,11 +2266,13 @@ void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQ::skills::Sk if (HasDied()) return; - if (CanSkillProc && HasSkillProcs()) + if (CanSkillProc && HasSkillProcs()) { TrySkillProc(other, skillinuse, ReuseTime); + } - if (CanSkillProc && (damage > 0) && HasSkillProcSuccess()) + if (CanSkillProc && (damage > 0) && HasSkillProcSuccess()) { TrySkillProc(other, skillinuse, ReuseTime, true); + } } bool Mob::CanDoSpecialAttack(Mob *other) { diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 9b7e74d82..782fd5d91 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1821,7 +1821,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Weapon Proc: %s (id %d)", spells[effect_value].name, procid); #endif - AddProcToWeapon(procid, false, 100 + spells[spell_id].limit_value[i], spell_id, caster_level, GetProcLimitTimer(spell_id, SE_WeaponProc)); + AddProcToWeapon(procid, false, 100 + spells[spell_id].limit_value[i], spell_id, caster_level, GetProcLimitTimer(spell_id, ProcType::MELEE_PROC)); break; } @@ -1831,7 +1831,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Ranged Proc: %+i", effect_value); #endif - AddRangedProc(procid, 100 + spells[spell_id].limit_value[i], spell_id, GetProcLimitTimer(spell_id, SE_RangedProc)); + AddRangedProc(procid, 100 + spells[spell_id].limit_value[i], spell_id, GetProcLimitTimer(spell_id, ProcType::RANGED_PROC)); break; } @@ -1841,7 +1841,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Defensive Proc: %s (id %d)", spells[effect_value].name, procid); #endif - AddDefensiveProc(procid, 100 + spells[spell_id].limit_value[i], spell_id, GetProcLimitTimer(spell_id, SE_DefensiveProc)); + AddDefensiveProc(procid, 100 + spells[spell_id].limit_value[i], spell_id, GetProcLimitTimer(spell_id, ProcType::DEFENSIVE_PROC)); break; } @@ -3156,7 +3156,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_LimitSpellClass: case SE_Sanctuary: case SE_PetMeleeMitigation: - case SE_SkillProc: + case SE_SkillProcAttempt: case SE_SkillProcSuccess: case SE_SpellResistReduction: case SE_Duration_HP_Pct: @@ -8518,6 +8518,87 @@ bool Mob::PassCharmTargetRestriction(Mob *target) { return true; } +bool Mob::PassLimitToSkill(EQ::skills::SkillType skill, int32 spell_id, int proc_type, int aa_id) +{ + /* + Check if SE_AddMeleProc or SE_RangedProc have a skill limiter. Passes automatically if no skill limiters present. + */ + int32 proc_type_spaid = 0; + if (proc_type == ProcType::MELEE_PROC) { + proc_type_spaid = SE_AddMeleeProc; + } + if (proc_type == ProcType::RANGED_PROC) { + proc_type_spaid = SE_RangedProc; + } + + bool match_proc_type = false; + bool has_limit_check = false; + + if (!aa_id && spellbonuses.LimitToSkill[EQ::skills::HIGHEST_SKILL + 3]) { + + if (spell_id == SPELL_UNKNOWN) { + return false; + } + + for (int i = 0; i < EFFECT_COUNT; i++) { + if (spells[spell_id].effect_id[i] == proc_type_spaid) { + match_proc_type = true; + } + if (match_proc_type && spells[spell_id].effect_id[i] == SE_LimitToSkill && spells[spell_id].base_value[i] <= EQ::skills::HIGHEST_SKILL) { + + has_limit_check = true; + if (spells[spell_id].base_value[i] == skill) { + return true; + } + } + } + } + else if (aabonuses.LimitToSkill[EQ::skills::HIGHEST_SKILL + 3]) { + + int rank_id = 1; + AA::Rank *rank = zone->GetAlternateAdvancementRank(aa_id); + + if (!rank) { + return true; + } + + AA::Ability *ability_in = rank->base_ability; + if (!ability_in) { + return true; + } + + for (auto &aa : aa_ranks) { + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa.first, aa.second.first); + auto ability = ability_rank.first; + auto rank = ability_rank.second; + + if (!ability) { + continue; + } + + for (auto &effect : rank->effects) { + if (effect.effect_id == proc_type_spaid) { + match_proc_type = true; + } + + if (match_proc_type && effect.effect_id == SE_LimitToSkill && effect.base_value <= EQ::skills::HIGHEST_SKILL) { + has_limit_check = true; + if (effect.base_value == skill) { + return true; + } + } + } + } + } + + if (has_limit_check) { + return false; //Limit was found, but not matched, fail. + } + else { + return true; //No limit is present, automatically pass. + } +} + bool Mob::CanFocusUseRandomEffectivenessByType(focusType type) { switch (type) { @@ -8760,7 +8841,7 @@ bool Mob::IsProcLimitTimerActive(int32 base_spell_id, uint32 proc_reuse_time, in for (int i = 0; i < MAX_PROC_LIMIT_TIMERS; i++) { - if (proc_type == SE_WeaponProc) { + if (proc_type == ProcType::MELEE_PROC) { if (spell_proclimit_spellid[i] == base_spell_id) { if (spell_proclimit_timer[i].Enabled()) { if (spell_proclimit_timer[i].GetRemainingTime() > 0) { @@ -8773,7 +8854,7 @@ bool Mob::IsProcLimitTimerActive(int32 base_spell_id, uint32 proc_reuse_time, in } } } - else if (proc_type == SE_RangedProc) { + else if (proc_type == ProcType::RANGED_PROC) { if (ranged_proclimit_spellid[i] == base_spell_id) { if (ranged_proclimit_timer[i].Enabled()) { if (ranged_proclimit_timer[i].GetRemainingTime() > 0) { @@ -8786,7 +8867,7 @@ bool Mob::IsProcLimitTimerActive(int32 base_spell_id, uint32 proc_reuse_time, in } } } - else if (proc_type == SE_DefensiveProc) { + else if (proc_type == ProcType::DEFENSIVE_PROC) { if (def_proclimit_spellid[i] == base_spell_id) { if (def_proclimit_timer[i].Enabled()) { if (def_proclimit_timer[i].GetRemainingTime() > 0) { @@ -8813,7 +8894,7 @@ void Mob::SetProcLimitTimer(int32 base_spell_id, uint32 proc_reuse_time, int pro for (int i = 0; i < MAX_PROC_LIMIT_TIMERS; i++) { - if (proc_type == SE_WeaponProc) { + if (proc_type == ProcType::MELEE_PROC) { if (!spell_proclimit_spellid[i] && !is_set) { spell_proclimit_spellid[i] = base_spell_id; spell_proclimit_timer[i].SetTimer(proc_reuse_time); @@ -8825,7 +8906,7 @@ void Mob::SetProcLimitTimer(int32 base_spell_id, uint32 proc_reuse_time, int pro } } - if (proc_type == SE_RangedProc) { + if (proc_type == ProcType::RANGED_PROC) { if (!ranged_proclimit_spellid[i] && !is_set) { ranged_proclimit_spellid[i] = base_spell_id; ranged_proclimit_timer[i].SetTimer(proc_reuse_time); @@ -8837,7 +8918,7 @@ void Mob::SetProcLimitTimer(int32 base_spell_id, uint32 proc_reuse_time, int pro } } - if (proc_type == SE_DefensiveProc) { + if (proc_type == ProcType::DEFENSIVE_PROC) { if (!def_proclimit_spellid[i] && !is_set) { def_proclimit_spellid[i] = base_spell_id; def_proclimit_timer[i].SetTimer(proc_reuse_time); diff --git a/zone/tune.cpp b/zone/tune.cpp index be806eb92..a5bf04fed 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -1014,8 +1014,6 @@ void Mob::TuneMeleeMitigation(Mob *attacker, DamageHitInfo &hit, int ac_override // +0.5 for rounding, min to 1 dmg hit.damage_done = std::max(static_cast(roll * static_cast(hit.base_damage) + 0.5), 1); - - //Shout("mitigation %d vs offense %d. base %d rolled %f damage %d", mitigation, hit.offense, hit.base_damage, roll, hit.damage_done); } int Mob::TuneACSum(bool skip_caps, int ac_override, int add_ac) @@ -1093,10 +1091,6 @@ int Mob::TuneACSum(bool skip_caps, int ac_override, int add_ac) auto over_cap = ac - softcap; ac = softcap + (over_cap * returns); } - //Shout("ACSum ac %i softcap %i returns %.2f", ac, softcap, static_cast(returns)); - } - else { - //Shout("ACSum ac %i", ac); } return ac; @@ -1384,7 +1378,6 @@ bool Mob::TuneCheckHitChance(Mob* other, DamageHitInfo &hit, int avoidance_overr Mob *attacker = other; Mob *defender = this; - //Shout("CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName()); if (defender->IsClient() && defender->CastToClient()->IsSitting()) return true; @@ -1402,7 +1395,6 @@ bool Mob::TuneCheckHitChance(Mob* other, DamageHitInfo &hit, int avoidance_overr // Then your chance to simply avoid the attack is checked (defender's avoidance roll beat the attacker's accuracy roll.) int tohit_roll = zone->random.Roll0(accuracy); int avoid_roll = zone->random.Roll0(avoidance); - //Shout("CheckHitChance accuracy(%d => %d) avoidance(%d => %d)", accuracy, tohit_roll, avoidance, avoid_roll); // tie breaker? Don't want to be biased any one way if (tohit_roll == avoid_roll)