Author Topic: New CLONE_EFFECT macro  (Read 2407 times)

Offline CamDawg

  • Infidel
  • Planewalker
  • *****
  • Posts: 859
  • Dreaming of a red Xmas
    • The Gibberlings Three
New CLONE_EFFECT macro
« on: April 01, 2014, 03:20:11 PM »
A little something I threw together for another project that may be useful for general modding, complete with docs, if you wish to include with future WeiDUs.

CLONE_EFFECT: This is a patch function for creature, item, or spell files that will match an existing effect and create a new one based on the matched effect. Numerous variables are available for matching the specified effect and for specifying new values in the new effect based on the matched effect.

The first batch of variables are meta-variables which will help determine the scope of the macro:

  • INT_VAR check_globals - This variable determines if the macro loops through global effects on items (also known as equipping effects) and spells if set to 1 (default is 1). Creature effects are all global effects, so this variable will always be considered to be one when this macro is run on a creature.
  • INT_VAR check_headers - This variable determines if the macro loops through effects on extended headers on items and spells if set to 1 (default is 1). Creatures have no extended headers, so this variable is ignored when used on creatures.
  • INT_VAR header - Allows the macro to target effects on one specific header, counting the first header as zero. A negative value will match all headers (default is -1). Creatures have no extended headers, so this variable is ignored when used on creatures.
  • INT_VAR header_type - Allows the macro to only seek out effects on extended headers of the specified type (1 - melee, 2 - ranged, etc.). Negative values will look at effects on all headers (default is -1). Creatures have no extended headers, so this variable is ignored when used on creatures.
  • INT_VAR multi_match - This variable determines how many effects to clone in the active stack. If you just want to match the first effect and have the macro stop, use 1. Otherwise the macro will continue matching until the number of cloned effects matches this value. The macro will always make at least one change (e.g. 0 or negative values are treated as 1). (default is 999).
  • INT_VAR debug - Spits out some very rudimentary information if the file is patched or not patched if set to 1 (default is 0).
  • STR_VAR insert - A value of 'below' puts the new, cloned effect immediately below the matched effect. Values of 'first' or last' will put the new effect at the top or bottom of the effect stack, respectively. All other values will default to 'above', where the effect is added immediately before the matched effect (default is 'above').

The next batch of variables sets the macro boundaries on matching an effect to clone. Any variables not specified will not be used to determine a match. The macro will only determine an effect is a match only if ALL of the variables specified are matched.

  • INT_VAR match_opcode - This variable must be set to a non-zero value. This variable checks the opcode of effects for a match (default -1).
  • INT_VAR match_target - This variable checks the target of effects for a match (default -1).
  • INT_VAR match_power - This variable checks the power of effects for a match (default -1).
  • INT_VAR match_parameter1 - This variable checks parameter1 of effects for a match (default -1).
  • INT_VAR match_parameter2 - This variable checks parameter2 of effects for a match (default -1).
  • INT_VAR match_timing - This variable checks the timing of effects for a match (default -1).
  • INT_VAR match_resist_dispel - This variable checks the resist/dispel setting of effects for a match (default -1).
  • INT_VAR match_duration - This variable checks the duration of effects for a match (default -1).
  • INT_VAR match_probability1 - This variable checks probability1 (the upper bound) of effects for a match (default -1).
  • INT_VAR match_probability2 - This variable checks probability2 (the lower bound) of effects for a match (default -1).
  • INT_VAR match_dicenumber - This variable checks the number of dice of effects for a match (default -1). This field is instead used for maximum hit-dice (HD) by some opcodes.
  • INT_VAR match_dicesize - This variable checks the size of dice of effects for a match (default -1). This field is used instead for minimum hit-dice (HD) by some opcodes.
  • INT_VAR match_savingthrow - This variable checks the saving throw type of effects for a match (default -1).
  • INT_VAR match_savebonus - This variable checks the saving trow bonus effects for a match (default -11). Since saving throws can range into negative values, this variable can match all the way down to -10.
  • INT_VAR match_special  - This variable checks the special field of effects for a match (default -1). The special field is used by some EE effects.
  • STR_VAR match_resource - This variable checks the resource of effects for a match (default "SAME").

Once a matching effect is found, a new effect is created (STR_VAR insert determines its placement) with all of the same specifications as the matched effect. The next series of variables allows the macro to change the fields to new values in the newly-created effect. Any variables not set in this batch will simply inherit their values from the matched effect.

  • INT_VAR opcode to the value the of the new effect's opcode.
  • INT_VAR target to the new effect's target.
  • INT_VAR power to the new effect's power.
  • INT_VAR parameter1 to the new effect's parameter1.
  • INT_VAR parameter2 to the new effect's parameter2.
  • INT_VAR timing to the new effect's timing mode.
  • INT_VAR resist_dispel to the new effect's resist/dispel setting.
  • INT_VAR duration to the new effect's duration.
  • INT_VAR probability1 to the new effect's probability1 (the upper bound).
  • INT_VAR probability2 to the new effect's probability2 (the lower bound).
  • INT_VAR dicenumber to the new effect's number of dice. This field is instead used for maximum hit-dice (HD) by some opcodes.
  • INT_VAR dicesize to the new effect's size of dice. This field is also instead for minimum hit-dice (HD) by some opcodes.
  • INT_VAR savingthrow to the new effect's saving-throw type.
  • INT_VAR savebonus to the new effect's saving-throw bonus/penalty. This variable can take negative values down to -10 while still writing to the corresponding field.
  • INT_VAR special to the new effect's special field. The special field is used by many EE effects.
  • STR_VAR resource to the new effect's resource reference.

Code: [Select]
DEFINE_PATCH_FUNCTION CLONE_EFFECT

  // defines what we're going to check
  INT_VAR check_globals       = 1
          check_headers       = 1     
          header              = "-1"   
          header_type         = "-1"
          multi_match         = 999
          debug               = 0

  // variables for finding the effect to match
          match_opcode        = "-1"   
          match_target        = "-1"   
          match_power         = "-1"   
          match_parameter1    = "-1"   
          match_parameter2    = "-1"   
          match_timing        = "-1"   
          match_resist_dispel = "-1"   
          match_duration      = "-1"   
          match_duration_high = "-1"   
          match_probability1  = "-1"   
          match_probability2  = "-1"   
          match_dicenumber    = "-1"   
          match_dicesize      = "-1"   
          match_savingthrow   = "-1"
          match_savebonus     = "-11"
          match_special       = "-1"

  // variables for the new effect
          opcode              = "-1"   
          target              = "-1"   
          power               = "-1"   
          parameter1          = "-1"   
          parameter2          = "-1"   
          timing              = "-1"   
          resist_dispel       = "-1"   
          duration            = "-1"   
          duration_high       = "-1"   
          probability1        = "-1"   
          probability2        = "-1"   
          dicenumber          = "-1"   
          dicesize            = "-1"
          savingthrow         = "-1"
          savebonus           = "-11"
          special             = "-1"

  // same for match and new STR_VAR
  STR_VAR match_resource      = "SAME"
          resource            = "SAME"
          insert              = "above"

