Updated AMS marker feats. Removed arcane & divine marker feats. Updated Dread Necromancer for epic progression. Updated weapon baseitem models. Updated new weapons for crafting & npc equip. Updated prefix. Updated release archive.
		
			
				
	
	
		
			1037 lines
		
	
	
		
			51 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1037 lines
		
	
	
		
			51 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| /////////////////////////////////////////////////////////////////////////////////////////////////
 | |
| //:: This is the prc_dispel_magic functions declarations.   The functions themselves are at the bottom
 | |
| //:: of the file.       I got tired of circular include statement errors and just decided to make
 | |
| //:: these both be just one file by adding my text to theirs.
 | |
| ///////////////////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| // GZ: Number of spells in GetSpellBreachProtections
 | |
| const int PRC_SPELLS_MAX_BREACH = 33;
 | |
| 
 | |
| //:: This is my remake of the spellsDispelMagic found in x0_i0_spells.   It's pretty much
 | |
| //:: identical to the old one except instead of calling the EffectDispelMagicBest() and
 | |
| //:: EffectDispelMagicAll() scripting functions it calls the ones I've specified in this
 | |
| //:: file to replace them.
 | |
| void spellsDispelMagicMod(object oTarget, int nCasterLevel, effect eVis, effect eImpac, int bAll = TRUE, int bBreachSpells = FALSE);
 | |
| 
 | |
| //:: This is my remake of spellsDispelAoE().  It's very different, and very short.   It
 | |
| //:: takes advantage of the way I've reworked AoE's so that it can simply use the caster
 | |
| //:: level stored in the AoE and do a proper dispel check against it.
 | |
| void spellsDispelAoEMod(object oTargetAoE, object oCaster, int nCasterLevel);
 | |
| 
 | |
| //:: This function is to replace EffectDispelMagicBest().   It goes through the references
 | |
| //:: in the three arrays that store the caster levels and references to effects on oTarget,
 | |
| //:: chooses the one with the highest caster level, and attempts to dispel it using the
 | |
| //:: caster level entry in the array that corresponds to the spell itself.
 | |
| void DispelMagicBestMod(object oTarget, int nCasterLevel);
 | |
| 
 | |
| //:: This function is to replace EffectDispelMagicAll().  It goest through all the references
 | |
| //:: in the three arrays that store the caster levels and references to effects on oTarget, and
 | |
| //:: attempts a dispel on each of them.  It only checks to dispel whole spells, not individual
 | |
| //:: separate effects one spell may place on a person.
 | |
| void DispelMagicAllMod(object oTarget, int nCasterLevel);
 | |
| 
 | |
| //:: This function sorts the 3 arrays in descending order of caster level, so entry 0 is the
 | |
| //:: highest, and the last entry is the lowest.  It only gets called from inside DispelMagicBest()
 | |
| void SortAll3Arrays(object oTarget);
 | |
| 
 | |
| //:: This function is just a helper function to include Infestation of Maggots among the list
 | |
| //:: of spells in effect on oTarget, so it can be sorted with the rest. It's only called by
 | |
| //:: DispelMagicBest()
 | |
| void HandleInfestationOfMaggots(object oTarget);
 | |
| 
 | |
| // This is only meant to be called withing SetAllAoEInts()  I've heard terrible stories that
 | |
| // say if an object is destroyed, it's local variables may remain in place eating up memory
 | |
| // so I decided I'd better mop up after setting all of these.
 | |
| void DeleteAllAoEInts(object oAoE);
 | |
| 
 | |
| // Returns the AoE's entire caster level, including any from prc's as stored in the local variable
 | |
| int AoECasterLevel(object oAoE = OBJECT_SELF);
 | |
| 
 | |
| // * Performs a spell breach up to nTotal spell are removed and
 | |
| // * nSR spell resistance is  lowered. nSpellId can be used to override
 | |
| // * the originating spell ID. If not specified, SPELL_GREATER_SPELL_BREACH
 | |
| // * is used
 | |
| void PRCDoSpellBreach(object oTarget, int nTotal, int nSR, int nSpellId = -1);
 | |
| 
 | |
| // * Performs a spell breach up to nTotal spells are removed and nSR spell
 | |
| // * resistance is lowered.
 | |
| int PRCGetSpellBreachProtection(int nLastChecked);
 | |
| 
 | |
| // * Remove all spell protections of a specific type
 | |
| int PRCRemoveProtections(int nSpell_ID, object oTarget, int nCount);
 | |
| 
 | |
| // * Handle dispel magic of AoEs
 | |
| void spellsDispelAoE(object oTargetAoE, object oCaster, int nCasterLevel);
 | |
| 
 | |
| // * dispel magic on one or multiple targets.
 | |
| // * if bAll is set to TRUE, all effects are dispelled from a creature
 | |
| // * else it will only dispel the best effect from each creature (used for AoE)
 | |
| // * Specify bBreachSpells to add Mord's Disjunction to the dispel
 | |
| void spellsDispelMagic(object oTarget, int nCasterLevel, effect eVis, effect eImpac, int bAll = TRUE, int bBreachSpells = FALSE);
 | |
| 
 | |
| #include "prc_effect_inc"
 | |
| #include "lookup_2da_spell"
 | |
| #include "spinc_remeffct"
 | |
| #include "inv_invoc_const"
 | |
| #include "prcsp_engine"
 | |
| 
 | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| 
 | |
| //:: Copy of the original function with 1 minor change: calls DispelMagicAll() and
 | |
| //:: DispelMagicBest() instead of EffectDispelMagicAll() and EffectDispelMagicBest()
 | |
| //:: That is the only change.
 | |
| //------------------------------------------------------------------------------
 | |
| // Attempts a dispel on one target, with all safety checks put in.
 | |
| //------------------------------------------------------------------------------
 | |
| void spellsDispelMagicMod(object oTarget, int nCasterLevel, effect eVis, effect eImpac, int bAll = TRUE, int bBreachSpells = FALSE)
 | |
| {
 | |
|     //--------------------------------------------------------------------------
 | |
|     // Don't dispel magic on petrified targets
 | |
|     // this change is in to prevent weird things from happening with 'statue'
 | |
|     // creatures. Also creature can be scripted to be immune to dispel
 | |
|     // magic as well.
 | |
|     //--------------------------------------------------------------------------
 | |
|     if (PRCGetHasEffect(EFFECT_TYPE_PETRIFY, oTarget) == TRUE
 | |
|         || GetLocalInt(oTarget, "X1_L_IMMUNE_TO_DISPEL") == 10)
 | |
|     {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     effect eDispel;
 | |
|     float fDelay = PRCGetRandomDelay(0.1, 0.3);
 | |
|     int nId = PRCGetSpellId();
 | |
| 
 | |
|     //--------------------------------------------------------------------------
 | |
|     // Fire hostile event only if the target is hostile...
 | |
|     //--------------------------------------------------------------------------
 | |
| 
 | |
|     if (spellsIsTarget(oTarget, SPELL_TARGET_STANDARDHOSTILE, OBJECT_SELF))
 | |
|         SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nId));
 | |
|     else
 | |
|         SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nId, FALSE));
 | |
| 
 | |
|     //--------------------------------------------------------------------------
 | |
|     // GZ: Bugfix. Was always dispelling all effects, even if used for AoE
 | |
|     //--------------------------------------------------------------------------
 | |
|     if (bAll == TRUE )
 | |
