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

Reply
 
Thread Tools Display Modes
  #1  
Old 07-02-2010, 01:42 AM
Caryatis
Dragon
 
Join Date: May 2009
Location: Milky Way
Posts: 541
Default COMMITTED: TriggerOnCast

I'm not too skilled with C++ but there are alot of spell effects I would like to see supported so here is my attempt at one.

This effect causes another spell to land at the completion of casting a spell. This is used by many spells, the enchanter Mana Flare line which adds a DD to any DD spell cast, the wizard Pyro/Cyromancy AAs that proc a snare or dot on mob after a nuke, priest AAs that make heals proc small hots, etc.

I've tested this on my server and it seems stable, however due to my complete lack of understanding of C, I'm sure it needs tweaking.

I'm not quite sure how to make those fancy diff files so please bear with me.

First I changed the GetBuffSlotFromType function from passing the type variable as an int8 to an int16 as it was not reading effects above 255.

spells - line 4436 - alter this

Code:
sint8 Mob::GetBuffSlotFromType(int8 type) {
to

Code:
sint8 Mob::GetBuffSlotFromType(int16 type) {
mob.h - line 524 - alter this

Code:
sint8	GetBuffSlotFromType(int8 type);
to

Code:
sint8	GetBuffSlotFromType(int16 type);
Then define the TriggerOnCast

mob.h - line 767 - add this
Code:
void TryTriggerOnCast(Mob* caster, Mob* spelltar, uint16 spell_id);
spells.cpp - line 3047 - add this
Code:
// Trigger on Cast Effects - restricted to single target spells that modify hps, have no duration and can use spell(so most procs don't trigger, but instant cast spells still can).
	
if(spells[spell_id].targettype == ST_Target && IsEffectHitpointsSpell(spell_id) && spells[spell_id].buffduration == 0 && CanUseSpell(spell_id, this->GetClass(), this->GetLevel())) {
		TryTriggerOnCast(this, spelltar, spell_id);
	}
spell effects.cpp - line 2820 - add this
Code:
case SE_TriggerOnCast:
			{
#ifdef SPELL_EFFECT_SPAM
				snprintf(effect_desc, _EDLEN, "Trigger on Cast: %+i", effect_value);
#endif
				// Stop the unknown spam
				break;
			}
spell effects.cpp - line 4138 - add this
Code:
void Mob::TryTriggerOnCast(Mob* caster, Mob* spelltar, uint16 spell_id)
{	
	int buffSlot = caster->GetBuffSlotFromType(SE_TriggerOnCast);
	if(buffSlot >= 0) {
		int trigger_spell = spells[buffs[buffSlot].spellid].base2[0];
                // Make sure it doesnt trigger on the trigger spell
		if(trigger_spell != spell_id) {
                        // Detrimental triggers only land on NPCs.
			if (IsDetrimentalSpell(trigger_spell) && spelltar->IsNPC()) {
				int trigger_chance = spells[buffs[buffSlot].spellid].base[0];
				if (MakeRandomFloat(0, 100) <= trigger_chance) {
					SpellOnTarget(trigger_spell, spelltar);
				}
			}
			else if (IsBeneficialSpell(trigger_spell)) {
				int trigger_chance = spells[buffs[buffSlot].spellid].base[0];
				if (MakeRandomFloat(0, 100) <= trigger_chance) {
					SpellOnTarget(trigger_spell, spelltar);
				}
			}
		}
	}
}

Last edited by Caryatis; 07-02-2010 at 02:10 AM.. Reason: fix
Reply With Quote
  #2  
Old 07-02-2010, 06:43 PM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

I added this but I changed it to use the common focus effect calculation instead of having all that stuff hard coded.
Reply With Quote
  #3  
Old 07-02-2010, 07:38 PM
Caryatis
Dragon
 
Join Date: May 2009
Location: Milky Way
Posts: 541
Default

Thanks KLS, will be good learning to see how you implemented it properly.

edit: was this intentional?
Code:
if(MakeRandomInt(0, 1000)
I assume you meant 100?
Reply With Quote
  #4  
Old 07-02-2010, 10:15 PM
Caryatis
Dragon
 
Join Date: May 2009
Location: Milky Way
Posts: 541
Default

Also, would your way allow it proc off of a passive AA(like Gift of Mana, pyromancy, etc are)? I know my way didnt and yours doesnt seem to either, although perhaps I have the AA set incorrectly. When I get back from the weekend, I will see about adding the functionality unless you see an easy fix.
Reply With Quote
  #5  
Old 07-03-2010, 01:50 AM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

The spells that have 10% chance to proc have 100 for their base value. Also no it doesn't but we could add that. That is more a limitation of focus effects in general than how we do it this one time.
Reply With Quote
  #6  
Old 11-05-2010, 07:35 PM
Caryatis
Dragon
 
Join Date: May 2009
Location: Milky Way
Posts: 541
Default

Updated this effect. Uses bonus system as well as loading an array to track many different cast effects. Also added support for AA Spell Triggers(ie Gift of mana)... blah
Reply With Quote
  #7  
Old 11-06-2010, 06:22 PM
Caryatis
Dragon
 
Join Date: May 2009
Location: Milky Way
Posts: 541
Default

So after posting I realized a better solution. What we lack is a way to calculate focus effects from AAs, which would benefit this situation but also alleviate the need to hardcode so many AAs.

Specifically related to this effect, this was the only way to accomplish passive AA triggers as there are no spells in the DB that trigger Gift of Mana or Healing Light type AAs(for activated AA triggers like Pyromancy, a buff is placed on your char which then triggers Pyromantic Ignition, but for Gift of Mana, there is no such "pre-buff").

Now you can build AAs just like spells(think of the aa_effects slot as an effect slot in a buff). Currently the list is pretty bare(only has the limits, improved dmg and triggeroncast) but I didnt want to bog down this update anymore than necessary as its quite large as it is. Later on, I will migrate the current hardcoded AAs so that the information is in the aa_effects DB.

REQUIRED SQL(changes base1 and base2 in aa_effects to be signed, as some focuses make use of negative values):
Code:
ALTER TABLE `aa_effects`  CHANGE COLUMN `base1` `base1` MEDIUMINT(8) NOT NULL DEFAULT '0' AFTER `effectid`,  CHANGE COLUMN `base2` `base2` MEDIUMINT(8) NOT NULL DEFAULT '0' AFTER `base1`;
DIFF:
Code:
Index: EQEmuServer/zone/bonuses.cpp
===================================================================
--- EQEmuServer/zone/bonuses.cpp	(revision 1714)
+++ EQEmuServer/zone/bonuses.cpp	(working copy)
@@ -584,16 +584,6 @@
 				break;
 			case SE_IncreaseRange:
 				break;
-			case SE_LimitEffect:
-				break;
-			case SE_LimitSpellType:
-				break;
-			case SE_LimitMinDur:
-				break;
-			case SE_LimitInstant:
-				break;
-			case SE_LimitCastTime:
-				break;
 			case SE_MaxHPChange:
 				newbon->MaxHP += base1;
 				break;
@@ -659,9 +649,20 @@
 			case SE_TotalHP:
 				newbon->HP += base1;
 				break;
+			case SE_TriggerOnCast:
+				for(int i = 0; i < MAX_SPELL_TRIGGER; i+=2)
+				{
+					if(!newbon->SpellTriggers[i])
+					{
+						// base1 = SpellID to be triggered, base2 = chance to fire
+						newbon->SpellTriggers[i] = base1;
+						newbon->SpellTriggers[i+1] = base2;
+						break;
+					}
+				}
+				break;
 		}
 	}
-
 }
 
 void Mob::CalcSpellBonuses(StatBonuses* newbon)
@@ -1206,6 +1207,18 @@
 					newbon->Accuracy = effect_value;
 				break;
 			}
+			case SE_TriggerOnCast:
+			{
+				for(int i = 0; i < MAX_SPELL_TRIGGER; i++)
+				{
+					if(!newbon->SpellTriggers[i])
+					{
+						newbon->SpellTriggers[i] = spell_id;
+						break;
+					}
+				}
+				break;
+			}
 
 				
 		}
Index: EQEmuServer/zone/client.h
===================================================================
--- EQEmuServer/zone/client.h	(revision 1714)
+++ EQEmuServer/zone/client.h	(working copy)
@@ -666,7 +666,9 @@
 	int32 GetAA(int32 aa_id) const;
 	bool SetAA(int32 aa_id, int32 new_value);
 	inline uint32 GetAAPointsSpent() { return m_pp.aapoints_spent; }
-
+	sint16 CalcAAFocusEffect(focusType type, int16 focus_spell, int16 spell_id);
+	sint16 CalcAAFocus(focusType type, uint32 aa_ID, int16 spell_id);
+	
 	sint16 acmod();
 
 	// Item methods
Index: EQEmuServer/zone/mob.cpp
===================================================================
--- EQEmuServer/zone/mob.cpp	(revision 1714)
+++ EQEmuServer/zone/mob.cpp	(working copy)
@@ -3085,28 +3085,90 @@
 }
 
 
-void Mob::TryTriggerOnCast(Mob *target, uint32 spell_id)
+void Mob::TryTriggerOnCast(uint32 spell_id, bool aa_trigger)
 {
-	if(target == NULL || !IsValidSpell(spell_id))
+	if(!IsValidSpell(spell_id))
+		return;
+	
+	if(aa_trigger)
 	{
-		return;
+		for(int i = 0; i < MAX_SPELL_TRIGGER; i+=2)
+		{
+			if(this->aabonuses.SpellTriggers[i])
+				TriggerOnCast(this->aabonuses.SpellTriggers[i], spell_id, this->aabonuses.SpellTriggers[i+1]);
+		}
 	}
+	else
+	{
+		if(this->itembonuses.SpellTriggers[0])
+		{
+			for(int i = 0; i < MAX_SPELL_TRIGGER; i++)
+			{
+				if(this->itembonuses.SpellTriggers[i])
+					TriggerOnCast(this->itembonuses.SpellTriggers[i], spell_id, 0);
+			}
+		}
+		if(this->spellbonuses.SpellTriggers[0])
+		{
+			for(int i = 0; i < MAX_SPELL_TRIGGER; i++)
+			{
+				if(this->spellbonuses.SpellTriggers[i])
+					TriggerOnCast(this->spellbonuses.SpellTriggers[i], spell_id, 0);
+			}
+		}
+	}
+}
 
-	uint32 buff_count = GetMaxTotalSlots();
-	for(int i = 0; i < buff_count; i++) 
+void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, uint8 aa_chance)
+{
+	if(!IsValidSpell(focus_spell) || !IsValidSpell(spell_id))
+		return;
+
+	sint32 focus = 0;
+	if(!aa_chance)
 	{
-		if(IsEffectInSpell(buffs[i].spellid, SE_TriggerOnCast))
+		focus = CalcFocusEffect(focusTriggerOnCast, focus_spell, spell_id);
+		if(focus)
 		{
-			sint32 focus = CalcFocusEffect(focusTriggerOnCast, buffs[i].spellid, spell_id);
-			if(focus == 1)
+			for(int i = 0; i < EFFECT_COUNT; i++)
 			{
-				if(MakeRandomInt(0, 1000) < spells[buffs[i].spellid].base[0])
+				if (spells[focus_spell].effectid[i] == SE_TriggerOnCast)
 				{
-					SpellOnTarget(spells[buffs[i].spellid].base2[0], target);
+					// 100 = 100% chance to proc... seriously KLS :)
+					if(MakeRandomInt(0, 99) < spells[focus_spell].base[i])
+					{
+						if(spells[spells[focus_spell].base2[i]].targettype == ST_Self || spells[spells[focus_spell].base2[i]].targettype == ST_Group)
+						{
+							SpellOnTarget(spells[focus_spell].base2[i], this);
+						}
+						else if (this->GetTarget())
+						{	
+							SpellOnTarget(spells[focus_spell].base2[i], this->GetTarget());
+						}
+					}
 				}
 			}
 		}
 	}
+	// Innate AA Triggers
+	else
+	{
+		focus = this->CastToClient()->CalcAAFocusEffect(focusTriggerOnCast, focus_spell, spell_id);
+		if(focus)
+		{
+			if(MakeRandomInt(0, 99) < aa_chance)
+			{
+				if(spells[focus_spell].targettype == ST_Self || spells[focus_spell].targettype == ST_Group)
+				{
+					SpellOnTarget(focus_spell, this);
+				}
+				else if (this->GetTarget())
+				{	
+					SpellOnTarget(focus_spell, this->GetTarget());
+				}
+			}
+		}
+	}
 }
 
 void Mob::TrySpellTrigger(Mob *target, uint32 spell_id)
