From 63ca4cac5e6edab3797cfdb21bbebfce88c800fe Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 17 Sep 2014 05:14:10 -0400 Subject: [PATCH 1/5] Fix for calculation for SE_ManaAbsorbPercentDamage --- zone/attack.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index a515a08c4..d52d2a6ba 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3331,10 +3331,13 @@ int32 Mob::ReduceAllDamage(int32 damage) if(damage <= 0) return damage; - if(spellbonuses.ManaAbsorbPercentDamage[0] && (GetMana() > damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100)) { - damage -= (damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100); - SetMana(GetMana() - damage); - TryTriggerOnValueAmount(false, true); + if(spellbonuses.ManaAbsorbPercentDamage[0]) { + int32 mana_reduced = damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100; + if (GetMana() >= mana_reduced){ + damage -= mana_reduced; + SetMana(GetMana() - mana_reduced); + TryTriggerOnValueAmount(false, true); + } } CheckNumHitsRemaining(NUMHIT_IncomingDamage); From d169d95ab02f5fd32d30671eb191254cd4dc1dbb Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Wed, 17 Sep 2014 12:08:01 -0400 Subject: [PATCH 2/5] Fix for resource tap when gaining/loosing HP. --- zone/spell_effects.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index f0bc8498b..5f85de374 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -6453,8 +6453,12 @@ void Mob::ResourceTap(int32 damage, uint16 spellid){ if (spells[spellid].max[i] && (damage > spells[spellid].max[i])) damage = spells[spellid].max[i]; - if (spells[spellid].base2[i] == 0) //HP Tap - SetHP((GetHP()+ damage)); + if (spells[spellid].base2[i] == 0){ //HP Tap + if (damage > 0) + HealDamage(damage); + else + Damage(this, -damage,0, SkillEvocation,false); + } if (spells[spellid].base2[i] == 1) //Mana Tap SetMana(GetMana() + damage); From c160b8716f48bef524e3b87d278bb8e41bdf9179 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Mon, 22 Sep 2014 18:02:40 -0400 Subject: [PATCH 3/5] Kayen: Spell recourse effects / triggerable spell effects will now be applied AFTER the base spells effects have been applied (consistent with live). --- changelog.txt | 3 ++ zone/spells.cpp | 105 +++--------------------------------------------- 2 files changed, 8 insertions(+), 100 deletions(-) diff --git a/changelog.txt b/changelog.txt index b002c0524..8517f38fe 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,11 +1,14 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- + + == 09/22/2014 == Akkadius: #resetaa now covers the function of #resetaa and #refundaa - #resetaa will wipe all AA data, refund the spent points into the available points and send character to character select properly Akkadius: Removed #refundaa Akkadius: Removed a lot of debug code for blob conversion Akkadius: Changed status logging for loads/saves to Debug category +Kayen: Spell recourse effects / triggerable spell effects will now be applied AFTER the base spells effects have been applied (consistent with live) == 09/21/2014 == Akkadius: Player Profile Blob to Database Conversion diff --git a/zone/spells.cpp b/zone/spells.cpp index d400e46ce..4d5f3c86c 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3606,108 +3606,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r spell_effectiveness = 100; } - // Recourse means there is a spell linked to that spell in that the recourse spell will - // be automatically casted on the casters group or the caster only depending on Targettype - // this is for things like dark empathy, shadow vortex - int recourse_spell=0; - recourse_spell = spells[spell_id].RecourseLink; - if(recourse_spell) - { - if(spells[recourse_spell].targettype == ST_Group || spells[recourse_spell].targettype == ST_GroupTeleport) - { - if(IsGrouped()) - { - Group *g = entity_list.GetGroupByMob(this); - if(g) - g->CastGroupSpell(this, recourse_spell); - else{ - SpellOnTarget(recourse_spell, this); -#ifdef GROUP_BUFF_PETS - if (GetPet()) - SpellOnTarget(recourse_spell, GetPet()); -#endif - } - } - else if(IsRaidGrouped() && IsClient()) - { - Raid *r = entity_list.GetRaidByClient(CastToClient()); - uint32 gid = 0xFFFFFFFF; - if(r) - gid = r->GetGroup(GetName()); - else - gid = 13; // Forces ungrouped spell casting - - if(gid < 12) - { - r->CastGroupSpell(this, recourse_spell, gid); - } - else{ - SpellOnTarget(recourse_spell, this); -#ifdef GROUP_BUFF_PETS - if (GetPet()) - SpellOnTarget(recourse_spell, GetPet()); -#endif - } - } - else if(HasOwner()) - { - if(GetOwner()->IsGrouped()) - { - Group *g = entity_list.GetGroupByMob(GetOwner()); - if(g) - g->CastGroupSpell(this, recourse_spell); - else{ - SpellOnTarget(recourse_spell, GetOwner()); - SpellOnTarget(recourse_spell, this); - } - } - else if(GetOwner()->IsRaidGrouped() && GetOwner()->IsClient()) - { - Raid *r = entity_list.GetRaidByClient(GetOwner()->CastToClient()); - uint32 gid = 0xFFFFFFFF; - if(r) - gid = r->GetGroup(GetOwner()->GetName()); - else - gid = 13; // Forces ungrouped spell casting - - if(gid < 12) - { - r->CastGroupSpell(this, recourse_spell, gid); - } - else - { - SpellOnTarget(recourse_spell, GetOwner()); - SpellOnTarget(recourse_spell, this); - } - } - else - { - SpellOnTarget(recourse_spell, GetOwner()); - SpellOnTarget(recourse_spell, this); - } - } - else - { - SpellOnTarget(recourse_spell, this); -#ifdef GROUP_BUFF_PETS - if (GetPet()) - SpellOnTarget(recourse_spell, GetPet()); -#endif - } - - } - else - { - SpellOnTarget(recourse_spell, this); - } - } - if(spelltar->spellbonuses.SpellDamageShield && IsDetrimentalSpell(spell_id)) spelltar->DamageShield(this, true); - TrySpellTrigger(spelltar, spell_id); - TryApplyEffect(spelltar, spell_id); - if (spelltar->IsAIControlled() && IsDetrimentalSpell(spell_id) && !IsHarmonySpell(spell_id)) { int32 aggro_amount = CheckAggroAmount(spell_id, isproc); mlog(SPELLS__CASTING, "Spell %d cast on %s generated %d hate", spell_id, spelltar->GetName(), aggro_amount); @@ -3746,7 +3647,11 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r return false; } - + TrySpellTrigger(spelltar, spell_id); + TryApplyEffect(spelltar, spell_id); + if (IsValidSpell(spells[spell_id].RecourseLink)) + SpellFinished(spells[spell_id].RecourseLink, this, 10, 0, -1, spells[spells[spell_id].RecourseLink].ResistDiff); + if (IsDetrimentalSpell(spell_id)) { CheckNumHitsRemaining(NUMHIT_OutgoingSpells); From 1f155690d879e5ff08dccc7055fc2e1a8a3849d2 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Mon, 22 Sep 2014 19:42:59 -0400 Subject: [PATCH 4/5] Fix to SE_ApplyEffect - Will now trigger spell from this effect at correct time. --- zone/mob.cpp | 20 -------------------- zone/mob.h | 1 - zone/spell_effects.cpp | 11 ++++++++++- zone/spells.cpp | 1 - 4 files changed, 10 insertions(+), 23 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 77ff4938a..638e680df 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3083,26 +3083,6 @@ void Mob::TrySpellTrigger(Mob *target, uint32 spell_id) } } -void Mob::TryApplyEffect(Mob *target, uint32 spell_id) -{ - if(target == nullptr || !IsValidSpell(spell_id)) - { - return; - } - - for(int i = 0; i < EFFECT_COUNT; i++) - { - if (spells[spell_id].effectid[i] == SE_ApplyEffect) - { - if(MakeRandomInt(0, 100) <= spells[spell_id].base[i]) - { - if(target) - SpellFinished(spells[spell_id].base2[i], target, 10, 0, -1, spells[spell_id].ResistDiff); - } - } - } -} - void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsPet) { /* diff --git a/zone/mob.h b/zone/mob.h index 4e72f0264..4a28d1883 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -580,7 +580,6 @@ public: void TryTriggerOnCast(uint32 spell_id, bool aa_trigger); void TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger); void TrySpellTrigger(Mob *target, uint32 spell_id); - void TryApplyEffect(Mob *target, uint32 spell_id); void TryTriggerOnValueAmount(bool IsHP = false, bool IsMana = false, bool IsEndur = false, bool IsPet = false); void TryTwincast(Mob *caster, Mob *target, uint32 spell_id); void TrySympatheticProc(Mob *target, uint32 spell_id); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 80a356e9f..e2061c6ee 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2729,6 +2729,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) Message(10, "The power of your next illusion spell will flow to your grouped target in your place."); break; } + + case SE_ApplyEffect: { + + if (caster && IsValidSpell(spells[spell_id].base2[i])){ + + if(MakeRandomInt(0, 100) <= spells[spell_id].base[i]) + caster->SpellFinished(spells[spell_id].base2[i], this, 10, 0, -1, spells[spell_id].ResistDiff); + } + break; + } // Handled Elsewhere case SE_ImmuneFleeing: @@ -2840,7 +2850,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_SkillDamageTaken: case SE_FcSpellVulnerability: case SE_SpellTrigger: - case SE_ApplyEffect: case SE_FcTwincast: case SE_DelayDeath: case SE_CastOnFadeEffect: diff --git a/zone/spells.cpp b/zone/spells.cpp index 4d5f3c86c..d3779f713 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3648,7 +3648,6 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r } TrySpellTrigger(spelltar, spell_id); - TryApplyEffect(spelltar, spell_id); if (IsValidSpell(spells[spell_id].RecourseLink)) SpellFinished(spells[spell_id].RecourseLink, this, 10, 0, -1, spells[spells[spell_id].RecourseLink].ResistDiff); From c03a70651c0c1de1fb04f2fc8eef909331da9139 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 23 Sep 2014 09:15:02 -0400 Subject: [PATCH 5/5] SE_ApplySpell and SE_TriggerSpell will now be applied based on which effect slot they are used in (instead of always before all spell effects are checked). Note: If a spell has multiple SE_TriggerSpell effects within it. Only one will be able to trigger. (If you want multiple spells use SE_ApplySpell) --- changelog.txt | 6 ++++-- zone/mob.cpp | 27 +++++++++++++-------------- zone/mob.h | 2 +- zone/spell_effects.cpp | 11 +++++++++++ zone/spells.cpp | 1 - 5 files changed, 29 insertions(+), 18 deletions(-) diff --git a/changelog.txt b/changelog.txt index 8517f38fe..4f6818041 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- - +== 09/23/2014 == +Kayen: Spell recourse effects will now be applied AFTER the base spells effects have been applied (consistent with live). +Kayen: SE_ApplySpell and SE_TriggerSpell will now be applied based on which effect slot they are used in (instead of always before all spell effects are checked). +Note: If a spell has multiple SE_TriggerSpell effects within it. Only one will be able to trigger. (If you want multiple spells use SE_ApplySpell) == 09/22/2014 == Akkadius: #resetaa now covers the function of #resetaa and #refundaa @@ -8,7 +11,6 @@ Akkadius: #resetaa now covers the function of #resetaa and #refundaa Akkadius: Removed #refundaa Akkadius: Removed a lot of debug code for blob conversion Akkadius: Changed status logging for loads/saves to Debug category -Kayen: Spell recourse effects / triggerable spell effects will now be applied AFTER the base spells effects have been applied (consistent with live) == 09/21/2014 == Akkadius: Player Profile Blob to Database Conversion diff --git a/zone/mob.cpp b/zone/mob.cpp index 638e680df..06e125aab 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3031,12 +3031,11 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger) } } -void Mob::TrySpellTrigger(Mob *target, uint32 spell_id) +bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) { - if(target == nullptr || !IsValidSpell(spell_id)) - { - return; - } + if(!target || !IsValidSpell(spell_id)) + return false; + int spell_trig = 0; // Count all the percentage chances to trigger for all effects for(int i = 0; i < EFFECT_COUNT; i++) @@ -3055,8 +3054,10 @@ void Mob::TrySpellTrigger(Mob *target, uint32 spell_id) if(MakeRandomInt(0, trig_chance) <= spells[spell_id].base[i]) { // If we trigger an effect then its over. - SpellFinished(spells[spell_id].base2[i], target, 10, 0, -1, spells[spell_id].ResistDiff); - break; + if (IsValidSpell(spells[spell_id].base2[i])){ + SpellFinished(spells[spell_id].base2[i], target, 10, 0, -1, spells[spell_id].ResistDiff); + return true; + } } else { @@ -3070,17 +3071,15 @@ void Mob::TrySpellTrigger(Mob *target, uint32 spell_id) // if the chances don't add to 100, then each effect gets a chance to fire, chance for no trigger as well. else { - for(int i = 0; i < EFFECT_COUNT; i++) + if(MakeRandomInt(0, 100) <= spells[spell_id].base[effect]) { - if (spells[spell_id].effectid[i] == SE_SpellTrigger) - { - if(MakeRandomInt(0, 100) <= spells[spell_id].base[i]) - { - SpellFinished(spells[spell_id].base2[i], target, 10, 0, -1, spells[spell_id].ResistDiff); - } + if (IsValidSpell(spells[spell_id].base2[effect])){ + SpellFinished(spells[spell_id].base2[effect], target, 10, 0, -1, spells[spell_id].ResistDiff); + return true; //Only trigger once of these per spell effect. } } } + return false; } void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsPet) diff --git a/zone/mob.h b/zone/mob.h index 4a28d1883..0d365fdac 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -579,7 +579,7 @@ public: void DoBuffWearOffEffect(uint32 index); void TryTriggerOnCast(uint32 spell_id, bool aa_trigger); void TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger); - void TrySpellTrigger(Mob *target, uint32 spell_id); + bool TrySpellTrigger(Mob *target, uint32 spell_id, int effect); void TryTriggerOnValueAmount(bool IsHP = false, bool IsMana = false, bool IsEndur = false, bool IsPet = false); void TryTwincast(Mob *caster, Mob *target, uint32 spell_id); void TrySympatheticProc(Mob *target, uint32 spell_id); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index e2061c6ee..b017a90b0 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -188,6 +188,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if (!IsPowerDistModSpell(spell_id)) SetSpellPowerDistanceMod(0); + + bool SE_SpellTrigger_HasCast = false; // iterate through the effects in the spell for (i = 0; i < EFFECT_COUNT; i++) @@ -2739,6 +2741,15 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) } break; } + + case SE_SpellTrigger: { + + if (!SE_SpellTrigger_HasCast) { + if (caster && caster->TrySpellTrigger(this, spell_id, i)) + SE_SpellTrigger_HasCast = true; + } + break; + } // Handled Elsewhere case SE_ImmuneFleeing: diff --git a/zone/spells.cpp b/zone/spells.cpp index d3779f713..5d60b11a2 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3647,7 +3647,6 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r return false; } - TrySpellTrigger(spelltar, spell_id); if (IsValidSpell(spells[spell_id].RecourseLink)) SpellFinished(spells[spell_id].RecourseLink, this, 10, 0, -1, spells[spells[spell_id].RecourseLink].ResistDiff);