Jump to content

Toss your semi-useful WeiDU macros here


Recommended Posts

On 8/26/2019 at 12:41 AM, K4thos said:

I remember reading about a function/macro that can assign spells to CLAB files and append new rows if needed (only if there are no free slot in the column left). I was sure that I will find it in this topic but can't see it mentioned in the first post. If anyone knows where to get this function please post a link.

Not sure there's a lot of value in this, since CLAB files are functionally unlimited, there is no benefit to inserting something into existing rows, versus just APPENDing a new row.  In fact there is actually a (minor) advantage in APPENDING, since you can use the first entry to denote what is being added in the new row.  (E.g. when I apply an effect to cleric kits that disables Turn Undead, the first entry in that CLAB row is "NO_TURN" so it is easy to read the CLAB table later and see which spell does that.)

Of course it's always possible I'm missing something, or not considering some use case!

Meantime, I have adapted K4thos fix missing 2da entries function to specifically address missing IDS values in kitlist.2da.  The original function doesn't work great here, since the default filler in that entry is not an integer, and even if it was it would not be "correct" (for the very limited definition of "correct" here).  This function sets the IDS entry to (0x4000 + (kitlist row # - 12)).  This should result in "correct" IDS numbers for any mod-added kits or kits that come after the mages and barbarian.  (E.g. when applied to a kitlist.2da with a missing GRIZZLY_BEAR entry, it sets it to 0x00004027.)

This does NOT add anything to KIT.IDS - I forget what rules would apply.  The use case is limited to creating a well-formed kitlist.2da table for mods (like mine) that perform a lot of reads of that table for various purposes.

Spoiler

 


DEFINE_ACTION_FUNCTION fix_kitlist_missing_ids BEGIN
	COPY_EXISTING ~kitlist.2da~ ~override~
		PRETTY_PRINT_2DA
		PATCH_IF ~%entry%~ STR_EQ ~~ BEGIN
			READ_2DA_ENTRY 1 0 1 "entry"
		END
		COUNT_2DA_COLS "cols"
		SET cnt = 0
		REPLACE_EVALUATE ~^\(.+\)$~ BEGIN
			PATCH_IF cnt >= 3 BEGIN
				INNER_PATCH_SAVE MATCH1 ~%MATCH1%~ BEGIN
					COUNT_REGEXP_INSTANCES ~ +~ num_matches
					WHILE (num_matches < (cols - 1)) BEGIN
						REPLACE_TEXTUALLY ~$~ ~ ZZZZZ~
						SET num_matches = num_matches + 1
					END
				END
			END ELSE BEGIN
				SET cnt = cnt + 1
			END
		END ~%MATCH1%~
		PRETTY_PRINT_2DA
	BUT_ONLY
	COPY_EXISTING ~kitlist.2da~ ~override~
		COUNT_2DA_ROWS 10 rows
		FOR (row = 1; row < rows; ++row) BEGIN
			SET val = (row - 12)
			TEXT_SPRINT new_ids ~000040%val%~
			READ_2DA_ENTRY row 9 10 ids_val
			PATCH_IF !(IS_AN_INT %ids_val%) BEGIN
				SET_2DA_ENTRY row 9 10 ~0x%new_ids%~
			END
		END
	BUT_ONLY
END

 

No variables, you just call the function with:

LAF fix_kitlist_missing_ids END

EDIT - updated a bit, now it works even if kitlist.2da has already been treated by the k4thos function and has "*" or some other non-integervalue in the KITIDS column.

Edited by subtledoctor
Link to post
On 7/29/2018 at 1:23 PM, K4thos said:

REPLACE_MULTILINE: Patch function that replaces set or all occurrences of the given regexp pattern in the file with the given string

Do you perhaps have a function to add something to a certain section of UI.MENU (e.g., adding a button to LEFT_SIDEBAR_BOTTOM...)

Link to post
On 1/2/2018 at 8:02 PM, CamDawg said:

cd_new_portrait_icon, another action function, will find the next available entry and add your strref and bam file to the list.
...

As above, it returns 'icon' with the value of the new entry for usage in your spells or items, and you still need to copy your BAM.

Anyone know what the requirements are for what the source .BAM file has to look like?  Does it need to be a particular size?  Or can I just feed it, say, something like a SPWIxxxb.BAM file?

Link to post

This is a set of functions that can be used to safely install pvrz-based tilesets without the danger of overwriting pvrz files from other mods or the game itself. It's an expanded version of the functionality already present in current WeiDU, so you can also install BAM V2 and MOS V2 files with it as well.

PVRZ filenames used by tilesets are limited to a specific naming scheme. Since it affects the modder prefix of a file there is always a chance to conflict with files from other mods or the game itself.

