Author Topic: BUT_ONLY trouble for .dlgs  (Read 12949 times)

Offline Galactygon

  • Modding since 2002
  • Planewalker
  • *****
  • Posts: 378
  • Gender: Male
  • Creator of spells
BUT_ONLY trouble for .dlgs
« on: July 23, 2010, 10:25:16 AM »
I'm new to .dlg files, this is what I have:
Code: [Select]
COPY_EXISTING_REGEXP GLOB ~^.+\.dlg$~ ~override~
  PATCH_IF ( SOURCE_SIZE > 0x33 ) BEGIN
  DECOMPILE_DLG_TO_D
    REPLACE_TEXTUALLY CASE_INSENSITIVE ~StateCheck(Myself,STATE_CHARMED)~ ~OR(2)
    StateCheck(Myself,STATE_CHARMED)
    Global("CHARMED","LOCALS",1)~
  COMPILE_D_TO_DLG
  END
BUT_ONLY_IF_IT_CHANGES
The block executes, but all .dlg files in the game get dumped into the override, and warnings appear "cannot verify action...", "cannot verify trigger...".

-Galactygon

Offline the bigg

  • The Avatar of Fighter / Thieves
  • Moderator
  • Planewalker
  • *****
  • Posts: 3804
  • Gender: Male
Re: BUT_ONLY trouble for .dlgs
« Reply #1 on: July 23, 2010, 11:06:33 AM »
all .dlg files in the game get dumped into the override
That's because most dlg files in the game vary by a byte or so after a DECOMPILE/COMPILE (E.G. because of CR/LF issues). All things considered, a DECOMPILE/RECOMPILE round will leave the file functionally identical, and dumping thousands of .dlg files in the override is a non-issue for Windows users.

Quote
and warnings appear "cannot verify action...", "cannot verify trigger...".
That's because many DLG files have errors in them. Put SILENT before the COPY block and VERBOSE after, it should help.

