Author Topic: Caster Level of Items  (Read 961 times)

Legacy_AharonShaw

  • Newbie
  • *
  • Posts: 16
  • Karma: +0/-0
Caster Level of Items
« on: January 16, 2012, 04:28:37 pm »


               Hi!

I'm new to NWN scripting, so please bear with me if my question is easily answered. I did a google-search beforehand, but it didn't turn up anything.

In PnP DnD, the number of spells a caster has is balanced, because the standard assumption is 4 encounters. In NWN (and NWN2), you encounter far more creatures, so the number of spells is rather low if you want to restrict yourself to 1 rest/48 minutes. Resting more often is possible, but takes the difficulty out of the game completely.

A solution might be spells cast from items, but those are often set at a low caster level and thus aren't very effective. Is there a way to change this so that items use the caster level of the item user? That way, one would have to invest in items, but the investment yields actual returns and isn't ineffective.

Thanks and best Regards,

Aharon
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Caster Level of Items
« Reply #1 on: January 16, 2012, 05:51:44 pm »


               yes, you have more choices:

1) change the level in iprp_spells.2da - however this will change the level on all items using that spell, advantage is that it doesnt require anything on clientside so its possible to use on "no-hak" servers

2) add new line in iprp_spells.2da with new line in custom TLK - this is more powerful as it let you to create specific item-cast spells but needs many effort to make it work and custom hak/tlk

3) using unofficial 1.70 patch, you can set variables on the item which can change the caster level/metamagic/DC for all spells cast from this item:
ITEM_CASTER_LEVEL_OVERRIDE / int / new caster level
ITEM_METAMAGIC_OVERRIDE / int / override metamagic, values match NWscript constants
ITEM_DC_OVERRIDE / int / overrides DC
               
               

               


                     Modifié par ShaDoOoW, 16 janvier 2012 - 05:52 .
                     
                  


            

Legacy_AharonShaw

  • Newbie
  • *
  • Posts: 16
  • Karma: +0/-0
Caster Level of Items
« Reply #2 on: January 16, 2012, 06:38:43 pm »


               Sorry, I guess I haven't been very clear. I don't want the item's caster level to be static - I want the item to use the caster level of the user:

I.e.,
if a Level 1 Wizard uses a Wand of Fire, he produces a 1d6 Fireball,
if a Level 6 Wizard uses the same Wand, he produces a 6d6 Fireball,
if a non-caster uses the Wand, the standard caster level is used.

I'm not really sure - is that what your patch does?
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Caster Level of Items
« Reply #3 on: January 16, 2012, 06:50:09 pm »


               I see, so iprp_spells is not useable in this case. My patch solution is static as well, however you can use it nevertheless though it requires a bit of scripting.

you would need to use so called SpellHook script and script it:
- find out if user can cast the spell normally - find out what class can cast the spell and what level is needed and then check whether user fulfil this or not
- if yes then you can set on the item this variable by
SetLocalInt(GetSpellCastItem(),"ITEM_CASTER_LEVEL_OVERRIDE", GetCasterLevel(OBJECT_SELF));

if you are not a scripter I guess I can write the script for you, lmk
               
               

               


                     Modifié par ShaDoOoW, 16 janvier 2012 - 06:50 .
                     
                  


            

Legacy_The Amethyst Dragon

  • Hero Member
  • *****
  • Posts: 2981
  • Karma: +0/-0
Caster Level of Items
« Reply #4 on: January 16, 2012, 06:52:52 pm »


               You would likely need to alter the scripts of all the spells in the module so that it checks if the spell is cast by an item, and if so, grabs the highest level of sorcerer or wizard or whatever, then uses that as the caster level.
               
               

               
            

Legacy_AharonShaw

  • Newbie
  • *
  • Posts: 16
  • Karma: +0/-0
Caster Level of Items
« Reply #5 on: January 16, 2012, 08:38:02 pm »


               @ShaDoOoW
Yes, that would be very nice, if the scripting isn't too much work for you, I would appreciate it. Thank you!

