This one might be slightly confusing as SpellShield was called SpellDamageShield so it also involves a little renaming to keep things consistent. Otherwise pretty straight forward, cast a spell and get damaged while DS mitigation reduces the ds in melee(wasnt sure if it applied to spell damage shields so atm it only affects the standard melee DS).
Code:
Index: EQEmuServer/common/ruletypes.h
===================================================================
--- EQEmuServer/common/ruletypes.h (revision 1715)
+++ EQEmuServer/common/ruletypes.h (working copy)
@@ -60,6 +60,7 @@
RULE_INT ( Character, ItemStunResistCap, 35)
RULE_INT ( Character, ItemStrikethroughCap, 35)
RULE_INT ( Character, ItemATKCap, 250)
+RULE_INT ( Character, ItemDSMitigationCap, 50)
RULE_INT ( Character, SkillUpModifier, 100) //skill ups are at 100%
RULE_BOOL ( Character, SharedBankPlat, false) //off by default to prevent duping for now
RULE_BOOL ( Character, BindAnywhere, false)
Index: EQEmuServer/zone/attack.cpp
===================================================================
--- EQEmuServer/zone/attack.cpp (revision 1715)
+++ EQEmuServer/zone/attack.cpp (working copy)
@@ -2330,52 +2330,70 @@
// a reverse ds causes damage to the wearer whenever it attack someone
// given this, a reverse ds must be checked each time the wearer is attacking
// and not when they're attacked
-void Mob::DamageShield(Mob* attacker) {
- //a damage shield on a spell is a negative value but on an item it's a positive value so add the spell value and subtract the item value to get the end ds value
- if(!attacker) return;
+//a damage shield on a spell is a negative value but on an item it's a positive value so add the spell value and subtract the item value to get the end ds value
+void Mob::DamageShield(Mob* attacker, bool spell_ds) {
- int DS = spellbonuses.DamageShield;
- int rev_ds = attacker->spellbonuses.ReverseDamageShield;
-
- if(DS == 0 && rev_ds == 0)
+ if(!attacker || this == attacker)
return;
- if(this == attacker) //I was crashing when I hit myself with melee with a DS on, not sure why but we shouldn't be reflecting damage onto ourselves anyway really.
+ int DS = 0;
+ int rev_ds = 0;
+ int16 spellid = 0;
+
+ if(!spell_ds)
+ {
+ DS = spellbonuses.DamageShield;
+ rev_ds = attacker->spellbonuses.ReverseDamageShield;
+
+ if(spellbonuses.DamageShieldSpellID != 0 && spellbonuses.DamageShieldSpellID != SPELL_UNKNOWN)
+ spellid = spellbonuses.DamageShieldSpellID;
+ }
+ else {
+ DS = spellbonuses.SpellDamageShield;
+ rev_ds = 0;
+ // This ID returns "you are burned", seemed most appropriate for spell DS
+ spellid = 2166;
+ }
+
+ if(DS == 0 && rev_ds == 0)
return;
-
+
mlog(COMBAT__HITS, "Applying Damage Shield of value %d to %s", DS, attacker->GetName());
-
- int16 spellid = SPELL_UNKNOWN;
- if(spellbonuses.DamageShieldSpellID != 0 && spellbonuses.DamageShieldSpellID != SPELL_UNKNOWN)
- spellid = spellbonuses.DamageShieldSpellID;
+
//invert DS... spells yield negative values for a true damage shield
if(DS < 0) {
- if (IsClient())
- {
- int dsMod = 100;
- switch (CastToClient()->GetAA(aaCoatofThistles))
- {
- case 1:
- dsMod = 110;
- break;
- case 2:
- dsMod = 115;
- break;
- case 3:
- dsMod = 120;
- break;
- case 4:
- dsMod = 125;
- break;
- case 5:
- dsMod = 130;
- break;
+ if(!spell_ds) {
+ if(IsClient()) {
+ int dsMod = 100;
+ switch (CastToClient()->GetAA(aaCoatofThistles))
+ {
+ case 1:
+ dsMod = 110;
+ break;
+ case 2:
+ dsMod = 115;
+ break;
+ case 3:
+ dsMod = 120;
+ break;
+ case 4:
+ dsMod = 125;
+ break;
+ case 5:
+ dsMod = 130;
+ break;
+ }
+ DS = ((DS * dsMod) / 100);
}
-
- DS = ((DS * dsMod) / 100);
+ DS -= itembonuses.DamageShield; //+Damage Shield should only work when you already have a DS spell
}
- DS -= itembonuses.DamageShield; //+Damage Shield should only work when you already have a DS spell
- attacker->Damage(this, -DS, spellid, ABJURE/*hackish*/, false);
+ if(!spell_ds) {
+ DS += attacker->itembonuses.DSMitigation;
+ attacker->Damage(this, -DS, spellid, ABJURE/*hackish*/, false);
+ }
+ else {
+ attacker->Damage(this, -DS, spellid, ABJURE/*hackish*/, false);
+ }
//we can assume there is a spell now
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct));
CombatDamage_Struct* cds = (CombatDamage_Struct*)outapp->pBuffer;
@@ -2386,7 +2404,7 @@
cds->damage = DS;
entity_list.QueueCloseClients(this, outapp);
safe_delete(outapp);
- } else {
+ } else if (DS > 0 && !spell_ds) {
//we are healing the attacker...
attacker->HealDamage(DS);
//TODO: send a packet???
@@ -2998,7 +3016,7 @@
else
{
// Reduce damage by the Spell Shielding first so that the runes don't take the raw damage.
- damage -= (damage * this->itembonuses.SpellDamageShield / 100);
+ damage -= (damage * this->itembonuses.SpellShield / 100);
// Do runes now.
slot = GetBuffSlotFromType(SE_MitigateSpellDamage);
@@ -3153,7 +3171,7 @@
// only apply DS if physical damage (no spell damage)
// damage shield calls this function with spell_id set, so its unavoidable
if (attacker && damage > 0 && spell_id == SPELL_UNKNOWN && skill_used != ARCHERY && skill_used != THROWING) {
- this->DamageShield(attacker);
+ this->DamageShield(attacker, 0);
uint32 buff_count = GetMaxTotalSlots();
for(uint32 bs = 0; bs < buff_count; bs++){
if((buffs[bs].spellid != SPELL_UNKNOWN) && buffs[bs].numhits > 0 && !IsDiscipline(buffs[bs].spellid)){
Index: EQEmuServer/zone/bonuses.cpp
===================================================================
--- EQEmuServer/zone/bonuses.cpp (revision 1715)
+++ EQEmuServer/zone/bonuses.cpp (working copy)
@@ -320,10 +320,10 @@
newbon->DamageShield += item->DamageShield;
}
if(item->SpellShield > 0) {
- if((newbon->SpellDamageShield + item->SpellShield) > RuleI(Character, ItemSpellShieldingCap))
- newbon->SpellDamageShield = RuleI(Character, ItemSpellShieldingCap);
+ if((newbon->SpellShield + item->SpellShield) > RuleI(Character, ItemSpellShieldingCap))
+ newbon->SpellShield = RuleI(Character, ItemSpellShieldingCap);
else
- newbon->SpellDamageShield += item->SpellShield;
+ newbon->SpellShield += item->SpellShield;
}
if(item->Shielding > 0) {
if((newbon->MeleeMitigation + item->Shielding) > RuleI(Character, ItemShieldingCap))
@@ -367,6 +367,12 @@
else
newbon->DoTShielding += item->DotShielding;
}
+ if(item->DSMitigation > 0) {
+ if((newbon->DSMitigation + item->DSMitigation) > RuleI(Character, ItemDSMitigationCap))
+ newbon->DSMitigation = RuleI(Character, ItemDSMitigationCap);
+ else
+ newbon->DSMitigation += item->DSMitigation;
+ }
if (item->Worn.Effect>0 && (item->Worn.Type == ET_WornEffect)) { // latent effects
ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon);
}
Index: EQEmuServer/zone/mob.h
===================================================================
--- EQEmuServer/zone/mob.h (revision 1715)
+++ EQEmuServer/zone/mob.h (working copy)
@@ -217,6 +217,7 @@
int DamageShield; // this is damage done to mobs that attack this
DmgShieldType DamageShieldType;
int SpellDamageShield;
+ int SpellShield;
int ReverseDamageShield; // this is damage done to the mob when it attacks
uint16 ReverseDamageShieldSpellID;
DmgShieldType ReverseDamageShieldType;
@@ -275,6 +276,7 @@
sint8 HundredHands; //extra haste, stacks with all other haste i
sint8 MeleeLifetap;
+ sint16 DSMitigation;
int XPRateMod;
sint8 Packrat; //weight reduction for items, 1 point = 10%
@@ -539,7 +541,7 @@
void ApplyMeleeDamageBonus(int16 skill, sint32 &damage);
virtual void MeleeMitigation(Mob *attacker, sint32 &damage, sint32 minhit);
- void DamageShield(Mob* other);
+ void DamageShield(Mob* other, bool spell_ds);
bool FindBuff(int16 spellid);
bool FindType(int8 type, bool bOffensive = false, int16 threshold = 100);
sint8 GetBuffSlotFromType(int16 type);
Index: EQEmuServer/zone/spells.cpp
===================================================================
--- EQEmuServer/zone/spells.cpp (revision 1715)
+++ EQEmuServer/zone/spells.cpp (working copy)
@@ -3128,6 +3128,9 @@
}
}
+ if(spelltar->spellbonuses.SpellDamageShield)
+ spelltar->DamageShield(this, 1);
+
TryTriggerOnCast(spelltar, spell_id);
TrySpellTrigger(spelltar, spell_id);
TryApplyEffect(spelltar, spell_id);