Index: EQEmuServer/zone/mob.h
===================================================================
--- EQEmuServer/zone/mob.h	(revision 1714)
+++ EQEmuServer/zone/mob.h	(working copy)
@@ -275,6 +275,7 @@
 
 	sint8 HundredHands;		//extra haste, stacks with all other haste  i
 	sint8 MeleeLifetap;
+	uint32 SpellTriggers[MAX_SPELL_TRIGGER];
 	int XPRateMod;
 
 	sint8	Packrat;	//weight reduction for items, 1 point = 10%
@@ -790,7 +791,8 @@
 	bool PassCharismaCheck(Mob* caster, Mob* spellTarget, int16 spell_id);
 	bool TryDeathSave();
 	void DoBuffWearOffEffect(uint32 index);
-	void TryTriggerOnCast(Mob *target, uint32 spell_id);
+	void TryTriggerOnCast(uint32 spell_id, bool aa_trigger);
+	void TriggerOnCast(uint32 focus_spell, uint32 spell_id, uint8 aa_chance);
 	void TrySpellTrigger(Mob *target, uint32 spell_id);
 	void TryApplyEffect(Mob *target, uint32 spell_id);
 	void TryTwincast(Mob *caster, Mob *target, uint32 spell_id);
Index: EQEmuServer/zone/spdat.h
===================================================================
--- EQEmuServer/zone/spdat.h	(revision 1714)
+++ EQEmuServer/zone/spdat.h	(working copy)
@@ -43,6 +43,7 @@
 #define DB_LoadSPDat	//load from DB vs spells_us.txt. for now, we're piggybacking NEW_LoadSPDat, so it will take precedence
 
 #define EFFECT_COUNT 12
+#define MAX_SPELL_TRIGGER 12	// One for each slot(only 6 for AA since AA use 2)
 
 const int Z_AGGRO=10;
 
Index: EQEmuServer/zone/spell_effects.cpp
===================================================================
--- EQEmuServer/zone/spell_effects.cpp	(revision 1714)
+++ EQEmuServer/zone/spell_effects.cpp	(working copy)
@@ -3765,6 +3765,183 @@
 		CalcBonuses();
 }
 
+sint16 Client::CalcAAFocusEffect(focusType type, int16 focus_spell, int16 spell_id) 
+{
+	uint32 slots = 0;
+	uint32 aa_AA = 0;
+	uint32 aa_value = 0;
+	
+	sint32 value = 0;
+	// Iterate through all of the client's AAs
+	for (int i = 0; i < MAX_PP_AA_ARRAY; i++) 
+	{	
+		aa_AA = this->aa[i]->AA;
+		aa_value = this->aa[i]->value;
+		if (aa_AA > 0 || aa_value > 0) 
+		{	
+			slots = zone->GetTotalAALevels(aa_AA);
+			if (slots > 0)
+			for(int j = 1;j <= slots; j++)
+			{
+				switch (aa_effects[aa_AA][j].skill_id)
+				{	
+					case SE_TriggerOnCast:
+						// If focus_spell matches the spell listed in the DB, load these restrictions
+						if(type == focusTriggerOnCast && focus_spell == aa_effects[aa_AA][j].base1)
+							value = CalcAAFocus(type, aa_AA, spell_id);
+					break;
+				}
+			}
+		}
+	}
+	return value;
+}
+
+
+sint16 Client::CalcAAFocus(focusType type, uint32 aa_ID, int16 spell_id) 
+{
+	const SPDat_Spell_Struct &spell = spells[spell_id];
+	
+	sint16 value = 0;
+	int lvlModifier = 100;
+	int lvldiff = 0;
+
+	int32 effect = 0;
+	int32 base1 = 0;
+	int32 base2 = 0;
+	int32 slot = 0;
+
+	std::map<uint32, std::map<uint32, AA_Ability> >::const_iterator find_iter = aa_effects.find(aa_ID);
+	if(find_iter == aa_effects.end())
+	{
+		return 0;
+	}
+
+	for (map<uint32, AA_Ability>::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) 
+	{
+		effect = iter->second.skill_id;
+		base1 = iter->second.base1;
+		base2 = iter->second.base2;
+		slot = iter->second.slot;
+	
+		switch (effect)
+		{
+			case SE_Blank:
+				break;
+			
+			// Limits
+			case SE_LimitResist:
+				if(base1)
+				{
+					if(spell.resisttype != base1)
+						return 0;
+				}
+			break;
+			case SE_LimitInstant:
+				if(spell.buffduration)
+					return 0;
+			break;
+			case SE_LimitMaxLevel:
+				lvldiff = (spell.classes[(GetClass()%16) - 1]) - base1;
+				//every level over cap reduces the effect by base2 percent
+				if(lvldiff > 0)
+				{ 
+					if(base2 > 0)
+					{
+						lvlModifier -= base2*lvldiff;
+						if(lvlModifier < 1)
+							return 0;
+					}
+					else {	
+						return 0;
+					}
+				}
+			break;
+			case SE_LimitMinLevel:
+				if((spell.classes[(GetClass()%16) - 1]) < base1)
+					return 0;
+			break;
+			case SE_LimitCastTime:
+				if (spell.cast_time < base1)
+					return 0;
+			break;
+			case SE_LimitSpell:
+				// Exclude spell(any but this)
+				if(base1 < 0) {	
+					if (spell_id == (base1*-1))
+						return 0;
+				} 
+				else {
+				// Include Spell(only this)
+					if (spell_id != base1)
+						return(0);
+				}
+			break;
+			case SE_LimitMinDur:
+				if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration))
+					return(0);
+			break;
+			case SE_LimitEffect:
+				// Exclude effect(any but this)
+				if(base1 < 0) {
+					if(IsEffectInSpell(spell_id,(base1*-1)))
+						return 0;
+				}
+				else {
+					// Include effect(only this)
+					if(!IsEffectInSpell(spell_id,base1)) 
+						return 0;
+				}
+			break;
+			case SE_LimitSpellType:
+				switch(base1)
+				{
+					case 0:
+						if (!IsDetrimentalSpell(spell_id))
+							return 0;
+						break;
+					case 1:
+						if (!IsBeneficialSpell(spell_id))
+							return 0;
+						break;
+				}
+			break;
+			
+			// Passive Focus Effects
+			case SE_ImprovedDamage:
+			switch (base2)
+			{
+				case 0:
+					if (type == focusImprovedDamage && base1 > value)
+						value = base1;
+				break;
+				case 1:
+					if (type == focusImprovedCritical && base1 > value)
+						value = base1;
+				break;
+				case 2:
+					if (type == focusImprovedUndeadDamage && base1 > value)
+						value = base1;
+				break;
+				case 3:
+					if (type == 10 && base1 > value)
+						value = base1;
+				break;
+			}
+			break;
+			
+			
+			// Unique Focus Effects
+			case SE_TriggerOnCast:
+				if(type == focusTriggerOnCast)
+					value = 1;
+			break;
+	
+		}
+	}
+	return(value*lvlModifier/100);
+}
+
 //given an item/spell's focus ID and the spell being cast, determine the focus ammount, if any
 //assumes that spell_id is not a bard spell and that both ids are valid spell ids
 sint16 Mob::CalcFocusEffect(focusType type, int16 focus_id, int16 spell_id) {
@@ -3999,9 +4176,8 @@
 		case SE_TriggerOnCast:
 		{
 			if(type == focusTriggerOnCast)
-			{
 				value = 1;
-			}
+		
 			break;
 		}
 		case SE_SpellVulnerability:
@@ -4140,7 +4316,32 @@
 				realTotal2 = Total2;
 			}
 	}