Also, your code will fail spectacularly if the StateCheck() is negated and/or inside an Or(). Currently, there's no way to do correctly what you're trying to do (at least, no way that would be codeable by a standard-issue human being).
Author or Co-Author: WeiDU (http://j.mp/bLtjOn) - Widescreen (http://j.mp/aKAiqG) - Generalized Biffing (http://j.mp/aVgw3U) - Refinements (http://j.mp/bLHoCc) - TB#Tweaks (http://j.mp/ba02Eg) - IWD2Tweaks (http://j.mp/98OFYY) - TB#Characters (http://j.mp/ak8J55) - Traify Tool (http://j.mp/g1Ry9A) - Some mods that I won't mention in public
Maintainer: Semi-Multi Clerics (http://j.mp/9UeIwB) - Nalia Mod (http://j.mp/dng9l0) - Nvidia Fix (http://j.mp/aRWjjg)
Code dumps: Detect custom secondary types (http://j.mp/hVzzXG) - Stutter Investigator (http://j.mp/gdtBn8)

If possible, send diffs, translations and other contributions using Git (http://j.mp/aBZFrq).

Offline Galactygon

  • Modding since 2002
  • Planewalker
  • *****
  • Posts: 378
  • Gender: Male
  • Creator of spells
Re: BUT_ONLY trouble for .dlgs
« Reply #2 on: July 23, 2010, 11:19:34 AM »
Also, your code will fail spectacularly if the StateCheck() is negated and/or inside an Or(). Currently, there's no way to do correctly what you're trying to do (at least, no way that would be codeable by a standard-issue human being).

So true. What suggestion do you have?

I'd like to have dialogue enabled for charmed creatures. I know there is an .exe fix for this, but I wanted the .cre in Charm person to be uncontrollable, so I mimicked the charm opcode and had it set allegiances and the "CHARMED" variable. And at the same time, I'd like this to be compatible in the likely event that someone installs the .exe patch.

-Galactygon

Offline the bigg

  • The Avatar of Fighter / Thieves
  • Moderator
  • Planewalker
  • *****
  • Posts: 3804
  • Gender: Male
Re: BUT_ONLY trouble for .dlgs
« Reply #3 on: July 23, 2010, 11:27:20 AM »
Well, I have sort-of an idea for the implementation of a REFACTOR_TRIGGER patch, but (having recently started working on my graduation) I don't know if/when I'll actually code it. Good enough for you?   :P
Author or Co-Author: WeiDU (http://j.mp/bLtjOn) - Widescreen (http://j.mp/aKAiqG) - Generalized Biffing (http://j.mp/aVgw3U) - Refinements (http://j.mp/bLHoCc) - TB#Tweaks (http://j.mp/ba02Eg) - IWD2Tweaks (http://j.mp/98OFYY) - TB#Characters (http://j.mp/ak8J55) - Traify Tool (http://j.mp/g1Ry9A) - Some mods that I won't mention in public
Maintainer: Semi-Multi Clerics (http://j.mp/9UeIwB) - Nalia Mod (http://j.mp/dng9l0) - Nvidia Fix (http://j.mp/aRWjjg)
Code dumps: Detect custom secondary types (http://j.mp/hVzzXG) - Stutter Investigator (http://j.mp/gdtBn8)

If possible, send diffs, translations and other contributions using Git (http://j.mp/aBZFrq).

Offline Galactygon

  • Modding since 2002
  • Planewalker
  • *****
  • Posts: 378
  • Gender: Male
  • Creator of spells
Re: BUT_ONLY trouble for .dlgs
« Reply #4 on: July 23, 2010, 11:35:49 AM »
Keep me posted. :)

-Galactygon

Offline Galactygon

  • Modding since 2002
  • Planewalker
  • *****
  • Posts: 378
  • Gender: Male
  • Creator of spells
Re: BUT_ONLY trouble for .dlgs
« Reply #5 on: July 23, 2010, 01:01:49 PM »
Switching to something else, I'm having trouble with APPENDs. After adding sectypes to msectype.2da, I go into some .spl and using a macro that counts the 2da rows of msectype.2da and looks for the appropriate entry.

That does not work, but when I exit the installer and go into some other component, everything works fine. Which means it probabbly has to do with APPEND not updating the rowcount until after the user exits the installer. Subsequent tests with PATCH_PRINT confirm the new rows are not taken into account.

-Galactygon
Code: [Select]
// Adding new sectype for Entangle
APPEND ~MSECTYPE.2da~ ~Entanglement            ENTANGLE~ UNLESS ~Entanglement~
OUTER_SET msectype_array = 1 // This variable tells the macro to recount the rows
COPY_EXISTING ~MSECTYPE.2da~ ~override~
              REPLACE CASE_SENSITIVE ~ENTANGLE~ @600
BUT_ONLY_IF_IT_CHANGES

COPY_EXISTING     ~SPPR105A.spl~ ~override~
  SPRINT msectype_entry "Entanglement"
  LAUNCH_PATCH_MACRO ~GET_MSECTYPE_ENTRY~ // input is msectype_entry, output is msectype_num. msectype_num returns 0 if no entry is found
          WRITE_SHORT 0x27 msectype_num // Sectype is Entanglement/Web
BUT_ONLY_IF_IT_CHANGES

Offline the bigg

  • The Avatar of Fighter / Thieves
  • Moderator
  • Planewalker
  • *****
  • Posts: 3804
  • Gender: Male
Re: BUT_ONLY trouble for .dlgs
« Reply #6 on: July 23, 2010, 01:19:29 PM »
I find that doubtful. Can I see the code to GET_MSECTYPE_ENTRY?
Author or Co-Author: WeiDU (http://j.mp/bLtjOn) - Widescreen (http://j.mp/aKAiqG) - Generalized Biffing (http://j.mp/aVgw3U) - Refinements (http://j.mp/bLHoCc) - TB#Tweaks (http://j.mp/ba02Eg) - IWD2Tweaks (http://j.mp/98OFYY) - TB#Characters (http://j.mp/ak8J55) - Traify Tool (http://j.mp/g1Ry9A) - Some mods that I won't mention in public
Maintainer: Semi-Multi Clerics (http://j.mp/9UeIwB) - Nalia Mod (http://j.mp/dng9l0) - Nvidia Fix (http://j.mp/aRWjjg)
Code dumps: Detect custom secondary types (http://j.mp/hVzzXG) - Stutter Investigator (http://j.mp/gdtBn8)

If possible, send diffs, translations and other contributions using Git (http://j.mp/aBZFrq).

Offline Galactygon

  • Modding since 2002
  • Planewalker
  • *****
  • Posts: 378
  • Gender: Male
  • Creator of spells
Re: BUT_ONLY trouble for .dlgs
« Reply #7 on: July 23, 2010, 01:20:38 PM »
Code: [Select]
DEFINE_PATCH_MACRO ~GET_MSECTYPE_ENTRY~ BEGIN

SET we_are_done = 0
PATCH_IF !( VARIABLE_IS_SET "%msectype_array%" ) BEGIN
                SET msectype_array = 1
END
PATCH_IF ( msectype_array = 1 ) BEGIN
INNER_ACTION BEGIN
COPY_EXISTING ~MSECTYPE.2da~ ~override~
COUNT_2DA_ROWS 2 msectype_rowcount
SET msectype_rowcount -= 1
FOR ( row=1; row<msectype_rowcount; row+=1 ) BEGIN
SET row_inside = row - 1
SET read_msectype_num = row_inside
READ_2DA_ENTRY row 0 2 read_msectype_name
SET $msectype_2da("%row_inside%" "0") = read_msectype_num
SPRINT $msectype_2da("%row_inside%" "1") "%read_msectype_name%"
PATCH_PRINT "%read_msectype_num% %read_msectype_name%"
END
SET msectype_array = 0
BUT_ONLY_IF_IT_CHANGES
END
END
PATCH_IF ( VARIABLE_IS_SET "%msectype_array%" ) BEGIN
SET we_are_looking = 1 // variable used at the end for PATCH_PRINT
// If we are doing the search for the first time, set some variables
PATCH_IF (!( VARIABLE_IS_SET "%msectype_num%" ) OR !( VARIABLE_IS_SET "%msectype_name%" )) BEGIN
SET msectype_num = 0
SPRINT msectype_name ""
SET we_are_looking = 0
END
// The previous search is remembered in msectype_name. If current seatch equals previous search, we skip the search
PATCH_IF (("%msectype_entry%" STRING_COMPARE_CASE "%msectype_name%" = 0) OR ("%msectype_entry%" STRING_COMPARE_CASE "" = 0)) BEGIN
SET we_are_done = 1
END
// start is set to 0 or the last index at the last search (stored in msectype_num)
/*PATCH_IF (VARIABLE_IS_SET "%msectype_num%") THEN BEGIN
SET start = msectype_num
END ELSE BEGIN
SET start = 0
END*/
// msectype_num is updated to the new index, if needed (when we_are_done =0). We loop from msectype_num to the end.
FOR ( row= 0 /*start*/; row<msectype_rowcount - 1 AND we_are_done = 0; row = row + 1 ) BEGIN
SET msectype_num = $msectype_2da("%row%" "0")
SPRINT msectype_name $msectype_2da("%row%" "1")
PATCH_IF ( "%msectype_entry%" STRING_COMPARE_CASE "%msectype_name%" = 0 ) BEGIN
SET we_are_done = 1
END
END
// This is needed if the index we are looking for is before the last index in our last search. We go through the entire array.
/*PATCH_IF ( start!=0 AND we_are_done = 0 ) BEGIN
FOR ( row=0; row<msectype_rowcount - 1 AND we_are_done = 0 AND FILE_EXISTS_IN_GAME "%msectype_file%.pro"; row = row + 1 ) BEGIN
SET msectype_num = $msectype_2da("%row%" "0")
SPRINT msectype_name $msectype_2da("%row%" "1")
PATCH_IF ( "%msectype_entry%" STRING_COMPARE_CASE "%msectype_name%" = 0 ) BEGIN
SET we_are_done = 1
END
END
END*/
PATCH_PRINT "%msectype_num%, %we_are_done%"
// If we didn't find anything, return blank variables
PATCH_IF ( we_are_done = 0 ) BEGIN
SET msectype_num = 0
SPRINT msectype_name ""
END
END

END

-Galactygon

Offline the bigg

  • The Avatar of Fighter / Thieves
  • Moderator
  • Planewalker
  • *****
  • Posts: 3804
  • Gender: Male
Re: BUT_ONLY trouble for .dlgs
« Reply #8 on: July 23, 2010, 01:43:59 PM »
            SET msectype_rowcount -= 1
Appears to work once you remove that line (prints "14, 1" if installed on plain BG2).
Author or Co-Author: WeiDU (http://j.mp/bLtjOn) - Widescreen (http://j.mp/aKAiqG) - Generalized Biffing (http://j.mp/aVgw3U) - Refinements (http://j.mp/bLHoCc) - TB#Tweaks (http://j.mp/ba02Eg) - IWD2Tweaks (http://j.mp/98OFYY) - TB#Characters (http://j.mp/ak8J55) - Traify Tool (http://j.mp/g1Ry9A) - Some mods that I won't mention in public
Maintainer: Semi-Multi Clerics (http://j.mp/9UeIwB) - Nalia Mod (http://j.mp/dng9l0) - Nvidia Fix (http://j.mp/aRWjjg)
Code dumps: Detect custom secondary types (http://j.mp/hVzzXG) - Stutter Investigator (http://j.mp/gdtBn8)

If possible, send diffs, translations and other contributions using Git (http://j.mp/aBZFrq).

Offline Galactygon

  • Modding since 2002
  • Planewalker
  • *****
  • Posts: 378
  • Gender: Male
  • Creator of spells
Re: BUT_ONLY trouble for .dlgs
« Reply #9 on: July 23, 2010, 01:46:15 PM »
I've done that because the header, "2DA V1.0" registers as a line. Does it give the .spl file the proper sectype?

EDIT: It does. I don't know why I wrote that.

Thanks the_bigg.

-Galactygon

Offline Galactygon

  • Modding since 2002
  • Planewalker
  • *****
  • Posts: 378
  • Gender: Male
  • Creator of spells
Re: BUT_ONLY trouble for .dlgs
« Reply #10 on: July 23, 2010, 02:19:30 PM »
Unbelievable. Not only did this one line fix this problem, but all the others as well.

Thanks to you the_bigg, SpellPack B6 will make it a day or two earlier. :)

-Galactygon

Offline the bigg

  • The Avatar of Fighter / Thieves
  • Moderator
  • Planewalker
  • *****
  • Posts: 3804
  • Gender: Male
Re: BUT_ONLY trouble for .dlgs
« Reply #11 on: July 24, 2010, 10:10:13 AM »
REFACTOR_TRIGGER
Done for .baf, .d will follow soon.

Code: [Select]
<<<<<<<< a.baf
IF
OR(2)
InParty("1")
True()
OR(2)
!InParty("2")
True()
InParty("3")
!InParty("4")
OR(3)
InParty("5")
!InParty("6")
True()
THEN
RESPONSE #100
Continue()
END
>>>>>>>>

COPY ~a.baf~ ~a.baf~
REFACTOR_BAF_TRIGGER CASE_SENSITIVE EVALUATE_REGEXP ~InParty(\(\"[0-9]\"\))~ ~OR(2) Dead(\1) !See(\1) Help(\1) !Exists(\1)~
Notes:
  This appears to be criminally slow (about 3x slower than REPLACE_TEXTUALLY on *.bcs my install).
  R_B_T will trash whitespace in the resulting file (while leaving it consistent for compilation purposes).
  The searchregexp must match exactly against a single trigger (E.G. ~InParty(\"Minsc\") InParty(\"Imoen\")~ won't be found even if it is in the file).
  You don't want to look at the resulting file :)
« Last Edit: July 24, 2010, 12:39:40 PM by the bigg »
Author or Co-Author: WeiDU (http://j.mp/bLtjOn) - Widescreen (http://j.mp/aKAiqG) - Generalized Biffing (http://j.mp/aVgw3U) - Refinements (http://j.mp/bLHoCc) - TB#Tweaks (http://j.mp/ba02Eg) - IWD2Tweaks (http://j.mp/98OFYY) - TB#Characters (http://j.mp/ak8J55) - Traify Tool (http://j.mp/g1Ry9A) - Some mods that I won't mention in public
Maintainer: Semi-Multi Clerics (http://j.mp/9UeIwB) - Nalia Mod (http://j.mp/dng9l0) - Nvidia Fix (http://j.mp/aRWjjg)
Code dumps: Detect custom secondary types (http://j.mp/hVzzXG) - Stutter Investigator (http://j.mp/gdtBn8)

If possible, send diffs, translations and other contributions using Git (http://j.mp/aBZFrq).

Offline the bigg

  • The Avatar of Fighter / Thieves
  • Moderator
  • Planewalker
  • *****
  • Posts: 3804
  • Gender: Male
Re: BUT_ONLY trouble for .dlgs
« Reply #12 on: July 24, 2010, 11:39:12 AM »
Also done for .d.

Code: [Select]
<<<<<<<< a.d
BEGIN A
IF ~InParty("1")~ wut
SAY ~wat~
IF ~OR(2) InParty("2") !InParty("3")~ EXIT
END

IF WEIGHT #0 ~InParty("1")~ when
SAY ~wat~
IF ~~ EXIT
END
>>>>>>>>

COPY ~a.d~ ~a.d~
REFACTOR_D_TRIGGER CASE_SENSITIVE EVALUATE_REGEXP ~InParty(\(\"[0-9]\"\))~ ~OR(2) Dead(\1) !See(\1) Help(\1) !Exists(\1)~

Up as beta.
« Last Edit: July 24, 2010, 12:39:15 PM by the bigg »
Author or Co-Author: WeiDU (http://j.mp/bLtjOn) - Widescreen (http://j.mp/aKAiqG) - Generalized Biffing (http://j.mp/aVgw3U) - Refinements (http://j.mp/bLHoCc) - TB#Tweaks (http://j.mp/ba02Eg) - IWD2Tweaks (http://j.mp/98OFYY) - TB#Characters (http://j.mp/ak8J55) - Traify Tool (http://j.mp/g1Ry9A) - Some mods that I won't mention in public
Maintainer: Semi-Multi Clerics (http://j.mp/9UeIwB) - Nalia Mod (http://j.mp/dng9l0) - Nvidia Fix (http://j.mp/aRWjjg)
Code dumps: Detect custom secondary types (http://j.mp/hVzzXG) - Stutter Investigator (http://j.mp/gdtBn8)

If possible, send diffs, translations and other contributions using Git (http://j.mp/aBZFrq).

Offline Galactygon

  • Modding since 2002
  • Planewalker
  • *****
  • Posts: 378
  • Gender: Male
  • Creator of spells
Re: BUT_ONLY trouble for .dlgs
« Reply #13 on: July 26, 2010, 05:38:55 AM »
How can I translate that into my very fancy block? I can't even read regexps.

Switching to something much more trivial, I'm stuck with block I posted below. It's supposed to be reading from a 2da file, and part of the block is supposed to be counting how many rows start with the same column. The counter starts when it spots the first "AND()", and counts until either the number in the AND is reached or when the rows don't match (except at columns 2,4,5).

But the counter miscounts the first 2 ANDs, and continues on until it reaches the next AND. If I go into RACE_IMMUNITY.2da, and change the first instance of "SPWI616.spl" to "SCWI616.spl", STRING_COMPARE_CASE returns as 1, and the block calculates that part correctly. Otherwise, PRINT confirms that STRING_COMPARE_CASE returns to 0 even when comparing "SPWI504.spl" with "SPWI616.spl".

Also, I would like to know how to set variable based on a regexp:
a.) I'd like to set some variable to the value inside the string "AND(xx)".
b.) I'd like to set a variable to xyz if a string contains "OPCODE=[xyz]".

-Galactygon

This is what I have so far:
Code: [Select]
COPY_EXISTING ~RACE_IMMUNITY.2da~ ~override~
              COUNT_2DA_ROWS 11 race_immunity_2da_rowcount
              FOR ( at_row = 0; at_row < race_immunity_2da_rowcount; at_row += 1 ) BEGIN
                            FOR ( at_col = 0; at_col < 11; at_col += 1 ) BEGIN
                                          READ_2DA_ENTRY at_row at_col 11 rr
                                          SPRINT $race_immunity_2da( "%at_row%" "%at_col%" ) "%rr%"
                            END
              END
BUT_ONLY_IF_IT_CHANGES

OUTER_FOR ( at_row = 0; at_row < race_immunity_2da_rowcount; at_row += 1 ) BEGIN
              OUTER_SPRINT read $race_immunity_2da( "%at_row%" "0" )
              ACTION_IF ( "%read%" STRING_MATCHES_REGEXP "AND([1-9])" = 0 ) BEGIN
                            OUTER_SET and_count = 1
                            OUTER_SET done_counting_ands = 0
                            OUTER_FOR ( at_row_plus_two = at_row + 2; at_row_plus_two < race_immunity_2da_rowcount AND done_counting_ands = 0; at_row_plus_two += 1 ) BEGIN
                                          OUTER_SET both_rows_are_the_same = 0
                                          OUTER_SET at_row_plus_one = at_row_plus_two - 1
                                          OUTER_FOR ( at_col = 0; at_col < 11 AND both_rows_are_the_same = 0; at_col += 1 ) BEGIN
                                                        ACTION_IF ( at_col != 2 AND at_col != 4 AND at_col != 5 ) BEGIN
                                                                      OUTER_SPRINT read_two $race_immunity_2da( "%at_row_plus_two%" "%at_col%" )
                                                                      OUTER_SPRINT read_one $race_immunity_2da( "%at_row_plus_one%" "%at_col%" )
                                                                      ACTION_IF at_col = 0 BEGIN
                                                                                    PRINT "Comparing: %read_one%, %read_two%"
                                                                      END
                                                                      ACTION_IF ( "%read_one%" STRING_COMPARE_CASE "%read_two%" = 1 ) BEGIN
                                                                                    OUTER_SET both_rows_are_the_same = 1
                                                                                    PRINT "First two things that don't match: %read_one%, %read_two%"
                                                                      END
                                                                      //ACTION_IF ( both_rows_are_the_same = 1 ) BEGIN
                                                                      //              PRINT "First two things that don't match: %read_one%, %read_two%"
                                                                      //END
                                                        END
                                          END
                                          ACTION_IF ( both_rows_are_the_same = 0 ) BEGIN
                                                        OUTER_SET and_count += 1
                                          END ELSE
                                          BEGIN
                                                        OUTER_SET done_counting_ands = 1
                                          END
                                          OUTER_SPRINT read_one $race_immunity_2da( "%at_row_plus_one%" "0" )
                            END
                            PRINT "Resource: %read_one%, ANDs: %and_count%"
              END
END

RACE_IMMUNITY.2da
Code: [Select]
AND(2)        ****      ****       ****      ****    **** ****         **** **** **** ****
SPWI402.spl   1-50      ****       OPCODE=146_EFFECT=5       RACESIZE      L_G          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI402.spl   1-50      ****       OPCODE=146_EFFECT=5       RACESIZE      L_G          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI504.spl   1-50      ****       OPCODE=146_EFFECT=5       RACESIZE      L_G          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
AND(4)        ****      ****       ****      ****    **** ****         **** **** **** ****
SPWI504.spl   1-5       ****       OPCODE=146_EFFECT=5       RACESIZE      M          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI504.spl   1-5       Y          OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI504.spl   1-5       Y          OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI504.spl   1-5       Y          OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI616.spl   1-50      ****       OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI616.spl   1-50      ****       OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
AND(5)        ****      ****       ****      ****    **** ****         **** **** **** ****
SPWI746.spl   1-20      ****       OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI746.spl   1-20      ****       OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI616.spl   1-50      ****       OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****

Offline Mike1072

  • Planewalker
  • *****
  • Posts: 298
  • Gender: Male
Re: BUT_ONLY trouble for .dlgs
« Reply #14 on: July 26, 2010, 07:20:23 AM »
Code: [Select]
COPY_EXISTING ~race_immunity.2da~ ~override~
  READ_2DA_ENTRIES_NOW ~r2en_race_immunity~ 11
  SET comparing_rows = 0
  FOR (row = 0; row < r2en_race_immunity; row += 1) BEGIN
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 0 entry
    PATCH_PRINT ~Reading row that starts with "%entry%"...~
    PATCH_IF (comparing_rows == 0) BEGIN // haven't found an AND() yet
      SET and_num = 0
      INNER_PATCH ~%entry%~ BEGIN
        REPLACE_EVALUATE ~AND(\([0-9]+\))~ BEGIN // look for AND(x) and extract x
          SET and_num = MATCH1
        END ~AND(%MATCH1%)~
      END
      PATCH_IF (and_num > 1) BEGIN
        PATCH_PRINT ~...and_num set to %and_num%!~
        SET comparing_rows = 1
        SET row += 1
        READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 0 entry
        PATCH_PRINT ~Reading row that starts with "%entry%"...~
        FOR (col = 0; col < 11; col += 1) BEGIN
          READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row col entry
          SPRINT $match(~%col%~) ~%entry%~
        END
        // TODO: stuff here?
       
        SET rows_processed = 1
        PATCH_PRINT ~...processed %rows_processed% of %and_num%~
      END
    END
    ELSE BEGIN // comparing rows
      FOR (col = 0; col < 11; col += 1) BEGIN
        PATCH_IF (col != 2 && col != 4 && col != 5) BEGIN
          SPRINT match $match(~%col%~)
          READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row col entry
          PATCH_IF (NOT (~%entry%~ STRING_EQUAL_CASE ~%match%~)) BEGIN
            SET comparing_rows = 0
          END
        END
      END
     
      PATCH_IF (comparing_rows == 1) BEGIN // row matched
        // TODO: stuff here?
       
        SET rows_processed += 1
        PATCH_PRINT ~...processed %rows_processed% of %and_num%~
        PATCH_IF (rows_processed == and_num) BEGIN
          SET comparing_rows = 0
          PATCH_PRINT ~...done processing!~
        END
      END
      ELSE BEGIN       
        PATCH_PRINT ~...row doesn't match, aborting!~
      END
    END
  END
  BUT_ONLY
Rewritten from scratch.  Includes debug messages.

a.) I'd like to set some variable to the value inside the string "AND(xx)".
b.) I'd like to set a variable to xyz if a string contains "OPCODE=[xyz]".
The first is done in the code above, the second can be done the same way.  You use a regexp to catch what you want with REPLACE_EVALUATE.  Each part of the regexp enclosed in \(...\) will be stored in a variable: MATCH1 will contain the contents of the first bracket pair, MATCH2 will have the contents of the second, and so on.

If you had a variable "entry" with the value OPCODE=146, you could extract the 146 and store it in the variable "opcode" with this:
Code: [Select]
INNER_PATCH ~%entry%~ BEGIN
  REPLACE_EVALUATE ~OPCODE=\([0-9]+\)~ BEGIN
    SET opcode = MATCH1
  END ~OPCODE=%MATCH1%~
END

Offline the bigg

  • The Avatar of Fighter / Thieves
  • Moderator
  • Planewalker
  • *****
  • Posts: 3804
  • Gender: Male
Re: BUT_ONLY trouble for .dlgs
« Reply #15 on: July 26, 2010, 08:30:46 AM »
How can I translate that into my very fancy block? I can't even read regexps.

Code: [Select]
COPY_EXISTING_REGEXP GLOB ~^.+\.dlg$~ ~override~
  PATCH_IF ( SOURCE_SIZE > 0x33 ) BEGIN
  DECOMPILE_DLG_TO_D
    REFACTOR_D_TRIGGER CASE_INSENSITIVE EXACT_MATCH ~StateCheck(Myself,STATE_CHARMED)~ ~OR(2)
    StateCheck(Myself,STATE_CHARMED)
    Global("CHARMED","LOCALS",1)~
  COMPILE_D_TO_DLG
  END
IF ~StateCheck.Myself.STATE_CHARMED~
BUT_ONLY_IF_IT_CHANGES
Author or Co-Author: WeiDU (http://j.mp/bLtjOn) - Widescreen (http://j.mp/aKAiqG) - Generalized Biffing (http://j.mp/aVgw3U) - Refinements (http://j.mp/bLHoCc) - TB#Tweaks (http://j.mp/ba02Eg) - IWD2Tweaks (http://j.mp/98OFYY) - TB#Characters (http://j.mp/ak8J55) - Traify Tool (http://j.mp/g1Ry9A) - Some mods that I won't mention in public
Maintainer: Semi-Multi Clerics (http://j.mp/9UeIwB) - Nalia Mod (http://j.mp/dng9l0) - Nvidia Fix (http://j.mp/aRWjjg)
Code dumps: Detect custom secondary types (http://j.mp/hVzzXG) - Stutter Investigator (http://j.mp/gdtBn8)

If possible, send diffs, translations and other contributions using Git (http://j.mp/aBZFrq).

Offline Galactygon

  • Modding since 2002
  • Planewalker
  • *****
  • Posts: 378
  • Gender: Male
  • Creator of spells
Re: BUT_ONLY trouble for .dlgs
« Reply #16 on: July 26, 2010, 05:35:39 PM »
Thanks a bunch for the codes.

The_Bigg: How does that REFRACTOR_D_TRIGGER work? This made me curious.

Mike: I've worked with your code, and I am nearly finished writing the macro, but I am still havig trouble with ANDs. Right now for each line it's supposed to create an array of RACE.IDS entries based on external .2da files (RACESIZE, RACEFLY, etc.), where the specified entries match. For example, if I want to create an array of large- and giant-sized RACE.IDS, I tell the macro to look for any entries that include either the letters "L or G" in the specified .2da file (RACESIZE.2da).

But sometimes, I want to be even more elaborate; say I'd like to discriminate Medium-sized Flying creatures (SPECTRE, WRAITH, MIST, GENIE but not BEHOLDER, WYVERN, etc). This is where the ANDs come in. The code builds an array for each row, and compares the array with the previous row: all values except the ones that appear in both arrays are set to -1. At the very end, the code reorders and rids the array from all -1's.

Unfortunately, the ANDs don't work out. When I look for Medium-sized flying creatures for SPWI504.spl, it returns large-sized flying creature RACE.IDS entries 118-WYVERN, and 123-BEHOLDER (probably has to do with reading an earlier row). Also, if I delete the first line of RACE_IMMUNITY.2da, the installer fails to install.

-Galactygon

RACE_IMMUNITY.2da
Code: [Select]
SPWI504.spl   1-50      ****       OPCODE=146_EFFECT=5       RACESIZE      L_G          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
AND(2)        ****      ****       ****      ****    **** ****         **** **** **** ****
SPWI402.spl   1-50      ****       OPCODE=146_EFFECT=5       RACESIZE      L_G          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI402.spl   1-50      ****       OPCODE=146_EFFECT=5       RACESIZE      L_G          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
AND(4)        ****      ****       ****      ****    **** ****         **** **** **** ****
SPWI504.spl   1-5       ****       OPCODE=146_EFFECT=5       RACESIZE      M          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI504.spl   1-5       Y          OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI504.spl   1-5       Y          OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI504.spl   1-5       Y          OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI616.spl   1-50      ****       OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI616.spl   1-50      ****       OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****

My code:
Code: [Select]
COPY_EXISTING ~race_immunity.2da~ ~override~
  PATCH_IF !(VARIABLE_IS_SET ~racesize_2da~) BEGIN
    INNER_ACTION BEGIN
      COPY_EXISTING ~RACESIZE.2da~ ~override~
        READ_2DA_ENTRIES_NOW ~racesize_2da~ 2
      BUT_ONLY
    END
  END
  PATCH_IF !(VARIABLE_IS_SET ~racefly_2da~) BEGIN
    INNER_ACTION BEGIN
      COPY_EXISTING ~RACEFLY.2da~ ~override~
        READ_2DA_ENTRIES_NOW ~racefly_2da~ 2
      BUT_ONLY
    END
  END
  READ_2DA_ENTRIES_NOW ~r2en_race_immunity~ 11
  SET comparing_rows = 0
  FOR (row = 0; row < r2en_race_immunity; row += 1) BEGIN
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 0 entry
    PATCH_PRINT ~Reading row that starts with "%entry%"...~
    PATCH_IF (comparing_rows == 0) BEGIN // haven't found an AND() yet
      SET and_num = 0
      INNER_PATCH ~%entry%~ BEGIN
        REPLACE_EVALUATE ~AND(\([0-9]+\))~ BEGIN // look for AND(x) and extract x
          SET and_num = MATCH1
        END ~AND(%MATCH1%)~
      END

      //\\ This is where we read all the stuff
      READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 0 to_edit_spell_file

      READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 1 to_edit_extended_headers
      INNER_PATCH ~%to_edit_extended_headers%~ BEGIN
        REPLACE_EVALUATE ~\([0-9]+\)-~ BEGIN
          SET to_edit_first_extended_header = MATCH1
        END ~%MATCH1%-~
      END
      INNER_PATCH ~%to_edit_extended_headers%~ BEGIN
        REPLACE_EVALUATE ~-\([0-9]+\)~ BEGIN
          SET to_edit_last_extended_header = MATCH1
        END ~-%MATCH1%~
      END

      READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 2 to_protect_from_itself

      // This happens when we've encountered a new row outside an AND() or the first row inside and AND()
      READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 3 to_start_where
      SET opcode_to_start_at = 0 - 1
      SET effect_to_start_at = 0 - 1
      INNER_PATCH ~%to_start_where%~ BEGIN
        REPLACE_EVALUATE ~OPCODE=\([0-9]+\)~ BEGIN
          SET opcode_to_start_at = MATCH1
        END ~OPCODE=%MATCH1%~
      END
      INNER_PATCH ~%to_start_where%~ BEGIN
        REPLACE_EVALUATE ~EFFECT=\([0-9]+\)~ BEGIN
          SET effect_to_start_at = MATCH1
        END ~EFFECT=%MATCH1%~
      END

      READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 4 to_use_which_2da

      READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 5 to_use_which_entries

      PATCH_IF (~%to_use_which_2da%~ STRING_EQUAL_CASE ~RACESIZE~) BEGIN
        SET used_racesize_entries_rows = 0
        SET used_entries_rows = 0
        FOR (racesize_row = 0; racesize_row < racesize_2da; racesize_row += 1) BEGIN
          READ_2DA_ENTRY_FORMER ~racesize_2da~ racesize_row 0 num
          READ_2DA_ENTRY_FORMER ~racesize_2da~ racesize_row 1 name
          PATCH_IF ( "%to_use_which_entries%" STRING_MATCHES_REGEXP ".*%num%.*" = 0 OR "%to_use_which_entries%" STRING_MATCHES_REGEXP ".*%name%.*" = 0 ) BEGIN
            //SET $used_racesize_entries( "%used_racesize_entries_rows%" ) = num
            SET $used_entries( "%used_entries_rows%" ) = num
            //SET used_racesize_entries_rows += 1
            SET used_entries_rows += 1
          END
        END
      END
      PATCH_IF (~%to_use_which_2da%~ STRING_EQUAL_CASE ~RACEFLY~) BEGIN
        SET used_racefly_entries_rows = 0
        SET used_entries_rows = 0
        FOR (racefly_row = 0; racefly_row < racefly_2da; racefly_row += 1) BEGIN
          READ_2DA_ENTRY_FORMER ~racefly_2da~ racefly_row 0 num
          READ_2DA_ENTRY_FORMER ~racefly_2da~ racefly_row 1 name
          PATCH_IF ( "%to_use_which_entries%" STRING_MATCHES_REGEXP ".*%num%.*" = 0 OR "%to_use_which_entries%" STRING_MATCHES_REGEXP ".*%name%.*" = 0 ) BEGIN
            //SET $used_racefly_entries( "%used_racefly_entries_rows%" ) = num
            SET $used_entries( "%used_entries_rows%" ) = num
            //SET used_racefly_entries_rows += 1
            SET used_entries_rows += 1
          END
        END
      END

      PATCH_IF (and_num > 1) BEGIN // If we are inside an AND
        PATCH_PRINT ~...and_num set to %and_num%!~
        SET comparing_rows = 1
        SET row += 1
        READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 0 entry
        PATCH_PRINT ~Reading row that starts with "%entry%"...~
        FOR (col = 0; col < 11; col += 1) BEGIN
          READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row col entry
          SPRINT $match(~%col%~) ~%entry%~
        END

        SET rows_processed = 1
        PATCH_PRINT ~...processed %rows_processed% of %and_num%~
      END // If we are inside an AND
      ELSE BEGIN // If we are not inside an AND

          SET used_entries_rows_final = used_entries_rows
          FOR ( c = 0; c < used_entries_rows_final; c += 1) BEGIN
            SET f = $used_entries( "%c%" )
            PATCH_PRINT "Uses RACE.IDS entry: %f%"
          END

        // This is where we do da real macro work
        PATCH_PRINT "We are not inside an AND."
      END

    END // If we haven't found an AND yet, or just found one.
    ELSE BEGIN // If we found an AND, and we are already inside. We need to compare rows
      FOR (col = 0; col < 11; col += 1) BEGIN
        PATCH_IF (col != 2 && col != 4 && col != 5) BEGIN
          SPRINT match $match(~%col%~)
          READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row col entry
          PATCH_IF (NOT (~%entry%~ STRING_EQUAL_CASE ~%match%~)) BEGIN
            SET comparing_rows = 0
          END
        END
      END

      PATCH_IF (comparing_rows == 1) BEGIN // If the stuff here is valid - happens if rows match accordingly

        READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 4 to_use_which_2da
        READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 5 to_use_which_entries

        PATCH_IF (~%to_use_which_2da%~ STRING_EQUAL_CASE ~RACESIZE~) BEGIN
          SET used_entries2_rows = 0
          FOR (racesize_row = 0; racesize_row < racesize_2da; racesize_row += 1) BEGIN
            READ_2DA_ENTRY_FORMER ~racesize_2da~ racesize_row 0 num
            READ_2DA_ENTRY_FORMER ~racesize_2da~ racesize_row 1 name
            PATCH_IF ( "%to_use_which_entries%" STRING_MATCHES_REGEXP ".*%num%.*" = 0 OR "%to_use_which_entries%" STRING_MATCHES_REGEXP ".*%name%.*" = 0 ) BEGIN
              SET $used_entries2( "%used_entries2_rows%" ) = num
              SET used_entries2_rows += 1
            END
          END
        END
        PATCH_IF (~%to_use_which_2da%~ STRING_EQUAL_CASE ~RACEFLY~) BEGIN
          SET used_entries2_rows = 0
          FOR (racefly_row = 0; racefly_row < racefly_2da; racefly_row += 1) BEGIN
            READ_2DA_ENTRY_FORMER ~racefly_2da~ racefly_row 0 num
            READ_2DA_ENTRY_FORMER ~racefly_2da~ racefly_row 1 name
            PATCH_IF ( "%to_use_which_entries%" STRING_MATCHES_REGEXP ".*%num%.*" = 0 OR "%to_use_which_entries%" STRING_MATCHES_REGEXP ".*%name%.*" = 0 ) BEGIN
              SET $used_entries2( "%used_entries2_rows%" ) = num
              SET used_entries2_rows += 1
            END
          END
        END
        // We compare this one with the previous one
        FOR ( a = 0; a < used_entries_rows; a += 1 ) BEGIN
          SPRINT aa $used_entries( "%a%" )
          SET aa_equals_ba = 1
          FOR ( b = 0; b < used_entries2_rows; b += 1 ) BEGIN
            SET ba = $used_entries2( "%b%" )
            PATCH_IF ( aa = ba ) BEGIN
              SET aa_equals_ba = 0
            END
          END
          PATCH_IF ( aa_equals_ba = 1 ) BEGIN
            SET $used_entries( "%a%" ) = 0 - 1
          END
        END

        SET rows_processed += 1
        PATCH_PRINT ~...processed %rows_processed% of %and_num%~
       
        PATCH_IF (rows_processed == and_num) BEGIN // If we finished all the processing

          PATCH_PRINT "Done!"
          // This part compresses the array $used_entries, so there are no -1s at the beginning.
          SET b = 0
          FOR ( a = 0; a < used_entries_rows AND b < used_entries_rows; a += 1 ) BEGIN
            SET a_set_to_b = 0
            PATCH_IF ( $used_entries( "%a%" ) = 0 - 1 ) BEGIN
              FOR ( b = a; b < used_entries_rows AND $used_entries( "%a%" ) = 0 - 1; b += 1 ) BEGIN
                PATCH_IF ( $used_entries( "%b%" ) != 0 - 1 ) BEGIN
                  SET $used_entries( "%a%" ) = $used_entries( "%b%" )
                  SET $used_entries( "%b%" ) = 0 - 1
                  SET a_set_to_b = 1
                END
              END
            END
            SET used_entries_rows_final = a
          END
          FOR ( c = 0; c < used_entries_rows_final; c += 1) BEGIN
            SET f = $used_entries( "%c%" )
            PATCH_PRINT "Uses RACE.IDS entry: %f%"
          END

          // This is where we do the real macro work with the spell files
          // But first we need to reduce $used_entries() to eliminate all the -1's
          SET comparing_rows = 0
        END
      END
      ELSE BEGIN
        PATCH_PRINT ~...row doesn't match, aborting!~
      END
    END
  END
  BUT_ONLY

I've also attached RACESIZE.2da and RACEFLY.2da:

RACESIZE.2da
Code: [Select]
2DA V1.0
0
           Size       
1          M         
2          M         
3          M         
4          S         
5          S         
6          S         
7          M         
101        L
102        L         
103        M         
104        M         
105        S         
106        M         
107        M         
108        M         
109        S         
110        M         
111        M         
112        S         
113        M         
114        M         
115        M         
116        M         
117        M         
118        L         
119        M         
120        M         
121        L         
122        M         
123        L
124        M         
125        M         
126        M         
127        L         
128        M         
129        M         
130        M         
131        M
132        M         
133        M
134        M         
135        M         
136        M         
137        S         
138        S         
139        S
140        M         
141        S         
142        G
143        M         
144        L
145        M
146        G         
147        M         
148        M
149        M         
150        M         
151        S         
152        M         
153        M         
154        M         
155        M         
156        L         
157        L         
158        L         
159        L
201        M         
202        M         
203        M
204        M         
205        M         
206        M         
207        M         
208        M         
209        M
210        M         
211        M         
212        M         
213        M         
214        M         
215        M         
255        M         

RACEFLY.2da:
Code: [Select]
2DA V1.0
0
           Does_it_fly       
1          N         
2          N         
3          N         
4          N         
5          N         
6          N         
7          N         
101        N         
102        N         
103        N
104        N         
105        N         
106        N         
107        N         
108        N         
109        N         
110        N         
111        N         
112        N         
113        N         
114        N
115        N         
116        N         
117        N
118        Y         
119        N         
120        N         
121        N         
122        N         
123        Y         
124        N         
125        N         
126        N         
127        N         
128        N         
129        N         
130        N         
131        N         
132        N         
133        Y
134        Y         
135        N
136        Y         
137        N         
138        N
139        Y         
140        N         
141        Y
142        N         
143        N         
144        N         
145        N         
146        N         
147        Y         
148        N         
149        N         
150        N         
151        N         
152        N         
153        N         
154        N         
155        Y         
156        N         
157        N         
158        N         
159        N         
201        N         
202        N         
203        N         
204        N         
205        N         
206        N         
207        N         
208        N         
209        N         
210        N         
211        N         
212        N         
213        N         
214        N         
215        N         
255        N         

Offline the bigg

  • The Avatar of Fighter / Thieves
  • Moderator
  • Planewalker
  • *****
  • Posts: 3804
  • Gender: Male
Re: BUT_ONLY trouble for .dlgs
« Reply #17 on: July 26, 2010, 06:05:52 PM »
The_Bigg: How does that REFRACTOR_D_TRIGGER work? This made me curious.
This is a good place to start reading on the theory behind it. The gist of it is that (valid) BAF triggers are expressed in a (non-canonical, non-minimal) Product of Sum form, and Boolean theory states that an arbitrarily complex Boolean expression can, in fact, always be reduced to a PoS form. Once that is done, it's just a (comparatively trivial) matter of reading the triggers, doing the substitution, calling the PoS algorithm, ad saving.

WeiDU does the PoS transformation via lots of patch work and duct tape (the brute force algorithm won't work because of SCSII, and I'm not smart enough to think and code a 'nice' algorithm). If you're bored and/or know OCaml and/or can read unknown languages comfortably, this is the file where the PoS transformation is done (start from the refactor function).
« Last Edit: July 26, 2010, 06:13:21 PM by the bigg »
Author or Co-Author: WeiDU (http://j.mp/bLtjOn) - Widescreen (http://j.mp/aKAiqG) - Generalized Biffing (http://j.mp/aVgw3U) - Refinements (http://j.mp/bLHoCc) - TB#Tweaks (http://j.mp/ba02Eg) - IWD2Tweaks (http://j.mp/98OFYY) - TB#Characters (http://j.mp/ak8J55) - Traify Tool (http://j.mp/g1Ry9A) - Some mods that I won't mention in public
Maintainer: Semi-Multi Clerics (http://j.mp/9UeIwB) - Nalia Mod (http://j.mp/dng9l0) - Nvidia Fix (http://j.mp/aRWjjg)
Code dumps: Detect custom secondary types (http://j.mp/hVzzXG) - Stutter Investigator (http://j.mp/gdtBn8)

If possible, send diffs, translations and other contributions using Git (http://j.mp/aBZFrq).

Offline Mike1072

  • Planewalker
  • *****
  • Posts: 298
  • Gender: Male
Re: BUT_ONLY trouble for .dlgs
« Reply #18 on: July 27, 2010, 12:59:58 AM »
Mike: I've worked with your code, and I am nearly finished writing the macro, but I am still havig trouble with ANDs. Right now for each line it's supposed to create an array of RACE.IDS entries based on external .2da files (RACESIZE, RACEFLY, etc.), where the specified entries match. For example, if I want to create an array of large- and giant-sized RACE.IDS, I tell the macro to look for any entries that include either the letters "L or G" in the specified .2da file (RACESIZE.2da).

But sometimes, I want to be even more elaborate; say I'd like to discriminate Medium-sized Flying creatures (SPECTRE, WRAITH, MIST, GENIE but not BEHOLDER, WYVERN, etc). This is where the ANDs come in. The code builds an array for each row, and compares the array with the previous row: all values except the ones that appear in both arrays are set to -1. At the very end, the code reorders and rids the array from all -1's.

Unfortunately, the ANDs don't work out. When I look for Medium-sized flying creatures for SPWI504.spl, it returns large-sized flying creature RACE.IDS entries 118-WYVERN, and 123-BEHOLDER (probably has to do with reading an earlier row). Also, if I delete the first line of RACE_IMMUNITY.2da, the installer fails to install.
Looking at the modified code, I can see where some problems might be in places where the comments don't match what's actually happening.

It would help if you could explain more about what the goal of all this code is.  The information dealing with compressing the array is confusing and might be irrelevant if the problem is dealt with in a different way.

First, what precisely do you want to do when you encounter a single row (no ANDs involved)?

Second, what should be done differently when multiple rows are ANDed together?  (I don't understand why some of the rows are identical, unless the race_immunity.2da provided above is just a dummy version of the file.)

Third, are racesize.2da and racefly.2da used in-game with your mod?  If not, there is an easier way to store this kind of information.

Offline Galactygon

  • Modding since 2002
  • Planewalker
  • *****
  • Posts: 378
  • Gender: Male
  • Creator of spells
Re: BUT_ONLY trouble for .dlgs
« Reply #19 on: July 27, 2010, 01:52:31 AM »
First, what precisely do you want to do when you encounter a single row (no ANDs involved)?
I'd like to store RACE.IDS entries in the array $used_entries( ), and print them. This happens for each row.

Second, what should be done differently when multiple rows are ANDed together?  (I don't understand why some of the rows are identical, unless the race_immunity.2da provided above is just a dummy version of the file.)
When the ANDS happen, the code builds an array of $used_entries( ) for the first line inside the AND. After that, it proceeds to the next line, comparing it with the previous line. When that happened, and next line is valid (comparing rows == 1), the code goes on to generate another array $used_entries2( ) based on the line it's at. Then it compares the two arrays for matching RACE.IDS entries. Any entry that is not in both arrays is set to -1 in array $used_entries( ).

At the very end, when the AND has run its course, the code goes into compressing the array so that the first entries give all the non -1 values, with the -1 values being shunted to the end. I did this so I can later go through with a simple loop when I add effects to the extended header.

The race_immunity.2da right now is purely a fooling-around version, with many erroneous duplicates. The code should be able to deal with those. What's relevant right now are the first two entries after the AND(2) that start with "SPWI504.spl". The AND(4) is supposed to be gathering a list of entries that appear as "M" in RACESIZE.2da, and "Y" in RACEFLY.2da. Which are medium-sized flying creatures.

Third, are racesize.2da and racefly.2da used in-game with your mod?  If not, there is an easier way to store this kind of information.
I invented them, so they are not used by anything except me. I use them for multiple components of SpellPack. They are supposed to be easily editable and patchable in case some other mod start adding RACE.IDS entries.

-Galactygon

Offline Mike1072

  • Planewalker
  • *****
  • Posts: 298
  • Gender: Male
Re: BUT_ONLY trouble for .dlgs
« Reply #20 on: July 27, 2010, 07:35:21 AM »
Okay, I understand you better now.  I rewrote my initial code because it was suboptimal for this task.  In each iteration of the FOR loop, the code will now either go through one independent line, or all of the lines associated with an AND line.

Differences from your code:

Instead of comparing arrays to determine if a race matches multiple criteria in an AND, each race is now given a flag to indicate if it is valid or not.  The flag is changed to invalid if the race doesn't match the criteria of a row.  When all rows have been checked, a loop iterates over all of the races, and if a race is valid at this point, it has matched all of the criteria.

The .2da files have been swapped for associative arrays.  They should be easy to patch with REPLACE_TEXTUALLY if someone needs to edit them.  Store these in one of your mod's folders:

racesize.tpa
Code: [Select]
ACTION_DEFINE_ASSOCIATIVE_ARRAY ~racesize~ BEGIN
  1   => M
  2   => M
  3   => M
  4   => S
  5   => S
  6   => S
  7   => M
  101 => L
  102 => L
  103 => M
  104 => M
  105 => S
  106 => M
  107 => M
  108 => M
  109 => S
  110 => M
  111 => M
  112 => S
  113 => M
  114 => M
  115 => M
  116 => M
  117 => M
  118 => L
  119 => M
  120 => M
  121 => L
  122 => M
  123 => L
  124 => M
  125 => M
  126 => M
  127 => L
  128 => M
  129 => M
  130 => M
  131 => M
  132 => M
  133 => M
  134 => M
  135 => M
  136 => M
  137 => S
  138 => S
  139 => S
  140 => M
  141 => S
  142 => G
  143 => M
  144 => L
  145 => M
  146 => G
  147 => M
  148 => M
  149 => M
  150 => M
  151 => S
  152 => M
  153 => M
  154 => M
  155 => M
  156 => L
  157 => L
  158 => L
  159 => L
  201 => M
  202 => M
  203 => M
  204 => M
  205 => M
  206 => M
  207 => M
  208 => M
  209 => M
  210 => M
  211 => M
  212 => M
  213 => M
  214 => M
  215 => M
  255 => M
END

racefly.tpa
Code: [Select]
ACTION_DEFINE_ASSOCIATIVE_ARRAY ~racefly~ BEGIN
  1   => N
  2   => N
  3   => N
  4   => N
  5   => N
  6   => N
  7   => N
  101 => N
  102 => N
  103 => N
  104 => N
  105 => N
  106 => N
  107 => N
  108 => N
  109 => N
  110 => N
  111 => N
  112 => N
  113 => N
  114 => N
  115 => N
  116 => N
  117 => N
  118 => Y
  119 => N
  120 => N
  121 => N
  122 => N
  123 => Y
  124 => N
  125 => N
  126 => N
  127 => N
  128 => N
  129 => N
  130 => N
  131 => N
  132 => N
  133 => Y
  134 => Y
  135 => N
  136 => Y
  137 => N
  138 => N
  139 => Y
  140 => N
  141 => Y
  142 => N
  143 => N
  144 => N
  145 => N
  146 => N
  147 => Y
  148 => N
  149 => N
  150 => N
  151 => N
  152 => N
  153 => N
  154 => N
  155 => Y
  156 => N
  157 => N
  158 => N
  159 => N
  201 => N
  202 => N
  203 => N
  204 => N
  205 => N
  206 => N
  207 => N
  208 => N
  209 => N
  210 => N
  211 => N
  212 => N
  213 => N
  214 => N
  215 => N
  255 => N
END
Then, after you INCLUDE the files, you can get the size of a race by checking the variable $racesize(~x~), or the airborne status of a race by checking $racefly(~x~).

Now, here's the code:
Code: [Select]
INCLUDE ~your_mod/racesize.tpa~
INCLUDE ~your_mod/racefly.tpa~

COPY_EXISTING ~race_immunity.2da~ ~override~
  READ_2DA_ENTRIES_NOW ~r2en_race_immunity~ 11
  FOR (row = 0; row < r2en_race_immunity; row += 1) BEGIN
    SET and_num = 0
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 0 entry
    INNER_PATCH ~%entry%~ BEGIN
      REPLACE_EVALUATE ~AND(\([0-9]+\))~ BEGIN // look for AND(x) and extract x
        SET and_num = MATCH1
      END ~AND(%MATCH1%)~
    END
    PATCH_IF (and_num > 1) BEGIN // if we just read an AND
      SET row += 1 // skip ahead to the first real line
      SET and_num -= 1 // decrement the number of rows remaining to be ANDed
    END
   
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 0 entry
    PATCH_PRINT ~Reading row that starts with "%entry%"...~
   
    // read the first row
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 4 race_info
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 5 which_types
    SET num_races = 0
    PATCH_IF (~%race_info%~ STRING_EQUAL_CASE ~RACESIZE~ || ~%race_info%~ STRING_EQUAL_CASE ~RACEFLY~) BEGIN
      TO_LOWER race_info
      PHP_EACH ~%race_info%~ AS ~race~ => ~info~ BEGIN // for each race
        SET $valid(~%race%~) = 0
        INNER_PATCH ~_%which_types%~ BEGIN
          REPLACE_EVALUATE ~_\([^_]+\)~ BEGIN // for each type specified (e.g. for L and G if which_types is L_G)
            // find if race matches specifications
            PATCH_IF (~%info%~ STRING_EQUAL_CASE ~%MATCH1%~) BEGIN // race matches specifications
              SET $valid(~%race%~) = 1
            END
          END ~_%MATCH1%~
        END
        // keep track of races
        SET $racelist(~%num_races%~) = race
        SET num_races += 1
      END
    END
   
    // if the first row was part of an AND, continue reading the rest of the rows
    SET rows_match = 1
    WHILE (and_num > 0 && rows_match == 1) BEGIN // continue filtering race list until rows no longer match or we read the specified number of rows
      SET row += 1
      SET and_num -= 1
     
      FOR (col = 0; col < 11; col += 1) BEGIN
        PATCH_IF (col != 2 && col != 4 && col != 5) BEGIN
          READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ (row - 1) col previous
          READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row col current
          PATCH_IF (NOT (~%current%~ STRING_EQUAL_CASE ~%previous%~)) BEGIN
            SET rows_match = 0
          END
        END
      END
     
      PATCH_IF (rows_match == 1) BEGIN
        READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 4 race_info
        READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 5 which_types
       
        PATCH_IF (~%race_info%~ STRING_EQUAL_CASE ~RACESIZE~ || ~%race_info%~ STRING_EQUAL_CASE ~RACEFLY~) BEGIN
          TO_LOWER race_info
          PHP_EACH ~%race_info%~ AS ~race~ => ~info~ BEGIN // for each race
            PATCH_IF (VARIABLE_IS_SET $valid(~%race%~)) BEGIN
              SET valid = 0
              INNER_PATCH ~_%which_types%~ BEGIN
                REPLACE_EVALUATE ~_\([^_]+\)~ BEGIN // for each type specified (e.g. for L and G if which_types is L_G)
                  PATCH_IF (~%info%~ STRING_EQUAL_CASE ~%MATCH1%~) BEGIN // race matches specifications
                    SET valid = 1
                  END
                END ~_%MATCH1%~
              END
              SET prev_valid = $valid(~%race%~)
              SET $valid(~%race%~) = prev_valid BAND valid // race is only valid if it meets all specifications
            END
          END
        END
      END ELSE BEGIN // row didn't match
        SET row -= 1 // redo this row separately in the next iteration of the FOR loop
      END
    END
   
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 0 to_edit_spell_file
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 1 to_edit_extended_headers
    INNER_PATCH ~%to_edit_extended_headers%~ BEGIN
      REPLACE_EVALUATE ~\([0-9]+\)-\([0-9]+\)~ BEGIN
        SET to_edit_first_extended_header = MATCH1
        SET to_edit_last_extended_header = MATCH2
      END ~%MATCH1%-%MATCH2%~
    END
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 2 to_protect_from_itself
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 3 to_start_where
    SET opcode_to_start_at = 0 - 1
    SET effect_to_start_at = 0 - 1
    INNER_PATCH ~%to_start_where%~ BEGIN
      REPLACE_EVALUATE ~OPCODE=\([0-9]+\)~ BEGIN
        SET opcode_to_start_at = MATCH1
      END ~OPCODE=%MATCH1%~
      REPLACE_EVALUATE ~EFFECT=\([0-9]+\)~ BEGIN
        SET effect_to_start_at = MATCH1
      END ~EFFECT=%MATCH1%~
    END
   
    FOR (i = 0; i < num_races; i += 1) BEGIN // iterate through races
      SET race = $racelist(~%i%~)
      SET valid = $valid(~%race%~)
      PATCH_IF (valid == 1) BEGIN
        PATCH_PRINT "Uses RACE.IDS entry: %race%"
        // TODO: add to new array for later use?
      END
    END
  END
  BUT_ONLY
« Last Edit: July 27, 2010, 07:44:33 AM by Mike1072 »

Offline Galactygon

  • Modding since 2002
  • Planewalker
  • *****
  • Posts: 378
  • Gender: Male
  • Creator of spells
Re: BUT_ONLY trouble for .dlgs
« Reply #21 on: July 27, 2010, 09:12:20 AM »
Very nice, I made random changes to RACE_IMMUNITY.2da, and the code passed all tests.

I've moved on and added another type of RACE parameters: RACETERRAIN. Unfortunately, the code doesn't work well with RACETERRAIN, and values different than what I was expecting are returned. For SPWI504.spl, I was looking for [ S ]mall creatures that live on the [ L ]and, but returned values like 4 [DWARF], 5 [HALFLING], 6 [GNOME], 139 [MEPHIT], 141 [IMP], some of which are marked as [ N ]=NotAvailable/Varies, [ I ]nner Plane, [ O ]uter Plane.

I've amended all instances of these:
Code: [Select]
PATCH_IF (~%race_info%~ STRING_EQUAL_CASE ~RACESIZE~ || ~%race_info%~ STRING_EQUAL_CASE ~RACEFLY~ || ~%race_info%~ STRING_EQUAL_CASE ~RACETERRAIN~) BEGIN

And added this to the code:

Code: [Select]
// This determines what the native terrain is for races (from RACE.IDS). Some spells and effects are patched according to this 2da table, so they affect creatures based on their native terrain.
// The following letters mean different native terrains: N[one], A[stral plane], F[orest], I[nner-planar], L[and], O[uter-planar] S[ubterranian], U[nderwater]
ACTION_DEFINE_ASSOCIATIVE_ARRAY ~raceterrain~ BEGIN
  1   => N
  2   => N
  3   => N
  4   => N
  5   => N
  6   => N
  7   => N
  101 => L
  102 => L
  103 => L
  104 => S
  105 => L
  106 => N
  107 => F
  108 => L
  109 => F
  110 => L
  111 => N
  112 => N
  113 => L
  115 => N
  116 => F
  117 => F
  118 => F
  119 => S
  120 => F
  121 => O
  122 => N
  123 => S
  124 => S
  125 => N
  126 => N
  127 => S
  128 => F
  129 => L
  130 => S
  131 => U
  133 => L
  134 => N
  135 => U
  136 => L
  137 => L
  138 => S
  139 => I
  140 => S
  141 => O
  142 => L
  143 => L
  144 => N
  145 => I
  146 => N
  147 => I
  148 => L
  149 => S
  150 => N
  151 => L
  152 => A
  153 => O
  154 => F
  155 => N
  156 => N
  157 => N
  158 => O
  159 => O
  201 => N
  202 => N
  203 => N
  204 => N
  205 => N
  206 => N
  207 => N
  208 => N
  209 => N
  210 => N
  211 => N
  212 => N
  213 => N
  214 => N
  215 => N
  255 => N
END

My RACE_IMMUNITY.2da
Code: [Select]
AND(2)        ****      ****       ****      ****    **** ****         **** **** **** ****
SPWI402.spl   1-50      ****       OPCODE=146_EFFECT=5       RACESIZE      L          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI402.spl   1-50      ****       OPCODE=146_EFFECT=5       RACEFLY       N          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
AND(4)        ****      ****       ****      ****    **** ****         **** **** **** ****
SPWI504.spl   1-5       ****       OPCODE=146_EFFECT=5       RACESIZE      S          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI504.spl   1-5       Y          OPCODE=146_EFFECT=5       RACETERRAIN   L          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI616.spl   1-50      ****       OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI616.spl   1-50      ****       OPCODE=146_EFFECT=5       RACEFLY       Y          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****

Since you're pretty much writing this for me, I might as well post everything I have in mind for this code:

I'd like it to be able to handle other inputs: RACEINTELLECT (tells how smart creatures are in a single character not numbers), RACEMAKE (tells what stuff they are made of), CLASSSIZE, CLASSFLY, CLASSTERRAIN, CLASSINTELLECT, and CLASSMAKE. The CLASSxxx files are the equivalent of RACExxx files; the game makes heavy use of differentiating creatures according to class, and there might be times when I'd like to differentiate those creatures. The only restriction: rows that contain RACExxx and CLASSxxx inside an AND() cannot match. We are either dealing with Races or Classes, they cannot mix. I haven't written any of the CLASS files yet, so feel free to give yourself some dummy class arrays (or duplicate the race arrays).

Also, I'd like the macro to be able to deal with actual .IDS files in the game like this:
Code: [Select]
SPWI402.spl   1-50      ****       OPCODE=146_EFFECT=5       GENERAL      3_UNDEAD_6          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
AND(2)        ****      ****       ****      ****    **** ****         **** **** **** ****
SPWI402.spl   1-50      ****       OPCODE=146_EFFECT=5       RACE           6_KOBOLD_3          RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****
SPWI402.spl   1-50      ****       OPCODE=146_EFFECT=5       RACEFLY      Y_3                      RESOURCE=PROPC206_RESISTTYPE=3    ****            ****            ****            ****

The first row would look into the actual GENERAL.IDS and return the entry values based on the next column: It would return values 3 [DEAD], 4 [UNDEAD], and 6 [FROZEN]. I mixed numbers and strings in the input column on purpose, ideally, the code would take both.

The third row (counting AND() as a row) would return the races 3 [HALF_ELF], 6 [GNOME], and 112 [KOBOLD]. the fourth would return all flying creatures plus 3 [HALF_ELF]. But since they are inside an AND(), and there exist no flying gnomes or kobolds, the array would only return 3 [HALF_ELF].

If there would be support for all the other IDS files (EA, GENDER, SPECIFIC, ALIGNMENT, etc.) that would be awesome. I will not write any more input types (ie EAMAKE, EAINTELLECT, EAFLY) for the other types of IDS files, only for races and classes. If you intend to include more than just races, I request that a variable be set to some INT value for each time the row loops, so I know we are dealing with races, classes, gendertypes, etc.

Many thanks for all your help,
-Galactygon

Offline Mike1072

  • Planewalker
  • *****
  • Posts: 298
  • Gender: Male
Re: BUT_ONLY trouble for .dlgs
« Reply #22 on: July 27, 2010, 03:21:45 PM »
I've moved on and added another type of RACE parameters: RACETERRAIN. Unfortunately, the code doesn't work well with RACETERRAIN, and values different than what I was expecting are returned. For SPWI504.spl, I was looking for [ S ]mall creatures that live on the [ L ]and, but returned values like 4 [DWARF], 5 [HALFLING], 6 [GNOME], 139 [MEPHIT], 141 [IMP], some of which are marked as [ N ]=NotAvailable/Varies, [ I ]nner Plane, [ O ]uter Plane.

I've amended all instances of these:
Code: [Select]
PATCH_IF (~%race_info%~ STRING_EQUAL_CASE ~RACESIZE~ || ~%race_info%~ STRING_EQUAL_CASE ~RACEFLY~ || ~%race_info%~ STRING_EQUAL_CASE ~RACETERRAIN~) BEGIN

And added this to the code:
[snip]
That should have worked if you included the new associative array file... no matter, I've updated the code to fit the other requests and it seems to be working.

Quote
If there would be support for all the other IDS files (EA, GENDER, SPECIFIC, ALIGNMENT, etc.) that would be awesome. I will not write any more input types (ie EAMAKE, EAINTELLECT, EAFLY) for the other types of IDS files, only for races and classes. If you intend to include more than just races, I request that a variable be set to some INT value for each time the row loops, so I know we are dealing with races, classes, gendertypes, etc.
IDS files, custom race specifications, and custom class specifications are now supported.  Note that custom race/class specifications must be associated with non-numerical values, because numerical values are treated as specific races/classes.

The variable ids_file identifies which property the entries are associated with.

Here you go:
Code: [Select]
INCLUDE ~your_mod/racesize.tpa~
INCLUDE ~your_mod/racefly.tpa~
INCLUDE ~your_mod/raceterrain.tpa~

COPY_EXISTING ~race_immunity.2da~ ~override~
  READ_2DA_ENTRIES_NOW ~r2en_race_immunity~ 11
  FOR (row = 0; row < r2en_race_immunity; row += 1) BEGIN
    SET and_num = 0
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 0 entry
    INNER_PATCH ~%entry%~ BEGIN
      REPLACE_EVALUATE ~AND(\([0-9]+\))~ BEGIN // look for AND(x) and extract x
        SET and_num = MATCH1
      END ~AND(%MATCH1%)~
    END
    PATCH_IF (and_num > 1) BEGIN // if we just read an AND
      SET row += 1 // skip ahead to the first real line
      SET and_num -= 1 // decrement the number of rows remaining to be ANDed
    END
   
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 0 entry
    PATCH_PRINT ~Reading row that starts with "%entry%"...~
   
    // read the first row
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 4 restriction_type
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 5 restrictions
   
    SET num_entries = 0
    PATCH_IF (FILE_EXISTS_IN_GAME ~%restriction_type%.ids~) BEGIN // first check to see if there is an IDS file with this name
      INNER_PATCH ~_%restrictions%~ BEGIN
        REPLACE_EVALUATE ~_\([^_]+\)~ BEGIN // for each entry specified (e.g. for 6, KOBOLD, and 3 if restrictions is 6_KOBOLD_3)
          PATCH_IF (IS_AN_INT MATCH1) BEGIN
            SET $valid(~%MATCH1%~) = 1
            SET $used_entries(~%num_entries%~) = MATCH1
            SET num_entries += 1
          END
          ELSE BEGIN // look up int for this symbol (e.g. turns KOBOLD into 112)
            SET entry = IDS_OF_SYMBOL (~%restriction_type%~ ~%MATCH1%~)
            PATCH_IF (entry > 0) BEGIN
              SET $valid(~%entry%~) = 1
              SET $used_entries(~%num_entries%~) = entry
              SET num_entries += 1
            END
          END
        END ~_%MATCH1%~
      END
    END
    // if it's not an actual IDS file, check to see if it's one of our custom RACEFLY/RACESIZE/etc. restrictions
    ELSE PATCH_IF ((~%restriction_type%~ STRING_COMPARE_REGEXP ~RACE.+~) == 1 || (~%restriction_type%~ STRING_COMPARE_REGEXP ~CLASS.+~) == 1) BEGIN
      // loop through the races and add the ones that match the restrictions listed
      TO_LOWER restriction_type
      PHP_EACH ~%restriction_type%~ AS ~identifier~ => ~value~ BEGIN // for each race or class
        SET $valid(~%identifier%~) = 0
        INNER_PATCH ~_%restrictions%~ BEGIN
          REPLACE_EVALUATE ~_\([^_]+\)~ BEGIN // for each valid value specified (e.g. for L and G if restrictions is L_G)
            // find if entry matches specifications
            PATCH_IF (~%value%~ STRING_EQUAL_CASE ~%MATCH1%~) BEGIN
              SET $valid(~%identifier%~) = 1
            END
          END ~_%MATCH1%~
        END
        SET $used_entries(~%num_entries%~) = identifier
        SET num_entries += 1
      END
      // add any additional values that were specified directly in the restrictions (e.g. 3 if restrictions is Y_3)
      INNER_PATCH ~_%restrictions%~ BEGIN
        REPLACE_EVALUATE ~_\([^_]+\)~ BEGIN
          PATCH_IF (IS_AN_INT MATCH1) BEGIN
            SET $valid(~%MATCH1%~) = 1
          END
        END ~_%MATCH1%~
      END
    END
   
    // if the first row was part of an AND, continue reading the rest of the rows
    SET rows_match = 1
    WHILE (and_num > 0 && rows_match == 1) BEGIN // continue filtering race list until rows no longer match or we read the specified number of rows
      SET row += 1
      SET and_num -= 1
     
      FOR (col = 0; col < 11; col += 1) BEGIN
        READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ (row - 1) col previous
        READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row col current
        PATCH_IF (col != 2 && col != 4 && col != 5) BEGIN
          PATCH_IF (NOT (~%current%~ STRING_EQUAL_CASE ~%previous%~)) BEGIN
            SET rows_match = 0
          END
        END
        ELSE PATCH_IF (col == 4) BEGIN
          PATCH_IF (NOT (~%current%~ STRING_EQUAL_CASE ~%previous%~)) BEGIN
            // if the restriction types don't match and it's not because one is RACEFLY and the other is RACESIZE
            PATCH_IF (NOT ((~%current%~ STRING_COMPARE_REGEXP ~RACE.*~) == 0 && (~%previous%~ STRING_COMPARE_REGEXP ~RACE.*~) == 0)
                  AND NOT ((~%current%~ STRING_COMPARE_REGEXP ~CLASS.*~) == 0 && (~%previous%~ STRING_COMPARE_REGEXP ~CLASS.*~) == 0)) BEGIN
              SET rows_match = 0
            END
          END
        END
      END
     
      PATCH_IF (rows_match == 1) BEGIN
        READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 4 restriction_type
        READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 5 restrictions
       
        PATCH_IF (FILE_EXISTS_IN_GAME ~%restriction_type%.ids~) BEGIN // first check to see if there is an IDS file with this name
          INNER_PATCH ~_%restrictions%~ BEGIN
            REPLACE_EVALUATE ~_\([^_]+\)~ BEGIN // for each entry specified (e.g. for 6, KOBOLD, and 3 if restrictions is 6_KOBOLD_3)
              SET valid = 0
              PATCH_IF (IS_AN_INT MATCH1) BEGIN
                SET valid = 1
                SET entry = MATCH1
              END
              ELSE BEGIN // look up int for this symbol (e.g. turns KOBOLD into 112)
                SET entry = IDS_OF_SYMBOL (~%restriction_type%~ ~%MATCH1%~)
                PATCH_IF (entry > 0) BEGIN
                  SET valid = 1
                END
              END
              PATCH_IF (VARIABLE_IS_SET $valid(~%entry%~)) BEGIN
                SET prev_valid = $valid(~%entry%~)
                SET $valid(~%entry%~) = prev_valid BAND valid // entry is only valid if it meets all specifications
              END
            END ~_%MATCH1%~
          END
        END
        // if it's not an actual IDS file, check to see if it's one of our custom RACEFLY/RACESIZE/etc. restrictions
        ELSE PATCH_IF ((~%restriction_type%~ STRING_COMPARE_REGEXP ~RACE.+~) == 1 || (~%restriction_type%~ STRING_COMPARE_REGEXP ~CLASS.+~) == 1) BEGIN
          TO_LOWER restriction_type
          PHP_EACH ~%restriction_type%~ AS ~identifier~ => ~value~ BEGIN // for each race or class
            PATCH_IF (VARIABLE_IS_SET $valid(~%identifier%~)) BEGIN
              SET valid = 0
              INNER_PATCH ~_%restrictions%~ BEGIN
                REPLACE_EVALUATE ~_\([^_]+\)~ BEGIN // for each valid value specified (e.g. for L and G if restrictions is L_G)
                  // find if entry matches specifications
                  PATCH_IF (~%value%~ STRING_EQUAL_CASE ~%MATCH1%~ || (IS_AN_INT MATCH1 && ~%identifier%~ STRING_EQUAL_CASE ~%MATCH1%~)) BEGIN
                    SET valid = 1
                  END
                END ~_%MATCH1%~
              END
              SET prev_valid = $valid(~%identifier%~)
              SET $valid(~%identifier%~) = prev_valid BAND valid // entry is only valid if it meets all specifications
            END
          END
        END
      END ELSE BEGIN // row didn't match
        SET row -= 1 // redo this row separately in the next iteration of the FOR loop
      END
    END
   
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 0 to_edit_spell_file
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 1 to_edit_extended_headers
    INNER_PATCH ~%to_edit_extended_headers%~ BEGIN
      REPLACE_EVALUATE ~\([0-9]+\)-\([0-9]+\)~ BEGIN
        SET to_edit_first_extended_header = MATCH1
        SET to_edit_last_extended_header = MATCH2
      END ~%MATCH1%-%MATCH2%~
    END
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 2 to_protect_from_itself
    READ_2DA_ENTRY_FORMER ~r2en_race_immunity~ row 3 to_start_where
    SET opcode_to_start_at = 0 - 1
    SET effect_to_start_at = 0 - 1
    INNER_PATCH ~%to_start_where%~ BEGIN
      REPLACE_EVALUATE ~OPCODE=\([0-9]+\)~ BEGIN
        SET opcode_to_start_at = MATCH1
      END ~OPCODE=%MATCH1%~
      REPLACE_EVALUATE ~EFFECT=\([0-9]+\)~ BEGIN
        SET effect_to_start_at = MATCH1
      END ~EFFECT=%MATCH1%~
    END
   
    SPRINT ids_file ~%restriction_type%~
    PATCH_IF ((~%restriction_type%~ STRING_COMPARE_REGEXP ~RACE.+~) == 1) BEGIN
      SPRINT ids_file ~RACE~
    END
    ELSE PATCH_IF ((~%restriction_type%~ STRING_COMPARE_REGEXP ~CLASS.+~) == 1) BEGIN
      SPRINT ids_file ~CLASS~
    END
    FOR (i = 0; i < num_entries; i += 1) BEGIN // iterate through entries
      SET entry = $used_entries(~%i%~)
      SET valid = $valid(~%entry%~)
      PATCH_IF (valid == 1) BEGIN
        PATCH_PRINT "Uses %ids_file%.IDS entry: %entry%"
      END
    END
  END
  BUT_ONLY
[/code

Offline Galactygon

  • Modding since 2002
  • Planewalker
  • *****
  • Posts: 378
  • Gender: Male
  • Creator of spells
Re: BUT_ONLY trouble for .dlgs
« Reply #23 on: July 28, 2010, 04:44:01 AM »
I'm pleased to say everything works as intended; I started making my own CLASSSIZE and CLASSFLY arrays, and called for values in the EA IDS files and so far so good. This would have taken me a week or more to code with less-than-optimal solutions, and here you do this in a few hours. It's like getting a free week for vacation. ;D

I had to make a little adjustment in the code, since it wasn't printing RACE.IDS or CLASS.IDS as it was supposed to.

I replaced these line of code
[qupte]
PATCH_IF ((~%restriction_type%~ STRING_COMPARE_REGEXP ~RACE.+~) == 1) BEGIN
PATCH_IF ((~%restriction_type%~ STRING_COMPARE_REGEXP ~CLASS.+~) == 1) BEGIN
[/quote]
with these ones:
[qupte]
PATCH_IF ((~%restriction_type%~ STRING_COMPARE_REGEXP ~RACE.+~) == 0) BEGIN
PATCH_IF ((~%restriction_type%~ STRING_COMPARE_REGEXP ~CLASS.+~) == 0) BEGIN
[/quote]
so that it would print well.

-Galactygon

Offline Mike1072

  • Planewalker
  • *****
  • Posts: 298
  • Gender: Male
Re: BUT_ONLY trouble for .dlgs
« Reply #24 on: July 28, 2010, 04:58:42 AM »
I'm pleased to say everything works as intended; I started making my own CLASSSIZE and CLASSFLY arrays, and called for values in the EA IDS files and so far so good. This would have taken me a week or more to code with less-than-optimal solutions, and here you do this in a few hours. It's like getting a free week for vacation. ;D
Good to hear.  If it messes up on anything, let me know.

Quote
I had to make a little adjustment in the code, since it wasn't printing RACE.IDS or CLASS.IDS as it was supposed to.

I replaced these line of code
Quote
PATCH_IF ((~%restriction_type%~ STRING_COMPARE_REGEXP ~RACE.+~) == 1) BEGIN
PATCH_IF ((~%restriction_type%~ STRING_COMPARE_REGEXP ~CLASS.+~) == 1) BEGIN
with these ones:
Quote
PATCH_IF ((~%restriction_type%~ STRING_COMPARE_REGEXP ~RACE.+~) == 0) BEGIN
PATCH_IF ((~%restriction_type%~ STRING_COMPARE_REGEXP ~CLASS.+~) == 0) BEGIN
Yeah, woops.  :)

 

With Quick-Reply you can write a post when viewing a topic without loading a new page. You can still use bulletin board code and smileys as you would in a normal post.

Warning: this topic has not been posted in for at least 120 days.
Unless you're sure you want to reply, please consider starting a new topic.

Name: Email:
Verification:
Type the letters shown in the picture
Listen to the letters / Request another image
Type the letters shown in the picture:
What color is grass?:
What is the seventh word in this sentence?:
What is five minus two (use the full word)?: