EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Development::Server Code Submissions (https://www.eqemulator.org/forums/forumdisplay.php?f=669)
-   -   COMMITTED: Heal Amt, Spell Dmg, Clairvoyance & SE_SpellDamage (https://www.eqemulator.org/forums/showthread.php?t=32431)

Caryatis 11-06-2010 11:32 PM

COMMITTED: Heal Amt, Spell Dmg, Clairvoyance & SE_SpellDamage
 
I found a post on the formula used for Spell Damage and Heal Amount(from items) so figured I would make these work. Clairvoyance is alittle different but wasnt too hard to find info on it. SE_SpellDamage is from bard songs like Garadell's Fatesong.

Rules SQL:
Code:

INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Character:ItemClairvoyanceCap', '250', 'Clairvoyance returns mana after a cast under certain circumstances');
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Character:ItemHealAmtCap', '250', 'Heal Amt adds to heal spells based on their cast & recast time');
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Character:ItemSpellDmgCap', '250', 'Spell Dmg adds to DD spells based on their cast & recast time');

Diff:
Code:

Index: EQEmuServer/common/ruletypes.h
===================================================================
--- EQEmuServer/common/ruletypes.h        (revision 1715)
+++ EQEmuServer/common/ruletypes.h        (working copy)
@@ -60,6 +60,9 @@
 RULE_INT ( Character, ItemStunResistCap, 35)
 RULE_INT ( Character, ItemStrikethroughCap, 35)
 RULE_INT ( Character, ItemATKCap, 250)
+RULE_INT ( Character, ItemHealAmtCap, 250)
+RULE_INT ( Character, ItemSpellDmgCap, 250)
+RULE_INT ( Character, ItemClairvoyanceCap, 250)
 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/bonuses.cpp
===================================================================
--- EQEmuServer/zone/bonuses.cpp        (revision 1715)
+++ EQEmuServer/zone/bonuses.cpp        (working copy)
@@ -367,6 +367,26 @@
                else
                        newbon->DoTShielding += item->DotShielding;
        }
+       
+        if(item->HealAmt > 0) {
+                if((newbon->HealAmt + item->HealAmt) > RuleI(Character, ItemHealAmtCap))
+                        newbon->HealAmt = RuleI(Character, ItemHealAmtCap);
+                else
+                        newbon->HealAmt += item->HealAmt;
+        }
+        if(item->SpellDmg > 0) {
+                if((newbon->SpellDmg + item->SpellDmg) > RuleI(Character, ItemSpellDmgCap))
+                        newbon->SpellDmg = RuleI(Character, ItemSpellDmgCap);
+                else
+                        newbon->SpellDmg += item->SpellDmg;
+        }
+        if(item->Clairvoyance > 0) {
+                if((newbon->Clairvoyance + item->Clairvoyance) > RuleI(Character, ItemClairvoyanceCap))
+                        newbon->Clairvoyance = RuleI(Character, ItemClairvoyanceCap);
+                else
+                        newbon->Clairvoyance += item->Clairvoyance;
+        }
+       
        if (item->Worn.Effect>0 && (item->Worn.Type == ET_WornEffect)) { // latent effects
                ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon);
        }
@@ -1206,8 +1226,12 @@
                                        newbon->Accuracy = effect_value;
                                break;
                        }
-
-                               
+                        case SE_SpellDamage:
+                        {
+                                // Only used for worn effects and to trigger a buff check
+                                newbon->SpellDmg += effect_value;
+                                break;
+                        }
                }
        }
 }
Index: EQEmuServer/zone/client.h
===================================================================
--- EQEmuServer/zone/client.h        (revision 1715)
+++ EQEmuServer/zone/client.h        (working copy)
@@ -390,6 +390,7 @@
        inline virtual sint16        GetHeroicCR()        const { return itembonuses.HeroicCR; }
        inline virtual sint16        GetHeroicCorrup()        const { return itembonuses.HeroicCorrup; }
 
+        sint32 Additional_SpellDmg(int16 spell_id);
        float GetActSpellRange(int16 spell_id, float range);
        sint32 GetActSpellDamage(int16 spell_id, sint32 value);
        sint32 GetActSpellHealing(int16 spell_id, sint32 value);