+	
+	// AA Focus
+	sint16 Total3 = 0;
+	sint16 realTotal3 = 0;
+	
+	uint32 slots = 0;
+	uint32 aa_AA = 0;
+	uint32 aa_value = 0;
+	
+	for (int i = 0; i < MAX_PP_AA_ARRAY; i++) 
+	{
+		aa_AA = this->aa[i]->AA;
+		aa_value = this->aa[i]->value;
+		if (aa_AA < 1 || aa_value < 1) 
+			continue;
+			
+		Total3 = CalcAAFocus(type, aa_AA, spell_id);
+		if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) {
+			realTotal3 = Total3;
+		} 
+		else if (Total3 < 0 && Total3 < realTotal3) {
+			realTotal3 = Total3;
+		}
+	}
 
+	
 	if(type == focusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact))
 		return 100;
 
@@ -4150,7 +4351,7 @@
 	//by reagent conservation for obvious reasons.
 	}
 
-	return realTotal + realTotal2;
+	return realTotal + realTotal2 + realTotal3;
 }
 
 //for some stupid reason SK procs return theirs one base off...
Index: EQEmuServer/zone/spells.cpp
===================================================================
--- EQEmuServer/zone/spells.cpp	(revision 1714)
+++ EQEmuServer/zone/spells.cpp	(working copy)
@@ -1072,6 +1072,14 @@
 		TrySympatheticProc(target, spell_id);
 
 	TryTwincast(this, target, spell_id);
+	
+	if(this->itembonuses.SpellTriggers[0] || this->spellbonuses.SpellTriggers[0])
+		TryTriggerOnCast(spell_id, 0);
+		
+	if(this->IsClient()) {
+		if(this->aabonuses.SpellTriggers[0])
+			TryTriggerOnCast(spell_id, 1);
+	}
 
 	// we're done casting, now try to apply the spell
 	if( !SpellFinished(spell_id, spell_target, slot, mana_used, inventory_slot) )
@@ -3128,7 +3136,6 @@
 			}
 		}
 
-	TryTriggerOnCast(spelltar, spell_id);
 	TrySpellTrigger(spelltar, spell_id);
 	TryApplyEffect(spelltar, spell_id);
For Testing...

This SQL will add the AA Gift of Mana so that you can easily test/see how it works to set an AA up under the new system(it scales to 100% proc rate, for testing purposes).

Code:
INSERT INTO `altadv_vars` (`skill_id`, `name`, `cost`, `max_level`, `hotkey_sid`, `hotkey_sid2`, `title_sid`, `desc_sid`, `type`, `spellid`, `prereq_skill`, `prereq_minpoints`, `spell_type`, `spell_refresh`, `classes`, `berserker`, `class_type`, `cost_inc`, `aa_expansion`, `special_category`, `sof_type`, `sof_cost_inc`, `sof_max_level`, `sof_next_skill`, `clientver`, `account_time_required`) VALUES (1435, 'Gift of Mana', 3, 3, 4294967295, 4294967295, 1435, 1435, 8, 0, 0, 0, 0, 0, 31812, 0, 66, 3, 9, 4294967295, 3, 3, 1, 1435, 1, 0);

INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (1435, 1, 339, 8105, 10);
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (1435, 2, 134, 70, 0);
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (1435, 3, 142, 65, 0);
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (1435, 4, 137, 0, 0);

INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (1436, 1, 339, 8105, 50);
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (1436, 2, 134, 70, 0);
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (1436, 3, 142, 65, 0);
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (1436, 4, 137, 0, 0);

INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (1437, 1, 339, 8105, 100);
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (1437, 2, 134, 70, 0);
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (1437, 3, 142, 65, 0);
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES (1437, 4, 137, 0, 0);
Reply With Quote
  #8  
Old 11-08-2010, 05:33 PM
Caryatis
Dragon
 
Join Date: May 2009
Location: Milky Way
Posts: 541
Default

I hate to keep making this submission larger but a few key elements were missing so, whats new:

1.) numhits for buffs now only affect the type of buff that is being effected. For example, if you had any buff that had the maxhits field populated, then it would drop after that number of hits, even though for non-DS, non-Rune style spells, that field is used to denote how many triggers you have for the spell. Now, numhits only increments down where appriopriate(ie melee for DS, spells for trigger, etc)[slight change to SE_NegateAttacks as well to use the numhits field]

2.) Added LimitMinMana, LimitTarget & NoCombatSkills - target &nocombat arent related to this(even though its used in a ton of focuses) but the minmana was important for this effect.

