Aller au contenu

Photo

Immunity to Epic Spells for creatures?


  • Veuillez vous connecter pour répondre
26 réponses à ce sujet

#1
Quilistan

Quilistan
  • Members
  • 111 messages
There are certain spells that I would like some of my extremely high level bosses be immune to. Such as Mass Fowl, Vampiric Feast, and I am sure there are at least a couple of others.

How can you make creatures immune to these spells/feats, and or make them make their saves to them?

#2
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
Edit the spell script itself, you can do it via spell hook for some of them, but some are area of effect which can target nearby and for those only editing the spell script will work.

#3
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
One way is to use spellhooking. You can define a certain script as spellhook script and every time a spell is cast, that script gets checked. You can, in that script, check for the spells in question and then script immunity for your bosses.

#4
Quilistan

Quilistan
  • Members
  • 111 messages
Could I possibly get an example script/s?

I can script but really it take me a long time to figure things out.

#5
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
Spell hooking

There also is an example in the CSL library i am maintaining more relevant to NWN2 named _SCDexSpellHooks.nss but i have a lot of custom things going on.

in module loaded

#include "x2_inc_switches"
void main()
{
	SetModuleOverrideSpellscript("_SCDexSpellHooks"); // THIS RUNS BEFORE ANY SPELL IS CAST AND ALLOWS YOU TO ABORT THE CALL
}


excerpt from my spellhook
/*

	This file is called each time a hook is done.
	
	Bascially the code here, and a few other scripts is run by each spell before it is run
	
*/
#include "_HkSpell"
#include "_CSLCore_Player"
// includes function to stop the spell script from firing
#include "x2_inc_switches"


//#include "_SCUtility"


void SCfizzleSpell( string sMessage = "Spell Fizzled", object oCaster = OBJECT_SELF );
void SCIncStack(object oCaster, int nInc = 1, int nStackLimit = 3);
int SCSpellStack(int iSpell, object oCaster);



//Note that this follows the reasoning that things should be permitted
void main()
{
	//if ( GetIsSinglePlayer() ) {DEBUGGING = 0;}	
	//DEBUGGING = GetLocalInt( GetModule(), "DEBUGLEVEL" );
	//if ( GetLocalInt( OBJECT_SELF, "SC_TESTER" ) )
	//{
	//	SendMessageToPC( OBJECT_SELF, "Running SpellHook Now for "+IntToString(GetSpellId()));;
	//}
	
	//if ( GetLocalInt( OBJECT_SELF, "SC_TESTER" ) )
	//{
	//	SendMessageToPC( OBJECT_SELF, "Spellhook:"+SCCacheStatsToString( OBJECT_SELF ) );
	//}
	
	// note that HKPERM_damagemodtype sets it for multiple castings...
	
	//this does random damage types
	//SetLocalInt( OBJECT_SELF, "HKTEMP_damagemodtype", CSLPickOneInt(DAMAGE_TYPE_COLD, DAMAGE_TYPE_FIRE, DAMAGE_TYPE_ACID, DAMAGE_TYPE_ELECTRICAL, DAMAGE_TYPE_SONIC, DAMAGE_TYPE_NEGATIVE, DAMAGE_TYPE_POSITIVE ) );
	//if (DEBUGGING >= 8) { CSLDebug( "Hook: Damage Set to <color=red>"+CSLDamagetypeToString( GetLocalInt( OBJECT_SELF, "HKTEMP_damagemodtype"))+"</color>" ); }
	
	// int nSpellDC=GetSpellSaveDC();
	object oTarget = HkGetSpellTarget();
	object oCaster = OBJECT_SELF;
	int iSpellId=GetSpellId();
	if (DEBUGGING >= 4) { CSLDebug(  "_SCDexSpellHooks: Caster = "+GetName( oCaster )+" Target = "+GetName( oTarget )+" Spell="+IntToString( iSpellId ), oCaster ); }
	int iAttributes = CSLGetSpellAttributes( oCaster );
	//CSLDebug( CSLCharacterStatsToString( oCaster ) );
	
	if (DEBUGGING >= 4) { CSLDebug(  "_SCDexSpellHooks: 2", oCaster ); }
	//SendMessageToPC( OBJECT_SELF, "Spellhook:"+SCCacheStatsToString( OBJECT_SELF ) );
	
	
	if ( !GetIsObjectValid(GetAreaFromLocation(GetLocation(oCaster))) )
	{
		SCfizzleSpell("Invalid Area.", oCaster );
		SetLocalString( oCaster, "CSL_ERRORSTRING", "Invalid Area" );
		return;
	}
	
	
	if ( CSLGetIsDM( oCaster, FALSE ) ) //  || GetIsDMPossessed( oCaster )
	{
		if (DEBUGGING >= 6) { CSLDebug( "Ending SpellHook, DM's are Not Restricted by This" ); }
		return; // DM's can do anything without regard for this
	}
		
	if (DEBUGGING >= 4) { CSLDebug(  "_SCDexSpellHooks: 3", oCaster ); }
	
	if ( !HkCheckIfCanCastSpell( oCaster, iSpellId, GetLastSpellCastclass() ) )
	{
		string sErrorMessage = GetLocalString( oCaster, "CSL_ERRORSTRING" );
		if ( sErrorMessage != "" )
		{
			SCfizzleSpell(sErrorMessage, oCaster);
		}
		else
		{
			SCfizzleSpell("You don't have the requirements to cast spells of that level!", oCaster);
		}
		SetLocalString( oCaster, "CSL_ERRORSTRING", "" );
		return;
	}
}


#6
Dann-J

Dann-J
  • Members
  • 3 161 messages
When does the OnSpellCastAt script fire - when the spell is cast or when the effects are dealt to the target?

If it fires on casting (before the effects of the spell are dealt) then you might be able to give the bosses custom OnSpellCastAt scripts that temporarily grant them a huge spell resistance value for a few seconds depending on what spell is cast at them.

Or is spell resistance determined when the spell is cast rather than when the impact script runs?

Spell hooking would be far more reliable, but an OnSpellCastAt script would be the easier of the two to impliment.

#7
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
Before it does the spell hook, which is actually inside the script for the spell.

The oncastat event is triggered by the signalevent inside the spell as well.

Spellresistance is inside the script, and determined by the myresistspell function ( which wraps resistspell and technically is broken )

Spell hooking is by far the easiest, as onspellcastat i think is mainly for NPC's and the AI so they react properly.

#8
Quilistan

Quilistan
  • Members
  • 111 messages
Thanks for the post, It will take me the night to look through it and understand it. I might/most likely have more questions. :D

Pain I will certainly be having some more questions about your CLS library. I know it has several features I am looking for, but I am nervous about integrating it properly.
I will save that for another thread though.

#9
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
Here is one way you could use spellhooking in this instance:

You first need to determine if the spell being cast is one of the spells you are looking for. So you need to define an integer as the ID# of the spell being cast. Then you need a conditional to check if the integer is equal to the spellID# of the spell you are looking for. Let's use vampiric feast for example.

Copy the code for vampiric feast into the conditional and follow it with the function to make the rest of the spell script not fire after the spellhook fires. Sorry, I don't have access to the name of it right now.

Now, you modify the code to vampiric feast to not affect any creatures that have the same tags as the bosses that you want to be immune to it.

Now you are done.

Replay if any of that is unclear and I'll try to explain it better.

#10
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
Assuming the spells are directly targeting your boss and not just AOE spells, the only way for an AOE type spell to be blocked is to edit the spell script for that epic spell. ( the script is defined in spells.2da )

you use the following -->
object oTarget = GetSpellTarget();
object oCaster = OBJECT_SELF;
int iSpellId=GetSpellId();

// define a var named BOSS with a value of 1 on the target creature
if ( GetLocalInt( oTarget, "BOSS") && ( iSpellId == SPELL_EPIC_RUIN || iSpellId == ANOTHERSPELL ) // ANOTHERSPELL can be the row number in spells.2da or any SPELL_* constant that you can lookup in the toolset
{
 // do the spell hook fizzle code here
}

M. Reider is saying edit the spell itself  --> nx_s2_vampiric_feast.nss

Use the open convo/script menu item in the toolset and type in "vamp" and it will search for this spell for you.

edit this line
if (spellsIsTarget(oTarget, SPELL_TARGET_SELECTIVEHOSTILE, OBJECT_SELF))	// Only ever effects enemies		{

to
if (spellsIsTarget(oTarget, SPELL_TARGET_SELECTIVEHOSTILE, OBJECT_SELF) && !GetLocalInt( oTarget, "BOSS")  )	// Only ever effects enemies who do not have the BOSS variable set to 1 or higher		{

( note: i am aiming you at using the BOSS variable as i've actually found other scripters from before my time using that variable, in my code you cannot clone bosses for example and i use that variable. )

You still should run the SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId(), FALSE)); on the target if it's blocked via BOSS, so the caster can be attacked by that boss.

Modifié par painofdungeoneternal, 07 mars 2012 - 11:13 .


#11
Dann-J

Dann-J
  • Members
  • 3 161 messages
I can envisage a way of encoding multiple spell ids into a single local string variable on a creature, so that all you'd have to do is compare a substring of the variable with the incoming spell id. There'd be no need to hardcode checks for specific spell ids then, and you'd have the flexibility of being able to make any creature in the module immune to certain spells on an individual basis with just one local variable.

I'd probably encode the local string something like this: 002101231258 (for spells 21, 123 & 1258), making sure that every spell id you want to check against had four characters (filling in zero prefixes where necessary). Then a loop in the spell hooking script could check each four-digit substring (converted to an integer) against the incoming spell id. The loop would end when a particular four-digit substring returned as "" (ie. a blank string).

AOE spells are tricky though, as you have to do a search around the spell target location for the creatures. I recently created a simplified version of Wild Magic using similar principles. I interogated spells.2da to determine whether a spell is AOE or not, then used the spellshape search functions.

Modifié par DannJ, 07 mars 2012 - 11:19 .


#12
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
You can't use it on vampiric feast, as the spellhook only sees the target and this spell does an AOE.

Here is a pastebin link for a script that should work for vampiric feast --> http://pastebin.com/t0PqwYbF

Dannj, I'd use a delimiter like 

",91,23,4567,"

Then do a string find for ","+spellid+",", if it comes back -1 its not there, if it's 0 or higher it's there.

string sDelimiter=",";
string sValue = YOUR_SPELL_ID;
int iPosition = FindSubString( sDelimiter+sHaystack+sDelimiter, sDelimiter+sValue+sDelimiter );
if ( iPosition == -1)
{
// not found
}
else
{
// found
}


Modifié par painofdungeoneternal, 07 mars 2012 - 11:26 .


#13
Dann-J

Dann-J
  • Members
  • 3 161 messages
See the edits in my previous post. You can check the targetting options in spells.2da to find out if a spell is AOE or not. If it is, you can search for targets around the spell target location or spell target object, rather than use the spell target function directly for a single creature. That's what I did in my own Wild Magic script, and it works a treat. Here's a snippet of the code I use:

 string sType = Get2DAString("spells", "TargetType", iSpell); 

 switch (iRandom)
 {
 case 1:
 { // Caster backlash
 SendMessageToPC(OBJECT_SELF, "Wild Magic - Backlash");
 BackLash(iDmg);
 break;
 }

 case 2:
 { // Random effect
 SetModuleOverrideSpellScriptFinished();
 SendMessageToPC(OBJECT_SELF, "Wild Magic - Spell Warped");
 object oTarget = GetSpellTargetObject();
 if (GetIsObjectValid(oTarget))
  lLoc = GetLocation(oTarget);
 float fRadius = IntToFloat(iDmg)/3;
 if (sType == "0x3E" || sType == "0x3F" || sType == "0x2E" || sType == "0x2F")
  {
  oTarget = GetFirstObjectInShape(SHAPE_SPHERE, fRadius, lLoc, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
      while (GetIsObjectValid(oTarget))
      {
          if(oTarget != OBJECT_SELF && spellsIsTarget(oTarget,SPELL_TARGET_STANDARDHOSTILE, OBJECT_SELF))
          {
    RandomDamage(iDmg, oTarget);
    iDmg = d8(iSpellLevel);
    }
   oTarget = GetNextObjectInShape(SHAPE_SPHERE, fRadius, lLoc, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE );
  }//end while
  }// end if
  else
  RandomDamage(iDmg, oTarget); 
 break;
 } 
 }// end switch

Modifié par DannJ, 07 mars 2012 - 11:25 .


#14
MasterChanger

MasterChanger
  • Members
  • 686 messages

DannJ wrote...

I can envisage a way of encoding multiple spell ids into a single local string variable on a creature, so that all you'd have to do is compare a substring of the variable with the incoming spell id. There'd be no need to hardcode checks for specific spell ids then, and you'd have the flexibility of being able to make any creature in the module immune to certain spells on an individual basis with just one local variable.

I'd probably encode the local string something like this: 002101231258 (for spells 21, 123 & 1258), making sure that every spell id you want to check against had four characters (filling in zero prefixes where necessary). Then a loop in the spell hooking script could check each four-digit substring (converted to an integer) against the incoming spell id. The loop would end when a particular four-digit substring returned as "" (ie. a blank string).


Pain, isn't there a way to do this using bitwise math rather than reinventing the wheel with strings? I can't quite wrap my head around how you'd store the spell ID's as bit flags but it seems like it should be doable.

#15
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
So if I was a wizard, and i cast it at the minions of the boss, then i'd have it misfire just because he might be a target?

#16
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages

MasterChanger wrote...

DannJ wrote...

I can envisage a way of encoding multiple spell ids into a single local string variable on a creature, so that all you'd have to do is compare a substring of the variable with the incoming spell id. There'd be no need to hardcode checks for specific spell ids then, and you'd have the flexibility of being able to make any creature in the module immune to certain spells on an individual basis with just one local variable.

I'd probably encode the local string something like this: 002101231258 (for spells 21, 123 & 1258), making sure that every spell id you want to check against had four characters (filling in zero prefixes where necessary). Then a loop in the spell hooking script could check each four-digit substring (converted to an integer) against the incoming spell id. The loop would end when a particular four-digit substring returned as "" (ie. a blank string).


Pain, isn't there a way to do this using bitwise math rather than reinventing the wheel with strings? I can't quite wrap my head around how you'd store the spell ID's as bit flags but it seems like it should be doable.


No, what he said did not really seem to be a direction that makes things simpler.

You can't store spells as bit flags really since bits are on and off flags, and there can only be 31 of them. By the time you are done, just using the spell constants makes much more sense.

Note that the spell resist function checks for immunity for a specific spell, but that is defined in a 2da ( not sure which ones it is controlled by ).
/** 
* Returns Item property spell immunity vs. specific spell. You must specify the
* spell to which the user will be immune(IP_CONST_IMMUNITYSPELL_*).
* The IP_CONST_IMMUNITYSPELL_* value can be retrieved off this type of item property using GetItemPropertyCostTableValue.
* @param nSpell
* @return  an item property
*/
itemproperty ItemPropertySpellImmunitySpecific(int nSpell);

/** 
* Create a Spell Immunity effect.
* There is a known bug with this function. There *must* be a parameter specified
* when this is called (even if the desired parameter is SPELL_ALL_SPELLS),
* otherwise an effect of type EFFECT_TYPE_INVALIDEFFECT will be returned.
* 
* 
* Returns an effect of spell immunity.
* 
* 
* 
* Returns an effect of spell immunity to SPELL_* type spells. 
* 
* Returns an effect of type EFFECT_TYPE_INVALIDEFFECT if nImmunityToSpell is invalid. 
* 
* nImmunityToSpell can be any integer value from the spells.2da file (thus constants SPELL_* are valid), or SPELL_ALL_SPELLS for all spells. 
* 
* The target this effect is applied to must be a creature for it to work. This effect cannot be applied instantly, only temporarily or permanently.
* 
* 
* This will provide direct and total immunity to nImmunityToSpell, *if* that spell uses the function ResistSpell() within it. 
* 
* The fact that no friendly spell uses ResistSpell() means that friendly spells will never be resisted, directly or not. 
* 
* Also, natural abilites obviously are not spells, so will also not be affected by this. 
* 
* Effect functions are Constructors, which are special methods that help construct effect "objects". You can declare and link effects, and apply them using an ApplyEffectToObject() Command. Once applied, each effect can be got seperately via. looping valid effects on the target (GetFirst/NextEffect()). See the Effect Tutorial for more details.
* 
* 
* @bug (Lexicon) Previously noted bug has been fixed in a patch some time ago.
* 
* 
* <b>Examples: ( From Lexicon )</b>
* \\code
* // Sample code for applying direct Immunity to the Fireball spell,
* // to a target (lucky him!)
* 
* void main()
* {
*     // This is the Object to apply the effect to.
*     object oTarget = OBJECT_SELF;
* 
*     // Create the effect to apply
*     effect eImmunity = EffectSpellImmunity(SPELL_FIREBALL);
* 
*     // Create the visual portion of the effect. This is instantly
*     // applied and not persistant with wether or not we have the
*     // above effect.
*     effect eVis = EffectVisualEffect(VFX_IMP_MAGIC_RESISTANCE_USE);
* 
*     // Apply the visual effect to the target
*     ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
*     // Apply the effect to the object   
*     ApplyEffectToObject(DURATION_TYPE_PERMANENT, eImmunity, oTarget);
* }
* \\endcode
*
* @onerror Returns an effect of type EFFECT_TYPE_INVALIDEFFECT if nImmunityToSpell is invalid.
* @param nImmunityToSpell \\ref SPELL_* ( DEFAULT: SPELL_ALL_SPELLS )
* @return 
*/
effect EffectSpellImmunity(int nImmunityToSpell=SPELL_ALL_SPELLS);

Modifié par painofdungeoneternal, 07 mars 2012 - 11:43 .


#17
Dann-J

Dann-J
  • Members
  • 3 161 messages

painofdungeoneternal wrote...

So if I was a wizard, and i cast it at the minions of the boss, then i'd have it misfire just because he might be a target?


You don't have to stop the spell working. You can use the spell hooking to give targets temporary and unbelievably high spell resistance. Even as bugged as it is, spell resistance still works for the first spell cast at the target (which is all you need in this case). The temporary SR effect only needs to last a few seconds.

Because spell hooking runs before the spell impact script does, there (hopefully) should be enough time for the SR effect to take hold before the impact script is run.

That all assumes that the epic spells don't ignore SR completely...Posted Image

Modifié par DannJ, 07 mars 2012 - 11:47 .


#18
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
I don't use stock spell resist, i would not really trust it. Even then to rely on spell resist means you can use that item property instead which gives immunity to a specific spell. You might have to adjust the epic spells to respect that though.

By the time you've got that all tested, you could recompile vampiric feast and not do too much harm to custom content out there. What you are describing is a lot more complex.

Modifié par painofdungeoneternal, 07 mars 2012 - 11:55 .


#19
Dann-J

Dann-J
  • Members
  • 3 161 messages

painofdungeoneternal wrote...

I don't use stock spell resist, i would not really trust it. Even then to rely on spell resist means you can use that item property instead which gives immunity to a specific spell. You might have to adjust the epic spells to respect that though.


If an SR effect proves too buggy, you could always grant one of the SR feats, then take it way again a few seconds later. Having to work around bugs is what gives NWN2 its own unique charm.

By the time you've got that all tested, you could recompile vampiric feast and not do too much harm to custom content out there. What you are describing is a lot more complex.


If you only wanted immunity to one spell, then I'd agree with you. If you wanted the flexibility to grant immunities on an individual basis, then one complex script can make the rest relatively simple (as specific spell immunity is just one local variable away).

Besides - what's the fun of scripting if things don't get complex? Posted Image

This thread has piqued my interest now, so I've half a mind to try to get the script I described up and running for my own amusement. Yes -  I'm easily amused...

#20
Dann-J

Dann-J
  • Members
  • 3 161 messages
Here's my quick-and-nasty attempt to script using Notepad here at work. It assumes that EffectSpellResistanceIncrease works reliably in NWN2 (which is a BIG assumption, knowing NWN2's SR issues). With this script, any creature could be made immune to one or more specific spells by setting a local string on them (four characters per spell ID). The area in question would also have to support spell hooking for companions (X2_L_WILD_MAGIC = 1).

The search radius for AOE spells is hardcoded (10.0m), but if there's a way of extracting this from spells.2DA for each spell then I'd be interested.

[Edit - it's been debugged, compiled and tested now. Everything works as I thought it would. Yes - even I was surprised.]


#include "NW_I0_SPELLS"

void CheckImmunity(object oTarget, int iSpellID)
{
string sImmunity = GetLocalString(oTarget,"Immunity");
if (sImmunity == "")
    return;
int i;
string sSpell = GetSubString(sImmunity, 0, 4);
while (sSpell != "")
    {
    if (StringToInt(sSpell) == iSpellID)
    {
    effect eSR = EffectSpellResistanceIncrease(99);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eSR, oTarget, 3.0);
    }//end if
    i++;
    sSpell = GetSubString(sImmunity, i*4, 4);
    }//end while
}

void main()
{
object oArea = GetArea(OBJECT_SELF);
int iWildmagic = GetLocalInt(oArea, "X2_L_WILD_MAGIC");
if (iWildmagic == 1)
    {
    float fRadius = 10.0;// search radius
    int iSpell = GetSpellId();
    string sType = Get2DAString("spells", "TargetType", iSpell);
    location lLoc = GetSpellTargetLocation();
    object oTarget = GetSpellTargetObject();
    if (GetIsObjectValid(oTarget))
        lLoc = GetLocation(oTarget);

    if (sType == "0x3E" || sType == "0x3F" || sType == "0x2E" || sType == "0x2F")
        {
        oTarget = GetFirstObjectInShape(SHAPE_SPHERE, fRadius, lLoc, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
            while (GetIsObjectValid(oTarget))
            {
                if (oTarget != OBJECT_SELF && spellsIsTarget(oTarget,SPELL_TARGET_STANDARDHOSTILE, OBJECT_SELF))               {
             CheckImmunity(oTarget, iSpell);
             }
         oTarget = GetNextObjectInShape(SHAPE_SPHERE, fRadius, lLoc, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE );
        }//end while
        }// end if AOE
    else
    CheckImmunity(oTarget, iSpell);   
}// end wildmagic if
}

Modifié par DannJ, 08 mars 2012 - 06:52 .


#21
Quilistan

Quilistan
  • Members
  • 111 messages
After reading through. I might actually be needing some direct help with this. It seems to be a bit over my head. I will keep working to understand it though.

#22
Dann-J

Dann-J
  • Members
  • 3 161 messages
I tested my script posted above, and apart from a missing include file and a couple of brackets (which I fixed in the previous post), it works just like I intended it to. To quote a great 80s philosopher; I love it when a plan comes together.

A single local string variable determines which spells a creature is immune to, with support for multiple spells. It works both for single-target and area-of-effect spells. However someone would have to verify whether epic spells allow for spell resistance checks.

#23
Morbane

Morbane
  • Members
  • 1 883 messages
http://www.nwnlexico...ll-hooking.html

#24
MasterChanger

MasterChanger
  • Members
  • 686 messages

DannJ wrote...
However someone would have to verify whether epic spells allow for spell resistance checks.


Pretty sure the answer is no, at least with vanilla scripts. I'm pretty sure they don't consider Spell Focus feats, Spellcraft bonus to saves against spells, or really act like spells at all.

#25
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
Depends on if they have this line in them ( or just MyResistSpell() or resistspell() )

if (!MyResistSpell(OBJECT_SELF, oTarget, fDelay))

So vampiric feast should obey it, however epic spells being feats causes some problems. Any spells that ignore mantles ( acid damage for example which you have in various spells including hellball would not be blockable )

Note that just giving the boss a item property of immunity, or via spawn in script giving them immunity would also work. Generally you don't want to have a lot of overhead on the spell hook, and in a complex setting with a lot of spells being cast that spell resistance is going to help that boss a lot more than it should every so often. If the resistspell function works, then the following probably works as well but you'd have to test it of course.

effect eImmune = EffectSpellImmunity(SPELL_*);