Jump to content

Leaving a file with Weidu commands in /Override...?


subtledoctor

Recommended Posts

You can use multiple keys in associative array:
// SPL resource , spell level => sphere
// DIVINE AID
SPPR101 , 1 => 1 // bless

 

 

Also note that you can't overwrite a spell level like that - it must match the filename, e.g. sppr101 must be level 1, or something won't work (at best).

Link to comment

You can use multiple keys in associative array

Mind = blown. But, how would I identify and use those variables? Something like:

ACTION_PHP_EACH spellsphere AS spl , lvl => sph BEGIN
  ACTION_IF (%sph% =1) BEGIN
    COPY %spl%.spl
      WRITE_SHORT 0x34 %lvl%
    BUT_ONLY
  END
END
?? If that's the case then I can reduce my ACTION_IF blocks from handling 140 possibilities to just handling 20... too bad I already spent last night coding up all 140 blocks! :(

 

Also note that you can't overwrite a spell level like that - it must match the filename, e.g. sppr101 must be level 1, or something won't work (at best).

Well, but that only matters of you're worried about interpreting spell.ids, no? We're adding spells to spellbooks by opcode 171 effects in CLABs, so that's not a concern.

 

Huh, I suppose scripts rely on spell.ids working, so maybe this could mess up AI performance...? In which case I'll need to add some ADD_SPELL code into those blocks.

 

But wait... ADD_SPELL will give the copied spell a new filename... which I won't know... so... crap. Am I going to have to write up some kind of routine to look things up in spell.ids, and then build filenames which to insert into my 171 effects? That sounds like a huge headache.

 

EDIT - maybe I could just do some text handling instead. Pull the 3-digit number out of the SPPR__ filename that makes up %spl%, then run a REPLACE_TEXTUALLY in spell.ids to change the digit identifying the level.

 

Nope, wouldn't work. Oy vey.

Link to comment
Mind = blown. But, how would I identify and use those variables? Something like:

 

That's what I asked Wisp for, but not sure if it's been implemented. If defining multiple keys doesn't work, you can do it old-fashioned way like:

ACTION_PHP_EACH spellsphere AS spl => sph BEGIN

OUTER_SET lvl = spl_1

ACTION_IF (%sph% =1) BEGIN

COPY %spl%.spl

WRITE_SHORT 0x34 %lvl%

BUT_ONLY

END

END

 

 

Huh, I suppose scripts rely on spell.ids working, so maybe this could mess up AI performance...? In which case I'll need to add some ADD_SPELL code into those blocks.

 

Yes, the HasSpell() trigger.

 

But wait... ADD_SPELL will give the copied spell a new filename... which I won't know... so... crap. Am I going to have to write up some kind of routine to look things up in spell.ids, and then build filenames which to insert into my 171 effects? That sounds like a huge headache.

 

Yeah, you see the problem :)

Best way imo is to handle it like SR does - clone SpellA into SpellA2, and disable SpellA for players. When AI wants to cast it, it will use SpellA (level unchanged), and players will use SpellA2 instead. The downside is that you can have AI think that Bless is still level 1, and have dozens of it memorized. But that's the price...

Link to comment

Best way imo is to handle it like SR does - clone SpellA into SpellA2, and disable SpellA for players. When AI wants to cast it, it will use SpellA (level unchanged), and players will use SpellA2 instead. The downside is that you can have AI think that Bless is still level 1, and have dozens of it memorized. But that's the price...

Ah! That would actually be perfectly acceptable, I think. And quite easy to plug into the system I have now.

 

(Maybe even, clone all the spells, and we'll know the cloned names, so we'll use the cloned spells for players, *then* run an ADD_SPELL command to change the base spell's level... of course you'd still need to find the .ids name... does READ_2DA_ENTRY work for .ids files? Eh, anyway I think incorporation of AI/NPCs will probably be something that waits until v2 of the mod. And may come in pieces, anyway.)

 

Re: OUTER_SET - I don't see what you did there. How does lvl=spl_1 interact with %spl% or %sph%? How does it find and utilize values between 1 and 7? (Or, is the idea that I've demarcated it in the array somewhere?)

 