This functionality was requested a while back in the PPG Forums (by @Sam., iirc). I'll post it here because PPG is currently unavailable.

The functions (caution: it's quite a lot of code):

Spoiler

/**
 * This function returns the PVRZ resource prefix based on the given TIS filename.
 * Available as ACTION and PATCH function.
 *
 * STR_VAR tis_res  The TIS filename with or without .tis extension.
 * RET prefix       The PVRZ resource prefix associated with the specified TIS filename.
 *                  Returns empty string on error.
 */
DEFINE_PATCH_FUNCTION TIS_RES_TO_PVRZ
  STR_VAR
    tis_res = ~~
  RET
    prefix
BEGIN
  // Make sure only filename without extension is specified
  PATCH_IF (~%tis_res%~ STRING_CONTAINS_REGEXP ~\.TIS$~ = 0) BEGIN
    LPF RES_OF_FILESPEC STR_VAR filespec = EVAL ~%tis_res%~ RET tis_res = res END
  END

  PATCH_IF (STRING_LENGTH ~%tis_res%~ > 1) BEGIN
    INNER_PATCH_SAVE prefix ~%tis_res%~ BEGIN DELETE_BYTES 1 1 END
  END ELSE BEGIN
    TEXT_SPRINT prefix ~~
  END
END

DEFINE_ACTION_FUNCTION TIS_RES_TO_PVRZ
  STR_VAR
    tis_res = ~~
  RET
    prefix
BEGIN
  OUTER_PATCH ~foo~ BEGIN
    LPF TIS_RES_TO_PVRZ STR_VAR tis_res RET prefix END
  END
END


/**
 * This PATCH function updates all PVRZ references in the BAM V2, MOS V2, or TIS V1 file to the next unoccupied block
 * of PVRZ indices. It's intended to be used in combination with the action function "INSTALL_PVRZ".
 *
 * INT_VAR target_base_index  Optional parameter. When specified, the function attempts to use a block of free PVRZ
 *                            indices starting at the specified value.
 *                            (default: 0 for TIS-related PVRZ files, 1000 otherwise)
 * RET original_base_index    Returns the lowest PVRZ index used by the source BAM, MOS, or TIS. Returns -1 on error.
 * RET new_base_index         Returns the lowest PVRZ index used by the target BAM, MOS, or TIS. Returns -1 on error.
 * RET index_range            Returns the range of reserved PVRZ indices, i.e. the difference between the smallest
 *                            and biggest PVRZ index inclusive. Returns 0 on error.
 */
DEFINE_PATCH_FUNCTION UPDATE_PVRZ_INDICES
  INT_VAR
    target_base_index = "-1"
  RET
    original_base_index
    new_base_index
    index_range
BEGIN
  SET original_base_index = "-1"
  SET new_base_index = "-1"
  SET index_range = 0
  SET max_base_index = 99999
  SET def_base_index = 1000
  TEXT_SPRINT prefix ~MOS~
  PATCH_IF (ENGINE_IS ~bgee bg2ee iwdee pstee~) BEGIN
    // initializations
    SET is_valid = 0
    READ_ASCII 0 sig (8)
    PATCH_MATCH ~%sig%~ WITH
      ~BAM V2  ~ BEGIN
        READ_LONG 0x10 num_blocks
        READ_LONG 0x1c ofs_blocks
        SET block_size = 28
        SET is_valid = 1
      END
      ~MOS V2  ~ BEGIN
        READ_LONG 0x10 num_blocks
        READ_LONG 0x14 ofs_blocks
        SET block_size = 28
        SET is_valid = 1
      END
      ~TIS V1  ~ BEGIN
        READ_LONG 0xc block_size
        PATCH_IF (block_size = 12) BEGIN
          READ_LONG 0x08 num_blocks
          READ_LONG 0x10 ofs_blocks
          // getting tis resref...
          PATCH_IF (DIRECTORY_EXISTS ~%DEST_FILESPEC%~) BEGIN
            TEXT_SPRINT tis_res ~%SOURCE_RES%~
          END ELSE BEGIN
            LPF RES_OF_FILESPEC STR_VAR filespec = EVAL ~%DEST_FILESPEC%~ RET tis_res = res END
          END
          // ...to derive pvrz prefix
          LPF TIS_RES_TO_PVRZ STR_VAR tis_res RET prefix END
          PATCH_IF (NOT ~%prefix%~ STR_EQ ~~) BEGIN
            SET max_base_index = 99
            SET def_base_index = 0
            SET is_valid = 1
          END
        END
      END
      DEFAULT
    END

    PATCH_IF (is_valid) BEGIN
      PATCH_IF (target_base_index < 0) BEGIN SET target_base_index = def_base_index END
      PATCH_IF (target_base_index > max_base_index) BEGIN
        PATCH_LOG ~Target base index (%target_base_index%) is out of range. Using default value (%def_base_index%).~
        SET target_base_index = def_base_index
      END

      // finding minimum and maximum pvrz index
      SET min = max_base_index + 1
      SET max = "-1"
      FOR (i = 0; i < num_blocks; ++i) BEGIN
        SET ofs = ofs_blocks + i * block_size
        READ_LONG ofs page
        PATCH_IF (page >= 0) BEGIN
          PATCH_IF (page < min) BEGIN SET min = page END
          PATCH_IF (page > max) BEGIN SET max = page END
        END
      END

      PATCH_IF (min >= 0 && max >= min) BEGIN
        SET index_range = max - min + 1
        LPF FIND_FREE_PVRZ_INDEX INT_VAR num_to_reserve = index_range start_index = target_base_index STR_VAR prefix RET free_index END
        PATCH_IF (free_index >= 0) BEGIN
          SET original_base_index = min
          SET new_base_index = free_index
          SET offset = new_base_index - original_base_index
          // updating pvrz references
          FOR (i = 0; i < num_blocks; ++i) BEGIN
            SET ofs = ofs_blocks + i * block_size
            WRITE_LONG ofs (THIS >= 0) ? (THIS + offset) : THIS
          END
          SET success = 1
        END ELSE BEGIN
          PATCH_WARN ~Unable to find free block of PVRZ indices. No changes have been made.~
        END
      END ELSE BEGIN
        PATCH_WARN ~File contains no pvrz references. No changes have been made.~
      END
    END ELSE BEGIN
      PATCH_WARN ~Unsupported resource type or corrupted BAM V2, MOS V2, or pvrz-based TIS detected. No changes have been made.~
    END
  END ELSE BEGIN
    PATCH_WARN ~Game is not supported.~
  END
END


/**
 * This ACTION function copies the specified PVRZ file into the target folder and updates the PVRZ index.
 * It should be used in conjunction with "UPDATE_PVRZ_INDICES".
 *
 * INT_VAR original_base_index  The current base index (returned by the function "UPDATE_PVRZ_INDICES" as
 *                              "original_base_index").
 * INT_VAR new_base_index       The new base index (returned by the function "UPDATE_PVRZ_INDICES" as
 *                              "new_base_index").
 * INT_VAR backup               Set to non-zero to have WeiDU create a backup that is restored when the mod is
 *                              uninstalled. Set to zero to forbid restoring the file when the mod is uninstalled.
 *                              (Default: 1 - create backup)
 * STR_VAR source_file          The source file to copy. For BAM and MOS files, the filename must match the regular
 *                              expression "MOS[0-9]{4,5}\.PVRZ" (e.g. MOS0000.PVRZ, mos1592.pvrz or Mos12345.PVRZ).
 *                              For TIS files, the filename must match the regular expression "%prefix%[0-9][0-9]\.PVRZ"
 *                              Case is ignored.
 * STR_VAR target_folder        The target folder to copy the source file into. (Default: override)
 * RET success                  Set to non-zero if the function returned successfully and set to zero on error.
 * RET SOURCE_*, DEST_*         Returns all variables that are automatically set by a WeiDU COPY operation on success.
 */
DEFINE_ACTION_FUNCTION INSTALL_PVRZ
  INT_VAR
    original_base_index = "-1"
    new_base_index = "-1"
    backup = 1
  STR_VAR
    source_file = ~~
    target_folder = ~override~
  RET
    success
    SOURCE_DIRECTORY SOURCE_FILESPEC SOURCE_FILE SOURCE_RES SOURCE_EXT SOURCE_SIZE
    DEST_DIRECTORY DEST_FILESPEC DEST_FILE DEST_RES DEST_EXT
BEGIN
  OUTER_SET success = 0
  ACTION_IF (ENGINE_IS ~bgee bg2ee iwdee pstee~) BEGIN
    ACTION_IF (original_base_index >= 0 && new_base_index >= 0 && FILE_EXISTS ~%source_file%~) BEGIN
      // Making sure that target points to a directory
      ACTION_IF (~%target_folder%~ STR_EQ ~~) BEGIN OUTER_TEXT_SPRINT target_folder ~.~ END
      ACTION_IF (DIRECTORY_EXISTS ~%target_folder%~) BEGIN
        LAF EXT_OF_FILESPEC STR_VAR filespec = EVAL ~%source_file%~ RET ext END
        LAF RES_OF_FILESPEC STR_VAR filespec = EVAL ~%source_file%~ RET res END
      END ELSE BEGIN
        LAF EXT_OF_FILESPEC STR_VAR filespec = EVAL ~%target_folder%~ RET ext END
        LAF RES_OF_FILESPEC STR_VAR filespec = EVAL ~%target_folder%~ RET res END
        LAF DIRECTORY_OF_FILESPEC STR_VAR filespec = EVAL ~%target_folder%~ RET target_folder = directory END
      END

      // initializations
      OUTER_SET failed = 0
      ACTION_IF (~%res%~ STRING_MATCHES_REGEXP ~MOS[0-9][0-9][0-9][0-9][0-9]?$~ = 0) BEGIN
        OUTER_SET max_index = 99999
        OUTER_TEXT_SPRINT fmt_index ~-4~
        // separate pvrz prefix and index
        OUTER_PATCH_SAVE res_index ~%res%~ BEGIN
          READ_ASCII 0 res_prefix (3)
          DELETE_BYTES 0 3
        END
      END ELSE ACTION_IF (~%res%~ STRING_MATCHES_REGEXP ~.+[0-9][0-9]$~ = 0) BEGIN
        OUTER_SET max_index = 99
        OUTER_TEXT_SPRINT fmt_index ~-2~
        // separate pvrz prefix and index
        OUTER_SET len = STRING_LENGTH ~%res%~
        OUTER_PATCH_SAVE res_index ~%res%~ BEGIN
          READ_ASCII 0 res_prefix (len - 2)
          DELETE_BYTES 0 (len - 2)
        END
      END ELSE BEGIN
        OUTER_SET failed = 1
        WARN ~Invalid source file specified: %source_file%. Skipping operation.~
      END

      // update filename and install pvrz file
      ACTION_IF (NOT failed) BEGIN
        OUTER_SET offset = new_base_index - original_base_index
        OUTER_SET old_index = res_index
        OUTER_SET new_index = old_index + offset
        ACTION_IF (new_index >= 0 && new_index <= max_index) BEGIN
          // ensure required number of digits
          OUTER_SNPRINT ~%fmt_index%~ new_index ~0000%new_index%~
          OUTER_TEXT_SPRINT new_res ~%res_prefix%%new_index%~
          OUTER_TEXT_SPRINT target_filespec ~%target_folder%/%new_res%.%ext%~
          ACTION_IF (backup) BEGIN
            COPY ~%source_file%~ ~%target_filespec%~
          END ELSE BEGIN
            COPY + ~%source_file%~ ~%target_filespec%~
          END
          OUTER_SET success = 1
        END ELSE BEGIN
          WARN ~New PVRZ index is out of range: %new_index%. Skipping file.~
        END
      END
    END ELSE BEGIN
      FAIL ~One or more required parameters are undefined.~
    END
  END ELSE BEGIN
    WARN ~Game is not supported.~
  END
END


/**
 * This PATCH function attempts to find the first available free PVRZ index of a contiguous block
 * which guarantees to fit at least "num_to_reserve" indices.
 *
 * INT_VAR num_to_reserve   Find a contiguous block of at least this number of free indices
 *                          (range: [1..100] for TIS-related PVRZ files, [1..999] otherwise, default: 1)
 * INT_VAR start_index      Index to start looking for (default: 0 for TIS-related PVRZ files, 1000 otherwise)
 * STR_VAR prefix           Prefix of the PVRZ files associated with the BAM, MOS, or TIS file.  For BAM and MOS files,
 *                          the prefix will be "MOS".  For TIS files it will be the TIS filename minus the second
 *                          character. Use function TIS_RES_TO_PVRZ to derive the PVRZ prefix from a TIS filename.
 *                          (default: MOS)
 * RET free_index           Returns the first available index matching the specified parameters if successful.
 *                          Returns -1 if no sufficiently large block of free slots could be found.
 */
DEFINE_PATCH_FUNCTION FIND_FREE_PVRZ_INDEX
  INT_VAR
    num_to_reserve = 1
    start_index = "-1"
  STR_VAR
    prefix = ~MOS~
  RET
    free_index
BEGIN
  SET free_index = "-1"

  SET failed = 0
  PATCH_IF (~%prefix%~ STR_EQ ~MOS~) BEGIN
    SET max_to_reserve = 999
    SET max_start_index = 100000
    PATCH_IF (start_index < 0) BEGIN SET start_index = 1000 END
  END ELSE PATCH_IF (STRING_LENGTH ~%prefix%~ > 0 && STRING_LENGTH ~%prefix%~ <= 6) BEGIN
    SET max_to_reserve = 100
    SET max_start_index = 100
    PATCH_IF (start_index < 0) BEGIN SET start_index = 0 END
  END ELSE BEGIN
    PATCH_WARN ~Invalid prefix specified: "%prefix%"~
    SET failed = 1
  END

  PATCH_IF (NOT failed && ENGINE_IS ~bgee bg2ee iwdee pstee~) BEGIN
    PATCH_IF (num_to_reserve < 1) BEGIN
      SET num_to_reserve = 1
      PATCH_LOG ~Block size too small. Using default of 1.~
    END ELSE PATCH_IF (num_to_reserve > max_to_reserve) BEGIN
      SET num_to_reserve = max_to_reserve
      PATCH_LOG ~Block size too big. Truncating to %max_to_reserve%.~
    END
    PATCH_IF (start_index + num_to_reserve > max_start_index) BEGIN
      SET start_index = max_start_index - num_to_reserve
      PATCH_LOG ~Start index too big. Setting start index to %start_index%.~
    END

    SET count = 0
    FOR (index = start_index; index < max_start_index; ++index) BEGIN
      LPF a7#__is_free_pvrz INT_VAR index STR_VAR prefix RET is_free_index END
      PATCH_IF (is_free_index) BEGIN
        PATCH_IF (count = 0) BEGIN
          SET free_index = index
        END
        SET count += 1

        // block found?
        PATCH_IF (count >= num_to_reserve) BEGIN
          SET index = max_start_index
        END
      END ELSE BEGIN
        // start counting anew
        SET count = 0
      END
    END

    PATCH_IF (count < num_to_reserve) BEGIN
      SET free_index = "-1"
    END
  END ELSE BEGIN
    PATCH_WARN ~Game is not supported.~
  END
END


/**
 * This ACTION function attempts to find the first available free PVRZ index of a contiguous block
 * which guarantees to fit at least "num_to_reserve" indices.
 *
 * INT_VAR num_to_reserve   Find a contiguous block of at least this number of free indices
 *                          (range: [1..100] for TIS-related PVRZ files, [1..999] otherwise, default: 1)
 * INT_VAR start_index      Index to start looking for (default: 0 for TIS-related PVRZ files, 1000 otherwise)
 * STR_VAR prefix           Prefix of the PVRZ files associated with the BAM, MOS, or TIS file.  For BAM and MOS files,
 *                          the prefix will be "MOS".  For TIS files it will be the TIS filename minus the second
 *                          character. Use function TIS_RES_TO_PVRZ to derive the PVRZ prefix from a TIS filename.
 *                          (default: MOS)
 * RET free_index           Returns the first available index matching the specified parameters if successful.
 *                          Returns -1 if no sufficiently large block of free slots could be found.
 */
DEFINE_ACTION_FUNCTION FIND_FREE_PVRZ_INDEX
  INT_VAR
    num_to_reserve = 1
    start_index = "-1"
  STR_VAR
    prefix = ~MOS~
  RET
    free_index
BEGIN
  OUTER_PATCH ~foo~ BEGIN
    LPF FIND_FREE_PVRZ_INDEX
      INT_VAR
        num_to_reserve
        start_index
      STR_VAR
        prefix
      RET
        free_index
    END
  END
END


// Used internally. Determines whether the file MOSxxxx.PVRZ or %prefix%xx.PVRZ is still unoccupied,
// where xxxx and xx are numeric indices.
DEFINE_PATCH_FUNCTION a7#__is_free_pvrz
  INT_VAR
    index = 0
  STR_VAR
    prefix = ~MOS~
  RET
    is_free_index
BEGIN
  SET max = (~%prefix%~ STR_EQ ~MOS~) ? 99999 : 99
  PATCH_IF (index < 0) BEGIN
    SET index = 0
  END ELSE PATCH_IF (index > max) BEGIN
    SET index = max
  END

  PATCH_IF (~%prefix%~ STR_EQ ~MOS~) BEGIN
    PATCH_IF (index <= 9999) BEGIN
      SNPRINT "-4" index ~0000%index%~
    END
  END ELSE BEGIN
    SNPRINT "-2" index ~00%index%~
  END
  TEXT_SPRINT cur_file ~%prefix%%index%.PVRZ~

  SET is_free_index = (FILE_EXISTS_IN_GAME ~%cur_file%~ ||
                       FILE_EXISTS ~%USER_DIRECTORY%/override/%cur_file%~ ||
                       FILE_EXISTS ~lang/%EE_LANGUAGE%/override/%cur_file%~) ? 0 : 1
END

 

Example usage:

// Installing all TIS files from the specified folder
ACTION_BASH_FOR ~%MOD_FOLDER%/tis~ ~^.+\.tis$~ BEGIN
  COPY ~%BASH_FOR_FILESPEC%~ ~override~
    LPF UPDATE_PVRZ_INDICES RET original_base_index new_base_index END

  // Installing associated PVRZ files for each tileset individually
  ACTION_IF (new_base_index >= 0) BEGIN
    LAF TIS_RES_TO_PVRZ STR_VAR tis_res = EVAL ~%BASH_FOR_FILESPEC%~ RET prefix END

    ACTION_BASH_FOR ~%MOD_FOLDER%/tis~ ~^%prefix%.+\.pvrz$~ BEGIN
      LAF INSTALL_PVRZ
        INT_VAR original_base_index new_base_index
        STR_VAR source_file = EVAL ~%BASH_FOR_FILESPEC%~
        RET success DEST_FILESPEC
      END

      ACTION_IF (NOT success) BEGIN
        FAIL ~Could not install "%BASH_FOR_FILESPEC%"!~
      END
    END
  END ELSE BEGIN
    FAIL ~Could not install "%BASH_FOR_FILESPEC%"!~
  END
END

 

Edited by argent77
Code changes
Link to post
1 hour ago, argent77 said:

This is a set of functions that can be used to safely install pvrz-based tilesets without the danger of overwriting pvrz files from other mods or the game itself.

This could use a separate thread as it should become standard for every mod adding areas to EE imho.

Link to post

I wrote a small tool and function to alter the searchmap bitmap files.

For Baldurans Seatower I made a new practical tool for an old problem. It was always a problem to edit searmap files, because you could only overwrite the existing file.
When two different mods edit the same searchmap, it was always difficult to find a solution.
Now I wrote a small tool and a function to solve this problem.

The tool SRmap_modding_tool now compares the modded searchmap with the originals from the classic and ee version and creates a 2da file with all bitmap changes.

The function is for the setup.tp2 file, which uses the 2da files to alter the existing bitmap with the changes.

So two different mods can alter the searchmap file.

Now a small instruction for mod authors:
-First you need to use the tool to create a file that lists the search map changes. This you need to do once for your mod.
-After that you include this "changes.tpa" inside your mod to patch the existing search map when the mod is installed.

 

Put the SRmap_modding_tool in your Baldurs Gate installation.

1. Go into SRmap_modding_tool\area directory

2. Put the classic, ee and your modded/new searchmap bitmap in the fitting directory

3. Open the setup-SRmap_modding_tool.tp2 with an editor

4. Enter the names of the bitmap files without the extension in the lines

filename_classic, filename_ee, filename_new
 

ALWAYS

//OUTER_SET areaname = ~AR1200~
OUTER_SPRINT originalfolder_classic ~%MOD_FOLDER%/area/original/classic~ //original unmodded searchmap folder from classic bg
OUTER_SPRINT originalfolder_ee ~%MOD_FOLDER%/area/original/ee~ //original unmodded searchmap folder from ee bg
OUTER_SPRINT filename_classic ~AR1200SR~ //original unmodded searchmap filename from classic bg
OUTER_SPRINT filename_ee ~BG1200SR~ //original unmodded searchmap filename from ee bg
OUTER_SPRINT newfolder ~%MOD_FOLDER%/area/new~ //modded searchmap folder
OUTER_SPRINT filename_new ~AR8100SR~ //modded searchmap filename
OUTER_SPRINT filename_changes_classic ~%filename_new%_changes_classic~ //filenames for the 2da files used by the mod
OUTER_SPRINT filename_changes_ee ~%filename_new%_changes_ee~ //filenames for the 2da files used by the mod
END


5. Save the file and start the tool. It will work a while

6. When it's finished. There are either two files "AR8100SR_changes_ee.2da" and "AR8100SR_changes_classic.2da" or if both files are identical there is only one file "AR8100SR_changes.2da"

7. Copy the 2da file from step 6 into your mod folder

8. Copy the alter_searchmap.tpa function to your mod functions. You find it in the SRmap_modding_tool\lib directory

Spoiler

DEFINE_ACTION_FUNCTION ~ALTER_SEARCHMAP~
	INT_VAR

	STR_VAR
	path_to_2da_file = ~~ // full path to the *changes.2da file, e.g. ~mymod/bmp/AR3700SR_changes_ee.2da~
	areaname = ~~ 		  // area name, e.g. ~AR3700~

	RET

BEGIN
	COPY ~%path_to_2da_file%~ ~%path_to_2da_file%~
		READ_2DA_ENTRIES_NOW ~newpixelarray~ 4
		COUNT_2DA_ROWS 4 ~pixelnumber~
		
	COPY_EXISTING ~%areaname%SR.bmp~ ~override~
		FOR (cnt=0; cnt<pixelnumber; cnt=cnt+1) BEGIN
			READ_2DA_ENTRY_FORMER ~newpixelarray~ cnt 0 ~offset~
			READ_BYTE ~offset~ ~oldpixel~
			READ_2DA_ENTRY_FORMER ~newpixelarray~ cnt 2 ~newpixel~
			READ_2DA_ENTRY_FORMER ~newpixelarray~ cnt 3 ~byte~
			SET left_oldpixel =  oldpixel / 16
			SET right_oldpixel =  oldpixel MODULO 16
			SET left_newpixel = newpixel / 16
			SET right_newpixel = newpixel MODULO 16
			PATCH_IF (~%byte%~ STRING_EQUAL ~b~)=1 BEGIN
				SET setpixel = newpixel
				//PATCH_PRINT ~%offset%: oldpixel %oldpixel% - newpixel %newpixel% - setpixel %setpixel%~
				//PATCH_PRINT ~%offset%: lo %left_oldpixel% ro %right_oldpixel% - ln %left_newpixel% rn %right_newpixel% - setpixel %setpixel%~
			END
			PATCH_IF (~%byte%~ STRING_EQUAL ~r~)=1 BEGIN
				SET setpixel = left_oldpixel * 16 + right_newpixel
			END
			PATCH_IF (~%byte%~ STRING_EQUAL ~l~)=1 BEGIN
				SET setpixel = left_newpixel * 16 + right_oldpixel
			END
			WRITE_BYTE offset ~%setpixel%~ 
		END
END

 


9. Put following lines into your setup-mymod.tp2
 

INCLUDE ~%MOD_FOLDER%/lib/alter_searchmap.tpa~
LAF ALTER_SEARCHMAP
STR_VAR
path_to_2da_file = EVAL ~%MOD_FOLDER%/Ramazith/AR7238SR_changes.2da~ // full path to the *changes.2da file, e.g. ~mymod/bam/AR3700SR_changes_ee.2da~
areaname = EVAL ~AR7238~ // area name, e.g. ~AR3700~
END


Enter your path to the 2da file and the areaname.

For ee and classic differnces, you have to make a query with ACTION_IF

Link to post
Posted (edited)
On 2/11/2020 at 12:36 PM, subtledoctor said:

Anyone know what the requirements are for what the source .BAM file has to look like?  Does it need to be a particular size?  Or can I just feed it, say, something like a SPWIxxxb.BAM file?

 

On 2/11/2020 at 4:30 PM, kjeron said:

13x13 pixels.

They autoscale down to size over the side-bar portrait, but not in the record screen, though they can be made to through some UI changes.

FINAL EDIT - I think I figured it out. IGNORE ME!

Is there any kind of guidance for making .BAM files for portrait icons?  I need to make new portrait icons for Spell Deflection and SR's Greater Spell Deflection - it seems that opcode 201 just applies the same portrait icon, regardless of which spell is applying it or how many separate sources of Deflection there are.  Since you can cast both Minor Deflecion and Spell Deflection on yourself, I would like a visual indicator of which is active.  (FYI, the IESDP does not mention anything about opcode 201 displaying a portrait icon...)

I tried going into the "Edit BAM" window in Near Infinity and reduce SPWI618C.BAM to 40%, which results in a 12x12 image, and to 45%, which results in a 14x14 image.  But they are garbage - pixellated nonsense, unrecognizable.  How does one make halfway-decent portrait icons?

Alternatively, any idea how to find the one already used by opcode 201?  Maybe I could just make three different recolored version of that.

EDIT - found it in STATES.BAM.  I'll probably just do recoloring.  But it might be nice for other readers if anyone has advice on this.

EDIT 2 - okay, I found the proper frame of STATES.BAM and saved that frame as a new .BAM file, then made two recolored versions of that .BAM file by adjusting the hue in Near Infinity's BAM editor, then I made a little test mod to add them with opcode 142  effects as  in this example.

Spoiler

 

 


COPY ~test/d5mdefl.bam~ ~override~
LAF cd_new_portrait_icon INT_VAR string = RESOLVE_STR_REF(~Minor Deflection~) STR_VAR bam_file = ~d5mdefl~ RET icon END
COPY_EXISTING ~spwi318.spl~ ~override~
  LPF CLONE_EFFECT INT_VAR silent = 1 multi_match = 1 match_opcode = 201 opcode = 142 parameter2 = icon END
IF_EXISTS BUT_ONLY

COPY ~test/d5sdefl.bam~ ~override~
LAF cd_new_portrait_icon INT_VAR string = RESOLVE_STR_REF(~Spell Deflection~) STR_VAR bam_file = ~d5sdefl~ RET icon END
COPY_EXISTING ~spwi522.spl~ ~override~
  LPF CLONE_EFFECT INT_VAR silent = 1 multi_match = 1 match_opcode = 201 opcode = 142 parameter1 = 0 parameter2 = icon END
IF_EXISTS BUT_ONLY

COPY ~test/d5gdefl.bam~ ~override~
LAF cd_new_portrait_icon INT_VAR string = RESOLVE_STR_REF(~Greater Deflection~) STR_VAR bam_file = ~d5gdefl~ RET icon END
COPY_EXISTING ~spwi701.spl~ ~override~
  LPF CLONE_EFFECT INT_VAR silent = 1 multi_match = 1 match_opcode = 201 opcode = 142 parameter1 = 0 parameter2 = icon END
IF_EXISTS BUT_ONLY

 

 

 

It patches STATDESC.2da correctly, the opcode 142 effects are generated correctly, and in-game in the character record sheet, I can see the text next to where the portrait icon should be.  But the portrait icons themselves are invisible.  Any idea why?  I'm attaching the three icons to this post.

d5_deflect_icons.zip

Edited by subtledoctor
Link to post
On 6/24/2017 at 4:31 PM, CamDawg said:

Post 49, K4thos

  • JOINABLE_NPC_ARRAY - Action macro that generates JOINABLE_NPC_ARRAY table which can be used to patch joinable NPC CRE files (more reliable method than checking CRE BIO offset)

Where'd it go?  I need this. 

Found it.  The link was just broken.  Had to meander through the pages to find it, but I did find it.

This is a thing of beauty, boss!

Edited by Lauriel
Link to post
On 6/1/2020 at 1:34 PM, subtledoctor said:

It patches STATDESC.2da correctly, the opcode 142 effects are generated correctly, and in-game in the character record sheet, I can see the text next to where the portrait icon should be.  But the portrait icons themselves are invisible.  Any idea why?  I'm attaching the three icons to this post.

d5_deflect_icons.zip 3.32 kB · 0 downloads

Baldur_JVk4nuDtnp.png

I would've replied earlier, but I didn't see this thread until now. Did you already fix it?

 

Edited by Bartimaeus
Link to post

@Lauriel NB that I have slightly updated K4thos’ code, my version of the function generates two arrays for use later: one of joinable NPCs and one of non-joinable NPCs. It’s a bit later in the thread, or you can see the code here, starting at line 209.

@Bartimaeus yeah I eventually figured it out, I think. When creating those BAMs I had removed the extraneous frames, but not all the extraneous cycles. Or vice versa. Dealing with BAMs is annoying.

Link to post
3 hours ago, subtledoctor said:

@Lauriel NB that I have slightly updated K4thos’ code, my version of the function generates two arrays for use later: one of joinable NPCs and one of non-joinable NPCs. It’s a bit later in the thread, or you can see the code here, starting at line 209.

@Bartimaeus yeah I eventually figured it out, I think. When creating those BAMs I had removed the extraneous frames, but not all the extraneous cycles. Or vice versa. Dealing with BAMs is annoying.

Yeah, I have no idea what any of it means, but I've had enough experience in clicking the buttons in the right order to figure it out, :p.

Link to post
5 hours ago, subtledoctor said:

@Lauriel NB that I have slightly updated K4thos’ code, my version of the function generates two arrays for use later: one of joinable NPCs and one of non-joinable NPCs. It’s a bit later in the thread, or you can see the code here, starting at line 209.

Thanks, @subtledoctor  :)

 

