Jump to content

problem with ADD_SPELL and scripts


subtledoctor

Recommended Posts

I am trying to turn Spell Thrust into an innate ability. Here is my code:

 

 

ADD_SPELL ~innate_magic/wizard/spwi321.spl~ 4 1 WIZARD_SPELL_THRUST
    SAY NAME1 @6053
    SAY UNIDENTIFIED_DESC @6054
 COPY_EXISTING_REGEXP GLOB ~^.+\.cre$~ ~override~
    PATCH_IF (SOURCE_SIZE > 0x2d3) BEGIN
        READ_BYTE 0x273 class
        PATCH_IF (class == 1 || class == 13 || class == 14 || class == 7 || class == 10 || class == 17) BEGIN // wizards
            ADD_KNOWN_SPELL ~%thrust_res%~ #0 ~innate~
            ADD_MEMORIZED_SPELL ~%thrust_res%~ #0 ~innate~
        END
    END
 BUT_ONLY
 COPY ~innate_magic/wizard/spwi321.spl~ ~override~
    SAY NAME1 @6053
    SAY UNIDENTIFIED_DESC @6054

 

 

Basically, my mod has an innate version of Spell Thrust; I use ADD_SPELL to add it as an spclxxx.spl file linked to the IDS name WIZARD_SPELL_THRUST in spell.ids. Then I give the ability to every wizard in the game. Then I copy my innate version into /override as spwi321.spl. This .spl file is no longer linked to anything in the IDS table, but it is there.

 

So: any script that uses

HaveSpell(WIZARD_SPELL_THRUST)

will find my innate version, and scripts that use

HaveSpellRES(spwi321)

will find my leftover version of spwi321.spl. This way, scripts should work with my innate version of the spell... and because it is a self-renewing ability, AI mages should be able to use it at will.

 

BUT: after I run the code above, existing BCS scripts in the game *change.* When I inspect AI scripts in Near Infinity, scripts that use to say

HaveSpell(WIZARD_SPELL_THRUST)

now say

HaveSpell(2321)

And of course, the IDS number of the old Spell Thrust spell now points to nothing, because ADD_SPELL changed the IDS number of WIZARD_SPELL_THRUST to something like 4107.

 

Why is this happening? How is this happening? I don't want to change any scripts - I want to look at them, and work with them as they already are! How can I account for how existing scripts work when my own code seems to change them? Can this be avoided? Or am I going to have to run something like this at the end of the mod:

LAF RES_NUM_OF_SPELL_NAME STR_VAR spell_name = ~WIZARD_SPELL_THRUST~ RET spell_num END
OUTER_SET thrust_num %spell_num%
COPY_EXISTING_REGEXP_GLOB ~^.+\.bcs$~ ~override~
  DECOMPILE_BCS_TO_BAF
  REPLACE_TEXTUALLY EVAL ~2321~ ~%thrust_num%~
  COMPILE_BAF_TO_BCS