OUTER_SET is not in my Weidu toolbox, which I know is kind of ridiculous because I see it everywhere in other mods and it seems very useful. But I've never properly learned it.

Link to comment

From WeiDU readme:

ACTION_PHP_EACH String1 AS String2 => String3 list BEGIN TP2 Action list END For every value of the string1 array that has been created or read, sets string2_0 to the first array parameter, string2_1 to the second array parameter, etc. and string3 to the result of the array. string2 will also contain the first array parameter (as a synonym of string2_0). then executes the actions listed.

 

So, if you have:

ACTION_DEFINE_ASSOCIATIVE_ARRAY spells BEGIN
SPPR101 , 1 => bless
SPPR203 , 2 => chant
SPPR316 , 3 => prayer
END

 

and then want to access it via ACTION_PHP_EACH, you do:
ACTION_PHP_EACH spells AS key => value BEGIN

PRINT ~%key%~ // displays "SPPR203"

PRINT ~%key_0%~ // also displays "SPPR203"
PRINT ~%key_1%~ // displays "2"
PRINT ~%value%~ // displays "chant"
END

 

 

So, in your case of spl=>sph, unless it's no problem for you to use less intuitive "spl" for the SPL filename, and "spl_1" for its level, you can simply set a custom "lvl" var to match "spl_1". As a heavy user of arrays myself, I always found it awkward to have to re-define the "lvl" or stick to "spl_1", so I asked sometime ago to allow for extended key definition in PHP_EACH function, but whether it's been ever implemented I don't know (I don't really check WeiDU forum anymore, or the modding forums in general for that matter :( )

As such

ACTION_PHP_EACH spellsphere AS spl , lvl => sph BEGIN

 

might have already been made possible, in which case disregard my two last posts as no longer relevant.

 

The OUTER_SET is because it's taking place in ACTION environment.

Link to comment

OUTER_SET is not in my Weidu toolbox, which I know is kind of ridiculous because I see it everywhere in other mods and it seems very useful. But I've never properly learned it.

SET is a way of assigning a numerical value to variable. SPRINT and TEXT_SPRINT are ways of assigning a string to a variable.

 

This code is equivalent:

WRITE_SHORT 0x10 5
SET amount = 5
WRITE_SHORT 0x10 amount
Link to comment

So if OUTER_SET assigns a numerical value, can I do numerical things with it? Like:

ACTION_PHP_EACH spellsphere AS spl => sph BEGIN
  OUTER_SET lvl = spl_1
  ACTION_IF (%sph% =1) BEGIN
    COPY %spl%.spl
      WRITE_SHORT 0x34 (%lvl% - 1)
Or even:
ACTION_PHP_EACH spellsphere AS spl => sph BEGIN
  OUTER_SET lvl = spl_1
  OUTER_SET flvl = (%lvl% - 1)
  ACTION_IF (%sph% =1) BEGIN
    COPY %spl%.spl
      WRITE_SHORT 0x34 %flvl%
Also: anyone know whether it's possible to READ_2DA_ENTRY from spell.ids so that I can do something like:
ACTION_PHP_EACH spellsphere AS spl => sph BEGIN
  OUTER_SET lvl = spl_1
  ACTION_IF (FILE_EXISTS_IN_GAME %sph%.spl) BEGIN
    COPY_EXISTING ~spell.ids~ ~override~
      COUNT_2DA_ROWS num_rows
      FOR (row = 1; row < (num_rows - 1); row += 1) BEGIN
        READ_2DA_ENTRY 1 row 1 spellfile
        PATCH_IF (~%spellfile%~ STRING_EQUAL_CASE ~%spl%~) BEGIN
          READ_2DA_ENTRY 1 row 2 spellname
        END
      END
    BUT_ONLY
  END
  COPY_EXISTING ~%spl%.spl~ ~override~
  ADD_SPELL ~override/%spl%.spl~ 1 %lvl% %spellname%