Index: EQEmuServer/zone/effects.cpp
===================================================================
--- EQEmuServer/zone/effects.cpp        (revision 1715)
+++ EQEmuServer/zone/effects.cpp        (working copy)
@@ -39,6 +39,25 @@
        return (range * extrange) / 100;
 }
 
+sint32 Client::Additional_SpellDmg(int16 spell_id)
+{
+        sint32 spell_dmg = 0;
+        uint32 buff_count = GetMaxTotalSlots();
+        sint16 focus = 0;
+       
+        for (int i=0; i < buff_count; i++)
+        {
+                if(IsEffectInSpell(buffs[i].spellid, SE_SpellDamage))
+                {
+                        focus = CalcFocusEffect(focusSpellDamage, buffs[i].spellid, spell_id);
+                        if(focus)
+                                spell_dmg += focus;
+                }
+        }
+        return spell_dmg;
+}
+
 sint32 Client::GetActSpellDamage(int16 spell_id, sint32 value) {
        // Important variables:
        // value: the actual damage after resists, passed from Mob::SpellEffect
@@ -47,7 +66,14 @@
        // chance: critital chance %
        //all of the ordering and stacking in here might be wrong, but I dont care right now.
       
-       
+        sint16 spell_dmg = 0;
+        // Formula = SpellDmg * (casttime + recastime) / 7
+        if(this->itembonuses.SpellDmg)
+                spell_dmg = this->itembonuses.SpellDmg * (spells[spell_id].cast_time + spells[spell_id].recast_time) / 7000;
+        // Spell-based SpellDmg adds directly but it restricted by focuses.
+        if(this->spellbonuses.SpellDmg)
+                spell_dmg += this->Additional_SpellDmg(spell_id);
+               
        sint32 modifier = 100;
       
        //Dunno if this makes sense:
@@ -208,22 +234,29 @@
                        mlog(SPELLS__CRITS, "Attempting spell crit. Spell: %s (%d), Value: %d, Modifier: %d, Chance: %d, Ratio: %d", spells[spell_id].name, spell_id, value, modifier, chance, ratio);
                        if(MakeRandomInt(0,100) <= chance) {
                                modifier += modifier*ratio/100;
-                                mlog(SPELLS__CRITS, "Spell crit successful. Final damage modifier: %d, Final Damage: %d", modifier, (value * modifier) / 100);
-                                entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s delivers a critical blast! (%d)", GetName(), ((-value * modifier) / 100));       
+                                spell_dmg *= 2;
+                                mlog(SPELLS__CRITS, "Spell crit successful. Final damage modifier: %d, Final Damage: %d", modifier, (value * modifier / 100) - spell_dmg);
+                                entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s delivers a critical blast! (%d)", GetName(), (-value * modifier / 100) + spell_dmg);       
                        } else
-                                mlog(SPELLS__CRITS, "Spell crit failed. Final Damage Modifier: %d, Final Damage: %d", modifier, (value * modifier) / 100);
+                                mlog(SPELLS__CRITS, "Spell crit failed. Final Damage Modifier: %d, Final Damage: %d", modifier, (value * modifier / 100) - spell_dmg);
                }
        }
       
-        return (value * modifier) / 100;
+        return ((value * modifier / 100) - spell_dmg);
 }
 
 sint32 Client::GetActSpellHealing(int16 spell_id, sint32 value) {
+       
        sint32 modifier = 100;
-
        modifier += GetFocusEffect(focusImprovedHeal, spell_id);
                                               
-        if(spells[spell_id].buffduration < 1) {
+        if(spells[spell_id].buffduration < 1)
+        {
+                sint16 heal_amt = 0;
+                // Formula = HealAmt * (casttime + recastime) / 7
+                if(this->itembonuses.HealAmt)
+                        heal_amt = this->itembonuses.HealAmt * (spells[spell_id].cast_time + spells[spell_id].recast_time) / 7000;
+               
                //non-dot
                switch(GetAA(aaHealingAdept)) {
                case 1:
@@ -299,22 +332,34 @@
    }
               
                if(MakeRandomInt(0,100) < chance) {
-                        entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), ((value * modifier) / 50));               
-                        return (value * modifier) / 50;
+                        entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), ((value * modifier / 50) + heal_amt*2));               
+                        return (value * modifier / 50) + heal_amt*2;
                }
                else{
-                        return (value * modifier) / 100;
+                        return (value * modifier / 100) + heal_amt;
                }               
        }
                                       