Code:
Index: EQEmuServer/zone/attack.cpp
===================================================================
--- EQEmuServer/zone/attack.cpp	(revision 1714)
+++ EQEmuServer/zone/attack.cpp	(working copy)
@@ -2900,23 +2900,23 @@
 
 sint32 Mob::ReduceDamage(sint32 damage)
 {
-	if(damage <= 0 || (!HasRune() && !HasPartialMeleeRune()))
-	{
+	if(damage <= 0)
 		return damage;
-	}
 
 	int slot = GetBuffSlotFromType(SE_NegateAttacks);
-	if(slot >= 0 && buffs[slot].melee_rune > 0)
+	if(slot >= 0 && buffs[slot].numhits > 0)
 	{
-		if(--buffs[slot].melee_rune == 0)
+		if(--buffs[slot].numhits == 0)
 		{
 			if(!TryFadeEffect(slot))
 				BuffFadeBySlot(slot);
-			UpdateRuneFlags();
 		}
 		return -6;
 	}
 
+	if(!HasRune() && !HasPartialMeleeRune())
+		return damage;
+
 	slot = GetBuffSlotFromType(SE_MitigateMeleeDamage);
 	if(slot >= 0)
 	{
@@ -2978,13 +2978,12 @@
 
 	// See if we block the spell outright first
 	int slot = GetBuffSlotFromType(SE_NegateAttacks);
-	if(slot >= 0 && buffs[slot].magic_rune > 0)
+	if(slot >= 0 && buffs[slot].numhits > 0)
 	{
-		if(--buffs[slot].melee_rune == 0)
+		if(--buffs[slot].numhits == 0)
 		{
 			if(!TryFadeEffect(slot))
 				BuffFadeBySlot(slot);
-			UpdateRuneFlags();
 		}
 		return -6;
 	}
@@ -3156,13 +3155,12 @@
 		this->DamageShield(attacker);
 		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)){
-				if(buffs[bs].numhits == 1){
-					BuffFadeBySlot(bs, true);
+			if((buffs[bs].spellid != SPELL_UNKNOWN) && IsEffectInSpell(buffs[bs].spellid, SE_DamageShield) && buffs[bs].numhits > 0){
+				if(--buffs[bs].numhits == 0)
+				{
+					if(!TryFadeEffect(bs))
+						BuffFadeBySlot(bs);
 				}
-				else{
-					buffs[bs].numhits--;
-				}
 			}
 		}		
 	}
@@ -4056,14 +4054,13 @@
 	//Rogue sneak attack disciplines make use of this, they are active for one hit
 	uint32 buff_count = GetMaxTotalSlots();
 	for(int bs = 0; bs < buff_count; bs++){
-		if((buffs[bs].spellid != SPELL_UNKNOWN) && buffs[bs].numhits > 0 && IsDiscipline(buffs[bs].spellid)){
+		if((buffs[bs].spellid != SPELL_UNKNOWN) && IsEffectInSpell(buffs[bs].spellid, SE_HitChance) && buffs[bs].numhits > 0){
 			if(skill == spells[buffs[bs].spellid].skill){
-				if(buffs[bs].numhits == 1){
-					BuffFadeBySlot(bs, true);
+				if(--buffs[bs].numhits == 0)
+				{
+					if(!TryFadeEffect(bs))
+						BuffFadeBySlot(bs, true);
 				}
-				else{
-					buffs[bs].numhits--;
-				}
 			}
 		}	
 	}	
Index: EQEmuServer/zone/bonuses.cpp
===================================================================
--- EQEmuServer/zone/bonuses.cpp	(revision 1714)
+++ EQEmuServer/zone/bonuses.cpp	(working copy)
@@ -584,16 +584,6 @@
 				break;
 			case SE_IncreaseRange:
 				break;
-			case SE_LimitEffect:
-				break;
-			case SE_LimitSpellType:
-				break;
-			case SE_LimitMinDur:
-				break;
-			case SE_LimitInstant:
-				break;
-			case SE_LimitCastTime:
-				break;
 			case SE_MaxHPChange:
 				newbon->MaxHP += base1;
 				break;
@@ -659,9 +649,20 @@
 			case SE_TotalHP:
 				newbon->HP += base1;
 				break;
+			case SE_TriggerOnCast:
+				for(int i = 0; i < MAX_SPELL_TRIGGER; i+=2)
+				{
+					if(!newbon->SpellTriggers[i])
+					{
+						// base1 = SpellID to be triggered, base2 = chance to fire
+						newbon->SpellTriggers[i] = base1;
+						newbon->SpellTriggers[i+1] = base2;
+						break;
+					}
+				}
+				break;
 		}
 	}
-
 }
 
 void Mob::CalcSpellBonuses(StatBonuses* newbon)
@@ -1206,6 +1207,18 @@
 					newbon->Accuracy = effect_value;
 				break;
 			}
+			case SE_TriggerOnCast:
+			{
+				for(int i = 0; i < MAX_SPELL_TRIGGER; i++)
+				{
+					if(!newbon->SpellTriggers[i])
+					{
+						newbon->SpellTriggers[i] = spell_id;
+						break;
+					}
+				}
+				break;
+			}
 
 				
 		}
Index: EQEmuServer/zone/client.h
===================================================================
--- EQEmuServer/zone/client.h	(revision 1714)
+++ EQEmuServer/zone/client.h	(working copy)
@@ -666,7 +666,9 @@
 	int32 GetAA(int32 aa_id) const;
 	bool SetAA(int32 aa_id, int32 new_value);
 	inline uint32 GetAAPointsSpent() { return m_pp.aapoints_spent; }
-
+	sint16 CalcAAFocusEffect(focusType type, int16 focus_spell, int16 spell_id);
+	sint16 CalcAAFocus(focusType type, uint32 aa_ID, int16 spell_id);
+	
 	sint16 acmod();
 
 	// Item methods
Index: EQEmuServer/zone/mob.cpp
===================================================================
--- EQEmuServer/zone/mob.cpp	(revision 1714)
+++ EQEmuServer/zone/mob.cpp	(working copy)
@@ -3085,28 +3085,100 @@
 }
 
 
