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.
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