Jump to content

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


subtledoctor

Recommended Posts

This ACTION_TO_UPPER and ACTION_TO_LOWER stuff is really annoying. I need to extract nice mixed-case versions of the spheres, because they get plugged into the kit descriptions.

Is there an ACTION_TO_MIXED?

EDIT - and the .tp2 entries for sphere access in the ~define_kit_info~ function have to be entered in the same case as they appear in the ~sphere_access~ array in compat.tpa, or they are ignored. I want to be able to ignore case, but I can't. Even if I comment out the FAIL check (which I'm guessing is a bad idea), even when I write

ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && STRING_EQUAL_CASE ~major~) BEGIN

...STRING_EQUAL_CASE should mean the match check doesn't care about case. But here, it fails if it's not a perfect match.

Very confused and annoyed right now. I don't understand the whole "validate spheres" section of compat.tpa.

 

EDIT 2 - figured that part out. Now to see if I can change the case of the spheres to stay mixed.

Link to comment

just judging by the name, STRING_EQUAL_CASE does exactly what I'd expect — case must be equal. However the docs do suggest you are right and it's more like STRING_EQUAL_ANY_CASE. You did forget an argument there though.

 

Write a trivial test case. Doesn't work? Tell Wisp, otherwise the problem is elsewhere.

Link to comment

I used TO_UPPER and TO_LOWER a lot because variable names are case sensitive.

 

If this array is defined:

 

ACTION_DEFINE_ASSOCIATIVE_ARRAY d5_fnp_spheres BEGIN
  LIFE => 0
  DEATH => 0
  BENEDICTION => 0
  DESTRUCTION => 0
  PROTECTION => 0
  WAR => 0
  KNOWLEDGE => 0
  DECEPTION => 0
  THOUGHT => 0
  DREAD => 0
  VIGOR => 0
  AFFLICTION => 0
  ANIMAL => 0
  PLANT => 0
  EARTH => 0
  WATER => 0
  AIR => 0
  FIRE => 0
  LIGHT => 0
  SHADOW => 0
  MAGIC => 0
END

Then VARIABLE_IS_SET $d5_fnp_spheres(~KNOWLEDGE~) would return true, while VARIABLE_IS_SET $d5_fnp_spheres(~knowLEDGE~) would return false. You should leave the case of these arrays alone.

 

If you want to access a prettified version of their values, then you have a few options.

 

1) Define an associative array that maps the unpretty version to the pretty version. (This is a good choice if the unpretty versions don't have an easy automated mapping to the pretty version.)

 

2) Write some code to prettify the value. If you have an all uppercase string and you want to lowercase every letter except the first, you could do something like this:

 

INNER_PATCH_SAVE mixed_sphere ~%sphere%~ BEGIN
  SET len = STRING_LENGTH ~%sphere%~
  READ_ASCII 1 end (len - 1)
  TO_LOWER end
  WRITE_ASCIIE 1 ~%end%~
END

I don't understand the whole "validate spheres" section of compat.tpa.

  // validate spheres
  ACTION_PHP_EACH d5_fnp_spheres AS sphere => val BEGIN
    ACTION_TO_LOWER sphere
    OUTER_TEXT_SPRINT sphere ~s_%sphere%~
    OUTER_TEXT_SPRINT access EVAL ~%%sphere%%~
    ACTION_TO_UPPER access
    ACTION_IF (NOT VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~)) BEGIN
      FAIL ~DEFINE_FNP_KIT_INFO: The access value (%access%) for the sphere %sphere% does not match one of the valid options: NONE, MAJOR, MINOR, FOCUS, PALADIN, or RANGER.~
    END
  END
Here's what it's doing in pseudocode:

 

- For each entry in the d5_fnp_spheres array, get the key and value as the variables sphere and val. (e.g. sphere = ~KNOWLEDGE~ and val = 0)
  - Lowercase the value of the sphere variable. (sphere = ~knowledge~)
  - Prepend the sphere variable with ~s_~. (sphere = ~s_knowledge~)
  - Set the access variable to the value of the variable named by the sphere variable.  (access = ~%s_knowledge%~, e.g. access = ~MAJOR~)
  - Uppercase the value of the access variable. (access = ~MAJOR~)
  - Check if the d5_fnp_sphere_access associative array contains a key matching the value of the access variable.
    - If it does not, the caller of the function specified an invalid value for one of the spheres (e.g. s_knowledge = ~MAJR~) and the installation should FAIL.