-void Mob::TryTriggerOnCast(Mob *target, uint32 spell_id)
+void Mob::TryTriggerOnCast(uint32 spell_id, bool aa_trigger)
 {
-	if(target == NULL || !IsValidSpell(spell_id))
+	if(!IsValidSpell(spell_id))
+		return;
+	
+	if(aa_trigger)
 	{
-		return;
+		for(int i = 0; i < MAX_SPELL_TRIGGER; i+=2)
+		{
+			if(this->aabonuses.SpellTriggers[i])
+				TriggerOnCast(this->aabonuses.SpellTriggers[i], spell_id, this->aabonuses.SpellTriggers[i+1]);
+		}
 	}
+	else
+	{
+		if(this->itembonuses.SpellTriggers[0])
+		{
+			for(int i = 0; i < MAX_SPELL_TRIGGER; i++)
+			{
+				if(this->itembonuses.SpellTriggers[i])
+					TriggerOnCast(this->itembonuses.SpellTriggers[i], spell_id, 0);
+			}
+		}
+		if(this->spellbonuses.SpellTriggers[0])
+		{
+			for(int i = 0; i < MAX_SPELL_TRIGGER; i++)
+			{
+				if(this->spellbonuses.SpellTriggers[i])
+					TriggerOnCast(this->spellbonuses.SpellTriggers[i], spell_id, 0);
+			}
+		}
+	}
+}
 
-	uint32 buff_count = GetMaxTotalSlots();
-	for(int i = 0; i < buff_count; i++) 
+void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, uint8 aa_chance)
+{
+	if(!IsValidSpell(focus_spell) || !IsValidSpell(spell_id))
+		return;
+
+	sint32 focus = 0;
+	if(!aa_chance)
 	{
-		if(IsEffectInSpell(buffs[i].spellid, SE_TriggerOnCast))
+		focus = CalcFocusEffect(focusTriggerOnCast, focus_spell, spell_id);
+		if(focus)
 		{
-			sint32 focus = CalcFocusEffect(focusTriggerOnCast, buffs[i].spellid, spell_id);
-			if(focus == 1)
+			for(int i = 0; i < EFFECT_COUNT; i++)
 			{
-				if(MakeRandomInt(0, 1000) < spells[buffs[i].spellid].base[0])
+				if (spells[focus_spell].effectid[i] == SE_TriggerOnCast)
 				{
-					SpellOnTarget(spells[buffs[i].spellid].base2[0], target);
+					// 100 = 100% chance to proc... seriously KLS :)
+					if(MakeRandomInt(0, 99) < spells[focus_spell].base[i])
+					{
+						if(spells[spells[focus_spell].base2[i]].targettype == ST_Self || spells[spells[focus_spell].base2[i]].targettype == ST_Group)
+						{
+							SpellOnTarget(spells[focus_spell].base2[i], this);
+						}
+						else if (this->GetTarget())
+						{	
+							SpellOnTarget(spells[focus_spell].base2[i], this->GetTarget());
+						}
+						// Take into account the max hit limit
+						uint32 buff_count = GetMaxTotalSlots();
+						for(uint32 bs = 0; bs < buff_count; bs++){
+							if((buffs[bs].spellid != SPELL_UNKNOWN) && IsEffectInSpell(buffs[bs].spellid, SE_TriggerOnCast) && buffs[bs].numhits > 0 && buffs[bs].spellid == focus_spell){
+								if(--buffs[bs].numhits == 0) {
+									if(!TryFadeEffect(bs))
+										BuffFadeBySlot(bs);
+								}
+							}
+						}
+					}
 				}
 			}
 		}
 	}
+	// Innate AA Triggers
+	else
+	{
+		focus = this->CastToClient()->CalcAAFocusEffect(focusTriggerOnCast, focus_spell, spell_id);
+		if(focus)
+		{
+			if(MakeRandomInt(0, 99) < aa_chance)
+			{
+				if(spells[focus_spell].targettype == ST_Self || spells[focus_spell].targettype == ST_Group)
+				{
+					SpellOnTarget(focus_spell, this);
+				}
+				else if (this->GetTarget())
+				{	
+					SpellOnTarget(focus_spell, this->GetTarget());
+				}
+			}
+		}
+	}
 }
 
 void Mob::TrySpellTrigger(Mob *target, uint32 spell_id)
Index: EQEmuServer/zone/mob.h
===================================================================
--- EQEmuServer/zone/mob.h	(revision 1714)
+++ EQEmuServer/zone/mob.h	(working copy)
@@ -275,6 +275,7 @@
 
 	sint8 HundredHands;		//extra haste, stacks with all other haste  i
 	sint8 MeleeLifetap;
+	uint32 SpellTriggers[MAX_SPELL_TRIGGER];
 	int XPRateMod;
 
 	sint8	Packrat;	//weight reduction for items, 1 point = 10%
@@ -790,7 +791,8 @@
 	bool PassCharismaCheck(Mob* caster, Mob* spellTarget, int16 spell_id);
 	bool TryDeathSave();
 	void DoBuffWearOffEffect(uint32 index);
-	void TryTriggerOnCast(Mob *target, uint32 spell_id);
+	void TryTriggerOnCast(uint32 spell_id, bool aa_trigger);
+	void TriggerOnCast(uint32 focus_spell, uint32 spell_id, uint8 aa_chance);
 	void TrySpellTrigger(Mob *target, uint32 spell_id);
 	void TryApplyEffect(Mob *target, uint32 spell_id);
 	void TryTwincast(Mob *caster, Mob *target, uint32 spell_id);
Index: EQEmuServer/zone/spdat.h
===================================================================
--- EQEmuServer/zone/spdat.h	(revision 1714)
+++ EQEmuServer/zone/spdat.h	(working copy)
@@ -43,6 +43,7 @@
 #define DB_LoadSPDat	//load from DB vs spells_us.txt. for now, we're piggybacking NEW_LoadSPDat, so it will take precedence
 
 #define EFFECT_COUNT 12
+#define MAX_SPELL_TRIGGER 12	// One for each slot(only 6 for AA since AA use 2)
 
 const int Z_AGGRO=10;
 
@@ -483,7 +484,7 @@
 //#define SE_Unknown345				345	//not used
 //#define SE_Unknown346				346	//not used
 //#define SE_Unknown347				347	//not used
-#define SE_Unknown348				348	//not implemented. looks like a rune based on how many times you cast a spell (cast a spell, decrease by 1. 0 = buff wears off)
+#define SE_LimitManaCost			348	//
 //#define SE_Unknown349				349	//not used
 #define SE_ManaBurn					350	//not implemented. no idea on the calculation
 										//from http://everquest.allakhazam.com/db/spell.html?spell=8452;page=1;howmany=50#m1184016444141306266 for Mana Blaze (base1 = 9000):