-        return (value * modifier) / 100;
+        return (value * modifier / 100);
 }
 
 sint32 Client::GetActSpellCost(int16 spell_id, sint32 cost)
 {
+        // Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell
+        if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] > GetLevel() - 5)
+        {
+                sint16 mana_back = this->itembonuses.Clairvoyance * MakeRandomInt(1, 100) / 100;
+                // Doesnt generate mana, so best case is a free spell
+                if(mana_back > cost)
+                        mana_back = cost;
+                       
+                cost -= mana_back;
+        }
+       
        // This formula was derived from the following resource:
        // http://www.eqsummoners.com/eq1/specialization-library.html
        // WildcardX
+       
        float PercentManaReduction = 0;
        float SpecializeSkill = GetSpecializeSkillValue(spell_id);
        int SuccessChance = MakeRandomInt(0, 100);
Index: EQEmuServer/zone/mob.h
===================================================================
--- EQEmuServer/zone/mob.h        (revision 1715)
+++ EQEmuServer/zone/mob.h        (working copy)
@@ -90,6 +90,7 @@
        focusSpellVulnerability,
        focusTwincast,
        focusSympatheticProc,
+        focusSpellDamage,
 } focusType;
 
 enum {
@@ -275,6 +276,10 @@
 
        sint8 HundredHands;                //extra haste, stacks with all other haste  i
        sint8 MeleeLifetap;
+        sint32 HealAmt;
+        sint32 SpellDmg;
+        sint32 Clairvoyance;
        int XPRateMod;
 
        sint8        Packrat;        //weight reduction for items, 1 point = 10%
Index: EQEmuServer/zone/spell_effects.cpp
===================================================================
--- EQEmuServer/zone/spell_effects.cpp        (revision 1715)
+++ EQEmuServer/zone/spell_effects.cpp        (working copy)
@@ -2893,6 +2893,7 @@
                        case SE_EffectOnFade:
                        case SE_MaxHPChange:
                        case SE_SympatheticProc:
+                        case SE_SpellDamage:
                        {
                                break;
                        }
@@ -4035,7 +4036,16 @@
                        }
                        break;
                }
+                case SE_SpellDamage:
+                {
+                        if(type == focusSpellDamage)
+                                value = focus_spell.base[i];
 
+                        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.


Caryatis 11-07-2010 04:04 PM

Slight change to add the restrictions to spelldmg and healamt, they should only trigger on spells within 5 levels of you and not add more dmg/heal than the spell itself.

Code:

Index: EQEmuServer/common/ruletypes.h
===================================================================
--- EQEmuServer/common/ruletypes.h        (revision 1715)
+++ EQEmuServer/common/ruletypes.h        (working copy)
@@ -60,6 +60,9 @@
 RULE_INT ( Character, ItemStunResistCap, 35)
 RULE_INT ( Character, ItemStrikethroughCap, 35)
 RULE_INT ( Character, ItemATKCap, 250)
+RULE_INT ( Character, ItemHealAmtCap, 250)
+RULE_INT ( Character, ItemSpellDmgCap, 250)
+RULE_INT ( Character, ItemClairvoyanceCap, 250)
 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/bonuses.cpp
===================================================================
--- EQEmuServer/zone/bonuses.cpp        (revision 1715)
+++ EQEmuServer/zone/bonuses.cpp        (working copy)
@@ -367,6 +367,26 @@
                else
                        newbon->DoTShielding += item->DotShielding;
        }
+       
+        if(item->HealAmt > 0) {
+                if((newbon->HealAmt + item->HealAmt) > RuleI(Character, ItemHealAmtCap))
+                        newbon->HealAmt = RuleI(Character, ItemHealAmtCap);
+                else
+                        newbon->HealAmt += item->HealAmt;
+        }
+        if(item->SpellDmg > 0) {
+                if((newbon->SpellDmg + item->SpellDmg) > RuleI(Character, ItemSpellDmgCap))
+                        newbon->SpellDmg = RuleI(Character, ItemSpellDmgCap);
+                else
+                        newbon->SpellDmg += item->SpellDmg;
+        }
+        if(item->Clairvoyance > 0) {
+                if((newbon->Clairvoyance + item->Clairvoyance) > RuleI(Character, ItemClairvoyanceCap))
+                        newbon->Clairvoyance = RuleI(Character, ItemClairvoyanceCap);
+                else
+                        newbon->Clairvoyance += item->Clairvoyance;
+        }
+       
        if (item->Worn.Effect>0 && (item->Worn.Type == ET_WornEffect)) { // latent effects
                ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon);
        }