Link to post

In case someone is looking for a way to send "level" to ADD_MEMORIZED_SPELL as a variable (or "charges1/2/3" to ADD_CRE_ITEM and the like):

Spoiler

// Replace "example" with your "%TP2_BASE_NAME%"

// blank file

<<<<<<<< .../example-inline/blank

>>>>>>>>

DEFINE_DIMORPHIC_FUNCTION "REINCLUDE_THIS"
STR_VAR
	"input" = ""
BEGIN
	COPY - ".../example-inline/blank" "override/temp_file.tph"
		DELETE_BYTES 0x0 BUFFER_LENGTH
		INSERT_BYTES 0x0 (STRING_LENGTH "%input%")
		WRITE_ASCIIE 0x0 "%input%"
	BUT_ONLY_IF_IT_CHANGES
	REINCLUDE "override/temp_file.tph"
END

// Example usage

COPY_EXISTING "BANDIT.CRE" "override"
  SET test = 0
  LPF REINCLUDE_THIS
  STR_VAR
  	input = "ADD_CRE_ITEM ~SW1H01~ #%test% #%test% #%test% ~none~ ~inv~"
  END
BUT_ONLY

 

This is in principle quite powerful if you edit ALTER_ITEM_HEADER and the like to allow for it:

Spoiler


LPF ALTER_ITEM_HEADER
INT_VAR
	header_type = 1
STR_VAR
	dicenumber = "THIS + 1"
	dicesize = "THIS + 5"
END

 

On the other hand, it's probably useful only in a 'functional programming' environment (yes, you're my master DavidW...)

Edited by Luke
Updated to WeiDU v247
Link to post
Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

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

×   Your previous content has been restored.   Clear editor

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

×
×
  • Create New...