Index: EQEmuServer/zone/spell_effects.cpp
===================================================================
--- EQEmuServer/zone/spell_effects.cpp	(revision 1714)
+++ EQEmuServer/zone/spell_effects.cpp	(working copy)
@@ -1580,9 +1580,7 @@
 #ifdef SPELL_EFFECT_SPAM
 				snprintf(effect_desc, _EDLEN, "Melee Negate Attack Rune: %+i", effect_value);
 #endif
-				buffs[buffslot].melee_rune = effect_value;
-				SetHasRune(true);
-				SetHasSpellRune(true);
+				buffs[buffslot].numhits = effect_value;
 				break;				  
 			}
 			case SE_AppraiseLDonChest:
@@ -2878,6 +2876,7 @@
 			case SE_LimitInstant:
 			case SE_LimitMinLevel:
 			case SE_LimitCastTime:
+			case SE_LimitManaCost:
 			case SE_NoCombatSkills:
 			case SE_TriggerOnCast:
 			case SE_HealRate:
@@ -2896,12 +2895,6 @@
 			{
 				break;
 			}
-			//currently missing effects:
-			//SE_SummonItem2
-			//SE_ReduceSpellHate
-			//SE_NoCombatSkills
-			//SE_CriticalDamageMob
-			//SE_Cloak
 
 			default:
 			{
@@ -3765,6 +3758,206 @@
 		CalcBonuses();
 }
 
+sint16 Client::CalcAAFocusEffect(focusType type, int16 focus_spell, int16 spell_id) 
+{
+	uint32 slots = 0;
+	uint32 aa_AA = 0;
+	uint32 aa_value = 0;
+	
+	sint32 value = 0;
+	// Iterate through all of the client's AAs
+	for (int i = 0; i < MAX_PP_AA_ARRAY; i++) 
+	{	
+		aa_AA = this->aa[i]->AA;
+		aa_value = this->aa[i]->value;
+		if (aa_AA > 0 || aa_value > 0) 
+		{	
+			slots = zone->GetTotalAALevels(aa_AA);
+			if (slots > 0)
+			for(int j = 1;j <= slots; j++)
+			{
+				switch (aa_effects[aa_AA][j].skill_id)
+				{	
+					case SE_TriggerOnCast:
+						// If focus_spell matches the spell listed in the DB, load these restrictions
+						if(type == focusTriggerOnCast && focus_spell == aa_effects[aa_AA][j].base1)
+							value = CalcAAFocus(type, aa_AA, spell_id);
+					break;
+				}
+			}
+		}
+	}
+	return value;
+}
+
+
+sint16 Client::CalcAAFocus(focusType type, uint32 aa_ID, int16 spell_id) 
+{
+	const SPDat_Spell_Struct &spell = spells[spell_id];
+	
+	sint16 value = 0;
+	int lvlModifier = 100;
+	int lvldiff = 0;
+
+	int32 effect = 0;
+	int32 base1 = 0;
+	int32 base2 = 0;
+	int32 slot = 0;
+
+	std::map<uint32, std::map<uint32, AA_Ability> >::const_iterator find_iter = aa_effects.find(aa_ID);
+	if(find_iter == aa_effects.end())
+	{
+		return 0;
+	}
+
+	for (map<uint32, AA_Ability>::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) 
+	{
+		effect = iter->second.skill_id;
+		base1 = iter->second.base1;
+		base2 = iter->second.base2;
+		slot = iter->second.slot;
+	
+		switch (effect)
+		{
+			case SE_Blank:
+				break;
+			
+			// Limits
+			case SE_LimitResist:
+				if(base1)
+				{
+					if(spell.resisttype != base1)
+						return 0;
+				}
+			break;
+			case SE_LimitInstant:
+				if(spell.buffduration)
+					return 0;
+			break;
+			case SE_LimitMaxLevel:
+				lvldiff = (spell.classes[(GetClass()%16) - 1]) - base1;
+				//every level over cap reduces the effect by base2 percent
+				if(lvldiff > 0)
+				{ 
+					if(base2 > 0)
+					{
+						lvlModifier -= base2*lvldiff;
+						if(lvlModifier < 1)
+							return 0;
+					}
+					else {	
+						return 0;
+					}
+				}
+			break;
+			case SE_LimitMinLevel:
+				if((spell.classes[(GetClass()%16) - 1]) < base1)
+					return 0;
+			break;
+			case SE_LimitCastTime:
+				if (spell.cast_time < base1)
+					return 0;
+			break;
+			case SE_LimitSpell:
+				// Exclude spell(any but this)
+				if(base1 < 0) {	
+					if (spell_id == (base1*-1))
+						return 0;
+				} 
+				else {
+				// Include Spell(only this)
+					if (spell_id != base1)
+						return(0);
+				}
+			break;
+			case SE_LimitMinDur:
+				if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration))
+					return(0);
+			break;
+			case SE_LimitEffect:
+				// Exclude effect(any but this)
+				if(base1 < 0) {
+					if(IsEffectInSpell(spell_id,(base1*-1)))
+						return 0;
+				}
+				else {
+					// Include effect(only this)
+					if(!IsEffectInSpell(spell_id,base1)) 
+						return 0;
+				}
+			break;
+			case SE_LimitSpellType:
+				switch(base1)
+				{
+					case 0:
+						if (!IsDetrimentalSpell(spell_id))
+							return 0;
+						break;
+					case 1:
+						if (!IsBeneficialSpell(spell_id))
+							return 0;
+						break;
+				}
+			break;
+			
+			case SE_LimitManaCost:
+				if(spell.mana < base1)
+					return 0;
+			break;
+			
+			case SE_LimitTarget:
+			// Exclude
+			if(base1 < 0){
+				if(-base1 == spell.targettype) 
+					return 0;
+			}
+			// Include
+			else {
+				if(base1 != spell.targettype)
+					return 0;
+			}
+			break;
+			
+			case SE_NoCombatSkills:
+				if(IsDiscipline(spell_id))
+					return 0;
+			break;
+			
+			// Passive Focus Effects
+			case SE_ImprovedDamage:
+			switch (base2)
+			{
+				case 0:
+					if (type == focusImprovedDamage && base1 > value)
+						value = base1;
+				break;
+				case 1:
+					if (type == focusImprovedCritical && base1 > value)
+						value = base1;
+				break;
+				case 2:
+					if (type == focusImprovedUndeadDamage && base1 > value)
+						value = base1;
+				break;
+				case 3:
+					if (type == 10 && base1 > value)
+						value = base1;
+				break;
+			}
+			break;
+			
+			
+			// Unique Focus Effects
+			case SE_TriggerOnCast:
+				if(type == focusTriggerOnCast)
+					value = 1;
+			break;
+	
+		}
+	}
+	return(value*lvlModifier/100);
+}
+
 //given an item/spell's focus ID and the spell being cast, determine the focus ammount, if any
 //assumes that spell_id is not a bard spell and that both ids are valid spell ids
 sint16 Mob::CalcFocusEffect(focusType type, int16 focus_id, int16 spell_id) {
@@ -3782,9 +3975,6 @@
 
 		//check limits
 
-		//missing limits:
-		//SE_LimitTarget
-
 		case SE_LimitResist:{
 			if(focus_spell.base[i]){
 				if(spell.resisttype != focus_spell.base[i])
@@ -3881,8 +4071,29 @@
 			}
 			break;
 
-
-
+		case SE_LimitManaCost:
+				if(spell.mana < focus_spell.base[i])
+					return 0;
+			break;
+		
+		case SE_LimitTarget:
+			// Exclude
+			if(focus_spell.base[i] < 0){
+				if(-focus_spell.base[i] == spell.targettype)
+					return 0;
+			}
+			// Include
+			else {
+				if(focus_spell.base[i] != spell.targettype)
+					return 0;
+			}
+			break;
+		
+		case SE_NoCombatSkills:
+			if(IsDiscipline(spell_id))
+				return 0;
+			break;
+		
 		//handle effects
 
 		case SE_ImprovedDamage:
@@ -3999,9 +4210,8 @@
 		case SE_TriggerOnCast:
 		{
 			if(type == focusTriggerOnCast)
-			{
 				value = 1;
-			}
+		
 			break;
 		}
 		case SE_SpellVulnerability:
@@ -4140,7 +4350,32 @@
 				realTotal2 = Total2;
 			}
 	}