@@ -1206,8 +1226,12 @@
                                        newbon->Accuracy = effect_value;
                                break;
                        }
-
-                               
+                        case SE_SpellDamage:
+                        {
+                                // Only used for worn effects and to trigger a buff check
+                                newbon->SpellDmg += effect_value;
+                                break;
+                        }
                }
        }
 }
Index: EQEmuServer/zone/client.h
===================================================================
--- EQEmuServer/zone/client.h        (revision 1715)
+++ EQEmuServer/zone/client.h        (working copy)
@@ -390,6 +390,7 @@
        inline virtual sint16        GetHeroicCR()        const { return itembonuses.HeroicCR; }
        inline virtual sint16        GetHeroicCorrup()        const { return itembonuses.HeroicCorrup; }
 
+        sint32 Additional_SpellDmg(int16 spell_id);
        float GetActSpellRange(int16 spell_id, float range);
        sint32 GetActSpellDamage(int16 spell_id, sint32 value);
        sint32 GetActSpellHealing(int16 spell_id, sint32 value);
Index: EQEmuServer/zone/effects.cpp
===================================================================
--- EQEmuServer/zone/effects.cpp        (revision 1715)
+++ EQEmuServer/zone/effects.cpp        (working copy)
@@ -39,6 +39,25 @@
        return (range * extrange) / 100;
 }
 
+sint32 Client::Additional_SpellDmg(int16 spell_id)
+{
+        sint32 spell_dmg = 0;
+        uint32 buff_count = GetMaxTotalSlots();
+        sint16 focus = 0;
+       
+        for (int i=0; i < buff_count; i++)
+        {
+                if(IsEffectInSpell(buffs[i].spellid, SE_SpellDamage))
+                {
+                        focus = CalcFocusEffect(focusSpellDamage, buffs[i].spellid, spell_id);
+                        if(focus)
+                                spell_dmg += focus;
+                }
+        }
+        return spell_dmg;
+}
+
+
 sint32 Client::GetActSpellDamage(int16 spell_id, sint32 value) {
        // Important variables:
        // value: the actual damage after resists, passed from Mob::SpellEffect
@@ -47,7 +66,17 @@
        // chance: critital chance %
        //all of the ordering and stacking in here might be wrong, but I dont care right now.
       
-       
+        sint16 spell_dmg = 0;
+        // Formula = SpellDmg * (casttime + recastime) / 7; Cant trigger off spell less than 5 levels below and cant cause more dmg than the spell itself.
+        if(this->itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] > GetLevel() - 5) {
+                spell_dmg = this->itembonuses.SpellDmg * (spells[spell_id].cast_time + spells[spell_id].recast_time) / 7000;
+                if(spell_dmg > -value)
+                        spell_dmg = -value;
+        }
+        // Spell-based SpellDmg adds directly but it restricted by focuses.
+        if(this->spellbonuses.SpellDmg)
+                spell_dmg += this->Additional_SpellDmg(spell_id);
+               
        sint32 modifier = 100;
       
        //Dunno if this makes sense:
@@ -208,22 +237,32 @@
                        mlog(SPELLS__CRITS, "Attempting spell crit. Spell: %s (%d), Value: %d, Modifier: %d, Chance: %d, Ratio: %d", spells[spell_id].name, spell_id, value, modifier, chance, ratio);
                        if(MakeRandomInt(0,100) <= chance) {
                                modifier += modifier*ratio/100;
-                                mlog(SPELLS__CRITS, "Spell crit successful. Final damage modifier: %d, Final Damage: %d", modifier, (value * modifier) / 100);
-                                entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s delivers a critical blast! (%d)", GetName(), ((-value * modifier) / 100));       
+                                spell_dmg *= 2;
+                                mlog(SPELLS__CRITS, "Spell crit successful. Final damage modifier: %d, Final Damage: %d", modifier, (value * modifier / 100) - spell_dmg);
+                                entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s delivers a critical blast! (%d)", GetName(), (-value * modifier / 100) + spell_dmg);       
                        } else
