View Full Version : COMMITTED: Spell & DoT Shielding
Caryatis
07-09-2010, 12:49 AM
This also includes a fix for the spell rune effects(Bulwark of Alendar (http://lucy.allakhazam.com/spell.html?id=4076&source=Live)) as they were incorrectly also reducing the damage on DoTs.
edit... this didnt fix the problem with spell runes.
edit2... also doesnt seem to apply properly to DoTs and DD, just does the highest one to both(yay for testing at cap for both stats). its late so will fix tomorrow
code...
mob.h - alter this - line 842
sint32 ReduceMagicalDamage(sint32 damage);
to this
sint32 ReduceMagicalDamage(sint32 damage, int16 spell_id);
attack.cpp - alter this - line 3177
damage = ReduceMagicalDamage(damage);
to this
damage = ReduceMagicalDamage(damage, spell_id);
attack.cpp - alter this - line 2932
sint32 Mob::ReduceMagicalDamage(sint32 damage)
{
if(damage <= 0 || (!HasSpellRune() && !HasPartialSpellRune()))
{
return damage;
}
int slot = GetBuffSlotFromType(SE_NegateAttacks);
if(slot >= 0 && buffs[slot].magic_rune > 0)
{
if(--buffs[slot].melee_rune == 0)
{
BuffFadeBySlot(slot);
UpdateRuneFlags();
}
return -6;
}
slot = GetBuffSlotFromType(SE_MitigateSpellDamage);
if(slot >= 0)
{
int damage_to_reduce = damage * GetPartialMagicRuneReduction(buffs[slot].spellid) / 100;
if(damage_to_reduce > buffs[slot].magic_rune)
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d"
" damage remaining, fading buff.", damage_to_reduce, buffs[slot].magic_rune);
damage -= damage_to_reduce;
BuffFadeBySlot(slot);
UpdateRuneFlags();
}
else
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
" damage remaining.", damage_to_reduce, buffs[slot].magic_rune);
buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce);
damage -= damage_to_reduce;
}
}
if(damage < 1)
{
return -6;
}
slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
while(slot >= 0)
{
int16 magic_rune_left = buffs[slot].magic_rune;
if(magic_rune_left >= damage)
{
magic_rune_left -= damage;
damage = 0;
buffs[slot].magic_rune = magic_rune_left;
break;
}
else
{
if(magic_rune_left > 0)
damage -= magic_rune_left;
BuffFadeBySlot(slot);
slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
UpdateRuneFlags();
}
}
return(damage);
}
to this
sint32 Mob::ReduceMagicalDamage(sint32 damage, int16 spell_id)
{
if(damage <= 0 || (!HasSpellRune() && !HasPartialSpellRune()) && this->itembonuses.SpellDamageShield == 0 && this->itembonuses.DoTShielding == 0)
{
return damage;
}
int slot = GetBuffSlotFromType(SE_NegateAttacks);
if(slot >= 0 && buffs[slot].magic_rune > 0)
{
if(--buffs[slot].melee_rune == 0)
{
BuffFadeBySlot(slot);
UpdateRuneFlags();
}
return -6;
}
for(int i = 0; i < EFFECT_COUNT; i++)
{
// Isolate the Direct Damage effects to be reduced by spell shielding and spell rune effects.
if ((spells[spell_id].buffduration == 0 && spells[spell_id].effectid[i] == SE_CurrentHP) || (spells[spell_id].buffduration > 0 && spells[spell_id].effectid[i] == SE_CurrentHPOnce))
{
damage -= (damage * this->itembonuses.SpellDamageShield / 100);
slot = GetBuffSlotFromType(SE_MitigateSpellDamage);
if(slot >= 0)
{
int damage_to_reduce = damage * GetPartialMagicRuneReduction(buffs[slot].spellid) / 100;
if(damage_to_reduce > buffs[slot].magic_rune)
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d"
" damage remaining, fading buff.", damage_to_reduce, buffs[slot].magic_rune);
damage -= damage_to_reduce;
BuffFadeBySlot(slot);
UpdateRuneFlags();
}
else
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
" damage remaining.", damage_to_reduce, buffs[slot].magic_rune);
buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce);
damage -= damage_to_reduce;
}
}
if(damage < 1)
{
return -6;
}
slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
while(slot >= 0)
{
int16 magic_rune_left = buffs[slot].magic_rune;
if(magic_rune_left >= damage)
{
magic_rune_left -= damage;
damage = 0;
buffs[slot].magic_rune = magic_rune_left;
break;
}
else
{
if(magic_rune_left > 0)
damage -= magic_rune_left;
BuffFadeBySlot(slot);
slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
UpdateRuneFlags();
}
}
return(damage);
}
// Isolate the DoT effects to be reduced by DoT shielding.
else if (spells[spell_id].buffduration > 0 && spells[spell_id].effectid[i] == SE_CurrentHP)
{
damage -= (damage * this->itembonuses.DoTShielding / 100);
return(damage);
}
}
return(damage);
}
Kayen
07-10-2010, 07:00 PM
Any chance you could apply the same logic for spell shielding to the following
Spell effect 296 Increase Incomming Spell damage.
Basically it would just be a reverse midigation without having to worry about the rune part.
Caryatis
07-10-2010, 08:56 PM
Yea actually, I needed to fix it as it was easy to get working for single effect spells like Ice Comet(DD) or Horror(DoT) but for spells like Ikaav Venom (http://lucy.allakhazam.com/spell.html?id=17057&source=Live) which have a DD and a DoT component, that was my problem. Then I noticed we have access to the bufftic so it was easy to seperate out those effects and now it is working 100%(as far as I can see), with the added support for SE_SpellVulnerability(or Increase Incoming Spell Damage). This also truly fixes the spell runes being used on DoT ticks as well.
edit... spoke too soon, SpellVulnerability works on clients but doesnt affect nukes cast on NPCs it seems. maybe I can fix it before my edit timer runs out...
... looks like the problem is with the focus code as it only increases spells you can cast on yourself, will have to look into alternative way of limiting what spells are affected by the vulnerability.
Ignore the previous code...
spell effects.cpp - line 2810 - add this
case SE_SpellVulnerability:
spell effects.cpp - line 3853 - add this
case SE_SpellVulnerability:
{
if(type == focusSpellVulnerability)
{
value = 1;
}
break;
}
mob.h - line 90 - add this
focusSpellVulnerability,
mob.h - line 843 - alter this
sint32 ReduceMagicalDamage(sint32 damage);
to this:
sint32 AffectMagicalDamage(sint32 damage, int16 spell_id, const bool iBuffTic);
attack.ccp - line 3189 - alter this
damage = ReduceMagicalDamage(damage);
to this:
damage = AffectMagicalDamage(damage, spell_id, iBuffTic);
attack.cpp - line 2932 - replace this function
sint32 Mob::ReduceMagicalDamage(sint32 damage)
{
...
}
with this:
sint32 Mob::AffectMagicalDamage(sint32 damage, int16 spell_id, const bool iBuffTic)
{
if(damage <= 0)
{
return damage;
}
// Increase magical damage before runes
uint32 buff_count = GetMaxTotalSlots();
for(int i = 0; i < buff_count; i++)
{
if(IsEffectInSpell(buffs[i].spellid, SE_SpellVulnerability))
{
sint32 focus = CalcFocusEffect(focusSpellVulnerability, buffs[i].spellid, spell_id);
if(focus == 1)
{
damage += damage * spells[buffs[i].spellid].base[0] / 100;
}
}
}
// If this is a DoT, use DoT Shielding...
if(iBuffTic)
{
damage -= (damage * this->itembonuses.DoTShielding / 100);
}
// This must be a DD then so lets apply Spell Shielding and all the various runes that can block or negate DD spells.
else
{
// See if we block the spell outright first
int slot = GetBuffSlotFromType(SE_NegateAttacks);
if(slot >= 0 && buffs[slot].magic_rune > 0)
{
if(--buffs[slot].melee_rune == 0)
{
BuffFadeBySlot(slot);
UpdateRuneFlags();
}
return -6;
}
// Reduce damage by the Spell Shielding first so that the runes don't take the raw damage.
damage -= (damage * this->itembonuses.SpellDamageShield / 100);
// Do runes now.
slot = GetBuffSlotFromType(SE_MitigateSpellDamage);
if(slot >= 0)
{
int damage_to_reduce = damage * GetPartialMagicRuneReduction(buffs[slot].spellid) / 100;
if(damage_to_reduce > buffs[slot].magic_rune)
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d"
" damage remaining, fading buff.", damage_to_reduce, buffs[slot].magic_rune);
damage -= damage_to_reduce;
BuffFadeBySlot(slot);
UpdateRuneFlags();
}
else
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
" damage remaining.", damage_to_reduce, buffs[slot].magic_rune);
buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce);
damage -= damage_to_reduce;
}
}
if(damage < 1)
{
return -6;
}
slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
while(slot >= 0)
{
int16 magic_rune_left = buffs[slot].magic_rune;
if(magic_rune_left >= damage)
{
magic_rune_left -= damage;
damage = 0;
buffs[slot].magic_rune = magic_rune_left;
break;
}
else
{
if(magic_rune_left > 0)
damage -= magic_rune_left;
BuffFadeBySlot(slot);
slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
UpdateRuneFlags();
}
}
}
return damage;
}
Caryatis
07-10-2010, 11:44 PM
OK this is fully functional as far as I can tell now. The spell and DoT shielding work perfectly, spell runes are limited to DDs and SE_SpellVulnerability works perfect for clients. I added a section to deal with NPCs casting on clients with vulnerabilities as well, its not the most elegant solution however it allows you to have an NPC cast a spell that will make clients vulnerable to DDs or DoTs of any or all resists. To make clients vulnerable to both DDs and DoTs at the same time you would have to implement both SE_LimitInstant and SE_LimitMinDur in the vulnerability spell, however counterintuitive that may be(perhaps is a better way to code it?).
Going to include all the code even though not all changed(figured this would be easiest for others)... bold headers are the ones that have changed from the second post.
spell effects.cpp - line 2810 - add this
case SE_SpellVulnerability:
spell effects.cpp - line 3853 - add this
case SE_SpellVulnerability:
{
if(type == focusSpellVulnerability)
{
value = 1;
}
break;
}
mob.h - line 90 - add this
focusSpellVulnerability,
mob.h - line 843 - alter this
sint32 ReduceMagicalDamage(sint32 damage);
to this
sint32 AffectMagicalDamage(sint32 damage, int16 spell_id, const bool iBuffTic, Mob* attacker);
attack.ccp - line 3189 - alter this
damage = ReduceMagicalDamage(damage);
to this
damage = AffectMagicalDamage(damage, spell_id, iBuffTic, attacker);
attack.cpp - line 2932 - replace this function
sint32 Mob::ReduceMagicalDamage(sint32 damage)
{
...
}
with this
sint32 Mob::AffectMagicalDamage(sint32 damage, int16 spell_id, const bool iBuffTic, Mob* attacker)
{
if(damage <= 0)
{
return damage;
}
// Increase magical damage before runes
uint32 buff_count = GetMaxTotalSlots();
for(int i = 0; i < buff_count; i++)
{
if(IsEffectInSpell(buffs[i].spellid, SE_SpellVulnerability))
{
// For Clients, Pets and Bots that are casting the spell, see if the vulnerability affects their spell.
if(!attacker->IsNPC())
{
sint32 focus = attacker->CalcFocusEffect(focusSpellVulnerability, buffs[i].spellid, spell_id);
if(focus == 1)
{
damage += damage * spells[buffs[i].spellid].base[0] / 100;
}
}
// If an NPC is casting the spell on a player that has a vulnerability, relaxed restrictions on focus
// so that either the Client is vulnerable to DoTs or DDs of various resists or all.
else if (attacker->IsNPC())
{
int npc_vulnerable = 0;
for(int j = 0; j < EFFECT_COUNT; j++)
{
switch (spells[buffs[i].spellid].effectid[j])
{
case SE_Blank:
break;
case SE_LimitResist:
if(spells[buffs[i].spellid].base[j])
{
if(spells[spell_id].resisttype == spells[buffs[i].spellid].base[j])
npc_vulnerable = 1;
}
break;
case SE_LimitInstant:
if(!iBuffTic)
{
npc_vulnerable = 1;
break;
}
case SE_LimitMinDur:
if(iBuffTic)
{
npc_vulnerable = 1;
break;
}
default:{
// look pretty
}
}
}
if (npc_vulnerable)
{
damage += damage * spells[buffs[i].spellid].base[0] / 100;
}
}
}
}
// If this is a DoT, use DoT Shielding...
if(iBuffTic)
{
damage -= (damage * this->itembonuses.DoTShielding / 100);
}
// This must be a DD then so lets apply Spell Shielding and all the various runes that can block or negate DD spells.
else
{
// See if we block the spell outright first
int slot = GetBuffSlotFromType(SE_NegateAttacks);
if(slot >= 0 && buffs[slot].magic_rune > 0)
{
if(--buffs[slot].melee_rune == 0)
{
BuffFadeBySlot(slot);
UpdateRuneFlags();
}
return -6;
}
// Reduce damage by the Spell Shielding first so that the runes don't take the raw damage.
damage -= (damage * this->itembonuses.SpellDamageShield / 100);
// Do runes now.
slot = GetBuffSlotFromType(SE_MitigateSpellDamage);
if(slot >= 0)
{
int damage_to_reduce = damage * GetPartialMagicRuneReduction(buffs[slot].spellid) / 100;
if(damage_to_reduce > buffs[slot].magic_rune)
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d"
" damage remaining, fading buff.", damage_to_reduce, buffs[slot].magic_rune);
damage -= damage_to_reduce;
BuffFadeBySlot(slot);
UpdateRuneFlags();
}
else
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
" damage remaining.", damage_to_reduce, buffs[slot].magic_rune);
buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce);
damage -= damage_to_reduce;
}
}
if(damage < 1)
{
return -6;
}
slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
while(slot >= 0)
{
int16 magic_rune_left = buffs[slot].magic_rune;
if(magic_rune_left >= damage)
{
magic_rune_left -= damage;
damage = 0;
buffs[slot].magic_rune = magic_rune_left;
break;
}
else
{
if(magic_rune_left > 0)
damage -= magic_rune_left;
BuffFadeBySlot(slot);
slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
UpdateRuneFlags();
}
}
}
return damage;
}
trevius
07-11-2010, 12:02 AM
I just want to say thanks for all of the spell effect submissions, Caryatis.
I would add them to the SVN directly myself, but I haven't messed with spell effect code at all, and I normally don't commit stuff unless I fully understand what it is that I am committing and what effect it will have.
Kayen knows spell effects much better than I do and he works on Storm Haven with me. I think I will add all of your submissions to my Live server (as apposed to my test server lol) and let Kayen test them when he has time. Then, if he says they all work as intended and don't seem to break anything else, I will commit them if someone else hasn't already done so.
We all appreciate anyone willing to submit new code to these forums and it is great to see someone who is interested in filling in some of the missing spell effects that have been needed for a long time. We have limited devs here and limited time to add submissions, and I don't want you to feel like the submissions you are posting are being ignored, because they are not. We have been busy with other things lately like working on the new Underfoot client from Steam and other projects here and there.
Hopefully between Kayen and I, we can get these tested and committed to the SVN. That is, if he is willing to test them out, which I assume he is. I think he is drooling to get at your new spell effects :)
I'll take a look at all this stuff soonish. I've just been trying to help get underfoot working is all.
Caryatis
07-11-2010, 12:27 AM
No worries, I'm excited about the work you guys are doing on the Underfoot client and while I have no ability to help with that, at least I can help out this way. Hopefully soon my understanding of the code increases to where your oversight is minimal however atm I bet there is still many ways to fine tune my code(like you did with the triggeroncast).
edit... ok one more fix to this logic as I think its better to negate spells first, originally I was thinking that would only apply to DDs but really there shouldnt be a limit on that.
new AffectMagicalDamage function...
sint32 Mob::AffectMagicalDamage(sint32 damage, int16 spell_id, const bool iBuffTic, Mob* attacker)
{
if(damage <= 0)
{
return damage;
}
// See if we block the spell outright first
int slot = GetBuffSlotFromType(SE_NegateAttacks);
if(slot >= 0 && buffs[slot].magic_rune > 0)
{
if(--buffs[slot].melee_rune == 0)
{
BuffFadeBySlot(slot);
UpdateRuneFlags();
}
return -6;
}
// Increase magical damage before runes
uint32 buff_count = GetMaxTotalSlots();
for(int i = 0; i < buff_count; i++)
{
if(IsEffectInSpell(buffs[i].spellid, SE_SpellVulnerability))
{
// For Clients, Pets and Bots that are casting the spell, see if the vulnerability affects their spell.
if(!attacker->IsNPC())
{
sint32 focus = attacker->CalcFocusEffect(focusSpellVulnerability, buffs[i].spellid, spell_id);
if(focus == 1)
{
damage += damage * spells[buffs[i].spellid].base[0] / 100;
}
}
// If an NPC is casting the spell on a player that has a vulnerability, relaxed restrictions on focus
// so that either the Client is vulnerable to DoTs or DDs of various resists or all.
else if (attacker->IsNPC())
{
int npc_vulnerable = 0;
for(int j = 0; j < EFFECT_COUNT; j++)
{
switch (spells[buffs[i].spellid].effectid[j])
{
case SE_Blank:
break;
case SE_LimitResist:
if(spells[buffs[i].spellid].base[j])
{
if(spells[spell_id].resisttype == spells[buffs[i].spellid].base[j])
npc_vulnerable = 1;
}
break;
case SE_LimitInstant:
if(!iBuffTic)
{
npc_vulnerable = 1;
break;
}
case SE_LimitMinDur:
if(iBuffTic)
{
npc_vulnerable = 1;
break;
}
default:{
// look pretty
}
}
}
if (npc_vulnerable)
{
damage += damage * spells[buffs[i].spellid].base[0] / 100;
}
}
}
}
// If this is a DoT, use DoT Shielding...
if(iBuffTic)
{
damage -= (damage * this->itembonuses.DoTShielding / 100);
}
// This must be a DD then so lets apply Spell Shielding and all the various runes that can block or negate DD spells.
else
{
// Reduce damage by the Spell Shielding first so that the runes don't take the raw damage.
damage -= (damage * this->itembonuses.SpellDamageShield / 100);
// Do runes now.
slot = GetBuffSlotFromType(SE_MitigateSpellDamage);
if(slot >= 0)
{
int damage_to_reduce = damage * GetPartialMagicRuneReduction(buffs[slot].spellid) / 100;
if(damage_to_reduce > buffs[slot].magic_rune)
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d"
" damage remaining, fading buff.", damage_to_reduce, buffs[slot].magic_rune);
damage -= damage_to_reduce;
BuffFadeBySlot(slot);
UpdateRuneFlags();
}
else
{
mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
" damage remaining.", damage_to_reduce, buffs[slot].magic_rune);
buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce);
damage -= damage_to_reduce;
}
}
if(damage < 1)
{
return -6;
}
slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
while(slot >= 0)
{
int16 magic_rune_left = buffs[slot].magic_rune;
if(magic_rune_left >= damage)
{
magic_rune_left -= damage;
damage = 0;
buffs[slot].magic_rune = magic_rune_left;
break;
}
else
{
if(magic_rune_left > 0)
damage -= magic_rune_left;
BuffFadeBySlot(slot);
slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
UpdateRuneFlags();
}
}
}
return damage;
}
trevius
07-11-2010, 01:33 AM
Just went through and added all of the submissions so I can test them out (or rather so Kayen can test them). I noticed that you use line numbers, which is helpful, but in some cases they don't match up with what is on the SVN already. Since things change a lot, it would be good to add in some way to know where to add stuff other than just the line number. That is where the normal diffs come in handy, because they show the surrounding code. If you don't want to do a normal diff, you could just say something like this:
In spell_effects.cpp after this:
case SE_InterruptCasting:
{
if(IsCasting())
{
if(MakeRandomInt(0, 100) <= spells[spell_id].base[i])
{
InterruptSpell();
}
}
break;
}
Add this:
case SE_ImprovedSpellEffect:
case SE_BossSpellTrigger:
case SE_CastOnWearoff:
{
if (ticsremaining == 1)
{
SpellOnTarget(spells[spell_id].base[i], this);
}
break;
}
Or here is another example:
In spell_effects.cpp in the DoBuffTic function before this (around line 3299):
default: {
// do we need to do anyting here?
}
Add this:
case SE_ImprovedSpellEffect:
case SE_BossSpellTrigger:
case SE_CastOnWearoff:
{
if (ticsremaining == 1)
{
SpellOnTarget(spells[spell_id].base[i], this);
}
break;
}
Not too big of a deal as the line numbers help enough in most cases, but as I was adding your submissions, I found a couple parts kinda hard to tell exactly where you intended them to go. Hopefully I got them in the right places lol.
Caryatis
07-11-2010, 02:06 AM
I feel retarded lol, I couldn't figure out how to make a diff file and just now realized how simple it is lol. From now on will make all my submissions as diffs, as you are correct the line numbers are only vaguely accurate for some fields(some were done with clean SVN and others done with code already in from previous effects). If you run into to problems I can reupdate the previous code as diffs but nothing is really super sensitive linewise so think it should be ok.
edit... One bug so far is that if you crit a spell on a vulnerable foe, the damage displayed is correct however the crit message is not the new value. I assume I will need to add some code to the crit section as well. Will update it tomo and post a proper diff.
Caryatis
07-11-2010, 11:44 PM
Here is the code for spell and dot shielding separated out... Spell effect coming later.
mob.h
Index: mob.h
================================================== =================
--- mob.h (revision 1597)
+++ mob.h (working copy)
@@ -839,7 +839,7 @@
inline int16 GetErrorNumber() const {return adverrorinfo;}
sint32 ReduceDamage(sint32 damage);
- sint32 ReduceMagicalDamage(sint32 damage);
+ sint32 AffectMagicalDamage(sint32 damage, int16 spell_id, const bool iBuffTic, Mob* attacker);
virtual void DoSpecialAttackDamage(Mob *who, SkillType skill, sint32 max_damage, sint32 min_damage = 1, sint32 hate_override = -1);
bool Flurry();
attack.cpp
Index: attack.cpp
================================================== =================
--- attack.cpp (revision 1597)
+++ attack.cpp (working copy)
@@ -2929,13 +2929,14 @@
return(damage);
}
-sint32 Mob::ReduceMagicalDamage(sint32 damage)
+sint32 Mob::AffectMagicalDamage(sint32 damage, int16 spell_id, const bool iBuffTic, Mob* attacker)
{
- if(damage <= 0 || (!HasSpellRune() && !HasPartialSpellRune()))
+ if(damage <= 0)
{
return damage;
}
+ // See if we block the spell outright first
int slot = GetBuffSlotFromType(SE_NegateAttacks);
if(slot >= 0 && buffs[slot].magic_rune > 0)
{
@@ -2946,55 +2947,67 @@
}
return -6;
}
-
- slot = GetBuffSlotFromType(SE_MitigateSpellDamage);
- if(slot >= 0)
+
+ // If this is a DoT, use DoT Shielding...
+ if(iBuffTic)
{
- int damage_to_reduce = damage * GetPartialMagicRuneReduction(buffs[slot].spellid) / 100;
- if(damage_to_reduce > buffs[slot].magic_rune)
+ damage -= (damage * this->itembonuses.DoTShielding / 100);
+ }
+ // This must be a DD then so lets apply Spell Shielding and runes.
+ else
+ {
+ // Reduce damage by the Spell Shielding first so that the runes don't take the raw damage.
+ damage -= (damage * this->itembonuses.SpellDamageShield / 100);
+
+ // Do runes now.
+ slot = GetBuffSlotFromType(SE_MitigateSpellDamage);
+ if(slot >= 0)
{
- mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d"
- " damage remaining, fading buff.", damage_to_reduce, buffs[slot].magic_rune);
- damage -= damage_to_reduce;
- BuffFadeBySlot(slot);
- UpdateRuneFlags();
+ int damage_to_reduce = damage * GetPartialMagicRuneReduction(buffs[slot].spellid) / 100;
+ if(damage_to_reduce > buffs[slot].magic_rune)
+ {
+ mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d"
+ " damage remaining, fading buff.", damage_to_reduce, buffs[slot].magic_rune);
+ damage -= damage_to_reduce;
+ BuffFadeBySlot(slot);
+ UpdateRuneFlags();
+ }
+ else
+ {
+ mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
+ " damage remaining.", damage_to_reduce, buffs[slot].magic_rune);
+ buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce);
+ damage -= damage_to_reduce;
+ }
}
- else
+
+ if(damage < 1)
{
- mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d"
- " damage remaining.", damage_to_reduce, buffs[slot].magic_rune);
- buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce);
- damage -= damage_to_reduce;
+ return -6;
}
- }
- if(damage < 1)
- {
- return -6;
- }
-
- slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
- while(slot >= 0)
- {
- int16 magic_rune_left = buffs[slot].magic_rune;
- if(magic_rune_left >= damage)
+ slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
+ while(slot >= 0)
{
- magic_rune_left -= damage;
- damage = 0;
- buffs[slot].magic_rune = magic_rune_left;
- break;
+ int16 magic_rune_left = buffs[slot].magic_rune;
+ if(magic_rune_left >= damage)
+ {
+ magic_rune_left -= damage;
+ damage = 0;
+ buffs[slot].magic_rune = magic_rune_left;
+ break;
+ }
+ else
+ {
+ if(magic_rune_left > 0)
+ damage -= magic_rune_left;
+ BuffFadeBySlot(slot);
+ slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
+ UpdateRuneFlags();
+ }
}
- else
- {
- if(magic_rune_left > 0)
- damage -= magic_rune_left;
- BuffFadeBySlot(slot);
- slot = GetBuffSlotFromType(SE_AbsorbMagicAtt);
- UpdateRuneFlags();
- }
}
-
- return(damage);
+ return damage;
}
bool Mob::HasProcs() const
@@ -3159,7 +3172,7 @@
mlog(COMBAT__HITS, "Melee Damage reduced to %d", damage);
} else {
sint32 origdmg = damage;
- damage = ReduceMagicalDamage(damage);
+ damage = AffectMagicalDamage(damage, spell_id, iBuffTic, attacker);
mlog(COMBAT__HITS, "Melee Damage reduced to %d", damage);
if (origdmg != damage && attacker && attacker->IsClient()) {
if(attacker->CastToClient()->GetFilter(FILTER_DAMAGESHIELD) != FilterHide)
Caryatis
07-12-2010, 02:15 AM
OK think this is pretty solid now, its pretty annoying to test but I tested every possible combination and seems working good. The only minor thing is that if you have a DoT spell that has a DD component, the DD won't be affected by the vulnerability(the DoT will be so I'm not sure how vital it is).
mob.h
Index: mob.h
================================================== =================
--- mob.h (revision 1597)
+++ mob.h (working copy)
@@ -87,6 +87,7 @@
focusResistRate,
focusSpellHateMod,
focusTriggerOnCast,
+ focusSpellVulnerability,
} focusType;
enum {
@@ -778,6 +779,7 @@
bool TryDeathSave();
void DoBuffWearOffEffect(uint32 index);
void TryTriggerOnCast(Mob *target, uint32 spell_id);
+ sint32 GetVulnerability(sint32 damage, Mob *caster, uint32 spell_id, int32 ticsremaining);
static int32 GetAppearanceValue(EmuAppearance iAppearance);
void SendAppearancePacket(int32 type, int32 value, bool WholeZone = true, bool iIgnoreSelf = false, Client *specific_target=NULL);
mob.cpp
Index: mob.cpp
================================================== =================
--- mob.cpp (revision 1597)
+++ mob.cpp (working copy)
@@ -3036,4 +3036,88 @@
}
}
}
+}
+
+sint32 Mob::GetVulnerability(sint32 damage, Mob *caster, uint32 spell_id, int32 ticsremaining)
+{
+ // If we increased the datatype on GetBuffSlotFromType, this wouldnt be needed
+ uint32 buff_count = GetMaxTotalSlots();
+ for(int i = 0; i < buff_count; i++)
+ {
+ if(IsEffectInSpell(buffs[i].spellid, SE_SpellVulnerability))
+ {
+ // For Clients, Pets and Bots that are casting the spell, see if the vulnerability affects their spell.
+ if(!caster->IsNPC())
+ {
+ sint32 focus = caster->CalcFocusEffect(focusSpellVulnerability, buffs[i].spellid, spell_id);
+ if(focus == 1)
+ {
+ damage += damage * spells[buffs[i].spellid].base[0] / 100;
+ break;
+ }
+ }
+ // If an NPC is casting the spell on a player that has a vulnerability, relaxed restrictions on focus
+ // so that either the Client is vulnerable to DoTs or DDs of various resists or all.
+ else if (caster->IsNPC())
+ {
+ int npc_resist = 0;
+ int npc_instant = 0;
+ int npc_duration = 0;
+ for(int j = 0; j < EFFECT_COUNT; j++)
+ {
+ switch (spells[buffs[i].spellid].effectid[j])
+ {
+
+ case SE_Blank:
+ break;
+
+ case SE_LimitResist:
+ if(spells[buffs[i].spellid].base[j])
+ {
+ if(spells[spell_id].resisttype == spells[buffs[i].spellid].base[j])
+ npc_resist = 1;
+ }
+ break;
+
+ case SE_LimitInstant:
+ if(!ticsremaining)
+ {
+ npc_instant = 1;
+ break;
+ }
+
+ case SE_LimitMinDur:
+ if(ticsremaining)
+ {
+ npc_duration = 1;
+ break;
+ }
+
+ default:{
+ // look pretty
+ break;
+ }
+ }
+ }
+ // DDs and Dots of all resists
+ if ((npc_instant) || (npc_duration))
+ damage += damage * spells[buffs[i].spellid].base[0] / 100;
+
+ else if (npc_resist)
+ {
+ // DDs and Dots restricted by resists
+ if ((npc_instant) || (npc_duration))
+ {
+ damage += damage * spells[buffs[i].spellid].base[0] / 100;
+ }
+ // DD and Dots of 1 resist ... these are to maintain compatibility with current spells, not ideal.
+ else if (!npc_instant && !npc_duration)
+ {
+ damage += damage * spells[buffs[i].spellid].base[0] / 100;
+ }
+ }
+ }
+ }
+ }
+ return damage;
}
\ No newline at end of file
spell effects.cpp
Index: spell_effects.cpp
================================================== =================
--- spell_effects.cpp (revision 1597)
+++ spell_effects.cpp (working copy)
@@ -203,8 +203,10 @@
//handles AAs and what not...
if(caster)
+ {
+ dmg = GetVulnerability(dmg, caster, spell_id, 0);
dmg = caster->GetActSpellDamage(spell_id, dmg);
-
+ }
dmg = -dmg;
Damage(caster, dmg, spell_id, spell.skill, false, buffslot, false);
}
@@ -2812,6 +2814,7 @@
case SE_LimitCastTime:
case SE_NoCombatSkills:
case SE_TriggerOnCast:
+ case SE_SpellVulnerability:
{
break;
}
@@ -3130,13 +3133,15 @@
if(!IsClient())
AddToHateList(caster, -effect_value);
}
-
+ effect_value = GetVulnerability(effect_value, caster, spell_id, ticsremaining);
TryDotCritical(spell_id, caster, effect_value);
}
effect_value = effect_value * modifier / 100;
}
if(effect_value < 0) {
+ if(caster && !caster->IsClient())
+ effect_value = GetVulnerability(effect_value, caster, spell_id, ticsremaining);
effect_value = -effect_value;
Damage(caster, effect_value, spell_id, spell.skill, false, i, true);
} else if(effect_value > 0) {
@@ -3860,6 +3865,14 @@
}
break;
}
+ case SE_SpellVulnerability:
+ {
+ if(type == focusSpellVulnerability)
+ {
+ value = 1;
+ }
+ break;
+ }
#if EQDEBUG >= 6
//this spits up a lot of garbage when calculating spell focuses
//since they have all kinds of extra effects on them.
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.