Link to comment

I think I've wrapped my head around it. I was seeing it backwards - or something. I mostly get it now.

You should leave the case of these arrays alone.


Ha ha, too late. I managed to set them all to be mixed-case. The trick is to make sure they are mixed-case in the array, and in the "s_xyz" variables in the function, and in the variables the modder sets when launching the function, and in the base .2da file. Once I changed everything to match, as long as they continue to match, they all use mixed case and it gives me pretty output to append to kit descriptions.

 

I also figured out how to make the sphere access - "major," minor" etc. - case-insensitive. This is good; the "s_xyz" variables will just be copied and pasted by modders from a form we provide, so I can reasonably rely on the case matching what's in the function. But modders will have to fill in the sphere access themselves, risking typos. Making this part case-insensitive will help the code to avoid stumbling over user error.

 

I've very nearly got this going. These new functions are all plugged in, I just need need to do the grunt-work of entering in sphere access and class access for all of the Divine Remix and Frosty Journey kits. (Anyone know of any other popular priest kit mods for which I should include compatibility?)

 

Then, I need to add some code to the item usability section: have it detect whether the kit identifies itself as an acolyte and if so, edit the kit's usability flag entry in kitlist.2da. Basically, it will

- run through kits, identifying cleric kits

- check whether each cleric kit is in our d5_class.2da file

- check whether "c_acolyte = 1"

- find the row of the kit in kitlist.2da* (this is pretty much the only part I'm still iffy on)

- SET_2DA_ENTRY the usability flag

 

Then, I need to cover any kits not already known. Probably add a default sphere access entry to the *base* .2da files, and have the kits use that access. Should be okay with HLAs, because the HLAs are dependent on sphere access, and these kits will all have identical (default) sphere access. Ergo, they can use the same HLA table. :)

 

And then, this puppy is done! And I will hand it off to people with more free time and creativity to make priest kits galore.

Link to comment

Dammit... so close! I need someone with eagle eyes to spot what I'm doing wrong. In the following code (which is to be used in conjunction with the .tpa file Mike uploaded a page back)...

LAM ~READ_FNP_KIT_INFO~
COPY_EXISTING ~kitlist.2da~ ~override~
    COUNT_2DA_ROWS ~9~ "rows"
    FOR ( index = 2 ; index < rows ; index = index + 1 ) BEGIN
        READ_2DA_ENTRY %index% 5 9 kit_clab
        READ_2DA_ENTRY %index% 8 9 class
        DEFINE_ASSOCIATIVE_ARRAY d5_deity_kits BEGIN "%kit_clab%" => "%class%" END
    END
BUT_ONLY
ACTION_PHP_EACH d5_deity_kits AS sam => iam BEGIN
  ACTION_IF (%iam% = 3) BEGIN //.................................................clerics
    ACTION_PHP_EACH d5_fnp_kits AS ind => kit BEGIN
      ACTION_IF (~%kit%~ STRING_EQUAL_CASE ~%sam%~) BEGIN
        ACTION_PHP_EACH d5_fnp_classes AS class => val BEGIN
          ACTION_IF (VARIABLE_IS_SET $d5_fnp_kit_class_access(~%class%~ ~%kit%~)) BEGIN
            OUTER_TEXT_SPRINT access $d5_fnp_kit_class_access(~%class%~ ~%kit%~)
            ACTION_IF (IS_AN_INT access && access == 1) BEGIN
              ACTION_IF (~%class%~ STRING_EQUAL_CASE ~acolyte~) BEGIN
                COPY_EXISTING - ~kitlist.2da~ ~override~
                  COUNT_2DA_COLS num_cols
                  READ_2DA_ENTRIES_NOW ~r2en_kitlist~ 9
                  FOR (row = 1; row < r2en_kitlist; row += 1) BEGIN
                    READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 5 kitclab
                    PATCH_IF (~%kitclab%~ STRING_EQUAL_CASE ~%sam%~) BEGIN
                      SET_2DA_ENTRY %row% 7 9 ~0x04000000~
                      PATCH_PRINT ~%kit% %row%~
                    END
                  END
                BUT_ONLY
              END
            END
          END
        END
      END
    END
  END