@The Amethyst Dragon
As I said, I'm new to scripting. I've looked at a few of the spell scripts, and they include the SpellHook ShaDoOoW describes. So why is it better to change each individual script instead of the SpellHook?
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Caster Level of Items
« Reply #6 on: January 16, 2012, 09:28:47 pm »


               We all know that I am not that much into the spell system.  However for them that are.  would it not be simple enough to just Hook the spell and if it is cast from an item.  Stop the spell from casting and then assign it to the caster to cast with the bCheat and bInstantSpell both set to TRUE?
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Caster Level of Items
« Reply #7 on: January 16, 2012, 09:40:39 pm »


               

AharonShaw wrote...

@ShaDoOoW
Yes, that would be very nice, if the scripting isn't too much work for you, I would appreciate it. Thank you!

@The Amethyst Dragon
As I said, I'm new to scripting. I've looked at a few of the spell scripts, and they include the SpellHook ShaDoOoW describes. So why is it better to change each individual script instead of the SpellHook?

you know the spellhook script im talking about is something different, the one that is inside each script - X2PreSpellCastCode cannot be changed by default itself and every change inside will not take effect, so what Amethyst Dragon mean is that if you would want to do that without my solution in patch you would have to open each script for each spell and replace function GetCasterLevel with your own function and add this function into x2_inc_spellhook library. What you want to do is not possible to do in X2PreSpellCastCode anyway.

However I did this already, I changed each spellscript exactly for the reason peoples like you wouldnt have to and you can to it easier via the caster level override feature in 1.70.

//script is coming soon

Lightfoot8 wrote...

We all know that I am not that much
into the spell system.  However for them that are.  would it not be
simple enough to just Hook the spell and if it is cast from an item.  
Stop the spell from casting and then assign it to the caster to cast
with the bCheat and bInstantSpell both set to TRUE?

not at all, what OP want cannot be done via spellhook without community patch 1.70 or changes into all spells as described upwards - actioncastspell with bCheat has its own caster level which is static (10 in most cases)
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Caster Level of Items
« Reply #8 on: January 16, 2012, 10:14:14 pm »


               So for the spellhook script.

Spellhook is in nwn scripting almost always meant a script that can run after player cast any spell. To make this script run you need to add a variable with name X2_S_UD_SPELLSCRIPT type of string and value of name of your script ("spell_hook" for example without quotes of course) onto module. (module properties, advances, variables -> ...)

And then you need to create this script and put this inside:

