Jump to content

best way to poll memorized spells


subtledoctor

Recommended Posts

For a wizard kit, I need to check which spells are memorized, and apply a related spell for each one.  (Say, if I have spwi101 memorized, I need to apply spwi101M.spl.)  

I think that means I need to use the HaveSpell trigger (EDIT - actually, HaveSpellRES I guess).  So I'll need to summon an invisible creature, and have it run a script... so the task is, generating a script that contains a little 'IF HaveSpell()' block for every spell that might possibly be memorized.  Anyone have a suggestion or maybe a even a shortcut for creating such a script?

I suppose it would be something like (pseudocode)

<<<<<<<<d5/inline_script.baf
IF
    NextTriggerObject(LastSummonerOf(Myself))
    HaveSpellRES("SPWI101")
THEN
    RESPONSE #100
    ActionOverride(LastSummonerOf(Myself),ApplySpellRes("SPWI101M",Myself))
    Continue()
END
>>>>>>>>
	COPY ~d5/inline_script.baf~ ~override/havespls.baf~

[derive array of learnable wizard spells]

ACTION_PHP_EACH scroll_spells AS ind => arcane_spell BEGIN
  ACTION_IF (ind > 0) BEGIN
    ACTION_IF !(~%arcane_spell%~ STRING_EQUAL_CASE ~spwi101~) BEGIN
      ACTION_IF FILE_EXISTS_IN_GAME ~%arcane_spell%.spl~ BEGIN
        APPEND ~havespls.baf~ ~
IF
    NextTriggerObject(LastSummonerOf(Myself))
    HaveSpellRES("%arcane_spell%")
THEN
    RESPONSE #100
    ActionOverride(LastSummonerOf(Myself),ApplySpellRes("%arcane_spell%M",Myself))
    Continue()
END~
      END
    END
  END
END

APPEND ~havespls.baf~ ~
IF
    True()
THEN
    RESPONSE #100
    DestroySelf()
END~

COMPILE ~override/havespls.baf~

Is that reasonable?  Is there a better/more efficient way to do it?

 

(EDIT - GOD these new forums are annoying.  Sorry for the post length, spoiler tags don't seem to work.)

Edited by subtledoctor
Link to comment

And on the third hand, does anyone have suggestions for the best way to generate an array of learnable wizard spells?  My current ideas are:

- Check all scrolls for 147 effects where the underlying .SPL is type=arcane;

- Trawl through SPELL.IDS for arcane spells of level 1 and higher

- Check all filenames conforming to [Ss][Pp][Ww][Ii][1-9][0-5][0-9]

...In fact I think I use each of those methods at different places in different mods.  Is there an accepted or more-recommended way to do this?

Link to comment

Nope, APPEND works fine - .baf (EDIT - and .d) files are essentially just text files. Of course it only adds to the bottom of such files, which can be limiting. 

EXTEND_ only works with already-compiled .bcs and .dlg files. Seems like a lot of processing to compile first and then EXTEND ~150 times... I assume APPENDing text is much simpler. 

Link to comment
  1. You should be starting with a blank .baf file.  Having the SPWI101 block in there means you have to take extra steps to avoid adding a duplicate block later.
  2. APPEND is generally for game files.  You don't really need your .baf file in the override.  You can use APPEND_OUTER to append to files that are not in the override.  It may even work with inlined files, which would simplify things.
Link to comment
3 hours ago, Mike1072 said:
  1. APPEND is generally for game files.  You don't really need your .baf file in the override.  You can use APPEND_OUTER to append to files that are not in the override.  It may even work with inlined files, which would simplify things.

Yeah - I had tried APPEND_OUTER with the inlined file in its imaginary directory, but that didn't work. Ultimately I'll copy the inlined file to a workspace directory and patch it there before compiling. 

(I would edit the code above to reflect this, but that's not possible in a mobile browser :( )

EDIT - there will actually be some spells that will need to be included that won't be available from scrolls and won't be in SPELL.IDS, so I'll likely have some pre-existing script blocks anyway.

Edited by subtledoctor
Link to comment
On 2/20/2019 at 3:32 PM, subtledoctor said:

Second question is, am I using Continue() correctly in that script? 

Guess it depends on what you wanna achieve. Continue() means your script is not forced to restart every time a block is executed...... This is probably fine for your application......

Link to comment

Basically the script should go through ~150 spells, and may find that ~20-30 are memorized, and it will perform an action based on each of those that return true as currently memorized spells. So yeah, sounds like Continue() will let all that happen in a single pass through the script. The alternative would be to set some variable for each spell when it returns true, so that a successive pass through the script would shiw it to be false and it would move on to the next spell. Which would mean processing the script ~20-30 times. Not ideal. 

(Though, setting those variables and then negating them at the end might be a good idea anyway, just for safety's sake.)

Link to comment
6 hours ago, subtledoctor said:

The alternative would be to set some variable for each spell when it returns true, so that a successive pass through the script would shiw it to be false and it would move on to the next spell. Which would mean processing the script ~20-30 times. Not ideal.

3

A one or a billion run thoughts, if nothing else is done, your one run just run the risk of no actions to be done correctly as all the actions are first validated as to be done... and then run as to be done... and doing them ... and the script still runs and orders are compiled as soon as they are validated ... it's less likely to get a thing done with Continue() than allow it to take 20 passes, which is by the by, less than just 2 seconds at 30 FPS, as that's 15 runs of the script PER second, without the action time.

Link to comment

I mean, I'd prefer it not take 2 seconds to run... that's actually a fairly large amount of time for something that's supposed to happen immediately and invisibly when you wake up in the morning, before you can cast any spells...

I've got a prototype of this working, it's going to be super fun.  (EE-only, alas - it makes heavy use of opcode 326 and splprot.2da.)  But there are still a few kinks.  Anyone have thoughts as to this?

On 2/20/2019 at 9:38 AM, subtledoctor said:

does anyone have suggestions for the best way to generate an array of all learnable wizard spells?  My current ideas are:

- Check all scrolls for 147 effects where the underlying .SPL is type=arcane;

- Trawl through SPELL.IDS for arcane spells of level 1 and higher

- Check all filenames conforming to [Ss][Pp][Ww][Ii][1-9][0-5][0-9]

...In fact I think I use each of those methods at different places in different mods.  Is there an accepted or more-recommended way to do this?

Any of those three methods might be prone to both false negatives and false positives, in an unpredictable modded game environment...

I suppose I could just combine a couple of them, and make a master .2da list of learnable wizard spells...

Link to comment

Moreover: anyone know why this fails?

ACTION_IF FILE_EXISTS_IN_GAME ~splstate.ids~ BEGIN
  ACTION_IF FILE_CONTAINS ~splstate.ids~ ~D5_SPL_PREP~ BEGIN
    COPY_EXISTING ~splstate.ids~ ~override~
      READ_2DA_ENTRIES_NOW rows cols
      FOR (row = 1; row < rows; ++row) BEGIN
        READ_2DA_ENTRY_FORMER rows row 1 ~state_name~
        READ_2DA_ENTRY_FORMER rows row 0 ~state_ind~
        PATCH_IF (~%state_name%~ STRING_EQUAL_CASE ~D5_SPL_PREP~) BEGIN
          SET prepared_spells_state = %state_ind%
        END
      END
    BUT_ONLY
  END
END

I get "error loading [splstate.ids]"

Link to comment

Not sure what that error is, but there is an issue with READ_2DA_ENTRIES_NOW row cols.  The second parameter is the required column count.  Instead of using cols (which doesn't appear to be defined), you could put a 1 there.

However, the entire section of code in the previous post could be replaced with this:

OUTER_SET prepared_spells_state = IDS_OF_SYMBOL (~splstate~ ~D5_SPL_PREP~)

 

Link to comment
7 hours ago, subtledoctor said:

 

On 2/20/2019 at 6:38 AM, subtledoctor said:

does anyone have suggestions for the best way to generate an array of all learnable wizard spells?  My current ideas are:

- Check all scrolls for 147 effects where the underlying .SPL is type=arcane;

- Trawl through SPELL.IDS for arcane spells of level 1 and higher

- Check all filenames conforming to [Ss][Pp][Ww][Ii][1-9][0-5][0-9]

...In fact I think I use each of those methods at different places in different mods.  Is there an accepted or more-recommended way to do this?

Any of those three methods might be prone to both false negatives and false positives, in an unpredictable modded game environment...

I suppose I could just combine a couple of them, and make a master .2da list of learnable wizard spells...

My first instinct would be to use filenames.  You might want to use filenames & 147 effects.

The big decider is how important it is that you catch every possible spell that a player could learn.  Are you aiming for just wizard spells or wizard and sorcerer spells?  What about spells added in CLAB files?

Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...