|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11-06-2010, 11:32 PM
|
Dragon
|
|
Join Date: May 2009
Location: Milky Way
Posts: 539
|
|
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.
|
|
|
|
|
|
|
11-07-2010, 04:04 PM
|
Dragon
|
|
Join Date: May 2009
Location: Milky Way
Posts: 539
|
|
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.
|
|
|
|
11-07-2010, 04:09 PM
|
Fire Beetle
|
|
Join Date: Nov 2010
Posts: 1
|
|
Great Work!
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -4. The time now is 05:15 AM.
|
|
|
|
|
|
|
|
|
|
|
|
|