void main()
{
object oCaster = OBJECT_SELF;
object oItem = GetSpellCastItem();
int nSpellId = GetSpellId();
int casterLevel = GetCasterLevel(oCaster);
 if(oItem != OBJECT_INVALID && GetBaseItemType(oItem) != BASE_ITEM_POTIONS)
 {//spell cast from item
 string sInnate;
 int nInnate;
 int bestLevel, reqLevel;
 int nLevel = GetLevelByclass(class_TYPE_BARD,oCaster);
  if(nLevel > 0)
  {
  sInnate = Get2DAString("spells","Bard",nSpellId);
  nInnate = StringToInt(sInnate);
   if(nInnate == 0 && sInnate == "0" || nInnate > 0)
   {
   reqLevel = nInnate*2;
    if(nLevel >= reqLevel && nLevel > bestLevel)
    {
    bestLevel = nLevel;
    }
   }
  }
nLevel = GetLevelByclass(class_TYPE_CLERIC,oCaster);
  if(nLevel > 0)
  {
  sInnate = Get2DAString("spells","Cleric",nSpellId);
  nInnate = StringToInt(sInnate);
   if(nInnate == 0 && sInnate == "0" || nInnate > 0)
   {
   reqLevel = (nInnate*2)-1;
    if(nLevel >= reqLevel && nLevel > bestLevel)
    {
    bestLevel = nLevel;
    }
   }
  }
nLevel = GetLevelByclass(class_TYPE_DRUID,oCaster);
  if(nLevel > 0)
  {
  sInnate = Get2DAString("spells","Druid",nSpellId);
  nInnate = StringToInt(sInnate);
   if(nInnate == 0 && sInnate == "0" || nInnate > 0)
   {
   reqLevel = (nInnate*2)-1;
    if(nLevel >= reqLevel && nLevel > bestLevel)
    {
    bestLevel = nLevel;
    }
   }
  }
nLevel = GetLevelByclass(class_TYPE_PALADIN,oCaster);
  if(nLevel > 0)
  {
  sInnate = Get2DAString("spells","Paladin",nSpellId);
  nInnate = StringToInt(sInnate);
   if(nInnate == 0 && sInnate == "0" || nInnate > 0)
   {
   reqLevel = nInnate*3+(nInnate > 1 ? 2 : 1);
    if(nLevel >= reqLevel && nLevel > bestLevel)
    {
    bestLevel = nLevel;
    }
   }
  }
nLevel = GetLevelByclass(class_TYPE_RANGER,oCaster);
  if(nLevel > 0)
  {
  sInnate = Get2DAString("spells","Ranger",nSpellId);
  nInnate = StringToInt(sInnate);
   if(nInnate == 0 && sInnate == "0" || nInnate > 0)
   {
   reqLevel = nInnate*3+(nInnate > 1 ? 2 : 1);
    if(nLevel >= reqLevel && nLevel > bestLevel)
    {
    bestLevel = nLevel;
    }
   }
  }
nLevel = GetLevelByclass(class_TYPE_WIZARD,oCaster);
  if(nLevel > 0)
  {
  sInnate = Get2DAString("spells","Wiz_Sorc",nSpellId);
  nInnate = StringToInt(sInnate);
   if(nInnate == 0 && sInnate == "0" || nInnate > 0)
   {
   reqLevel = (nInnate*2)-1;
    if(nLevel >= reqLevel && nLevel > bestLevel)
    {
    bestLevel = nLevel;
    }
   }
  }
nLevel = GetLevelByclass(class_TYPE_SORCERER,oCaster);
  if(nLevel > 0)
  {
  sInnate = Get2DAString("spells","Wiz_Sorc",nSpellId);
  nInnate = StringToInt(sInnate);
   if(nInnate == 0 && sInnate == "0" || nInnate > 0)
   {
   reqLevel = nInnate*2;
    if(nLevel >= reqLevel && nLevel > bestLevel)
    {
    bestLevel = nLevel;
    }
   }
  }
  if(bestLevel > casterLevel)
  {
  SetLocalInt(oItem,"ITEM_CASTER_LEVEL_OVERRIDE",bestLevel);
  SendMessageToPC(oCaster,"DEBUG: caster level overriden: "+IntToString(bestLevel));
  }
 }
}


I havent tested it much except it works on my character with wizard/fighter classes casting from scroll properly. I added debug message for testing purposes. I have also disabled this feature for normal potions, crafted potions will however probably benefit from this change.

Of course this will work only if you upgrade onto 1.70, lmk if you will have troubles set this script up.

PS. for other scripters feel free to improve my ugly script, I was trying to get this done ASAP and I had not much time to think about it

EDIT: due to the bug in these forums, replace every class_ instance with uppercase class_ otherwise you wont be able to compile it
               
               

               


                     Modifié par ShaDoOoW, 16 janvier 2012 - 10:42 .
                     
                  


            

Legacy_AharonShaw

  • Newbie
  • *
  • Posts: 16
  • Karma: +0/-0
Caster Level of Items
« Reply #9 on: January 17, 2012, 08:48:44 am »


               @ShaDoOoW
Yep, it works perfectly. Thanks a lot!
Three followup questions:
1) Is there a way to make this work via override, so that it applies to all modules I play?
2) As I said, I feel the same about NWN2. Is it possible to adapt your script for NWN2?
3) Also, I used nwnnsscomp to change some spell scripts before. If I want to make the same changes to the patched spells, I only get the message "Errors occured in compiling." What can I do about this?
               
               

               


                     Modifié par AharonShaw, 17 janvier 2012 - 09:13 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Caster Level of Items
