mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 18:52:22 +00:00
[Spells] Implemented SPA 512 SE_Proc_Timer_Modifier, Fixed AA procs not working (#1646)
* update for SPA 511 * remove debugs, AA implemented * update * twinprocfix * AA procs added * format update * update * proctimer limits * update * rename function renamed function only check for buffs value > 0, don't need to check for AA's which are negative ID's * pre merge * variable updates * Update spell_effects.cpp * var rename update var name to better represent its function. * updated proc struct added reuse timer * reuse timer to spell procs * updates * debug remove * Update mob.cpp * fix * merge
This commit is contained in:
+146
-35
@@ -3380,17 +3380,37 @@ int32 Mob::ReduceAllDamage(int32 damage)
|
||||
|
||||
bool Mob::HasProcs() const
|
||||
{
|
||||
for (int i = 0; i < MAX_PROCS; i++)
|
||||
if (PermaProcs[i].spellID != SPELL_UNKNOWN || SpellProcs[i].spellID != SPELL_UNKNOWN)
|
||||
for (int i = 0; i < MAX_PROCS; i++) {
|
||||
if (PermaProcs[i].spellID != SPELL_UNKNOWN || SpellProcs[i].spellID != SPELL_UNKNOWN) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsClient()) {
|
||||
for (int i = 0; i < MAX_AA_PROCS; i += 4) {
|
||||
if (aabonuses.SpellProc[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Mob::HasDefensiveProcs() const
|
||||
{
|
||||
for (int i = 0; i < MAX_PROCS; i++)
|
||||
if (DefensiveProcs[i].spellID != SPELL_UNKNOWN)
|
||||
for (int i = 0; i < MAX_PROCS; i++) {
|
||||
if (DefensiveProcs[i].spellID != SPELL_UNKNOWN) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsClient()) {
|
||||
for (int i = 0; i < MAX_AA_PROCS; i += 4) {
|
||||
if (aabonuses.DefensiveProc[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3415,9 +3435,19 @@ bool Mob::HasSkillProcSuccess() const
|
||||
|
||||
bool Mob::HasRangedProcs() const
|
||||
{
|
||||
for (int i = 0; i < MAX_PROCS; i++)
|
||||
if (RangedProcs[i].spellID != SPELL_UNKNOWN)
|
||||
for (int i = 0; i < MAX_PROCS; i++){
|
||||
if (RangedProcs[i].spellID != SPELL_UNKNOWN) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsClient()) {
|
||||
for (int i = 0; i < MAX_AA_PROCS; i += 4) {
|
||||
if (aabonuses.RangedProc[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4051,33 +4081,61 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HasDefensiveProcs())
|
||||
if (!HasDefensiveProcs()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!on->HasDied() && on->GetHP() > 0) {
|
||||
|
||||
float ProcChance, ProcBonus;
|
||||
on->GetDefensiveProcChances(ProcBonus, ProcChance, hand, this);
|
||||
|
||||
if (hand != EQ::invslot::slotPrimary)
|
||||
if (hand != EQ::invslot::slotPrimary) {
|
||||
ProcChance /= 2;
|
||||
}
|
||||
|
||||
int level_penalty = 0;
|
||||
int level_diff = GetLevel() - on->GetLevel();
|
||||
if (level_diff > 6)//10% penalty per level if > 6 levels over target.
|
||||
if (level_diff > 6) {//10% penalty per level if > 6 levels over target.
|
||||
level_penalty = (level_diff - 6) * 10;
|
||||
}
|
||||
|
||||
ProcChance -= ProcChance*level_penalty / 100;
|
||||
|
||||
if (ProcChance < 0)
|
||||
if (ProcChance < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Spell Procs and Quest added procs
|
||||
for (int i = 0; i < MAX_PROCS; i++) {
|
||||
if (IsValidSpell(DefensiveProcs[i].spellID)) {
|
||||
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);
|
||||
if (!IsProcLimitTimerActive(DefensiveProcs[i].base_spellID, DefensiveProcs[i].proc_reuse_time, SE_DefensiveProc)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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];
|
||||
|
||||
if (aa_rank_id) {
|
||||
if (!IsProcLimitTimerActive(-aa_rank_id, aa_proc_reuse_timer, SE_DefensiveProc)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4122,7 +4180,9 @@ void Mob::TryWeaponProc(const EQ::ItemInstance* weapon_g, Mob *on, uint16 hand)
|
||||
|
||||
void Mob::TryWeaponProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, Mob *on, uint16 hand)
|
||||
{
|
||||
|
||||
if (!on) {
|
||||
return;
|
||||
}
|
||||
if (!weapon)
|
||||
return;
|
||||
uint16 skillinuse = 28;
|
||||
@@ -4206,6 +4266,10 @@ void Mob::TryWeaponProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon
|
||||
|
||||
void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon, Mob *on, uint16 hand)
|
||||
{
|
||||
if (!on) {
|
||||
return;
|
||||
}
|
||||
|
||||
float ProcBonus = static_cast<float>(spellbonuses.SpellProcChance +
|
||||
itembonuses.SpellProcChance + aabonuses.SpellProcChance);
|
||||
float ProcChance = 0.0f;
|
||||
@@ -4239,7 +4303,7 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
|
||||
|
||||
// Not ranged
|
||||
if (!rangedattk) {
|
||||
// Perma procs (AAs)
|
||||
// Perma procs (Not used for AA, they are handled below)
|
||||
if (PermaProcs[i].spellID != SPELL_UNKNOWN) {
|
||||
if (zone->random.Roll(PermaProcs[i].chance)) { // TODO: Do these get spell bonus?
|
||||
LogCombat("Permanent proc [{}] procing spell [{}] ([{}] percent chance)", i, PermaProcs[i].spellID, PermaProcs[i].chance);
|
||||
@@ -4256,32 +4320,79 @@ void Mob::TrySpellProc(const EQ::ItemInstance *inst, const EQ::ItemData *weapon,
|
||||
poison_slot=i;
|
||||
continue; // Process the poison proc last per @mackal
|
||||
}
|
||||
|
||||
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);
|
||||
CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0,
|
||||
SpellProcs[i].base_spellID);
|
||||
}
|
||||
else {
|
||||
LogCombat("Spell proc [{}] failed to proc [{}] ([{}] percent chance)", i, SpellProcs[i].spellID, chance);
|
||||
|
||||
if (!IsProcLimitTimerActive(SpellProcs[i].base_spellID, SpellProcs[i].proc_reuse_time, SE_WeaponProc)) {
|
||||
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);
|
||||
CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0, SpellProcs[i].base_spellID);
|
||||
}
|
||||
else {
|
||||
LogCombat("Spell proc [{}] failed to proc [{}] ([{}] percent chance)", i, SpellProcs[i].spellID, chance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rangedattk) { // ranged only
|
||||
// ranged spell procs (buffs)
|
||||
if (RangedProcs[i].spellID != SPELL_UNKNOWN) {
|
||||
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);
|
||||
|
||||
if (!IsProcLimitTimerActive(RangedProcs[i].base_spellID, RangedProcs[i].proc_reuse_time, SE_RangedProc)) {
|
||||
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);
|
||||
}
|
||||
else {
|
||||
LogCombat("Ranged proc [{}] failed to proc [{}] ([{}] percent chance)", i, RangedProcs[i].spellID, chance);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LogCombat("Ranged proc [{}] failed to proc [{}] ([{}] percent chance)", i, RangedProcs[i].spellID, chance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//AA Procs
|
||||
if (IsClient()) {
|
||||
for (int i = 0; i < MAX_AA_PROCS; i += 4) {
|
||||
|
||||
int32 aa_rank_id = 0;
|
||||
int32 aa_spell_id = SPELL_UNKNOWN;
|
||||
int32 aa_proc_chance = 100;
|
||||
uint32 aa_proc_reuse_timer = 0;
|
||||
int proc_type = 0; //used to deterimne which timer array is used.
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (aa_rank_id) {
|
||||
if (!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);
|
||||
ExecWeaponProc(nullptr, aa_spell_id, on);
|
||||
SetProcLimitTimer(-aa_rank_id, aa_proc_reuse_timer, proc_type);
|
||||
}
|
||||
else {
|
||||
LogCombat("AA proc [{}] failed to proc [{}] ([{}] percent chance)", aa_rank_id, aa_spell_id, chance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user