BEGIN

  // set variables and offsets based on the file type
  SET new_fx = 0
  PATCH_IF ("%SOURCE_FILE%" STRING_COMPARE_REGEXP "^.+\.spl" = 0) BEGIN
    READ_LONG   0x6a fx_off   ELSE 0
    SET counter_offset = 0x70
    SET abil_length    = 0x28
    SET fx_type        = 0
    SET min_size       = 0x72
    PATCH_IF (check_headers = 0) BEGIN
      SET abil_num = 0
    END ELSE BEGIN
      READ_LONG   0x64 abil_off ELSE 0
      READ_SHORT  0x68 abil_num ELSE 0
    END
  END ELSE
  PATCH_IF ("%SOURCE_FILE%" STRING_COMPARE_REGEXP "^.+\.itm" = 0) BEGIN
    READ_LONG   0x6a fx_off   ELSE 0
    SET counter_offset = 0x70
    SET abil_length    = 0x38
    SET fx_type        = 0
    SET min_size       = 0x72
    PATCH_IF (check_headers = 0) BEGIN
      SET abil_num = 0
    END ELSE BEGIN
      READ_LONG   0x64 abil_off ELSE 0
      READ_SHORT  0x68 abil_num ELSE 0
    END
  END ELSE
  PATCH_IF ("%SOURCE_FILE%" STRING_COMPARE_REGEXP "^.+\.cre" = 0) BEGIN // creature effects treated like they're a single, global loop
    SET abil_off = 0 // basically prevents the ability effect loop
    SET abil_num = 0
    READ_LONG  0x2c4 fx_off ELSE 0
    SET counter_offset = 0x2c8
    SET abil_length = 0
    READ_BYTE 0x33 fx_type ELSE 2
    SET min_size = 0x2d4
    SET check_globals = 1
  END ELSE BEGIN
    SET min_size = "-1" // kill macro as the file type is not recognized
  END
  PATCH_IF (SOURCE_SIZE >= min_size) BEGIN // sanity check
    FOR (index = (0 - check_globals) ; index < abil_num ; ++index) BEGIN // we start at -1 for global effects
      PATCH_IF (index < 0) BEGIN // if loop through globals needed
        SET abil_fx_idx = 0  // start with effect 0 since we're in the global loop
        SET abil_type = "-1" // basically, ignore header type checks for global loop
      END ELSE BEGIN // otherwise normal ability
        READ_SHORT  (abil_off +        (abil_length * index)) abil_type
        SET counter_offset = (abil_off + 0x1e + (abil_length * index))
        WRITE_SHORT (abil_off + 0x20 + (abil_length * index)) (THIS + new_fx) // update index with previously added effects
        READ_SHORT  (abil_off + 0x20 + (abil_length * index)) abil_fx_idx
      END
      READ_SHORT counter_offset counter // fx_num on global loop, otherwise abil_fx_num
      PATCH_IF (((abil_type = header_type) OR (abil_type < 0) OR (header_type < 0)) AND // only look on the right header types, if specified...
                ((header = index) OR (header < 0))) BEGIN                               // and only on the right # header, if specified
        SET last = 0                              // and only on the right # header, if specified
        SET local_multi = multi_match
        FOR (index2 = 0 ; index2 < (counter - last) ; ++index2) BEGIN

          // read the variables from the current effect
          READ_SHORT (fx_off        + (0x08 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_opcode
          READ_BYTE  (fx_off + 0x02 + (0x0a * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_target
          READ_BYTE  (fx_off + 0x03 + (0x0d * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_power
          READ_LONG  (fx_off + 0x04 + (0x10 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_parameter1
          READ_LONG  (fx_off + 0x08 + (0x10 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_parameter2
          READ_BYTE  (fx_off + 0x0c + (0x10 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_timing
          READ_BYTE  (fx_off + 0x0d + (0x47 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_resist_dispel
          READ_LONG  (fx_off + 0x0e + (0x12 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_duration
          READ_BYTE  (fx_off + 0x12 + (0x12 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_probability1
          READ_BYTE  (fx_off + 0x13 + (0x13 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_probability2
          READ_ASCII (fx_off + 0x14 + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_resource
          READ_LONG  (fx_off + 0x1c + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_dicenumber
          READ_LONG  (fx_off + 0x20 + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_dicesize
          READ_LONG  (fx_off + 0x24 + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_savingthrow
          READ_LONG  (fx_off + 0x28 + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_savebonus
          READ_LONG  (fx_off + 0x2c + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_special

          // match ALL these variables, if specified
          PATCH_IF (((match_opcode        = o_opcode)        OR (match_opcode < 0))        AND
                    ((match_target        = o_target)        OR (match_target < 0))        AND
                    ((match_power         = o_power)         OR (match_power < 0))         AND
                    ((match_parameter1    = o_parameter1)    OR (match_parameter1 < 0))    AND
                    ((match_parameter2    = o_parameter2)    OR (match_parameter2 < 0))    AND
                    ((match_timing        = o_timing)        OR (match_timing < 0))        AND
                    ((match_resist_dispel = o_resist_dispel) OR (match_resist_dispel < 0)) AND
                    ((match_duration      = o_duration)      OR (match_duration < 0))      AND
                    ((match_probability1  = o_probability1)  OR (match_probability1 < 0))  AND
                    ((match_probability2  = o_probability2)  OR (match_probability2 < 0))  AND
                    ((match_dicenumber    = o_dicenumber)    OR (match_dicenumber < 0))    AND
                    ((match_dicesize      = o_dicesize)      OR (match_dicesize < 0))      AND
                    ((match_savingthrow   = o_savingthrow)   OR (match_savingthrow < 0))   AND
                    ((match_savebonus     = o_savebonus)     OR (match_savebonus < "-10")) AND
                    ((match_special       = o_special)       OR (match_special < 0))       AND
                    (("%match_resource%" STRING_COMPARE_CASE "%o_resource%" = 0) OR ("%match_resource%" STRING_COMPARE_CASE "SAME" = 0))) BEGIN

            // now that we've got a match, read-and-clone it:
            READ_ASCII   (fx_off        + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) clone (0x30 + (0xd8 * fx_type))
            PATCH_IF ("%insert%" STRING_COMPARE_CASE "below" = 0) BEGIN
              SET base = (fx_off        + ((abil_fx_idx + index2 + 1) * (0x30 + (0xd8 * fx_type))))
            END ELSE
            PATCH_IF ("%insert%" STRING_COMPARE_CASE "first" = 0) BEGIN
              SET base = (fx_off        + (abil_fx_idx * (0x30 + (0xd8 * fx_type))))
            END ELSE
            PATCH_IF ("%insert%" STRING_COMPARE_CASE "last" = 0) BEGIN
              SET base = (fx_off        + ((abil_fx_idx + counter) * (0x30 + (0xd8 * fx_type))))
            END ELSE BEGIN
              SET base = (fx_off        + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type))))
            END
            INSERT_BYTES base (0x30 + (0xd8 * fx_type))
            WRITE_ASCIIE base "%clone%"

            // overwrite the cloned effect with the new variables, if specified
            PATCH_IF (opcode >= 0)        BEGIN WRITE_SHORT (base        + (0x08 * fx_type)) opcode        END
            PATCH_IF (target >= 0)        BEGIN WRITE_BYTE  (base + 0x02 + (0x0a * fx_type)) target        END
            PATCH_IF (power >= 0)         BEGIN WRITE_BYTE  (base + 0x03 + (0x0d * fx_type)) power         END
            PATCH_IF (parameter1 >= 0)    BEGIN WRITE_LONG  (base + 0x04 + (0x10 * fx_type)) parameter1    END
            PATCH_IF (parameter2 >= 0)    BEGIN WRITE_LONG  (base + 0x08 + (0x10 * fx_type)) parameter2    END
            PATCH_IF (timing >= 0)        BEGIN WRITE_BYTE  (base + 0x0c + (0x10 * fx_type)) timing        END
            PATCH_IF (resist_dispel >= 0) BEGIN WRITE_BYTE  (base + 0x0d + (0x47 * fx_type)) resist_dispel END
            PATCH_IF (duration >= 0)      BEGIN WRITE_LONG  (base + 0x0e + (0x12 * fx_type)) duration      END
            PATCH_IF (probability1 >= 0)  BEGIN WRITE_BYTE  (base + 0x12 + (0x12 * fx_type)) probability1  END
            PATCH_IF (probability2 >= 0)  BEGIN WRITE_BYTE  (base + 0x13 + (0x13 * fx_type)) probability2  END
            PATCH_IF (dicenumber >= 0)    BEGIN WRITE_LONG  (base + 0x1c + (0x14 * fx_type)) dicenumber    END
            PATCH_IF (dicesize >= 0)      BEGIN WRITE_LONG  (base + 0x20 + (0x14 * fx_type)) dicesize      END
            PATCH_IF (savingthrow >= 0)   BEGIN WRITE_LONG  (base + 0x24 + (0x14 * fx_type)) savingthrow   END
            PATCH_IF (savebonus >= "-10") BEGIN WRITE_LONG  (base + 0x28 + (0x14 * fx_type)) savebonus     END
            PATCH_IF (special >= 0)       BEGIN WRITE_LONG  (base + 0x2c + (0x14 * fx_type)) special       END
            PATCH_IF ("%resource%" STRING_COMPARE_CASE "SAME" != 0) BEGIN
              WRITE_ASCIIE (base + 0x14 + (0x14 * fx_type)) "%resource%" #8
            END

            // update the tracking vars
            SET new_fx += 1
            SET counter += 1
            PATCH_IF (local_multi < 2) BEGIN  // kill loop if we only want one match
              SET index2 = counter
            END ELSE BEGIN // otherwise bump vars and keep going
              SET local_multi  -= 1
              PATCH_IF ("%insert%" STRING_COMPARE_CASE "last" = 0) BEGIN
                SET last += 1
              END ELSE BEGIN
                SET index2 += 1
              END
            END

          END // end patch_if for a matched effect
        END // end of the for loop through effects
      END // end patch_if for matched/specified headers
      WRITE_SHORT counter_offset counter // fx_num on global loop, otherwise abil_fx_num
    END // end loop through effects on ability
  END // end ability loop

  // now adjust offsets for creature files
  PATCH_IF (("%SOURCE_FILE%" STRING_COMPARE_REGEXP "^.+\.cre" = 0) AND (new_fx > 0)) BEGIN // fix offsets for cre files if fx inserted
    SET inserted = ((0x30 + (0xd8 * fx_type)) * new_fx)
    PATCH_FOR_EACH offset IN 0x2a0 0x2a8 0x2b0 0x2b8 0x2bc BEGIN
      READ_LONG offset off
      PATCH_IF (fx_off < off) BEGIN
        WRITE_LONG offset (off + inserted)
      END
    END
  END

  // spit out some info if debug is set
  PATCH_IF (debug = 1) BEGIN
    READ_LONG 0x0c strref
    PATCH_IF ((strref > 0) AND (strref < 200000)) BEGIN
      READ_STRREF 0x0c name
    END ELSE BEGIN
      READ_STRREF 0x08 name
    END
    PATCH_IF (new_fx = 0) BEGIN
      PATCH_PRINT "  Warning: No effects added to %SOURCE_FILE% (%name%)"
    END ELSE BEGIN
      PATCH_PRINT "              ~%SOURCE_FILE%~   ~override~ // %name%, %new_fx% effect(s) added"
    END
  END

END
« Last Edit: May 05, 2014, 01:09:05 PM by CamDawg »
The Gibberlings Three - Home of IE Mods

The BG2 Fixpack - All the fixes of Baldurdash, plus a few hundred more. Now available, with more fixes being added in every release.

Offline Wisp

  • Moderator
  • Planewalker
  • *****
  • Posts: 1176
Re: New CLONE_EFFECT macro
« Reply #1 on: April 03, 2014, 01:54:17 PM »
Looks nice. I'll give it a more thorough read/think at a later date but consider it tentatively included.

Offline CamDawg

  • Infidel
  • Planewalker
  • *****
  • Posts: 859
  • Dreaming of a red Xmas
    • The Gibberlings Three
Re: New CLONE_EFFECT macro
« Reply #2 on: April 03, 2014, 02:05:27 PM »
I've had a request to add an insert_point, so lemme take another run at this first.
The Gibberlings Three - Home of IE Mods

The BG2 Fixpack - All the fixes of Baldurdash, plus a few hundred more. Now available, with more fixes being added in every release.

Offline CamDawg

  • Infidel
  • Planewalker
  • *****
  • Posts: 859
  • Dreaming of a red Xmas
    • The Gibberlings Three
Re: New CLONE_EFFECT macro
« Reply #3 on: April 10, 2014, 08:13:26 AM »
Alright, I've added STR_VAR insert and updated the code and docs above. INT_VAR multi_match can now be fine-tuned to match 1, 2, or 1000 effects.

We're using these internally on a project, so we're going through some testing now to make sure everything works as it should.
The Gibberlings Three - Home of IE Mods

The BG2 Fixpack - All the fixes of Baldurdash, plus a few hundred more. Now available, with more fixes being added in every release.

Offline CamDawg

  • Infidel
  • Planewalker
  • *****
  • Posts: 859
  • Dreaming of a red Xmas
    • The Gibberlings Three
Re: New CLONE_EFFECT macro
« Reply #4 on: April 10, 2014, 08:44:43 AM »
In the same vein, I've been asked to code up a universal DELETE_EFFECT and ALTER_EFFECT. While these do essentially the same thing as the existing DELETE/ALTER series, there's a lot more fine-tuning available, so I'll leave inclusion/exclusion up to you. These are also being used at the moment, so it's likely I'll find and fix a few bugs here and there in the shakedown.

DELETE_EFFECT: This is a patch function for creature, item, or spell files that will match an existing effect and then delete it. Numerous variables are available for matching the specified effect.

The first batch of variables are meta-variables which will help determine the scope of the macro:

  • INT_VAR check_globals - This variable determines if the macro loops through global effects on items (also known as equipping effects) and spells if set to 1 (default is 1). Creature effects are all global effects, so this variable will always be considered to be one when this macro is run on a creature.
  • INT_VAR check_headers - This variable determines if the macro loops through effects on extended headers on items and spells if set to 1 (default is 1). Creatures have no extended headers, so this variable is ignored when used on creatures.
  • INT_VAR header - Allows the macro to target effects on one specific header, counting the first header as zero. A negative value will match all headers (default is -1). Creatures have no extended headers, so this variable is ignored when used on creatures.
  • INT_VAR header_type - Allows the macro to only seek out effects on extended headers of the specified type (1 - melee, 2 - ranged, etc.). Negative values will look at effects on all headers (default is -1). Creatures have no extended headers, so this variable is ignored when used on creatures.
  • INT_VAR multi_match - This variable determines how many effects to delete in the active stack. If you just want to match the first effect and have the macro stop, use 1. Otherwise the macro will continue matching until the number of deleted effects matches this value. The macro will always make at least one change (e.g. 0 or negative values are treated as 1). (default is 999).
  • INT_VAR debug - Spits out some very rudimentary information if the file is patched or not patched if set to 1 (default is 0).

The next batch of variables sets the macro boundaries on matching an effect to delete. Any variables not specified will not be used to determine a match. The macro will only determine an effect is a match only if ALL of the variables specified are matched.

  • INT_VAR match_opcode - This variable must be set to a non-zero value. This variable checks the opcode of effects for a match (default -1).
  • INT_VAR match_target - This variable checks the target of effects for a match (default -1).
  • INT_VAR match_power - This variable checks the power of effects for a match (default -1).
  • INT_VAR match_parameter1 - This variable checks parameter1 of effects for a match (default -1).
  • INT_VAR match_parameter2 - This variable checks parameter2 of effects for a match (default -1).
  • INT_VAR match_timing - This variable checks the timing of effects for a match (default -1).
  • INT_VAR match_resist_dispel - This variable checks the resist/dispel setting of effects for a match (default -1).
  • INT_VAR match_duration - This variable checks the duration of effects for a match (default -1).
  • INT_VAR match_probability1 - This variable checks probability1 (the upper bound) of effects for a match (default -1).
  • INT_VAR match_probability2 - This variable checks probability2 (the lower bound) of effects for a match (default -1).
  • INT_VAR match_dicenumber - This variable checks the number of dice of effects for a match (default -1). This field is instead used for maximum hit-dice (HD) by some opcodes.
  • INT_VAR match_dicesize - This variable checks the size of dice of effects for a match (default -1). This field is used instead for minimum hit-dice (HD) by some opcodes.
  • INT_VAR match_savingthrow - This variable checks the saving throw type of effects for a match (default -1).
  • INT_VAR match_savebonus - This variable checks the saving trow bonus effects for a match (default -11). Since saving throws can range into negative values, this variable can match all the way down to -10.
  • INT_VAR match_special  - This variable checks the special field of effects for a match (default -1). The special field is used by some EE effects.
  • STR_VAR match_resource - This variable checks the resource of effects for a match (default "SAME").

Once a matching effect is found it is deleted. The macro will continue to delete effects from the stack until the number of effects deleted matches the multi_match variable.

ALTER_EFFECT: This is a patch function for creature, item, or spell files that will match an existing effect and alter it based on the defined variables. Numerous variables are available for matching the specified effect and for specifying new values.

The first batch of variables are meta-variables which will help determine the scope of the macro:

  • INT_VAR check_globals - This variable determines if the macro loops through global effects on items (also known as equipping effects) and spells if set to 1 (default is 1). Creature effects are all global effects, so this variable will always be considered to be one when this macro is run on a creature.
  • INT_VAR check_headers - This variable determines if the macro loops through effects on extended headers on items and spells if set to 1 (default is 1). Creatures have no extended headers, so this variable is ignored when used on creatures.
  • INT_VAR header - Allows the macro to target effects on one specific header, counting the first header as zero. A negative value will match all headers (default is -1). Creatures have no extended headers, so this variable is ignored when used on creatures.
  • INT_VAR header_type - Allows the macro to only seek out effects on extended headers of the specified type (1 - melee, 2 - ranged, etc.). Negative values will look at effects on all headers (default is -1). Creatures have no extended headers, so this variable is ignored when used on creatures.
  • INT_VAR multi_match - This variable determines how many effects to alter in the active stack. If you just want to match the first effect and have the macro stop, use 1. Otherwise the macro will continue matching until the number of altered effects matches this value. The macro will always make at least one change (e.g. 0 or negative values are treated as 1). (default is 999).
  • INT_VAR debug - Spits out some very rudimentary information if the file is patched or not patched if set to 1 (default is 0).

The next batch of variables sets the macro boundaries on matching an effect to alter. Any variables not specified will not be used to determine a match. The macro will only determine an effect is a match only if ALL of the variables specified are matched.

  • INT_VAR match_opcode - This variable must be set to a non-zero value. This variable checks the opcode of effects for a match (default -1).
  • INT_VAR match_target - This variable checks the target of effects for a match (default -1).
  • INT_VAR match_power - This variable checks the power of effects for a match (default -1).
  • INT_VAR match_parameter1 - This variable checks parameter1 of effects for a match (default -1).
  • INT_VAR match_parameter2 - This variable checks parameter2 of effects for a match (default -1).
  • INT_VAR match_timing - This variable checks the timing of effects for a match (default -1).
  • INT_VAR match_resist_dispel - This variable checks the resist/dispel setting of effects for a match (default -1).
  • INT_VAR match_duration - This variable checks the duration of effects for a match (default -1).
  • INT_VAR match_probability1 - This variable checks probability1 (the upper bound) of effects for a match (default -1).
  • INT_VAR match_probability2 - This variable checks probability2 (the lower bound) of effects for a match (default -1).
  • INT_VAR match_dicenumber - This variable checks the number of dice of effects for a match (default -1). This field is instead used for maximum hit-dice (HD) by some opcodes.
  • INT_VAR match_dicesize - This variable checks the size of dice of effects for a match (default -1). This field is used instead for minimum hit-dice (HD) by some opcodes.
  • INT_VAR match_savingthrow - This variable checks the saving throw type of effects for a match (default -1).
  • INT_VAR match_savebonus - This variable checks the saving trow bonus effects for a match (default -11). Since saving throws can range into negative values, this variable can match all the way down to -10.
  • INT_VAR match_special  - This variable checks the special field of effects for a match (default -1). The special field is used by some EE effects.
  • STR_VAR match_resource - This variable checks the resource of effects for a match (default "SAME").

Once a matching effect is found, the next series of variables allows the macro to change the fields to these new values in the matched effect. Any variables not set in this batch will keep their existing values.

  • INT_VAR opcode to the value the of the altered effect's opcode.
  • INT_VAR target to the altered effect's target.
  • INT_VAR power to the altered effect's power.
  • INT_VAR parameter1 to the altered effect's parameter1.
  • INT_VAR parameter2 to the altered effect's parameter2.
  • INT_VAR timing to the altered effect's timing mode.
  • INT_VAR resist_dispel to the altered effect's resist/dispel setting.
  • INT_VAR duration to the altered effect's duration.
  • INT_VAR probability1 to the altered effect's probability1 (the upper bound).
  • INT_VAR probability2 to the altered effect's probability2 (the lower bound).
  • INT_VAR dicenumber to the altered effect's number of dice. This field is instead used for maximum hit-dice (HD) by some opcodes.
  • INT_VAR dicesize to the altered effect's size of dice. This field is also instead for minimum hit-dice (HD) by some opcodes.
  • INT_VAR savingthrow to the altered effect's saving-throw type.
  • INT_VAR savebonus to the altered effect's saving-throw bonus/penalty. This variable can take negative values down to -10 while still writing to the corresponding field.
  • INT_VAR special to the new effect's special field. The special field is used by many EE effects.
  • STR_VAR resource to the altered effect's resource reference.

Code: [Select]
DEFINE_PATCH_FUNCTION DELETE_EFFECT

  // defines what we're going to check
  INT_VAR check_globals       = 1     
          check_headers       = 1     
          header              = "-1"   
          header_type         = "-1"
          multi_match         = 999
          debug               = 0

  // variables for finding the effect to match
          match_opcode        = "-1"   
          match_target        = "-1"   
          match_power         = "-1"   
          match_parameter1    = "-1"   
          match_parameter2    = "-1"   
          match_timing        = "-1"   
          match_resist_dispel = "-1"   
          match_duration      = "-1"   
          match_duration_high = "-1"   
          match_probability1  = "-1"   
          match_probability2  = "-1"   
          match_dicenumber    = "-1"   
          match_dicesize      = "-1"
          match_savingthrow   = "-1"
          match_savebonus     = "-11"
          match_special       = "-1"

  // same for match and new STR_VAR
  STR_VAR match_resource      = "SAME"

BEGIN

  // set variables and offsets based on the file type
  SET new_fx = 0
  PATCH_IF ("%SOURCE_FILE%" STRING_COMPARE_REGEXP "^.+\.spl" = 0) BEGIN
    READ_LONG   0x6a fx_off   ELSE 0
    SET counter_offset = 0x70
    SET abil_length    = 0x28
    SET fx_type        = 0
    SET min_size       = 0x72
    PATCH_IF (check_headers = 0) BEGIN
      SET abil_num = 0
    END ELSE BEGIN
      READ_LONG   0x64 abil_off ELSE 0
      READ_SHORT  0x68 abil_num ELSE 0
    END
  END ELSE
  PATCH_IF ("%SOURCE_FILE%" STRING_COMPARE_REGEXP "^.+\.itm" = 0) BEGIN
    READ_LONG   0x6a fx_off   ELSE 0
    SET counter_offset = 0x70
    SET abil_length    = 0x38
    SET fx_type        = 0
    SET min_size       = 0x72
    PATCH_IF (check_headers = 0) BEGIN
      SET abil_num = 0
    END ELSE BEGIN
      READ_LONG   0x64 abil_off ELSE 0
      READ_SHORT  0x68 abil_num ELSE 0
    END
  END ELSE
  PATCH_IF ("%SOURCE_FILE%" STRING_COMPARE_REGEXP "^.+\.cre" = 0) BEGIN // creature effects treated like they're a single, global loop
    SET abil_off = 0 // basically prevents the ability effect loop
    SET abil_num = 0
    READ_LONG  0x2c4 fx_off ELSE 0
    SET counter_offset = 0x2c8
    SET abil_length = 0
    READ_BYTE 0x33 fx_type ELSE 2
    SET min_size = 0x2d4
    SET check_globals = 1
  END ELSE BEGIN
    SET min_size = "-1" // kill macro as the file type is not recognized
  END
  PATCH_IF (SOURCE_SIZE >= min_size) BEGIN // sanity check
    FOR (index = (0 - check_globals) ; index < abil_num ; ++index) BEGIN // we start at -1 for global effects
      PATCH_IF (index < 0) BEGIN // if loop through globals needed
        SET abil_fx_idx = 0  // start with effect 0 since we're in the global loop
        SET abil_type = "-1" // basically, ignore header type checks for global loop
      END ELSE BEGIN // otherwise normal ability
        READ_SHORT  (abil_off +        (abil_length * index)) abil_type
        SET counter_offset = (abil_off + 0x1e + (abil_length * index))
        WRITE_SHORT (abil_off + 0x20 + (abil_length * index)) (THIS + new_fx) // update index with previously added effects
        READ_SHORT  (abil_off + 0x20 + (abil_length * index)) abil_fx_idx
      END
      READ_SHORT counter_offset counter // fx_num on global loop, otherwise abil_fx_num
      PATCH_IF (((abil_type = header_type) OR (abil_type < 0) OR (header_type < 0)) AND // only look on the right header types, if specified...
                ((header = index) OR (header < 0))) BEGIN                               // and only on the right # header, if specified
        SET local_multi = multi_match
        FOR (index2 = 0 ; index2 < counter ; ++index2) BEGIN

          // read the variables from the current effect
          READ_SHORT (fx_off        + (0x08 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_opcode
          READ_BYTE  (fx_off + 0x02 + (0x0a * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_target
          READ_BYTE  (fx_off + 0x03 + (0x0d * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_power
          READ_LONG  (fx_off + 0x04 + (0x10 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_parameter1
          READ_LONG  (fx_off + 0x08 + (0x10 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_parameter2
          READ_BYTE  (fx_off + 0x0c + (0x10 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_timing
          READ_BYTE  (fx_off + 0x0d + (0x47 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_resist_dispel
          READ_LONG  (fx_off + 0x0e + (0x12 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_duration
          READ_BYTE  (fx_off + 0x12 + (0x12 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_probability1
          READ_BYTE  (fx_off + 0x13 + (0x13 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_probability2
          READ_ASCII (fx_off + 0x14 + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_resource
          READ_LONG  (fx_off + 0x1c + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_dicenumber
          READ_LONG  (fx_off + 0x20 + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_dicesize
          READ_LONG  (fx_off + 0x24 + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_savingthrow
          READ_LONG  (fx_off + 0x28 + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_savebonus
          READ_LONG  (fx_off + 0x2c + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_special

          // match ALL these variables, if specified
          PATCH_IF (((match_opcode        = o_opcode)        OR (match_opcode < 0))        AND
                    ((match_target        = o_target)        OR (match_target < 0))        AND
                    ((match_power         = o_power)         OR (match_power < 0))         AND
                    ((match_parameter1    = o_parameter1)    OR (match_parameter1 < 0))    AND
                    ((match_parameter2    = o_parameter2)    OR (match_parameter2 < 0))    AND
                    ((match_timing        = o_timing)        OR (match_timing < 0))        AND
                    ((match_resist_dispel = o_resist_dispel) OR (match_resist_dispel < 0)) AND
                    ((match_duration      = o_duration)      OR (match_duration < 0))      AND
                    ((match_probability1  = o_probability1)  OR (match_probability1 < 0))  AND
                    ((match_probability2  = o_probability2)  OR (match_probability2 < 0))  AND
                    ((match_dicenumber    = o_dicenumber)    OR (match_dicenumber < 0))    AND
                    ((match_dicesize      = o_dicesize)      OR (match_dicesize < 0))      AND
                    ((match_savingthrow   = o_savingthrow)   OR (match_savingthrow < 0))   AND
                    ((match_savebonus     = o_savebonus)     OR (match_savebonus < "-10")) AND
                    ((match_special       = o_special)       OR (match_special < 0))       AND
                    (("%match_resource%" STRING_COMPARE_CASE "%o_resource%" = 0) OR ("%match_resource%" STRING_COMPARE_CASE "SAME" = 0))) BEGIN

            // now that we've got a match, read-and-clone it:
            DELETE_BYTES   (fx_off        + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) (0x30 + (0xd8 * fx_type))

            // update the tracking vars
            SET new_fx -= 1
            SET counter -= 1
            SET index2 -= 1
            PATCH_IF (local_multi < 2) BEGIN  // kill loop if we only want one match
              SET index2 = counter
            END ELSE BEGIN // otherwise bump vars and keep going
              SET local_multi  -= 1
            END

          END // end patch_if for a matched effect
        END // end of the for loop through effects
      END // end patch_if for matched/specified headers
      WRITE_SHORT counter_offset counter // fx_num on global loop, otherwise abil_fx_num
    END // end loop through effects on ability
  END // end ability loop

  // now adjust offsets for creature files
  PATCH_IF (("%SOURCE_FILE%" STRING_COMPARE_REGEXP "^.+\.cre" = 0) AND (new_fx != 0)) BEGIN // fix offsets for cre files if fx inserted
    SET inserted = ((0x30 + (0xd8 * fx_type)) * new_fx)
    PATCH_FOR_EACH offset IN 0x2a0 0x2a8 0x2b0 0x2b8 0x2bc BEGIN
      READ_LONG offset off
      PATCH_IF (fx_off < off) BEGIN
        WRITE_LONG offset (off + inserted)
      END
    END
  END

  // spit out some info if debug is set
  PATCH_IF (debug = 1) BEGIN
    READ_LONG 0x0c strref
    PATCH_IF ((strref > 0) AND (strref < 200000)) BEGIN
      READ_STRREF 0x0c name
    END ELSE BEGIN
      READ_STRREF 0x08 name
    END
    PATCH_IF (new_fx = 0) BEGIN
      PATCH_PRINT "  Warning: No effects added to %SOURCE_FILE% (%name%)"
    END ELSE BEGIN
      PATCH_PRINT "              ~%SOURCE_FILE%~   ~override~ // %name%, %new_fx% effect(s) deleted"
    END
  END

END

DEFINE_PATCH_FUNCTION ALTER_EFFECT

  // defines what we're going to check
  INT_VAR check_globals       = 1     
          check_headers       = 1
          header              = "-1"   
          header_type         = "-1"
          multi_match         = 999
          debug               = 0

  // variables for finding the effect to match
          match_opcode        = "-1"   
          match_target        = "-1"   
          match_power         = "-1"   
          match_parameter1    = "-1"   
          match_parameter2    = "-1"   
          match_timing        = "-1"   
          match_resist_dispel = "-1"   
          match_duration      = "-1"   
          match_duration_high = "-1"   
          match_probability1  = "-1"   
          match_probability2  = "-1"   
          match_dicenumber    = "-1"   
          match_dicesize      = "-1"
          match_savingthrow   = "-1"
          match_savebonus     = "-11"
          match_special       = "-1"

  // variables for the new effect
          opcode              = "-1"   
          target              = "-1"   
          power               = "-1"   
          parameter1          = "-1"   
          parameter2          = "-1"   
          timing              = "-1"   
          resist_dispel       = "-1"   
          duration            = "-1"   
          duration_high       = "-1"   
          probability1        = "-1"   
          probability2        = "-1"   
          dicenumber          = "-1"   
          dicesize            = "-1"
          savingthrow         = "-1"   
          savebonus           = "-11"
          special             = "-1"

  // same for match and new STR_VAR
  STR_VAR match_resource      = "SAME"
          resource            = "SAME"

BEGIN

  // set variables and offsets based on the file type
  SET alter = 0
  PATCH_IF ("%SOURCE_FILE%" STRING_COMPARE_REGEXP "^.+\.spl" = 0) BEGIN
    READ_LONG   0x6a fx_off   ELSE 0
    SET counter_offset = 0x70
    SET abil_length    = 0x28
    SET fx_type        = 0
    SET min_size       = 0x72
    PATCH_IF (check_headers = 0) BEGIN
      SET abil_num = 0
    END ELSE BEGIN
      READ_LONG   0x64 abil_off ELSE 0
      READ_SHORT  0x68 abil_num ELSE 0
    END
  END ELSE
  PATCH_IF ("%SOURCE_FILE%" STRING_COMPARE_REGEXP "^.+\.itm" = 0) BEGIN
    READ_LONG   0x6a fx_off   ELSE 0
    SET counter_offset = 0x70
    SET abil_length    = 0x38
    SET fx_type        = 0
    SET min_size       = 0x72
    PATCH_IF (check_headers = 0) BEGIN
      SET abil_num = 0
    END ELSE BEGIN
      READ_LONG   0x64 abil_off ELSE 0
      READ_SHORT  0x68 abil_num ELSE 0
    END
  END ELSE
  PATCH_IF ("%SOURCE_FILE%" STRING_COMPARE_REGEXP "^.+\.cre" = 0) BEGIN // creature effects treated like they're a single, global loop
    SET abil_off = 0 // basically prevents the ability effect loop
    SET abil_num = 0
    READ_LONG  0x2c4 fx_off ELSE 0
    SET counter_offset = 0x2c8
    SET abil_length = 0
    READ_BYTE 0x33 fx_type ELSE 2
    SET min_size = 0x2d4
    SET check_globals = 1
  END ELSE BEGIN
    SET min_size = "-1" // kill macro as the file type is not recognized
  END
  PATCH_IF (SOURCE_SIZE >= min_size) BEGIN // sanity check
    FOR (index = (0 - check_globals) ; index < abil_num ; ++index) BEGIN // we start at -1 for global effects
      PATCH_IF (index < 0) BEGIN // if loop through globals needed
        SET abil_fx_idx = 0  // start with effect 0 since we're in the global loop
        SET abil_type = "-1" // basically, ignore header type checks for global loop
      END ELSE BEGIN // otherwise normal ability
        READ_SHORT  (abil_off +        (abil_length * index)) abil_type
        SET counter_offset = (abil_off + 0x1e + (abil_length * index))
        READ_SHORT  (abil_off + 0x20 + (abil_length * index)) abil_fx_idx
      END
      READ_SHORT counter_offset counter // fx_num on global loop, otherwise abil_fx_num
      PATCH_IF (((abil_type = header_type) OR (abil_type < 0) OR (header_type < 0)) AND // only look on the right header types, if specified...
                ((header = index) OR (header < 0))) BEGIN                               // and only on the right # header, if specified
        SET local_multi = multi_match
        FOR (index2 = 0 ; index2 < counter ; ++index2) BEGIN

          // read the variables from the current effect
          READ_SHORT (fx_off        + (0x08 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_opcode
          READ_BYTE  (fx_off + 0x02 + (0x0a * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_target
          READ_BYTE  (fx_off + 0x03 + (0x0d * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_power
          READ_LONG  (fx_off + 0x04 + (0x10 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_parameter1
          READ_LONG  (fx_off + 0x08 + (0x10 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_parameter2
          READ_BYTE  (fx_off + 0x0c + (0x10 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_timing
          READ_BYTE  (fx_off + 0x0d + (0x47 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_resist_dispel
          READ_LONG  (fx_off + 0x0e + (0x12 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_duration
          READ_BYTE  (fx_off + 0x12 + (0x12 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_probability1
          READ_BYTE  (fx_off + 0x13 + (0x13 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_probability2
          READ_ASCII (fx_off + 0x14 + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_resource
          READ_LONG  (fx_off + 0x1c + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_dicenumber
          READ_LONG  (fx_off + 0x20 + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_dicesize
          READ_LONG  (fx_off + 0x24 + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_savingthrow
          READ_LONG  (fx_off + 0x28 + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_savebonus
          READ_LONG  (fx_off + 0x2c + (0x14 * fx_type) + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type)))) o_special

          // match ALL these variables, if specified
          PATCH_IF (((match_opcode        = o_opcode)        OR (match_opcode < 0))        AND
                    ((match_target        = o_target)        OR (match_target < 0))        AND
                    ((match_power         = o_power)         OR (match_power < 0))         AND
                    ((match_parameter1    = o_parameter1)    OR (match_parameter1 < 0))    AND
                    ((match_parameter2    = o_parameter2)    OR (match_parameter2 < 0))    AND
                    ((match_timing        = o_timing)        OR (match_timing < 0))        AND
                    ((match_resist_dispel = o_resist_dispel) OR (match_resist_dispel < 0)) AND
                    ((match_duration      = o_duration)      OR (match_duration < 0))      AND
                    ((match_probability1  = o_probability1)  OR (match_probability1 < 0))  AND
                    ((match_probability2  = o_probability2)  OR (match_probability2 < 0))  AND
                    ((match_dicenumber    = o_dicenumber)    OR (match_dicenumber < 0))    AND
                    ((match_dicesize      = o_dicesize)      OR (match_dicesize < 0))      AND
                    ((match_savingthrow   = o_savingthrow)   OR (match_savingthrow < 0))   AND
                    ((match_savebonus     = o_savebonus)     OR (match_savebonus < "-10")) AND
                    ((match_special       = o_special)       OR (match_special < 0))       AND
                    (("%match_resource%" STRING_COMPARE_CASE "%o_resource%" = 0) OR ("%match_resource%" STRING_COMPARE_CASE "SAME" = 0))) BEGIN

            // lazily re-use code
            SET base = (fx_off        + ((abil_fx_idx + index2) * (0x30 + (0xd8 * fx_type))))

            // overwrite the cloned effect with the new variables, if specified
            PATCH_IF (opcode >= 0)        BEGIN WRITE_SHORT (base        + (0x08 * fx_type)) opcode        END
            PATCH_IF (target >= 0)        BEGIN WRITE_BYTE  (base + 0x02 + (0x0a * fx_type)) target        END
            PATCH_IF (power >= 0)         BEGIN WRITE_BYTE  (base + 0x03 + (0x0d * fx_type)) power         END
            PATCH_IF (parameter1 >= 0)    BEGIN WRITE_LONG  (base + 0x04 + (0x10 * fx_type)) parameter1    END
            PATCH_IF (parameter2 >= 0)    BEGIN WRITE_LONG  (base + 0x08 + (0x10 * fx_type)) parameter2    END
            PATCH_IF (timing >= 0)        BEGIN WRITE_BYTE  (base + 0x0c + (0x10 * fx_type)) timing        END
            PATCH_IF (resist_dispel >= 0) BEGIN WRITE_BYTE  (base + 0x0d + (0x47 * fx_type)) resist_dispel END
            PATCH_IF (duration >= 0)      BEGIN WRITE_LONG  (base + 0x0e + (0x12 * fx_type)) duration      END
            PATCH_IF (probability1 >= 0)  BEGIN WRITE_BYTE  (base + 0x12 + (0x12 * fx_type)) probability1  END
            PATCH_IF (probability2 >= 0)  BEGIN WRITE_BYTE  (base + 0x13 + (0x13 * fx_type)) probability2  END
            PATCH_IF (dicenumber >= 0)    BEGIN WRITE_LONG  (base + 0x1c + (0x14 * fx_type)) dicenumber    END
            PATCH_IF (dicesize >= 0)      BEGIN WRITE_LONG  (base + 0x20 + (0x14 * fx_type)) dicesize      END
            PATCH_IF (savingthrow >= 0)   BEGIN WRITE_LONG  (base + 0x24 + (0x14 * fx_type)) savingthrow   END
            PATCH_IF (savebonus >= "-10") BEGIN WRITE_LONG  (base + 0x28 + (0x14 * fx_type)) savebonus     END
            PATCH_IF (special >= 0)       BEGIN WRITE_LONG  (base + 0x2c + (0x14 * fx_type)) special       END
            PATCH_IF ("%resource%" STRING_COMPARE_CASE "SAME" != 0) BEGIN
              WRITE_ASCIIE (base + 0x14 + (0x14 * fx_type)) "%resource%" #8
            END

            // update the tracking vars
            SET alter += 1
            PATCH_IF (local_multi < 2) BEGIN  // kill loop if we only want one match
              SET index2 = counter
            END ELSE BEGIN // otherwise bump vars and keep going
              SET local_multi  -= 1
            END

          END // end patch_if for a matched effect
        END // end of the for loop through effects
      END // end patch_if for matched/specified headers
    END // end loop through effects on ability
  END // end ability loop

  // spit out some info if debug is set
  PATCH_IF (debug = 1) BEGIN
    READ_LONG 0x0c strref
    PATCH_IF ((strref > 0) AND (strref < 200000)) BEGIN
      READ_STRREF 0x0c name
    END ELSE BEGIN
      READ_STRREF 0x08 name
    END
    PATCH_IF (alter = 0) BEGIN
      PATCH_PRINT "  Warning: No effects altered on %SOURCE_FILE% (%name%)"
    END ELSE BEGIN
      PATCH_PRINT "              ~%SOURCE_FILE%~   ~override~ // %name%, %alter% effect(s) altered"
    END
  END

END
« Last Edit: May 05, 2014, 01:11:27 PM by CamDawg »
The Gibberlings Three - Home of IE Mods

The BG2 Fixpack - All the fixes of Baldurdash, plus a few hundred more. Now available, with more fixes being added in every release.

Offline CamDawg

  • Infidel
  • Planewalker
  • *****
  • Posts: 859
  • Dreaming of a red Xmas
    • The Gibberlings Three
Re: New CLONE_EFFECT macro
« Reply #5 on: May 05, 2014, 01:12:41 PM »
One last batch of requested changes--match_opcode is no longer required, and support added for matching/setting the 'special' field, which is used by some EE effects.

We've been using these for the past month-ish, so I feel pretty good about being bug-free. I don't think I'll have further changes.
« Last Edit: May 05, 2014, 02:27:32 PM by CamDawg »
The Gibberlings Three - Home of IE Mods

The BG2 Fixpack - All the fixes of Baldurdash, plus a few hundred more. Now available, with more fixes being added in every release.

Offline Wisp

  • Moderator
  • Planewalker
  • *****
  • Posts: 1176
Re: New CLONE_EFFECT macro
« Reply #6 on: August 01, 2014, 02:23:23 PM »
I'm going over this bit by bit.

CLONE_EFFECT:
I'm altering the implementation to check the signature instead of SOURCE_FILE, since the latter can be screwed with by INNER_ACTION.
Likewise, BUFFER_LENGTH instead of SOURCE_SIZE.
I'm cutting the debug variable and providing debug information as needed. Also WARN instead of PRINT on warnings.
I'm adding a verbose variable for the information printed on success.

Offline Wisp

  • Moderator
  • Planewalker
  • *****
  • Posts: 1176
Re: New CLONE_EFFECT macro
« Reply #7 on: August 02, 2014, 07:41:50 AM »
(ALTER|DELETE)_EFFECT:
The problem is we already have this functionality, albeit under different interfaces, and I don't want to add yet more code for doing things we can already do. I'm not opposed to smarter interfaces, so my preferred course of action would be to amend the interfaces of existing functions to include the additional functionality offered by (ALTER|DELETE)_EFFECT and then use this to implement (ALTER|DELETE)_EFFECT. I can do this if no one else wants to, but I'm not sure I'll be able to do it in time for v237.
« Last Edit: August 02, 2014, 07:44:50 AM by Wisp »

Offline Wisp

  • Moderator
  • Planewalker
  • *****
  • Posts: 1176
Re: New CLONE_EFFECT macro
« Reply #8 on: August 03, 2014, 08:32:26 AM »
(ALTER|DELETE)_EFFECT:
Instead of being uncooperative I'll include them now and refactor later.
Same type of changes as what CLONE_EFFECT got, except DELETE_EFFECT does not warn if no effects were deleted.

Thanks, CamDawg.

 

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)?: