You are here

Tutorial: How to modify caster level, DC or metamagic dynamically without need to recompile all spellscripts

This tutorial shows and explains the spell scripting features that added the Community Patch Project (CPP) in the new spell engine.

The new spell engine from CPP allows to overwrite the caster level, DC and also metamagic of any spell easily using variables.

These variables are:


For spells cast by players (not DM) and NPCs, but only for spells drawn from the spell list tab - not special abilities.


For spells cast by DM, monsters, when the spell is drawn from special abilities tab, spells fired by projectile traps and also for spells cast via scripting with bCheat parameter set to TRUE.


For spells cast from items, doesn't matter if manually or automatically from "On Hit: Spell Cast" item property.
Note: the red colored variables are specific to CPP 1.71 and are not present in 1.70. But we won't need those - so this tutorial is applicable on 1.70 as well (whatever is the reason anyone still use that version).

This is repeating of the informations from CPP readme. Question you probably ask is - how is this usefull when I want to modify caster level only for spells from certain class or spell school?

The answer is spellhook. You need to set up spellhook script first. If you aren't familiar with this term read here first.


Now, assuming you have spellhook set and you are in toolset with the spellhook script opened. What you need to do is essentially:

1. reset the caster level, dc, metamagic variables to null (because as you soon find out they possess a values from last spell that has been cast)
2. calculate the caster level, dc, metamagic the spell should have
3. and set the variables on PC and thats it

If you are still not catching up whats going on here, here is an example spellhook script:

void main()
object oCaster = OBJECT_SELF;//get caster
object oItem = GetSpellCastItem();//get item from which was spell cast
int nSpellId = GetSpellId();//get spell id
int nClass = GetLastSpellCastClass();
int origCasterLevel = GetCasterLevel(oCaster);//get original caster level
int origDC = GetSpellSaveDC();//get original DC
int origMeta = GetMetaMagicFeat();//get original metamagic feat

SetLocalInt(oCaster,"SPELL_DC_OVERRIDE",0);//reset to default
SetLocalInt(oCaster,"SPELL_CASTER_LEVEL_OVERRIDE",0);//reset to default

 if(oItem != OBJECT_INVALID) return;//if the spell was cast from item then exit because the bonuses shown here are not applicable for items

int newCasterLevel = origCasterLevel;
int newDC = origDC;
int newMeta = origMeta;

//now lets calculate some bonuses

 //example 1: say add champion of torm levels to caster level if spell is cast from paladin spell book
 newCasterLevel+= GetLevelByClass(CLASS_TYPE_DIVINE_CHAMPION,oCaster);
 //example 2: say add +1caster level and +1DC when character has more than 1 milion experiences
 if(GetXP(oCaster) >= 1000000)
 newCasterLevel+= 1;
 newDC+= 1;
 //example 3: say make spell automatically maximized if caster wearing specific staff
 if(GetTag(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oCaster)) == "staff_of_maximize")
 //example 4: say halve the caster level for paladin and ranger as per DnD 3.5 rules
 newCasterLevel/= 2;
 //example 5: increase caster level of call lightning spell when raining in the area
  if(GetWeather(GetArea(oCaster)) == WEATHER_RAIN)
  newCasterLevel+= 2;
 //example 6: stack cleric and druid levels for spells they share
 if(nClass == CLASS_TYPE_CLERIC)
 int bDruid = Get2DAString("spells","Druid",nSpellId) != "";//if the 2da lookup returns "" spell is not on druid list
  if(bDruid == TRUE)
  newCasterLevel+= GetLevelByClass(CLASS_TYPE_DRUID,oCaster);
 else if(nClass == CLASS_TYPE_DRUID)
 int bCleric = Get2DAString("spells","Cleric",nSpellId) != "";//if the 2da lookup returns "" spell is not on druid list
  if(bCleric == TRUE)
  newCasterLevel+= GetLevelByClass(CLASS_TYPE_CLERIC,oCaster);

//now when are we done, set the variables

//done, the spell which is triggered right after this script ends will use these values

That should give you an idea. As you can see, the potential is endless. With this method you have an absolute control over the caster level, dc and metamagic of the spells cast by players.

This method is useable also for spells cast by monsters, if someone wouldn't be satisfied with the default variables that CPP offers. But keep in mind that the spellhook script doesn't fire for NPCs. To enable that you need to modify 70_spellhook script first. After that, to check whether the spell was cast by NPC in spellhook script, check whether nClass == CLASS_TYPE_INVALID, if this is TRUE then the SPECIAL_ABILITY_* variables apply for this spell not the SPELL_* ones.

Similarly with spells cast from item - if you want to adjust these, then you need to check for oItem != OBJECT_INVALID. If thats true then the ITEM_* variables apply for this spell not the SPELL_* ones.

In case of interest I can make an example module or ERF package. Let me know.

First Release: 
  • up
  • down

Can you do a sample that incorporates HGLL's into caster levels.

I've been away from the community for a few years and am just discovering CPP.  I know just enough scripting to break everything.  Help would be appreciated.

Actually I believe what I'm looking for is a spell hook script that can run after ExecuteScript("70_spellhook",OBJECT_SELF,): is called to add HGLL levels to spell.Level


  • up
  • down

Im not familiar with HGLL. I assume they use local integer for a legendary levels or rather persistent integer, then all you need is to find how is the legendary level stored, retrieve that value and add together into newcasterlevel variable. Try bioware forums for help  they are more active than forum on this site.

  • up
  • down