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
Code:
case SE_SpellVulnerability:
spell effects.cpp - line 3853 - add this
Code:
case SE_SpellVulnerability:
{
if(type == focusSpellVulnerability)
{
value = 1;
}
break;
}
mob.h - line 90 - add this
Code:
focusSpellVulnerability,
mob.h - line 843 - alter this
Code:
sint32 ReduceMagicalDamage(sint32 damage);
to this
Code:
sint32 AffectMagicalDamage(sint32 damage, int16 spell_id, const bool iBuffTic, Mob* attacker);
attack.ccp - line 3189 - alter this
Code:
damage = ReduceMagicalDamage(damage);
to this
Code:
damage = AffectMagicalDamage(damage, spell_id, iBuffTic, attacker);
attack.cpp - line 2932 - replace this function
Code:
sint32 Mob::ReduceMagicalDamage(sint32 damage)
{
...
}
with this
Code:
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;
}