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
Code:
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
Code:
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
Code:
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.