...Because, with SCS scripts weighing in at ~30,000 lines each, decompiling and compiling them all to make a simple text change could take a looooong time... :(

 

Any ideas?

Link to comment

Why is this happening?

Any ideas?

Well, because the .bcs scripts are already compiled scripts. Aka the numbers are already set in them ... the scripts you thing you are watching with Near Infinity are the source .baf's aka text file made out of them. for debug'ging..

 

So yeah, you need to recompile the scripts again.

 

And instead of DECOMPILE_BCS_TO_BAF --- COMPILE_BAF_TO_BCS , use the DECOMPILE_AND_PATCH BEGIN --- END routine.

Link to comment

Yeah but why would NI show me different BAF text for an AI BCS script before and after I ADD_SPELL a spell? Is the BCS content in fact changed by the later mod?

 

If the BCS script content is static, then what is actually referenced in them? If I can't trust NI to tell me, does anyone know the answer? What should I be targeting with my mod? The IDS number?

Link to comment

If the BCS script content is static, then what is actually referenced in them? If I can't trust NI to tell me...

Well the thing is, the NI shows you the Script source(decompiled) which is the .baf code, when it's decoded by the games current libraries, but you can also view the Script code which is the actual files content. And I don't think you wish to touch that.
Link to comment

BCS byte code stores the numeric value of the respective spells. The IDS file is only used to translate the number into a symbolic name when NI or WeiDU decompiles the script into the BAF source or vice versa. If you change the spell from SPWI321 into SPCL101 (or whatever ADD_SPELL is returning) then you have to change all instances of "2321" into "4101" in all existing BCS files of the game if they should use your new spell instead of the original one.

You can easily inspect the BCS byte code in NI by switching to the "Script code" tab. As an example, the trigger "HaveSpell(WIZARD_SPELL_THRUST)" is translated into

TR
16433 2321 0 0 0 "" "" OB
0 0 0 0 0 0 0 0 0 0 0 0 ""OB
TR

in an unmodded game. 16433 is the trigger ID of "HaveSpell()" and 2321 is the function argument which translates into WIZARD_SPELL_THRUST via SPELL.IDS.

 

When you change the value assigned to WIZARD_SPELL_THRUST in SPELL.IDS from 2321 to any other value then the decompiler can't resolve the number from the byte code above into a symbolic name. It will fall back to display the raw number instead.

Link to comment

@argent77 - thank you for the explanation. So it looks like in order to "fool" AI scripts into using my alternate version of Spell Thrust, I have to target the IDS number instead of the name. Which may be difficult or even impossible... :( And separate issue, it means that it would be difficult or impossible to change the level of any spell without breaking scripts.

 

Meaning, possibly, that the only answer is indeed to DECOMPILE_AND_PATCH every .bcs script in the game...? Ouch.

 

...

 

Alternatively: I could just make Spell Thrust self-renewing as a wizard spell. The Wondrous Recall opcode can do this, but it only works for the earliest spell that is memorized and already cast. I.e. the furthest to the left in the spell screen when looking at your spellbook. Does anyone know how the organization of known spells in the .cre file translates to being earliest or latest in the spellbook screen? Is there any way to make it so that AI wizard .CREs get Spell Thrust as the "earliest" 3rd level spell?

 

Can I do something with this code to make sure of it, and therefore make sure that any application of the Wondrous Recall opcode will always restore Spell Thrust?

COPY_EXISTING_REGEXP GLOB ~^.+\.cre$~ ~override~
    PATCH_IF (SOURCE_SIZE > 0x2d3) BEGIN
        READ_BYTE 0x273 class
        PATCH_IF (class == 1 || class == 13 || class == 14 || class == 7 || class == 10 || class == 17) BEGIN // wizards
            ADD_KNOWN_SPELL ~%thrust_res%~ #0 ~innate~
            ADD_MEMORIZED_SPELL ~%thrust_res%~ #0 ~innate~
        END
    END
 BUT_ONLY
Link to comment

Can I do something with this code to make sure of it, and therefore make sure that any application of the Wondrous Recall opcode will always restore Spell Thrust?

Well unless you rearrange their spell memorization table. In theory you could do that. But then what happens when the player get's fireballs instead of spell thrusts. :p
Link to comment

what happens when the player get's fireballs instead of spell thrusts. :p

That's precisely the issue. A possible plan is to split this into using two different methods:

1) The PC and joinable NPCs will get an innate ability at level 5 that is self-renewing via opcode 171

2) Non-joinable NPCs will have Spell Thrust as a normal wizard spell, but it will be patched to use opcode 261 to renew itself upon casting. They could be given a bonus to 3rd-level spell slots to make up for using up one of them on Spell Thrust.

 

That could work perfectly in-game (every wizard can cast Spell Thrust at will) *as long as* the spell tables of the non-joinable .CREs can be edited such that Spell Thrust is the first memorized 3rd-level spell, and thus will always be renewed when the .CRE is affected by Wondrous Recall.

 

It's that last part I have no idea how to do. But I want to see if it's possible, before deciding to decompile and patch every BCS script.

Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...