END

The PATCH_PRINT line successfully prints the name of each kit identified as an Acolyte, and the correct row of that kit in kitlist.2da. Since that row is obtainable, the "SET_2DA_ENTRY %row% 7 9 ~0x04000000~" patch should work, right? But it doesn't.

 

After an hour of fiddling I turned to Google, and found this issue:

http://gibberlings3.net/forums/index.php?showtopic=27287&page=3

 

So I changed the line to this:

TEXT_SPRINT acolyte_use ~04000000~
SET_2DA_ENTRY row 7 9 ~0x%acolyte_use%~

...but that doesn't work either.

 

Tearing my hair out here...

 

EDIT - since we're using the priest of Lathander usability flag, I decided to READ_2DA_ENTRY it so that I would have the value in the same format. So:

       ACTION_IF (~%class%~ STRING_EQUAL_CASE ~acolyte~) BEGIN
         COPY_EXISTING - ~kitlist.2da~ ~override~
           READ_2DA_ENTRY 22 7 9 ~usability~
           READ_2DA_ENTRIES_NOW ~r2en_kitlist~ 9
           FOR (row = 1; row < r2en_kitlist; row += 1) BEGIN
             READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 5 kitclab
             PATCH_IF (~%kitclab%~ STRING_EQUAL_CASE ~%sam%~) BEGIN
               SET_2DA_ENTRY %row% 7 9 ~%usability%~
               PATCH_PRINT ~%kitclab% %row% %usability%~
             END
           END
         BUT_ONLY
       END

Here again, the PATCH_PRINT displays the correct usability code, but the SET_2DA_ENTRY fails to change the file.

 

To quote a wise man: what gives???

Link to comment

My eagle eyes missed this typo in fnp_compat.tpa on line 136:

ACTION_IF (NOT FILE_EXISTS ~%clab_name%.2da~) BEGIN

It should be:

ACTION_IF (NOT FILE_EXISTS_IN_GAME ~%clab_name%.2da~) BEGIN

I also wanted to point out that the code above has a lot of indenting, some of it unnecessary (looping through all kits but then checking if the kit matches a specific value) and it could be simplified:

COPY_EXISTING ~kitlist.2da~ ~override~
  COUNT_2DA_COLS num_cols
  READ_2DA_ENTRIES_NOW ~r2en_kitlist~ 9
  FOR (row = 1; row < r2en_kitlist; row += 1) BEGIN
    READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 5 kit_clab
    READ_2DA_ENTRY_FORMER ~r2en_kitlist~ row 8 class_num
    PATCH_IF (class_num == 3) BEGIN // cleric
      PATCH_IF (VARIABLE_IS_SET $d5_fnp_kit_class_access(~ACOLYTE~ ~%kit_clab%~)) BEGIN
        TEXT_SPRINT access $d5_fnp_kit_class_access(~ACOLYTE~ ~%kit_clab%~)
        PATCH_IF (IS_AN_INT access && access == 1) BEGIN
          TEXT_SPRINT hex ~04000000~
          SET_2DA_ENTRY_LATER ~s2el_kitlist~ row 7 ~0x%hex%~ // usability
          PATCH_PRINT ~%row% %kit_clab% 0x%hex%~
        END
      END
    END
    SET_2DA_ENTRIES_NOW ~s2el_kitlist~ 9
  END
  BUT_ONLY
I understand you probably need to do more than this for each kit, but that could be accomplished with some functions thrown in there. By the way, I'd recommend that if you need to do things repeatedly, like "checking if class A has access to kit B", you could create a function that does that, hiding all of the VARIABLE_IS_SET and related array lookups.
Link to comment

My eagle eyes missed this typo in fnp_compat.tpa on line 136:

 

Erm, I didn't notice because I currently have that warning commented out :devlook: (It was popping up for almost every kit, I think because I have most of my clab files in lower-case, and that warning fires if it doesn't find them in upper-case, so I was getting tons of false positives.)

 