END
That's off the top of my head, I'm sure I got some of the READ_2DA_ENTRY values wrong, but you see what I'm doing there: I need to derive the IDS spell name as a variable so that I can plug it into the ADD_SPELL command, which will set the level per %lvl% and patch spell.ids with the updated spell for the sake of scripts & AI. Does that sound feasible?

 

EDIT - Thanks Wisp

Link to comment

Ah! So, "RET" = return value. But, when I search github I just see the code for the function, I don't see anything about usage. Like, what kind of input does it need... a STR_VAR? For instance, I want to convert Slow Poison into a 1st-level spell and then find the filename of the new spell:

 

 

COPY_EXISTING ~sppr212.spl~ ~override~
 
ADD_SPELL ~override/sppr212.spl~ 1 1 CLERIC_SLOW_POISON
    WRITE_LONG 0x34 1
 
LAF RES_NUM_OF_SPELL_NAME STR_VAR ~CLERIC_SLOW_POISON~ END
 
PRINT %spell_num%

 

That doesn't work... but I have no idea of in what way it is malformed. (Just tried 20 variations of the above, and didn't hit on the right form.)

Link to comment

the macro is defined further down the file. These three functions take one argument of the three and return the other two values. Looks like you need to set spell_name for it, though I don't understand the syntax, sorry.

Link to comment

It's used same as any other function. You invoke one function just like you invoke another. The syntax is the same, regardless of whether it is CLONE_EFFECT or something else.

LAF RES_NUM_OF_SPELL_NAME
  STR_VAR
    spell_name = "CLERIC_SLOW_POISON"
  RET
    spell_num // Whatever number CLERIC_SLOW_POISON has in spell.ids
    spell_res // Whatever resref spell_num corresponds to
END
 
PRINT "spell_num is %spell_num%" // E.g., "1212"
PRINT "spell_res is %spell_res%" // E.g., "SPPR212"
Link to comment

Best way imo is to handle it like SR does - clone SpellA into SpellA2, and disable SpellA for players. When AI wants to cast it, it will use SpellA (level unchanged), and players will use SpellA2 instead. The downside is that you can have AI think that Bless is still level 1, and have dozens of it memorized. But that's the price...

So, I followed this advice and have set up a sphere system that assigns cloned spells to spheres, and assigns those spheres based on kit/deity. But, I just realized a much bigger downside: this becomes a problem if any other spell in the game references the clone's original spell.

 

E.g., (I forget if Death Ward works this way, but:) let's say there is a spell that protects against Finger of Death. It might use opcode 206 "Protection from Spell" with "SPPR709" in the effect's RESOURCE field. Now our PC priest casts Finger of Death, and he is actiually casting "d5_1709," which is the clone spell. Because the protection spell does not protect from "d5_1709," the spell works, and the whole system breaks a little bit.

 

SO... back to the drawing board. :(

 

I have succeeded in basing my spell => sphere array on IDS names instead of file names. So I think I should be able to run ADD_SPELL inside the PHP_EACH block to change levels if necessary while keeping the spell avsilable to the AI and scripts. So hopefully I can make the whole system work without needing separate cloned spells for the player. The only other alternatives that occur to me are:

 

1) have the player's clone spells just use opcode 146 to cast the original spell

 

2) run a COPY_EXISTING_REGEXP_GLOB to go through every single spell (EDIT - and every item!), and CLONE_EFFECT every effect whose RESOURCE field covers the original priest spell... and run this inside the PHP_EACH for every spell in the array (i.e. every priest spell, *and* every new spell we're adding). *That* would add some processing time!

 

EDIT - no, ADD_SPELLing everything wouldn't work any better, since it would still change the file names. Plus we're using various wizard spells as well. (Clone Magic Missile as a priest spell, and Shield won't protect from the new spell.)

 

So, it's either option 1) using opcode 146 everywhere (which I'm not comfortable with because I'm not sure of all the implications of it), or else run thousands of iterations of CLONE_EFFECT during installation... yikes.

Link to comment

Archived

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

×
×
  • Create New...