+	
+	// AA Focus
+	sint16 Total3 = 0;
+	sint16 realTotal3 = 0;
+	
+	uint32 slots = 0;
+	uint32 aa_AA = 0;
+	uint32 aa_value = 0;
+	
+	for (int i = 0; i < MAX_PP_AA_ARRAY; i++) 
+	{
+		aa_AA = this->aa[i]->AA;
+		aa_value = this->aa[i]->value;
+		if (aa_AA < 1 || aa_value < 1) 
+			continue;
+			
+		Total3 = CalcAAFocus(type, aa_AA, spell_id);
+		if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) {
+			realTotal3 = Total3;
+		} 
+		else if (Total3 < 0 && Total3 < realTotal3) {
+			realTotal3 = Total3;
+		}
+	}
 
+	
 	if(type == focusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact))
 		return 100;
 
@@ -4150,7 +4385,7 @@
 	//by reagent conservation for obvious reasons.
 	}
 
-	return realTotal + realTotal2;
+	return realTotal + realTotal2 + realTotal3;
 }
 
 //for some stupid reason SK procs return theirs one base off...
Index: EQEmuServer/zone/spells.cpp
===================================================================
--- EQEmuServer/zone/spells.cpp	(revision 1714)
+++ EQEmuServer/zone/spells.cpp	(working copy)
@@ -1072,6 +1072,14 @@
 		TrySympatheticProc(target, spell_id);
 
 	TryTwincast(this, target, spell_id);
+	
+	if(this->itembonuses.SpellTriggers[0] || this->spellbonuses.SpellTriggers[0])
+		TryTriggerOnCast(spell_id, 0);
+		
+	if(this->IsClient()) {
+		if(this->aabonuses.SpellTriggers[0])
+			TryTriggerOnCast(spell_id, 1);
+	}
 
 	// we're done casting, now try to apply the spell
 	if( !SpellFinished(spell_id, spell_target, slot, mana_used, inventory_slot) )
@@ -3128,7 +3136,6 @@
 			}
 		}
 
-	TryTriggerOnCast(spelltar, spell_id);
 	TrySpellTrigger(spelltar, spell_id);
 	TryApplyEffect(spelltar, spell_id);
 
@@ -4867,7 +4874,7 @@
 }
 void Mob::UpdateRuneFlags()
 {
-	bool Has_SE_Rune = false, Has_SE_AbsorbMagicAtt = false, Has_SE_NegateAttacks = false, Has_SE_MitigateMeleeDamage = true, Has_SE_MitigateSpellDamage = true;
+	bool Has_SE_Rune = false, Has_SE_AbsorbMagicAtt = false, Has_SE_MitigateMeleeDamage = true, Has_SE_MitigateSpellDamage = true;
 	uint32 buff_count = GetMaxTotalSlots();
 	for (unsigned int i = 0; i < buff_count; ++i)
 	{
@@ -4887,18 +4894,11 @@
 						Has_SE_AbsorbMagicAtt = true;
 						break;
 					}
-					case SE_NegateAttacks:
-					{
-						Has_SE_NegateAttacks = true;
-						break;
-					}
-
 					case SE_MitigateMeleeDamage:
 					{
 						Has_SE_MitigateMeleeDamage = true;
 						break;
 					}
-
 					case SE_MitigateSpellDamage:
 					{
 						Has_SE_MitigateSpellDamage = true;
@@ -4912,8 +4912,8 @@
 		}
 	}
 
-	SetHasRune(Has_SE_Rune || Has_SE_NegateAttacks);
-	SetHasSpellRune(Has_SE_AbsorbMagicAtt || Has_SE_NegateAttacks);
+	SetHasRune(Has_SE_Rune);
+	SetHasSpellRune(Has_SE_AbsorbMagicAtt);
 	SetHasPartialMeleeRune(Has_SE_MitigateMeleeDamage);
 	SetHasPartialSpellRune(Has_SE_MitigateSpellDamage);
 }
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 09:21 PM.


 

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