-                                mlog(SPELLS__CRITS, "Spell crit failed. Final Damage Modifier: %d, Final Damage: %d", modifier, (value * modifier) / 100);
+                                mlog(SPELLS__CRITS, "Spell crit failed. Final Damage Modifier: %d, Final Damage: %d", modifier, (value * modifier / 100) - spell_dmg);
                }
        }
       
-        return (value * modifier) / 100;
+        return ((value * modifier / 100) - spell_dmg);
 }
 
 sint32 Client::GetActSpellHealing(int16 spell_id, sint32 value) {
+       
        sint32 modifier = 100;
-
        modifier += GetFocusEffect(focusImprovedHeal, spell_id);
                                               
-        if(spells[spell_id].buffduration < 1) {
+        if(spells[spell_id].buffduration < 1)
+        {
+                sint16 heal_amt = 0;
+                // Formula = HealAmt * (casttime + recastime) / 7; Cant trigger off spell less than 5 levels below and cant heal more than the spell itself.
+                if(this->itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] > GetLevel() - 5) {
+                        heal_amt = this->itembonuses.HealAmt * (spells[spell_id].cast_time + spells[spell_id].recast_time) / 7000;
+                        if(heal_amt > value)
+                                heal_amt = value;
+                }
+               
                //non-dot
                switch(GetAA(aaHealingAdept)) {
                case 1:
@@ -299,22 +338,34 @@
    }
               
                if(MakeRandomInt(0,100) < chance) {
-                        entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), ((value * modifier) / 50));               
-                        return (value * modifier) / 50;
+                        entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), ((value * modifier / 50) + heal_amt*2));               
+                        return (value * modifier / 50) + heal_amt*2;
                }
                else{
-                        return (value * modifier) / 100;
+                        return (value * modifier / 100) + heal_amt;
                }               
        }
                                       
-        return (value * modifier) / 100;
+        return (value * modifier / 100);
 }
 
 sint32 Client::GetActSpellCost(int16 spell_id, sint32 cost)
 {
+        // Formula = Unknown exact, based off a random percent chance up to mana cost(before focuses) of the cast spell
+        if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] > GetLevel() - 5)
+        {
+                sint16 mana_back = this->itembonuses.Clairvoyance * MakeRandomInt(1, 100) / 100;
+                // Doesnt generate mana, so best case is a free spell
+                if(mana_back > cost)
+                        mana_back = cost;
+                       
+                cost -= mana_back;
+        }
+       
        // This formula was derived from the following resource:
        // http://www.eqsummoners.com/eq1/specialization-library.html
        // WildcardX
Index: EQEmuServer/zone/mob.h
===================================================================
--- EQEmuServer/zone/mob.h        (revision 1715)
+++ EQEmuServer/zone/mob.h        (working copy)
@@ -90,6 +90,7 @@
        focusSpellVulnerability,
        focusTwincast,
        focusSympatheticProc,
+        focusSpellDamage,
 } focusType;
 
 enum {
@@ -275,6 +276,10 @@
 
        sint8 HundredHands;                //extra haste, stacks with all other haste  i
        sint8 MeleeLifetap;
+        sint32 HealAmt;
+        sint32 SpellDmg;
+        sint32 Clairvoyance;
        int XPRateMod;
 
        sint8        Packrat;        //weight reduction for items, 1 point = 10%
Index: EQEmuServer/zone/spell_effects.cpp
===================================================================
--- EQEmuServer/zone/spell_effects.cpp        (revision 1715)
+++ EQEmuServer/zone/spell_effects.cpp        (working copy)
@@ -2893,6 +2893,7 @@
                        case SE_EffectOnFade:
                        case SE_MaxHPChange:
                        case SE_SympatheticProc:
+                        case SE_SpellDamage:
                        {
                                break;
                        }
@@ -4035,7 +4036,16 @@
                        }
                        break;
                }
+                case SE_SpellDamage:
+                {
+                        if(type == focusSpellDamage)
+                                value = focus_spell.base[i];
 
+                        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.


oldfart 11-07-2010 04:09 PM

Great Work!


All times are GMT -4. The time now is 11:36 AM.

Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.