Skip to content

ActionCastSpellAtObject/Location with specific caster level

I need a way to modify the caster level of a spell cast by ActionCastSpellAtObject/Location. As far as I can tell, the only way to do this is to modify all ~800 spell scripts and add a check for a local variable.

It's not a whole lot of work if I can come up with a good regex. Problem is, it will dramatically increase module size and compile time, and if any spell scripts are modified by Beamdog in the future, I'll need to redo those.

Is there any better way?

Comments

  • WilliamDracoWilliamDraco Member Posts: 175
    Short answer - No.

    While on the path of doing this the long-way, be sure to be aware of all of the caster-level hooks in spellcasting.
    Our Mod uses a single script with GetSpellID and a switch function to cast all spells from one file, this may help your size/compile time issue by cutting quantity (although is does make for a very large spell-script file, it should still be faster).
    We implemented a similar custom-casting system. We used a 'global scope' (I.E before the aforementioned switch statement) function to deal with:
    1. Caster Level - to replace GetCasterLevel() checks
    2. Casting Ability Modifier - To let such custom-casting scale correctly (as the default only checks for the wizard class, uses INT if it exists, or using CHA if it doesn't)
    3. Spell DCs - to replace GetSpellDC() check as Ability Modifier is a component of DC.
    4. Spell Resist - As Caster Level is a component. We created an alternative to MyResistSpell() except that, when using custom-casting, if ResistSpell() returned 1 or 0 (2 or 3 are for absorption/immunity) it manually rolls the SR check.
    For any particular cast, the custom override is only used if a custom-casting flag is set (via LocalInt in the script immediately before calling ActionCastSpellAtObject/Location, and which deletes on a short delay afterwards). This custom-casting flag can be set differently to get the character level, Local Variables on the caster, or default to the normal checks (or future variations, if needed).

    It doesn't resolve the issue of re-doing every spell, as you'd need to change them all to pull the new global-scope instead of the per-spell scope variables that the bioware defaults use. Just hope to highlight some of the pitfalls while going through and doing so.
  • ShadooowShadooow Member Posts: 402
    edited September 2019
    Arkenez, with community patch all that work has been done already so you can use variable SPECIAL_ABILITY_CASTER_LEVEL_OVERRIDE int X on the object casting the spell and it will work (with one minor drawback with monk SR which can be fixed with nwnx).
  • ArkezenArkezen Member Posts: 4
    I like that the community patch doesn't require compiling because the files are just added to the override, but then there's the matter of merging my existing spell changes with the new spell scripts.

    I also like the idea of having one spell script do everything; merging would be less trouble, and I could make it more flexible with more potential local variable overrides (damage, DC, etc), but the initial work to create the system would be extensive.

    I suppose the community patch is less work overall; it probably wouldn't take too long to merge ~150 spells.

    There's still the issue of potential changes to spells from Beamdog in the future, but I think that's unlikely.


  • ShadooowShadooow Member Posts: 402
    edited September 2019
    @Arkezen yes indeed that is required to do and can take a lot of time. On the other hand if you do it, you get a lot of benefits.

    Also a tip. Basic/minor changes into spells can be done dynamically without touching spell scripts via the variable based spell modification features.

    Check this code - I run it in OnModuleLoad event and it modifies spells for all users (player/creature).
    void SpellChanges()
    {
        SetLocalInt(OBJECT_SELF,IntToString(SPELL_SUNBEAM)+"_DAMAGE_TYPE_OVERRIDE",DAMAGE_TYPE_POSITIVE);
        SetLocalInt(OBJECT_SELF,IntToString(SPELL_SUNBURST)+"_DAMAGE_TYPE_OVERRIDE",DAMAGE_TYPE_POSITIVE);
        SetLocalInt(OBJECT_SELF,IntToString(SPELL_ISAACS_LESSER_MISSILE_STORM)+"_LIMIT_OVERRIDE",7);//number of missiles to 7
        SetLocalInt(OBJECT_SELF,IntToString(SPELL_ISAACS_GREATER_MISSILE_STORM)+"_LIMIT_OVERRIDE",15);//number of missiles to 15
        SetLocalInt(OBJECT_SELF,IntToString(SPELL_HEALING_STING)+"_SAVING_THROW_OVERRIDE",SAVING_THROW_TYPE_NONE);
    }
    
Sign In or Register to comment.