That is indeed nicer code, and will probably save some processor cycles. Should work fine for the item usability (I think I'd have to add an INNER_ACTION to append stuff to acolyte clab tables). But for the spheres and deity-choice sections, I'm not sure - they do a lot of text handling and some other stuff. The deity choice system, especially, relies on moving through an array and SETting block_num = (%block_num% + 1) in each iteration, building a dialogue with a bunch of unique GOTO commands. But, now I understand a bit better how it all works, I'll take a look at streamlining.

 

But apart from streamlining, I think the only thing left to do is figure out the best to give default sphere access to mod kits that have not opted in to our system. That, and integrate Aquadrizzt's code for Shaman spell choice dialogues. After that, assuming it doesn't all fall apart at the seams when people play it, it will be ready to go!

Link to comment

That typo is why the warning would pop up all the time. My test mod was only adding fake kits that didn't have an actual CLAB file in the game, so I didn't notice it wasn't working properly until I tried adding info for the vanilla cleric kits. The warning is there in case the CLAB file is misspelled. It provides a warning instead of failing the installation because if someone wanted to run the function before running ADD_KIT, that would be fine, but the CLAB wouldn't have been copied yet.

Link to comment

More eagle eyes needed! Many moons later, I've discovered created a bug. This is the code in beta 41 of the mod, which patches sphere spells into cleric clab tables perfectly:

 

 

LAM ~READ_FNP_KIT_INFO~
COPY_EXISTING ~kitlist.2da~ ~override~
    COUNT_2DA_ROWS ~9~ "rows"
    FOR ( index = 2 ; index < rows ; index = index + 1 ) BEGIN
        READ_2DA_ENTRY %index% 5 9 clab
        READ_2DA_ENTRY %index% 8 9 class
        DEFINE_ASSOCIATIVE_ARRAY d5_sphere_kits BEGIN "%clab%" => "%class%" END
    END
BUT_ONLY
ACTION_PHP_EACH d5_sphere_kits AS fox => sox BEGIN
  ACTION_IF (%sox% = 3) BEGIN //...................................................clerics
    OUTER_INNER_PATCH ~~ BEGIN
        SNPRINT 6 ~lufox~ ~%fox%~
    END
    COPY ~faiths_and_powers/spheres/hlas/luclxyz.2da~ ~override/lu%lufox%.2da~
    ACTION_PHP_EACH d5_fnp_spheres AS sphere => val BEGIN
      ACTION_IF (VARIABLE_IS_SET $d5_fnp_kit_sphere_access(~%sphere%~ ~%fox%~)) BEGIN
        OUTER_TEXT_SPRINT access $d5_fnp_kit_sphere_access(~%sphere%~ ~%fox%~)
        ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && ~%access%~ STRING_EQUAL_CASE ~FOCUS~) BEGIN
          COPY_EXISTING ~%fox%.2da~ ~override~
            LPM remove_blank_lines
            APPEND_FILE ~faiths_and_powers/spheres/%game%/%sphere%_focus.txt~
          BUT_ONLY
          OUTER_TEXT_SPRINT focus_sphere_list ~%focus_sphere_list% %sphere%~
          COPY_EXISTING ~lu%lufox%.2da~ ~override~
            APPEND_FILE ~faiths_and_powers/spheres/hlas/%sphere%/hlas_%sphere%.txt~
          BUT_ONLY
        END
        ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && ~%access%~ STRING_EQUAL_CASE ~MAJOR~) BEGIN
          COPY_EXISTING ~%fox%.2da~ ~override~
            LPM remove_blank_lines
            APPEND_FILE ~faiths_and_powers/spheres/%game%/%sphere%_major.txt~
          BUT_ONLY
          OUTER_TEXT_SPRINT major_sphere_list ~%major_sphere_list% %sphere%,~
          COPY_EXISTING ~lu%lufox%.2da~ ~override~
            APPEND_FILE ~faiths_and_powers/spheres/hlas/%sphere%/hlas_%sphere%.txt~
          BUT_ONLY
        END
        ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && ~%access%~ STRING_EQUAL_CASE ~MINOR~) BEGIN
          COPY_EXISTING ~%fox%.2da~ ~override~
            LPM remove_blank_lines
            APPEND_FILE ~faiths_and_powers/spheres/%game%/%sphere%_minor.txt~
          BUT_ONLY
          OUTER_TEXT_SPRINT minor_sphere_list ~%minor_sphere_list% %sphere%,~
        END
      END
    END
END

