Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Server Code Submissions

Reply
 
Thread Tools Display Modes
  #1  
Old 11-06-2010, 11:32 PM
Caryatis
Dragon
 
Join Date: May 2009
Location: Milky Way
Posts: 539
Default 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.
Reply With Quote
  #2  
Old 11-07-2010, 04:04 PM
Caryatis
Dragon
 
Join Date: May 2009
Location: Milky Way
Posts: 539
Default

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.
Reply With Quote
  #3  
Old 11-07-2010, 04:09 PM
oldfart
Fire Beetle
 
Join Date: Nov 2010
Posts: 1
Default

Great Work!
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 05:15 AM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3