|     {
 | |
|         //:: This is the first of 2 changes I made.
 | |
|         DispelMagicAllMod(oTarget, nCasterLevel);
 | |
| 
 | |
|         // The way it used to get done.
 | |
|         //eDispel = EffectDispelMagicAll(nCasterLevel);
 | |
| 
 | |
|         //----------------------------------------------------------------------
 | |
|         // GZ: Support for Mord's disjunction
 | |
|         //----------------------------------------------------------------------
 | |
|         if (bBreachSpells)
 | |
|         {
 | |
|             PRCDoSpellBreach(oTarget, 6, 10, nId);
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         //:: This is the second of the 2 changes I made.
 | |
|         //:: There are no other changes.
 | |
|         DispelMagicBestMod(oTarget, nCasterLevel);
 | |
| 
 | |
|         // The way it used to get done
 | |
|         //eDispel = EffectDispelMagicBest(nCasterLevel);
 | |
| 
 | |
|         if (bBreachSpells)
 | |
|         {
 | |
|            PRCDoSpellBreach(oTarget, 2, 10, nId);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
 | |
|     DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDispel, oTarget));
 | |
| }
 | |
| 
 | |
| /////////////////////////////////////////////////////////////////////////////////////
 | |
| //::  This one's so small I hope not to lose track of it.
 | |
| 
 | |
| //:: Replaces the normal spellsDispelAoE
 | |
| //:: I reworked all AoE's to store their caster level as a local int on themselves,
 | |
| //:: so it's possible to just do a proper caster level check instead of doing
 | |
| //:: something complicated.
 | |
| 
 | |
| void spellsDispelAoEMod(object oTargetAoE, object oCaster, int nCasterLevel)
 | |
| {
 | |
|    int ModWeave;
 | |
|    int nBonus = 0;
 | |
|    string SchoolWeave = lookup_spell_school(GetLocalInt(oTargetAoE, "X2_AoE_SpellID"));
 | |
|    int Weave = GetHasFeat(FEAT_SHADOWWEAVE,oCaster)+ GetLocalInt(oCaster, "X2_AoE_SpecDispel");
 | |
|    if (GetLocalInt(oTargetAoE, " X2_Effect_Weave_ID_") && !Weave) ModWeave = 4;
 | |
|    if (SchoolWeave=="V" ||SchoolWeave=="T"  ) ModWeave = 0;
 | |
|    if (GetLocalInt(oTargetAoE, "PRC_Power_DispellingBuffer_Active")) nBonus += 5;
 | |
|    if (GetHasFeat(FEAT_SPELL_GIRDING, oTargetAoE)) nBonus += 2;
 | |
|    if (GetLevelByClass(CLASS_TYPE_SUEL_ARCHANAMACH, oTargetAoE) >= 1) nBonus += 6;
 | |
| 
 | |
|    int iDice = d20(1);
 | |
| //   SendMessageToPC(GetFirstPC(), "Spell :"+ IntToString(PRCGetSpellId())+" T "+GetName(oTargetAoE));
 | |
| //   SendMessageToPC(GetFirstPC(), "Dispell :"+IntToString(iDice + nCasterLevel)+" vs DC :"+IntToString(11 + GetLocalInt(oTargetAoE, "X2_AoE_Caster_Level")+ModWeave)+" Weave :"+IntToString(ModWeave)+" "+SchoolWeave);
 | |
| 
 | |
|    if(iDice + nCasterLevel >= GetLocalInt(oTargetAoE, "X2_AoE_Caster_Level") + ModWeave + nBonus)
 | |
|    {
 | |
|      if(GetLocalInt(oTargetAoE, "X2_AoE_SpellID") == INVOKE_CHILLING_FOG)
 | |
|      {
 | |
|            if(DEBUG) DoDebug("Clearing Chilling Fog Lock");
 | |
|            DeleteLocalInt(GetAreaOfEffectCreator(oTargetAoE), "ChillingFogLock");
 | |
|      }
 | |
|      DestroyObject(oTargetAoE);
 | |
|    }
 | |
| }
 | |
| 
 | |
|  ///////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| 
 | |
| //:: Goes through all the references to effects stored in the 3 variable arrays,
 | |
| //:: picks the one with the highest caster level (breaking ties by just keeping the
 | |
| //:: first one it comes to) and then attempts a dispel check on it.
 | |
| //:: It goes by spell, not spell effect, so a successful check removes all spell
 | |
| //:: affects from that spell itself.
 | |
| 
 | |
| void DispelMagicBestMod(object oTarget, int nCasterLevel)
 | |
| {
 | |
|   /// I *really*  want to rewrite this one so that it simply dispels the most useful effect
 | |
|   /// instead of just the one with the highest caster level.
 | |
|   /// Sure hate to dispel mage armor on somebody who's immune to necromancy.   Difficult Decision, these.
 | |
| 
 | |
| 
 | |
|   //:: calls a function to determine whether infestation of maggots is in effect
 | |
|   //:: on the target.   If so, it adds it to the 3 arrays so it can be sorted with them.
 | |
| 
 | |
|   HandleInfestationOfMaggots(oTarget);
 | |
| 
 | |
|   //:: calls a function to arrange the values in the 3 arrays in order of highest caster level to lowest
 | |
|   //:: Index 0 will be the highest, and nLastEntry will be the lowest.
 | |
| 
 | |
|   SortAll3Arrays(oTarget);
 | |
| 
 | |
|   int nCurrentEntry;
 | |
|   int nLastEntry = GetLocalInt(oTarget, "X2_Effects_Index_Number");
 | |
| 
 | |
|   int nEffectSpellID, nEffectCastLevel;
 | |
|   object oEffectCaster;
 | |
|   int ModWeave;
 | |
|   int nBonus = 0;
 | |
| 
 | |
|   string sSelf = "Dispelled: ";
 | |
|   string sCast = "Dispelled on "+GetName(oTarget)+": ";
 | |
| 
 | |
|   int Weave = GetHasFeat(FEAT_SHADOWWEAVE,OBJECT_SELF)+ GetLocalInt(OBJECT_SELF, "X2_AoE_SpecDispel");
 | |
|   if (GetLocalInt(oTarget, "PRC_Power_DispellingBuffer_Active")) nBonus += 5;
 | |
|   if (GetHasFeat(FEAT_SPELL_GIRDING, oTarget)) nBonus += 2;
 | |
|   if (GetLevelByClass(CLASS_TYPE_SUEL_ARCHANAMACH, oTarget) >= 1) nBonus += 6;
 | |
| 
 | |
| 
 | |
|   for(nCurrentEntry = 0; nCurrentEntry <= nLastEntry; nCurrentEntry++)
 | |
|   {
 | |
|     nEffectSpellID = GetLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nCurrentEntry));
 | |
|     oEffectCaster = GetLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nCurrentEntry));
 | |
|     //:: Make sure the effect it refers to is still in place before making it
 | |
|     //:: number one.
 | |
|     if(IsStillRealEffect(nEffectSpellID, oEffectCaster, oTarget))
 | |
|     {
 | |
|       ModWeave = 0;
 | |
|       string SchoolWeave = lookup_spell_school(nEffectSpellID);
 | |
|       string SpellName = GetStringByStrRef(StringToInt(lookup_spell_name(nEffectSpellID)));
 | |
|       nEffectCastLevel = GetLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nCurrentEntry));
 | |
|       if (GetLocalInt(oTarget, " X2_Effect_Weave_ID_"+ IntToString(nCurrentEntry)) && !Weave) ModWeave = 4;
 | |
|       if (SchoolWeave=="V" ||SchoolWeave=="T"  ) ModWeave = 0;
 | |
| 
 | |
|       int iDice = d20(1);
 | |
| //      SendMessageToPC(GetFirstPC(), "Spell :"+ IntToString(nEffectSpellID)+" T "+GetName(oTarget)+" C "+GetName(oEffectCaster));
 | |
| //      SendMessageToPC(GetFirstPC(), "Dispell :"+ IntToString(iDice + nCasterLevel)+" vs DC :"+IntToString(11 + nEffectCastLevel+ModWeave)+" Mod Weave"+IntToString(ModWeave)+" "+SchoolWeave);
 | |
|       if(iDice + nCasterLevel >= 11 + nEffectCastLevel + ModWeave + nBonus)
 | |
|       {
 | |
|         if(nEffectSpellID != SPELL_INFESTATION_OF_MAGGOTS)
 | |
|         {// If it isn't infestation of maggots we remove it one way, if it is, we remove it another.
 | |
|             effect eToDispel = GetFirstEffect(oTarget);
 | |
|             while(GetIsEffectValid(eToDispel))
 | |
|             {
 | |
|                 if(GetEffectSpellId(eToDispel) == nEffectSpellID)
 | |
|                 {
 | |
|                     if(GetEffectCreator(eToDispel) == oEffectCaster)
 | |
|                     {
 | |
|                       if(GetEffectSpellId(eToDispel) == INVOKE_RETRIBUTIVE_INVISIBILITY && GetLocalInt(oTarget, "DangerousInvis"))
 | |
|                       {
 | |
|                         location lTarget = GetLocation(oTarget);
 | |
|                         effect eRetrVis = EffectVisualEffect(VFX_IMP_SONIC);
 | |
|                         effect eRetrPulse = EffectVisualEffect(VFX_IMP_PULSE_WIND);
 | |
|                         effect eRetrStun = EffectStunned();
 | |
|                         effect eDam;
 | |
|                         int nDamage;
 | |
|                         int nDC;
 | |
|                         float fDelay;
 | |
|                         int RICasterLvl = GetLocalInt(oTarget, "DangerousInvis");
 | |
|                         SPApplyEffectToObject(DURATION_TYPE_INSTANT, eRetrPulse, oTarget);
 | |
|                         DeleteLocalInt(oTarget, "DangerousInvis");
 | |
|                         
 | |
|                         //Declare the spell shape, size and the location.  Capture the first target object in the shape.
 | |
|                         object oVictim = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(20.0), lTarget, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
 | |
|                         //Cycle through the targets within the spell shape until an invalid object is captured.
 | |
|                         while (GetIsObjectValid(oVictim))
 | |
|                         {
 | |
|                             if (spellsIsTarget(oVictim, SPELL_TARGET_STANDARDHOSTILE, oTarget))
 | |
|                             {
 | |
|                                     //Fire cast spell at event for the specified target
 | |
|                                     SignalEvent(oVictim, EventSpellCastAt(oTarget, INVOKE_RETRIBUTIVE_INVISIBILITY));
 | |
|                                     //Get the distance between the explosion and the target to calculate delay
 | |
|                                     fDelay = GetDistanceBetweenLocations(lTarget, GetLocation(oVictim))/20;
 | |
|                                     if (!PRCDoResistSpell(oTarget, oVictim, RICasterLvl, fDelay))
 | |
|                                     {
 | |
|                                         //Roll damage for each target
 | |
|                                         nDamage = d6(4);
 | |
|                                         //nDamage += ApplySpellBetrayalStrikeDamage(oVictim, oTarget, FALSE);
 | |
|                                         nDC = 16 + GetAbilityModifier(ABILITY_CHARISMA, oTarget);
 | |
|                                         
 | |
|                                         //save
 | |
|                                         if(PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_SPELL))
 | |
|                                         {
 | |
|                                             nDamage = nDamage / 2;
 | |
|                                             if(GetHasMettle(oTarget, SAVING_THROW_FORT)) nDamage = 0;
 | |
|                                         }
 | |
|                                         else
 | |
|                                             DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eRetrStun, oVictim, RoundsToSeconds(1)));
 | |
|                                             
 | |
|                                         if(nDamage > 0)
 | |
|                                         {
 | |
|                                             //Set the damage effect
 | |
|                                             eDam = PRCEffectDamage(oVictim, nDamage, DAMAGE_TYPE_SONIC);
 | |
|                                             // Apply effects to the currently selected target.
 | |
|                                             DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oVictim));
 | |
|                                             PRCBonusDamage(oVictim);
 | |
|                                             //This visual effect is applied to the target object not the location as above.  This visual effect
 | |
|                                             //represents the flame that erupts on the target not on the ground.
 | |
|                                             DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eRetrVis, oVictim));
 | |
|                                         }
 | |
|                                      }
 | |
|                                 
 | |
|                             }
 | |
|                            //Select the next target within the spell shape.
 | |
|                            oVictim = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(20.0), lTarget, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
 | |
|                         }
 | |
|                       }
 | |
|                       else if(GetEffectSpellId(eToDispel) == INVOKE_PAINFUL_SLUMBER_OF_AGES && GetLocalInt(oTarget, "PainfulSleep"))
 | |
|                       {
 | |
|                           effect eSleepDam = EffectDamage(GetLocalInt(oTarget, "PainfulSleep"), DAMAGE_TYPE_MAGICAL);
 | |
|                           ApplyEffectToObject(DURATION_TYPE_INSTANT, eSleepDam, oTarget);
 | |
|                           DeleteLocalInt(oTarget, "PainfulSleep");
 | |
|                           RemoveEventScript(oTarget, EVENT_VIRTUAL_ONDAMAGED, "inv_painsleep", FALSE, FALSE);
 | |
|                       }
 | |
| 
 | |
|                       
 | |
|                       RemoveEffect(oTarget, eToDispel);
 | |
|                       
 | |
|                       if(GetSpellId() == INVOKE_VORACIOUS_DISPELLING)
 | |
|                       {
 | |
|                           //Get spell level
 | |
|                           int nEffectSpellLevel = StringToInt(Get2DACache("spells", "Innate", nEffectSpellID));
 | |
|                           //Damage = spell level
 | |
|                           effect eSlashDam = EffectDamage(DAMAGE_TYPE_MAGICAL, nEffectSpellLevel);
 | |
| 
 | |
|                           SPApplyEffectToObject(DURATION_TYPE_INSTANT, eSlashDam, oTarget);
 | |
|                       }
 | |
|                       
 | |
|                       else if(GetSpellId() == INVOKE_DEVOUR_MAGIC)
 | |
|                       {
 | |
|                           //Get spell level
 | |
|                           int nEffectSpellLevel = StringToInt(Get2DACache("spells", "Innate", nEffectSpellID));
 | |
|                           //HP = 5 * spell level
 | |
|                           effect eDracHP = EffectTemporaryHitpoints(5 * nEffectSpellLevel);
 | |
| 
 | |
|                           //can't stack HP from multiple dispels
 | |
|                           if (GetHasSpellEffect(GetSpellId(),OBJECT_SELF))
 | |
|                           {
 | |
|                               PRCRemoveSpellEffects(GetSpellId(), OBJECT_SELF, OBJECT_SELF);
 | |
|                           }
 | |
|                   
 | |
|                           SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDracHP, OBJECT_SELF, 60.0);
 | |
|                       }
 | |
| 
 | |
|                       else if(GetSpellId() == SPELL_SLASHING_DISPEL)
 | |
|                       {
 | |
|                           //Get spell level
 | |
|                           int nEffectSpellLevel = StringToInt(Get2DACache("spells", "Innate", nEffectSpellID));
 | |
|                           //Damage = 2 * spell level
 | |
|                           effect eSlashDam = EffectDamage(DAMAGE_TYPE_MAGICAL, 2 * nEffectSpellLevel);
 | |
| 
 | |
|                           SPApplyEffectToObject(DURATION_TYPE_INSTANT, eSlashDam, oTarget);
 | |
|                       }
 | |
| 
 | |
|                     }// end if effect comes from this caster
 | |
|                 }// end if effect comes from this spell
 | |
|                 eToDispel = GetNextEffect(oTarget);
 | |
|             }// end of while loop
 | |
|         }// end if infestation is not the spell
 | |
|         else
 | |
|         {
 | |
|           DeleteLocalInt(oTarget, "XP2_L_SPELL_CASTER_LVL_" + IntToString (SPELL_INFESTATION_OF_MAGGOTS));
 | |
|           // Deleting this variable is what actually ends the spell effect's damage.
 | |
|           DeleteLocalInt(oTarget,"XP2_L_SPELL_SAVE_DC_" + IntToString (SPELL_INFESTATION_OF_MAGGOTS));
 | |
|           DeleteLocalInt(oTarget,"XP2_L_SPELL_WEAVE" + IntToString (SPELL_INFESTATION_OF_MAGGOTS));
 | |
|           effect eToDispel = GetFirstEffect(oTarget);
 | |
|           while(GetIsEffectValid(eToDispel))
 | |
|           {
 | |
|             //:: We don't worry about who cast it.  A person can only really have one infestation
 | |
|             //:: going on at a time, I think.
 | |
|             if(GetEffectSpellId(eToDispel) == nEffectSpellID)
 | |
|             {
 | |
|               RemoveEffect(oTarget, eToDispel);
 | |
|             }// end if effect comes from this spell
 | |
|             eToDispel = GetNextEffect(oTarget);
 | |
|           }// end of while loop
 | |
|         }// end else
 | |
| 
 | |
|         //:: Since the effect has been removed, delete the references to it.
 | |
|         //:: This will help out the sweeping function when it gets called next (not now, though)
 | |
|         // These are stored for one round for Spell Rebirth
 | |
|         SetLocalInt(oTarget, "TrueSpellRebirthSpellId", GetLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nCurrentEntry)));
 | |
|         SetLocalInt(oTarget, "TrueSpellRebirthCasterLvl", GetLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nCurrentEntry)));
 | |
|         DelayCommand(6.0, DeleteLocalInt(oTarget, "TrueSpellRebirthSpellId"));
 | |
|         DelayCommand(6.0, DeleteLocalInt(oTarget, "TrueSpellRebirthCasterLvl"));
 | |
| 
 | |
|         DeleteLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nCurrentEntry));
 | |
|         DeleteLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nCurrentEntry));
 | |
|         DeleteLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nCurrentEntry));
 | |
|         DeleteLocalInt(oTarget, " X2_Effect_Weave_ID_" + IntToString(nCurrentEntry));
 | |
| 
 | |
|         //:: Display a message to all involved.
 | |
|         SendMessageToPC(OBJECT_SELF, sCast+SpellName);
 | |
|         if (oTarget != OBJECT_SELF) SendMessageToPC(oTarget, sSelf+SpellName);
 | |
| 
 | |
|         //:: If the check was successful, then we're done.
 | |
|         return;
 | |
|       }// end if check is successful.
 | |
|     }// end if is still a valid spell.
 | |
|     else
 | |
|     {
 | |
|         // These are stored for one round for Spell Rebirth
 | |
|         SetLocalInt(oTarget, "TrueSpellRebirthSpellId", GetLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nCurrentEntry)));
 | |
|         SetLocalInt(oTarget, "TrueSpellRebirthCasterLvl", GetLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nCurrentEntry)));
 | |
|         DelayCommand(6.0, DeleteLocalInt(oTarget, "TrueSpellRebirthSpellId"));
 | |
|         DelayCommand(6.0, DeleteLocalInt(oTarget, "TrueSpellRebirthCasterLvl"));
 | |
| 
 | |
|       // If it's not a real effect anymore, then delete the variables that refer to it.
 | |
|       DeleteLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nCurrentEntry));
 | |
|       DeleteLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nCurrentEntry));
 | |
|       DeleteLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nCurrentEntry));
 | |
|       DeleteLocalInt(oTarget, " X2_Effect_Weave_ID_" + IntToString(nCurrentEntry));
 | |
|     }// end of else statement.
 | |
| 
 | |
|   }// end of for loop
 | |
| 
 | |
|   // If we got here, the return function above never ran, so nothing got removed:
 | |
|   SendMessageToPC(OBJECT_SELF, sCast+"None");
 | |
|   if (oTarget != OBJECT_SELF) SendMessageToPC(oTarget, sSelf+"None");
 | |
| } // End Of Function
 | |
| 
 | |
| ///////////////////////////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| //:: Goes through and tries to remove each and every spell effect, doing a
 | |
| //:: separate caster level check for each spell.   It goes by spell, not spell
 | |
| //:: effect, so a successful check removes all spell affects from that spell
 | |
| //:: itself.
 | |
| 
 | |
| void DispelMagicAllMod(object oTarget, int nCasterLevel)
 | |
| {
 | |
| 
 | |
|   int nIndex = 0;
 | |
|   int nEffectSpellID;
 | |
|   int nEffectCasterLevel;
 | |
|   object oEffectCaster;
 | |
|   int ModWeave;
 | |
|   int nBonus = 0;
 | |
| 
 | |
|   int nLastEntry = GetLocalInt(oTarget, "X2_Effects_Index_Number");
 | |
|   effect eToDispel;
 | |
| 
 | |
|   string sList, SpellName;
 | |
|   string sSelf = "Dispelled: ";
 | |
|   string sCast = "Dispelled on "+GetName(oTarget)+": ";
 | |
| 
 | |
|   int Weave = GetHasFeat(FEAT_SHADOWWEAVE,OBJECT_SELF)+ GetLocalInt(OBJECT_SELF, "X2_AoE_SpecDispel");
 | |
|   if (GetLocalInt(oTarget, "PRC_Power_DispellingBuffer_Active")) nBonus += 5;
 | |
|   if (GetHasFeat(FEAT_SPELL_GIRDING, oTarget)) nBonus += 2;
 | |
|   if (GetLevelByClass(CLASS_TYPE_SUEL_ARCHANAMACH, oTarget) >= 1) nBonus += 6;
 | |
| 
 | |
|   //:: Do the dispel check for each and every spell in effect on oTarget.
 | |
|   for(nIndex; nIndex <= nLastEntry; nIndex++)
 | |
|   {
 | |
|     nEffectSpellID = GetLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nIndex));
 | |
|     if(GetHasSpellEffect(nEffectSpellID, oTarget))
 | |
|     {
 | |
|       ModWeave = 0;
 | |
|       string SchoolWeave = lookup_spell_school(nEffectSpellID);
 | |
|       SpellName = GetStringByStrRef(StringToInt(lookup_spell_name(nEffectSpellID)));
 | |
|       nEffectCasterLevel = GetLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nIndex));
 | |
|       if (GetLocalInt(oTarget, " X2_Effect_Weave_ID_"+ IntToString(nIndex)) && !Weave) ModWeave = 4;
 | |
|       if (SchoolWeave=="V" ||SchoolWeave=="T"  ) ModWeave = 0;
 | |
| 
 | |
|       int iDice = d20(1);
 | |
|  //     SendMessageToPC(GetFirstPC(), "Spell :"+ IntToString(nEffectSpellID)+" T "+GetName(oTarget)+" C "+GetName(GetLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nIndex))));
 | |
|  //     SendMessageToPC(GetFirstPC(), "Dispell :"+IntToString(iDice + nCasterLevel)+" vs DC :"+IntToString(11 + nEffectCasterLevel+ModWeave)+" Weave :"+IntToString(ModWeave)+" "+SchoolWeave);
 | |
| 
 | |
|       if(iDice + nCasterLevel >= 11 + nEffectCasterLevel + ModWeave + nBonus)
 | |
|       {
 | |
|         sList += SpellName+", ";
 | |
|         oEffectCaster = GetLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nIndex));
 | |
| 
 | |
|         //:: Was going to use this function but upon reading it it became apparent it might not remove
 | |
|         //:: all of the given spells effects, but just one instead.
 | |
| 
 | |
|         //PRCRemoveSpellEffects(nEffectSpellID, oEffectCaster, oTarget);
 | |
| 
 | |
|         //:: If the check is successful, go through and remove all effects originating
 | |
|         //:: from that particular spell.
 | |
|         effect eToDispel = GetFirstEffect(oTarget);
 | |
|         while(GetIsEffectValid(eToDispel))
 | |
|         {
 | |
|           if(GetEffectSpellId(eToDispel) == nEffectSpellID)
 | |
|           {
 | |
|             if(GetEffectCreator(eToDispel) == oEffectCaster)
 | |
|             {
 | |
|               
 | |
|               if(GetEffectSpellId(eToDispel) == INVOKE_RETRIBUTIVE_INVISIBILITY && GetLocalInt(oTarget, "DangerousInvis"))
 | |
|               {
 | |
|                   location lTarget = GetLocation(oTarget);
 | |
|                   effect eRetrVis = EffectVisualEffect(VFX_IMP_SONIC);
 | |
|                   effect eRetrPulse = EffectVisualEffect(VFX_IMP_PULSE_WIND);
 | |
|                   effect eRetrStun = EffectStunned();
 | |
|                   int RICasterLvl = GetLocalInt(oTarget, "DangerousInvis");
 | |
|                   effect eDam;
 | |
|                   int nDamage;
 | |
|                   float fDelay;
 | |
|                   int nDC;
 | |
|                   SPApplyEffectToObject(DURATION_TYPE_INSTANT, eRetrPulse, oTarget);
 | |
|                   DeleteLocalInt(oTarget, "DangerousInvis");
 | |
|                         
 | |
|                   //Declare the spell shape, size and the location.  Capture the first target object in the shape.
 | |
|                   object oVictim = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(20.0), lTarget, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
 | |
|                   //Cycle through the targets within the spell shape until an invalid object is captured.
 | |
|                   while (GetIsObjectValid(oVictim))
 | |
|                   {
 | |
|                       if (spellsIsTarget(oVictim, SPELL_TARGET_STANDARDHOSTILE, oTarget))
 | |
|                       {
 | |
|                               //Fire cast spell at event for the specified target
 | |
|                               SignalEvent(oVictim, EventSpellCastAt(oTarget, INVOKE_RETRIBUTIVE_INVISIBILITY));
 | |
|                               //Get the distance between the explosion and the target to calculate delay
 | |
|                               fDelay = GetDistanceBetweenLocations(lTarget, GetLocation(oVictim))/20;
 | |
|                               if (!PRCDoResistSpell(oTarget, oVictim, RICasterLvl, fDelay))
 | |
|                               {
 | |
|                                   //Roll damage for each target
 | |
|                                   nDamage = d6(4);
 | |
|                                   nDamage += ApplySpellBetrayalStrikeDamage(oVictim, oTarget, FALSE);
 | |
|                                   nDC = 16 + GetAbilityModifier(ABILITY_CHARISMA, oTarget);
 | |
|                                         
 | |
|                                   //save
 | |
|                                   if(PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_SPELL))
 | |
|                                   {
 | |
|                                       nDamage = nDamage / 2;
 | |
|                                       if(GetHasMettle(oTarget, SAVING_THROW_FORT)) nDamage = 0;
 | |
|                                   }
 | |
|                                   else
 | |
|                                       DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eRetrStun, oVictim, RoundsToSeconds(1)));
 | |
|                                             
 | |
|                                   if(nDamage > 0)
 | |
|                                   {
 | |
|                                       //Set the damage effect
 | |
|                                       eDam = PRCEffectDamage(oVictim, nDamage, DAMAGE_TYPE_SONIC);
 | |
|                                       // Apply effects to the currently selected target.
 | |
|                                       DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oVictim));
 | |
|                                       PRCBonusDamage(oVictim);
 | |
|                                       //This visual effect is applied to the target object not the location as above.  This visual effect
 | |
|                                       //represents the flame that erupts on the target not on the ground.
 | |
|                                       DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eRetrVis, oVictim));
 | |
|                                   }
 | |
|                                }
 | |
|                           
 | |
|                        }
 | |
|                        //Select the next target within the spell shape.
 | |
|                        oVictim = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(20.0), lTarget, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
 | |
|                    }
 | |
|                }
 | |
|                
 | |
|                else if(GetEffectSpellId(eToDispel) == INVOKE_PAINFUL_SLUMBER_OF_AGES && GetLocalInt(oTarget, "PainfulSleep"))
 | |
|                {
 | |
|                     effect eSleepDam = EffectDamage(GetLocalInt(oTarget, "PainfulSleep"), DAMAGE_TYPE_MAGICAL);
 | |
|                     ApplyEffectToObject(DURATION_TYPE_INSTANT, eSleepDam, oTarget);
 | |
|                     DeleteLocalInt(oTarget, "PainfulSleep");
 | |
|                     RemoveEventScript(oTarget, EVENT_VIRTUAL_ONDAMAGED, "inv_painsleep", FALSE, FALSE);
 | |
|                }
 | |
|                
 | |
|               RemoveEffect(oTarget, eToDispel);
 | |
| 
 | |
|               if(GetSpellId() == INVOKE_VORACIOUS_DISPELLING)
 | |
|               {
 | |
|                   //Get spell level
 | |
|                   int nEffectSpellLevel = StringToInt(Get2DACache("spells", "Innate", nEffectSpellID));
 | |
|                   //Damage = spell level
 | |
|                   effect eSlashDam = EffectDamage(DAMAGE_TYPE_MAGICAL, nEffectSpellLevel);
 | |
| 
 | |
|                   SPApplyEffectToObject(DURATION_TYPE_INSTANT, eSlashDam, oTarget);
 | |
|               }
 | |
|                       
 | |
|               else if(GetSpellId() == INVOKE_DEVOUR_MAGIC)
 | |
|               {
 | |
|                   //Get spell level
 | |
|                   int nEffectSpellLevel = StringToInt(Get2DACache("spells", "Innate", nEffectSpellID));
 | |
|                   //HP = 5 * spell level
 | |
|                   effect eDracHP = EffectTemporaryHitpoints(5 * nEffectSpellLevel);
 | |
|                   
 | |
|                   //can't stack HP from multiple dispels
 | |
|                   if (GetHasSpellEffect(GetSpellId(),OBJECT_SELF))
 | |
|                   {
 | |
|                       PRCRemoveSpellEffects(GetSpellId(), OBJECT_SELF, OBJECT_SELF);
 | |
|                   }
 | |
| 
 | |
|                   SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDracHP, OBJECT_SELF, 60.0);
 | |
|               }
 | |
| 
 | |
|               else if(GetSpellId() == SPELL_SLASHING_DISPEL)
 | |
|               {
 | |
|               //Get spell level
 | |
|               int nEffectSpellLevel = StringToInt(Get2DACache("spells", "Innate", nEffectSpellID));
 | |
|               //Damage = 2 * spell level
 | |
|               effect eSlashDam = EffectDamage(DAMAGE_TYPE_MAGICAL, 2 * nEffectSpellLevel);
 | |
| 
 | |
|               SPApplyEffectToObject(DURATION_TYPE_INSTANT, eSlashDam, oTarget);
 | |
|               }
 | |
|  
 | |
|               //Spell Removal Check
 | |
|               SpellRemovalCheck(oEffectCaster, oTarget);
 | |
| 
 | |
|             }// end if effect comes from this caster
 | |
|           }// end if effect comes from this spell
 | |
|           eToDispel = GetNextEffect(oTarget);
 | |
|         }// end of while loop
 | |
| 
 | |
| 
 | |
|     // These are stored for one round for Spell Rebirth
 | |
|         SetLocalInt(oTarget, "TrueSpellRebirthSpellId", GetLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nIndex)));
 | |
|         SetLocalInt(oTarget, "TrueSpellRebirthCasterLvl", GetLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nIndex)));
 | |
|         DelayCommand(6.0, DeleteLocalInt(oTarget, "TrueSpellRebirthSpellId"));
 | |
|         DelayCommand(6.0, DeleteLocalInt(oTarget, "TrueSpellRebirthCasterLvl"));
 | |
| 
 | |
|         // Delete the saved references to the spell's effects.
 | |
|         // This will save some time when reordering things a bit.
 | |
|         DeleteLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nIndex));
 | |
|         DeleteLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nIndex));
 | |
|         DeleteLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nIndex));
 | |
|         DeleteLocalInt(oTarget, " X2_Effect_Weave_ID_" + IntToString(nIndex));
 | |
| 
 | |
|       }// end of if caster check is sucessful
 | |
|     }// end of if oTarget has effects from this spell
 | |
|   }// end of for statement
 | |
| 
 | |
| 
 | |
|   // Additional Code to dispel any infestation of maggots effects.
 | |
| 
 | |
|   // If check to take care of infestation of maggots is in effect.
 | |
|   // with the highest caster level on it right now.
 | |
|   // If it is, we remove it instead of the other effect.
 | |
|   int bHasInfestationEffects = GetLocalInt(oTarget,"XP2_L_SPELL_CASTER_LVL_" + IntToString (SPELL_INFESTATION_OF_MAGGOTS));
 | |
| 
 | |
|   if(bHasInfestationEffects)
 | |
|   {
 | |
|     ModWeave =0;
 | |
|     if (GetLocalInt(oTarget, " XP2_L_SPELL_WEAVE" +IntToString (SPELL_INFESTATION_OF_MAGGOTS)) && !Weave) ModWeave = 4;
 | |
| 
 | |
|     if(d20(1) + nCasterLevel >= bHasInfestationEffects + 11 + ModWeave + nBonus)
 | |
|     {
 | |
|       DeleteLocalInt(oTarget,"XP2_L_SPELL_SAVE_DC_" + IntToString (SPELL_INFESTATION_OF_MAGGOTS));
 | |
|       DeleteLocalInt(oTarget,"XP2_L_SPELL_CASTER_LVL_" + IntToString (SPELL_INFESTATION_OF_MAGGOTS));
 | |
|       effect eToDispel = GetFirstEffect(oTarget);
 | |
|       nEffectSpellID = SPELL_INFESTATION_OF_MAGGOTS;
 | |
| 
 | |
|       SpellName = GetStringByStrRef(StringToInt(lookup_spell_name(nEffectSpellID)));
 | |
|       sList += SpellName+", ";
 | |
| 
 | |
|       while(GetIsEffectValid(eToDispel))
 | |
|       {
 | |
|         if(GetEffectSpellId(eToDispel) == nEffectSpellID)
 | |
|         {
 | |
|           RemoveEffect(oTarget, eToDispel);
 | |
|         }// end if effect comes from this spell
 | |
|         eToDispel = GetNextEffect(oTarget);
 | |
|       }// end of while loop
 | |
|     }// end if caster level check was a success.
 | |
|   }// end if infestation of maggots is in effect on oTarget/
 | |
| 
 | |
|   // If the loop to rid the target of the effects of infestation of maggots
 | |
|   // runs at all, this next loop won't because eToDispel has to be invalid for this
 | |
|   // loop to terminate and the other to begin - but it won't begin if eToDispel is
 | |
|   // already invalid :)
 | |
| 
 | |
|   if (sList == "") sList = "None  ";
 | |
|   sList = GetStringLeft(sList, GetStringLength(sList) - 2); // truncate the last ", "
 | |
| 
 | |
|   SendMessageToPC(OBJECT_SELF, sCast+sList);
 | |
|   if (oTarget != OBJECT_SELF) SendMessageToPC(oTarget, sSelf+sList);
 | |
| 
 | |
| }// End of function.
 | |
| 
 | |
| ///////////////////////////////////////////////////////////////////////////////////////////
 | |
| //:: Sorts the 3 arrays in order of highest at index 0 on up to lowest at index nLastEntry
 | |
| //////////////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| void SortAll3Arrays(object oTarget)
 | |
| {
 | |
| 
 | |
|   int nLastEntry = GetLocalInt(oTarget, "X2_Effects_Index_Number");
 | |
|   int nCurrEntry;
 | |
|   int nCurrEntry2;
 | |
|   int nSpellID, nSpellIDHigh, nCasterLvl, nCasterLvl2, nHighCastLvl, nHighestEntry,iWeave,iWeaveHigh;
 | |
|   object oMaker, oMakerHigh;
 | |
| 
 | |
|   for(nCurrEntry = 0; nCurrEntry <= nLastEntry; nCurrEntry++)
 | |
|   {
 | |
|     nCasterLvl = GetLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nCurrEntry));
 | |
|     nHighCastLvl = nCasterLvl;
 | |
| 
 | |
|     for(nCurrEntry2 = nCurrEntry + 1; nCurrEntry2 <= nLastEntry; nCurrEntry2++)
 | |
|     {
 | |
|       nCasterLvl2 = GetLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nCurrEntry2));
 | |
| 
 | |
|       if(nCasterLvl2 >= nHighCastLvl)
 | |
|       {
 | |
|         nHighestEntry = nCurrEntry2;
 | |
|         nHighCastLvl = nCasterLvl2;
 | |
|       }
 | |
|     }// End of second for statement.
 | |
|     if(nHighCastLvl != nCasterLvl)
 | |
|     // If the entry we're currently looking at already is the highest caster level left,
 | |
|     // we leave it there.  Otherwise we swap the highest level entry with this one.
 | |
|     // nHighCastLvl will still be equal to nCasterLvl unless a higher level effect was found.
 | |
|     {
 | |
|       nSpellID = GetLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nCurrEntry));
 | |
|       oMaker = GetLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nCurrEntry));
 | |
|       iWeave = GetLocalInt(oTarget, " X2_Effect_Weave_ID_" + IntToString(nCurrEntry));
 | |
| 
 | |
|       nSpellIDHigh = GetLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nHighestEntry));
 | |
|       oMakerHigh = GetLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nHighestEntry));
 | |
|       iWeaveHigh = GetLocalInt(oTarget, " X2_Effect_Weave_ID_" + IntToString(nHighestEntry));
 | |
| 
 | |
|       DeleteLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nCurrEntry));
 | |
|       DeleteLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nCurrEntry));
 | |
|       DeleteLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nCurrEntry));
 | |
|       DeleteLocalInt(oTarget, " X2_Effect_Weave_ID_" + IntToString(nCurrEntry));
 | |
| 
 | |
|       DeleteLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nHighestEntry));
 | |
|       DeleteLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nHighestEntry));
 | |
|       DeleteLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nHighestEntry));
 | |
|       DeleteLocalInt(oTarget, " X2_Effect_Weave_ID_" + IntToString(nHighestEntry));
 | |
| 
 | |
|       ///////////////////////////////////////////////////////////////////////////////
 | |
|       SetLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nCurrEntry), nHighCastLvl);
 | |
|       SetLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nCurrEntry), nSpellIDHigh);
 | |
|       SetLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nCurrEntry), oMakerHigh);
 | |
|       SetLocalInt(oTarget, " X2_Effect_Weave_ID_" + IntToString(nCurrEntry), iWeaveHigh);
 | |
| 
 | |
|       //
 | |
|       SetLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nHighestEntry),nCasterLvl);
 | |
|       SetLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nHighestEntry), nSpellID);
 | |
|       SetLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nHighestEntry), oMaker);
 | |
|       SetLocalInt(oTarget, " X2_Effect_Weave_ID_" + IntToString(nHighestEntry), iWeave);
 | |
| 
 | |
|     }  // End if the caster levels of the 2 entries are actually different.
 | |
|   }// End of first for statement.
 | |
| }
 | |
| 
 | |
| //////////////////////////////////////////////////////////////////////////////////////////////
 | |
| //:: Finished sorting.
 | |
| /////////////////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| 
 | |
| 
 | |
| /////////////////////////////////////////////////////////////////////////////////
 | |
| //:: Infestation of maggots is a special case because it won't end until a local
 | |
| //:: int is deleted.   It must be handled specially.
 | |
| /////////////////////////////////////////////////////////////////////////////////
 | |
| void HandleInfestationOfMaggots(object oTarget)
 | |
| {
 | |
|                           //:: Special to trap an infestation of maggots effect.
 | |
|   int nHasInfestationEffect = GetLocalInt(oTarget, "XP2_L_SPELL_CASTER_LVL_" + IntToString (SPELL_INFESTATION_OF_MAGGOTS));
 | |
| 
 | |
|   int nLastEntry = GetLocalInt(oTarget, "X2_Effects_Index_Number");
 | |
|   if(nHasInfestationEffect)
 | |
|   {
 | |
|     // If they have infestation of maggots on them, then add it to the end of the list.
 | |
|     // I would add it during the spell script itself but it might get swept up before the spell has
 | |
|     // really ended, I fear.
 | |
|     nLastEntry++;
 | |
|     DeleteLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nLastEntry));
 | |
|     DeleteLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nLastEntry));
 | |
|     DeleteLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nLastEntry));
 | |
|     DeleteLocalInt(oTarget, " X2_Effect_Weave_ID_" + IntToString(nLastEntry));
 | |
|     DeleteLocalInt(oTarget, "X2_Effects_Index_Number");
 | |
| 
 | |
|     SetLocalInt(oTarget, " X2_Effect_Spell_ID_" + IntToString(nLastEntry), SPELL_INFESTATION_OF_MAGGOTS);
 | |
|     SetLocalInt(oTarget, " X2_Effect_Cast_Level_" + IntToString(nLastEntry), nHasInfestationEffect);
 | |
|     SetLocalInt(oTarget, " X2_Effect_Weave_ID_" + IntToString(nLastEntry), GetLocalInt(oTarget, " XP2_L_SPELL_WEAVE" +IntToString (SPELL_INFESTATION_OF_MAGGOTS)));
 | |
|     //:: Won't bother with this one. I think a creature can only have one infestation at a time.
 | |
|     //SetLocalObject(oTarget, " X2_Effect_Caster_" + IntToString(nLastEntry));
 | |
|     SetLocalInt(oTarget, "X2_Effects_Index_Number", nLastEntry);
 | |
|   }
 | |
| }
 | |
| //////////////////////////////////////////////////////////////////////////////////////////////
 | |
| //:: End of section to trap infestation of maggots.
 | |
| ////////////////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| // Just returns the stored value.
 | |
| int AoECasterLevel(object oAoE = OBJECT_SELF)
 | |
| {
 | |
|    int toReturn = GetLocalInt(oAoE, "X2_AoE_Caster_Level");
 | |
|    return toReturn;
 | |
| }
 | |
| 
 | |
| void PRCDoSpellBreach(object oTarget, int nTotal, int nSR, int nSpellId = -1)
 | |
| {
 | |
|     if (nSpellId == -1)
 | |
|     {
 | |
|         nSpellId =  SPELL_GREATER_SPELL_BREACH;
 | |
|     }
 | |
|     effect eSR = EffectSpellResistanceDecrease(nSR);
 | |
|     effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);
 | |
| 
 | |
|     effect eVis = EffectVisualEffect(VFX_IMP_BREACH);
 | |
|     int nCnt, nIdx;
 | |
|     if(!GetIsReactionTypeFriendly(oTarget))
 | |
|     {
 | |
|         //Fire cast spell at event for the specified target
 | |
|         SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nSpellId ));
 | |
|         //Search through and remove protections.
 | |
|         while(nCnt <= PRC_SPELLS_MAX_BREACH && nIdx < nTotal)
 | |
|         {
 | |
|             nIdx = nIdx + PRCRemoveProtections(PRCGetSpellBreachProtection(nCnt), oTarget, nCnt);
 | |
|             nCnt++;
 | |
|         }
 | |
|         effect eLink = EffectLinkEffects(eDur, eSR);
 | |
|         //--------------------------------------------------------------------------
 | |
|         // This can not be dispelled
 | |
|         //--------------------------------------------------------------------------
 | |
|         eLink = ExtraordinaryEffect(eLink);
 | |
|         SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(10),TRUE);
 | |
|     }
 | |
|     ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
 | |
| 
 | |
| }
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // Returns the nLastChecked-nth highest spell on the creature for use in
 | |
| // the spell breach routines
 | |
| // Please modify the constatn PRC_SPELLS_MAX_BREACH at the top of this file
 | |
| // if you change the number of spells.
 | |
| //------------------------------------------------------------------------------
 | |
| int PRCGetSpellBreachProtection(int nLastChecked)
 | |
| {
 | |
|     //--------------------------------------------------------------------------
 | |
|     // GZ: Protections are stripped in the order they appear here
 | |
|     //--------------------------------------------------------------------------
 | |
|     if(nLastChecked == 1) {return SPELL_GREATER_SPELL_MANTLE;}
 | |
|     else if (nLastChecked == 2){return SPELL_PREMONITION;}
 | |
|     else if(nLastChecked == 3) {return SPELL_SPELL_MANTLE;}
 | |
|     else if(nLastChecked == 4) {return SPELL_SHADOW_SHIELD;}
 | |
|     else if(nLastChecked == 5) {return SPELL_GREATER_STONESKIN;}
 | |
|     else if(nLastChecked == 6) {return SPELL_ETHEREAL_VISAGE;}
 | |
|     else if(nLastChecked == 7) {return SPELL_GLOBE_OF_INVULNERABILITY;}
 | |
|     else if(nLastChecked == 8) {return SPELL_ENERGY_BUFFER;}
 | |
|     else if(nLastChecked == 9) {return 443;} // greater sanctuary
 | |
|     else if(nLastChecked == 10) {return SPELL_MINOR_GLOBE_OF_INVULNERABILITY;}
 | |
|     else if(nLastChecked == 11) {return SPELL_SPELL_RESISTANCE;}
 | |
|     else if(nLastChecked == 12) {return SPELL_STONESKIN;}
 | |
|     else if(nLastChecked == 13) {return SPELL_LESSER_SPELL_MANTLE;}
 | |
|     else if(nLastChecked == 14) {return SPELL_MESTILS_ACID_SHEATH;}
 | |
|     else if(nLastChecked == 15) {return SPELL_MIND_BLANK;}
 | |
|     else if(nLastChecked == 16) {return SPELL_ELEMENTAL_SHIELD;}
 | |
|     else if(nLastChecked == 17) {return SPELL_PROTECTION_FROM_SPELLS;}
 | |
|     else if(nLastChecked == 18) {return SPELL_PROTECTION_FROM_ELEMENTS;}
 | |
|     else if(nLastChecked == 19) {return SPELL_RESIST_ELEMENTS;}
 | |
|     else if(nLastChecked == 20) {return SPELL_DEATH_ARMOR;}
 | |
|     else if(nLastChecked == 21) {return SPELL_GHOSTLY_VISAGE;}
 | |
|     else if(nLastChecked == 22) {return SPELL_ENDURE_ELEMENTS;}
 | |
|     else if(nLastChecked == 23) {return SPELL_SHADOW_SHIELD;}
 | |
|     else if(nLastChecked == 24) {return SPELL_SHADOW_CONJURATION_MAGE_ARMOR;}
 | |
|     else if(nLastChecked == 25) {return SPELL_NEGATIVE_ENERGY_PROTECTION;}
 | |
|     else if(nLastChecked == 26) {return SPELL_SANCTUARY;}
 | |
|     else if(nLastChecked == 27) {return SPELL_MAGE_ARMOR;}
 | |
|     else if(nLastChecked == 28) {return SPELL_STONE_BONES;}
 | |
|     else if(nLastChecked == 29) {return SPELL_SHIELD;}
 | |
|     else if(nLastChecked == 30) {return SPELL_SHIELD_OF_FAITH;}
 | |
|     else if(nLastChecked == 31) {return SPELL_LESSER_MIND_BLANK;}
 | |
|     else if(nLastChecked == 32) {return SPELL_IRONGUTS;}
 | |
|     else if(nLastChecked == 33) {return SPELL_RESISTANCE;}
 | |
|     return nLastChecked;
 | |
| }
 | |
| 
 | |
| int PRCRemoveProtections(int nSpell_ID, object oTarget, int nCount)
 | |
| {
 | |
|     //Declare major variables
 | |
|     effect eProtection;
 | |
|     int nCnt = 0;
 | |
|     if(GetHasSpellEffect(nSpell_ID, oTarget))
 | |
|     {
 | |
|         //Search through the valid effects on the target.
 | |
|         eProtection = GetFirstEffect(oTarget);
 | |
|         while (GetIsEffectValid(eProtection))
 | |
|         {
 | |
|             //If the effect was created by the spell then remove it
 | |
|             if(GetEffectSpellId(eProtection) == nSpell_ID)
 | |
|             {
 | |
|                 RemoveEffect(oTarget, eProtection);
 | |
|                 //return 1;
 | |
|                 nCnt++;
 | |
|             }
 | |
|             //Get next effect on the target
 | |
|             eProtection = GetNextEffect(oTarget);
 | |
|         }
 | |
|     }
 | |
|     if(nCnt > 0)
 | |
|     {
 | |
|         return 1;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         return 0;
 | |
|     }
 | |
| }
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // Attempts a dispel on one target, with all safety checks put in.
 | |
| //------------------------------------------------------------------------------
 | |
| void spellsDispelMagic(object oTarget, int nCasterLevel, effect eVis, effect eImpac, int bAll = TRUE, int bBreachSpells = FALSE)
 | |
| {
 | |
|     //--------------------------------------------------------------------------
 | |
|     // Don't dispel magic on petrified targets
 | |
|     // this change is in to prevent weird things from happening with 'statue'
 | |
|     // creatures. Also creature can be scripted to be immune to dispel
 | |
|     // magic as well.
 | |
|     //--------------------------------------------------------------------------
 | |
|     if (PRCGetHasEffect(EFFECT_TYPE_PETRIFY, oTarget) == TRUE || GetLocalInt(oTarget, "X1_L_IMMUNE_TO_DISPEL") == 10)
 | |
|     {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     effect eDispel;
 | |
|     float fDelay = PRCGetRandomDelay(0.1, 0.3);
 | |
|     int nId = PRCGetSpellId();
 | |
| 
 | |
|     //--------------------------------------------------------------------------
 | |
|     // Fire hostile event only if the target is hostile...
 | |
|     //--------------------------------------------------------------------------
 | |
|     if (spellsIsTarget(oTarget, SPELL_TARGET_STANDARDHOSTILE, OBJECT_SELF))
 | |
|     {
 | |
| 
 | |
|         SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nId));
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nId, FALSE));
 | |
|     }
 | |
| 
 | |
|     //--------------------------------------------------------------------------
 | |
|     // GZ: Bugfix. Was always dispelling all effects, even if used for AoE
 | |
|     //--------------------------------------------------------------------------
 | |
|     if (bAll == TRUE )
 | |
|     {
 | |
|         eDispel = EffectDispelMagicAll(nCasterLevel);
 | |
|         //----------------------------------------------------------------------
 | |
|         // GZ: Support for Mord's disjunction
 | |
|         //----------------------------------------------------------------------
 | |
|         if (bBreachSpells)
 | |
|         {
 | |
|             PRCDoSpellBreach(oTarget, 6, 10, nId);
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         eDispel = EffectDispelMagicBest(nCasterLevel);
 | |
|         if (bBreachSpells)
 | |
|         {
 | |
|            PRCDoSpellBreach(oTarget, 2, 10, nId);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
 | |
|     DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDispel, oTarget));
 | |
| }
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // Handle Dispelling Area of Effects
 | |
| // Before adding this AoE's got automatically destroyed. Since NWN does not give
 | |
| // the required information to do proper dispelling on AoEs, we do some simulated
 | |
| // stuff here:
 | |
| // - Base chance to dispel is 25, 50, 75 or 100% depending on the spell
 | |
| // - Chance is modified positive by the caster level of the spellcaster as well
 | |
| // - as the relevant ability score
 | |
| // - Chance is modified negative by the highest spellcasting class level of the
 | |
| //   AoE creator and the releavant ability score.
 | |
| // Its bad, but its not worse than just dispelling the AoE as the game did until
 | |
| // now
 | |
| //------------------------------------------------------------------------------
 | |
| void spellsDispelAoE(object oTargetAoE, object oCaster, int nCasterLevel)
 | |
| {
 | |
|     object oCreator = GetAreaOfEffectCreator(oTargetAoE);
 | |
|     int nChance;
 | |
|     int nId   = PRCGetSpellId();
 | |
|     int nClassCaster = PRCGetLastSpellCastClass();
 | |
|     if ( nId == SPELL_LESSER_DISPEL )
 | |
|     {
 | |
|         nChance = 25;
 | |
|     }
 | |
|     else if ( nId == SPELL_DISPEL_MAGIC)
 | |
|     {
 | |
|         nChance = 50;
 | |
|     }
 | |
|     else if ( nId == SPELL_GREATER_DISPELLING )
 | |
|     {
 | |
|         nChance = 75;
 | |
|     }
 | |
|     else if ( nId == SPELL_MORDENKAINENS_DISJUNCTION )
 | |
|     {
 | |
|         nChance = 100;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     nChance += ((nCasterLevel + (GetAbilityScoreForClass(nClassCaster, oCaster)-10)/2) - (GetCasterLevel(oCreator))); // yes this is a sucky stupid hack
 | |
| 
 | |
|     //--------------------------------------------------------------------------
 | |
|     // the AI does cheat here, because it can not react as well as a player to
 | |
|     // AoE effects. Also DMs are always successful
 | |
|     //--------------------------------------------------------------------------
 | |
|     if (!GetIsPC(oCaster))
 | |
|     {
 | |
|         nChance +=30;
 | |
|     }
 | |
| 
 | |
|     if (oCaster == oCreator)
 | |
|     {
 | |
|         nChance = 100;
 | |
|     }
 | |
| 
 | |
|     int nRand = Random(100);
 | |
| 
 | |
|     if ((nRand < nChance )|| GetIsDM(oCaster) || GetIsDMPossessed(oCaster))
 | |
|     {
 | |
|         
 | |
|      	if(GetLocalInt(oTargetAoE, "X2_AoE_SpellID") == INVOKE_CHILLING_FOG)
 | |
|      	{
 | |
|            if(DEBUG) DoDebug("Clearing Chilling Fog Lock");
 | |
|            DeleteLocalInt(GetAreaOfEffectCreator(oTargetAoE), "ChillingFogLock");
 | |
|     	}
 | |
|         FloatingTextStrRefOnCreature(100929,oCaster);  // "AoE dispelled"
 | |
|         DestroyObject (oTargetAoE);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         FloatingTextStrRefOnCreature(100930,oCaster); // "AoE not dispelled"
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| // Test main
 | |
| //void main(){}
 |