[Spells] Throwing procs fixed and other proc updates (#1871)

* first updating sbindex defines

* updates

* updates

* proctypes added for organization

* debug

* updates

* range procs cleaned up

* skill proc clean up

* fix

* remove debugs

* [Spells] Throwing procs fixed and other proc updates

* [Spells] Throwing procs fixed and other proc updates

bot fix

* [Spells] Throwing procs fixed and other proc updates

proctype updates
This commit is contained in:
KayenEQ 2021-12-14 12:34:51 -05:00 committed by GitHub
parent 73acc3310c
commit 119b2d023f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 393 additions and 253 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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<float>(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<float>(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<float>(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) {
@ -4376,13 +4390,15 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
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<float>(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<float>(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<float>(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)
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.*/
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<float>(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<float>(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<float>(limit_value);
}
@ -5225,12 +5255,14 @@ float Mob::GetSkillProcChances(uint16 ReuseTime, uint16 hand) {
if (!ReuseTime && hand) {
weapon_speed = GetWeaponSpeedbyHand(hand);
ProcChance = static_cast<float>(weapon_speed) * (RuleR(Combat, AvgProcsPerMinute) / 60000.0f);
if (hand == EQ::invslot::slotSecondary)
if (hand == EQ::invslot::slotSecondary) {
ProcChance /= 2;
}
}
else
else {
ProcChance = static_cast<float>(ReuseTime) * (RuleR(Combat, AvgProcsPerMinute) / 60000.0f);
}
return ProcChance;
}

View File

@ -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; }

View File

@ -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()) {

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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,12 +4242,14 @@ 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);
}
}
}
void Mob::SetDelta(const glm::vec4& delta) {
@ -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;

View File

@ -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);

View File

@ -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:

View File

@ -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,
@ -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,35 +901,40 @@ 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);
}
}
}
bool Mob::TryProjectileAttack(Mob *other, const EQ::ItemData *item, EQ::skills::SkillType skillInUse,
@ -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
@ -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) {

View File

@ -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);

View File

@ -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<int>(roll * static_cast<double>(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<float>(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)