« Reply #10 on: January 17, 2012, 09:43:03 am »


               1) unfortunately I dont think so, spellhook script have to be set on module - so the only way would be to alter X2PreSpellCastCode and put my code in there, but that needs to recompile all spellscripts (however advantage is that you dont have to alter spellscripts manually since 1.70, just recompile). If you want this to be done, you need:
- download 1.70 builders resources
- modify x2_inc_spellhook script (I can help you with that)
- put this include into folder "1.70 builders resources/1.70 spell scripts/includes" and run  compile_it.bat inside 1.70 spell scripts folder - then you get all spells recompiled with this change
- last take all *.ncs from subfolders in 1.70 spell scripts and put them into override (which is quite messy)

(alternatively you can wait a while for upcoming 1.71 beta which will allow to change x2_inc_spellhook without recompiling)

2) not 100% sure, I doubt my spell engine is compatible with NWN2 and you need new 1.70 spell engine to get this work, there also might be a default way how to override caster level? not sure but definitely can be done from scratch like Amethyst Dragon suggested, though it requires really lot of manual work

3) hmm strange it should work, are you able to compile these spells in toolset? If so there must be something set up wrong in the commandline compiler, I would have to see your batch file and include folder (if any) to tell you more
               
               

               


                     Modifié par ShaDoOoW, 17 janvier 2012 - 09:43 .
                     
                  


            

Legacy_AharonShaw

  • Newbie
  • *
  • Posts: 16
  • Karma: +0/-0
Caster Level of Items
« Reply #11 on: January 17, 2012, 11:22:49 am »


               1) Well, that seems like more work than changing the modules, so I won't do that..
2) OK. I'll wait with that, then - there are many NWN1-modules I want to play first, anyway.
3) That's probably it, but there isn't any help anywhere. What I did was open the commandline and type nwnnsscomp.exe *.nss - I didn't use a batch file or an include folder. It works correctly in the toolset, but if I make the changes there, it is module-specific again, I think?
               
               

               


                     Modifié par AharonShaw, 17 janvier 2012 - 11:23 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Caster Level of Items
« Reply #12 on: January 17, 2012, 12:21:28 pm »


               

AharonShaw wrote...

3) That's probably it, but there isn't any help anywhere. What I did was open the commandline and type nwnnsscomp.exe *.nss - I didn't use a batch file or an include folder. It works correctly in the toolset, but if I make the changes there, it is module-specific again, I think?

uh hm

its a bit complicated, toolset allows to work only with modules however once you make some script in there you can export it or manualy copy it into override (make sure you copy also *.ncs one) where it then affect any module you play UNLESS the module in question changed the same script differently - in that case module version has higher priority (that means that neither any Patch changes in such spell applies as Patch files has lowest priority).

Anyway... I assume it worked before installing 1.70 right? can you send me the folder on which you run the commandline compiler? (PM me)
               
               

               
            

Legacy_AharonShaw

  • Newbie
  • *
  • Posts: 16
  • Karma: +0/-0
Caster Level of Items
« Reply #13 on: January 17, 2012, 01:20:12 pm »


               Hi ShaDoOoW, thanks for the help. I figured out how to export from the module, so I'll manually copy the spells I want to change. No need to figure out how to work nwnnsscomp right now :-) Thanks for all the help, I'll enjoy NWN a lot more this way!
               
               

               
            

Legacy_AharonShaw

  • Newbie
  • *
  • Posts: 16
  • Karma: +0/-0
Caster Level of Items
« Reply #14 on: January 17, 2012, 05:17:50 pm »


               OK, another follow-up question:
If I also want to use the SaveDC of the caster if the CL was changed, how do I manage that? I figured I have to add a line with

SetLocalInt(oItem, "ITEM_DC_OVERRIDE", Caster's DC);

in the last If-clause of your code, but I'm not sure how I get the DC of the caster.