Meanwhile, after making a few additions to add support for multiclass kits in beta 51, this new code adds sphere spells twice to every kit. Basically the three APPEND_FILE commands are being applied twice and I can't figure out why. It's not actually much of a problem in-game - adding the same spell twice to a priest spellbook has no effect - but I want to know why it's wrong.

 

 

LAM ~READ_FNP_KIT_INFO~
  COPY_EXISTING ~kitlist.2da~ ~override~
    COUNT_2DA_ROWS ~9~ "rows"
    FOR ( index = 3 ; index < rows ; index = index + 1 ) BEGIN
        READ_2DA_ENTRY %index% 5 9 clab
        READ_2DA_ENTRY %index% 1 9 name
        READ_2DA_ENTRY %index% 4 9 desc
        READ_2DA_ENTRY %index% 9 9 code
        READ_2DA_ENTRY %index% 8 9 class
        DEFINE_ASSOCIATIVE_ARRAY d5_sphere_kits BEGIN "%clab%" , "%name%" , "%desc%" , "%code%" => "%class%" END
    END
BUT_ONLY
ACTION_PHP_EACH d5_sphere_kits AS fox => sox BEGIN
  ACTION_IF (%sox% = 3 || %sox% = 11 || %sox% = 8 || %sox% = 14 || %sox% = 15 || %sox% = 18) BEGIN //.......clerics
    OUTER_INNER_PATCH ~~ BEGIN
        SNPRINT 6 ~lufox~ ~%fox%~
    END
    COPY ~faiths_and_powers/spheres/hlas/luclxyz.2da~ ~override/lu%lufox%.2da~
    ACTION_IF (%sox% = 11) BEGIN
        COPY ~faiths_and_powers/spheres/hlas/ludrxyz.2da~ ~override/lu%lufox%.2da~
    END
    ACTION_PHP_EACH d5_fnp_spheres AS sphere => val BEGIN
      ACTION_IF (VARIABLE_IS_SET $d5_fnp_kit_sphere_access(~%sphere%~ ~%fox%~)) BEGIN
        OUTER_TEXT_SPRINT access $d5_fnp_kit_sphere_access(~%sphere%~ ~%fox%~)
        ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && ~%access%~ STRING_EQUAL_CASE ~FOCUS~) BEGIN
          COPY_EXISTING ~lu%lufox%.2da~ ~override~
            APPEND_FILE ~faiths_and_powers/spheres/hlas/%sphere%/hlas_%sphere%.txt~
          BUT_ONLY
          COPY_EXISTING ~%fox%.2da~ ~override~
            LPM remove_blank_lines
            APPEND_FILE ~faiths_and_powers/spheres/%game%/%sphere%_focus.txt~
          BUT_ONLY
          OUTER_TEXT_SPRINT focus_sphere_list ~%focus_sphere_list% %sphere%~
        END
        ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && ~%access%~ STRING_EQUAL_CASE ~MAJOR~) BEGIN
          COPY_EXISTING ~lu%lufox%.2da~ ~override~
            APPEND_FILE ~faiths_and_powers/spheres/hlas/%sphere%/hlas_%sphere%.txt~
          BUT_ONLY
          COPY_EXISTING ~%fox%.2da~ ~override~
            LPM remove_blank_lines
            APPEND_FILE ~faiths_and_powers/spheres/%game%/%sphere%_major.txt~
          BUT_ONLY
          OUTER_TEXT_SPRINT major_sphere_list ~%major_sphere_list% %sphere%,~
        END
        ACTION_IF (VARIABLE_IS_SET $d5_fnp_sphere_access(~%access%~) && ~%access%~ STRING_EQUAL_CASE ~MINOR~) BEGIN
          COPY_EXISTING ~%fox%.2da~ ~override~
            LPM remove_blank_lines
            APPEND_FILE ~faiths_and_powers/spheres/%game%/%sphere%_minor.txt~
          BUT_ONLY
          OUTER_TEXT_SPRINT minor_sphere_list ~%minor_sphere_list% %sphere%,~
        END
      END
    END
END

 

And Mike I have a version of this using a straight R2EN and patching of kitlist, but it's not quite working right and it involves craziness like this:

 

COPY
  PATCH_IF
    INNER_ACTION
      COPY
        PATCH_IF
          INNER_ACTION
  ...

I want to set it aside for now and figure out why my current code doesn't work.

Link to comment

Archived

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

×
×
  • Create New...