If we're suggesting functions, here's a bunch I've been using for lazy IWD/BGEE fixpack patching. I'll happily write up docs if they get included:
DEFINE_PATCH_FUNCTION cd_convert_bg_iwd_durations BEGIN
READ_LONG 0x6a fx_off
READ_LONG 0x64 abil_off
READ_SHORT 0x68 abil_num
PATCH_IF ("%SOURCE_FILE%" STRING_COMPARE_REGEXP "^.+\.itm" = 0) BEGIN SET abil_length = 0x38 END ELSE BEGIN SET abil_length = 0x28 END
PATCH_IF (abil_num > 0) BEGIN // if there are headers, figure out the final effect
READ_SHORT (abil_off + 0x1e + ((abil_num - 1) * abil_length)) abil_fx_num
READ_SHORT (abil_off + 0x20 + ((abil_num - 1) * abil_length)) abil_fx_idx
SET fx_num = abil_fx_num + abil_fx_idx
END ELSE BEGIN // else read the last global
READ_SHORT 0x70 fx_num
END
FOR (index = 0 ; index < fx_num ; ++index) BEGIN
READ_LONG (fx_off + 0x0e + (index * 0x30)) duration
PATCH_IF (duration > 5) BEGIN // skip 0 duration or short lived cosmetic/auditory
WRITE_LONG (fx_off + 0x0e + (index * 0x30)) ((duration * 7) / 6)
END
END
END
///// \\\\\
///// area functions \\\\\
///// \\\\\
DEFINE_PATCH_FUNCTION cd_area_alter_entrance
INT_VAR x_coord = "-1" // negative values not written
y_coord = "-1" // negative values not written
orient = "-1" // negative values not written
STR_VAR entry_name = ""
BEGIN
READ_LONG 0x68 ent_off
READ_LONG 0x6c ent_num
FOR (index = 0 ; index < ent_num ; ++index) BEGIN
READ_ASCII (ent_off + (index * 0x68)) "ent_name" (32) NULL
PATCH_IF ("%ent_name%" STRING_COMPARE_REGEXP "%entry_name%" = 0) BEGIN
PATCH_IF ("%x_coord%" >= 0) BEGIN WRITE_SHORT (ent_off + 0x20 + (index * 0x68)) "%x_coord%" END
PATCH_IF ("%y_coord%" >= 0) BEGIN WRITE_SHORT (ent_off + 0x22 + (index * 0x68)) "%y_coord%" END
PATCH_IF ("%orient%" >= 0) BEGIN WRITE_LONG (ent_off + 0x24 + (index * 0x68)) "%orient%" END
END
END
END
DEFINE_PATCH_FUNCTION cd_area_alter_triggers
INT_VAR type = "-1"
cursor = "-1"
trap_detect = "-1"
trap_remove = "-1"
trapped = "-1"
detected = "-1"
flag_locked = "-1"
flag_resets = "-1"
flag_party_required = "-1"
flag_trap_detectable = "-1"
flag_trap_enemies = "-1"
flag_tutorial = "-1"
flag_trap_npcs = "-1"
flag_silent = "-1"
flag_deactivated = "-1"
flag_impassable_npc = "-1"
flag_activation_point = "-1"
flag_connect_to_door = "-1"
STR_VAR trig_name = ""
dest_area = "same"
ent_name = "same"
door_key = "same"
door_script = "same"
BEGIN
READ_SHORT 0x5a trig_num
READ_LONG 0x5c trig_off
FOR (index = 0 ; index < trig_num ; ++index) BEGIN
READ_ASCII (trig_off + (index * 0xc4)) "trig_name_file" (32) NULL
PATCH_IF ("%trig_name%" STRING_COMPARE_REGEXP "%trig_name_file%" = 0) BEGIN
PATCH_IF ("%type%" >= 0) BEGIN WRITE_SHORT (trig_off + 0x20 + (index * 0xc4)) "%type%" END
PATCH_IF ("%cursor%" >= 0) BEGIN WRITE_LONG (trig_off + 0x34 + (index * 0xc4)) "%cursor%" END
PATCH_IF ("%trap_detect%" >= 0) BEGIN WRITE_SHORT (trig_off + 0x68 + (index * 0xc4)) "%trap_detect%" END
PATCH_IF ("%trap_remove%" >= 0) BEGIN WRITE_SHORT (trig_off + 0x6a + (index * 0xc4)) "%trap_remove%" END
PATCH_IF ("%trapped%" >= 0) BEGIN WRITE_SHORT (trig_off + 0x6c + (index * 0xc4)) "%trapped%" END
PATCH_IF ("%detected%" >= 0) BEGIN WRITE_SHORT (trig_off + 0x6e + (index * 0xc4)) "%detected%" END
PATCH_IF ("%flag_locked%" = 0) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BAND 0b11111110) END
PATCH_IF ("%flag_resets%" = 0) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BAND 0b11111101) END
PATCH_IF ("%flag_party_required%" = 0) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BAND 0b11111011) END
PATCH_IF ("%flag_trap_detectable%" = 0) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BAND 0b11110111) END
PATCH_IF ("%flag_trap_enemies%" = 0) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BAND 0b11101111) END
PATCH_IF ("%flag_tutorial%" = 0) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BAND 0b11011111) END
PATCH_IF ("%flag_trap_npcs%" = 0) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BAND 0b10111111) END
PATCH_IF ("%flag_silent%" = 0) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BAND 0b01111111) END
PATCH_IF ("%flag_deactivated%" = 0) BEGIN WRITE_BYTE (trig_off + 0x61 + (index * 0xc4)) (THIS BAND 0b11111110) END
PATCH_IF ("%flag_impassable_npc%" = 0) BEGIN WRITE_BYTE (trig_off + 0x61 + (index * 0xc4)) (THIS BAND 0b11111101) END
PATCH_IF ("%flag_activation_point%" = 0) BEGIN WRITE_BYTE (trig_off + 0x61 + (index * 0xc4)) (THIS BAND 0b11111011) END
PATCH_IF ("%flag_connect_to_door%" = 0) BEGIN WRITE_BYTE (trig_off + 0x61 + (index * 0xc4)) (THIS BAND 0b11110111) END
PATCH_IF ("%flag_locked%" = 1) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BOR BIT0) END
PATCH_IF ("%flag_resets%" = 1) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BOR BIT1) END
PATCH_IF ("%flag_party_required%" = 1) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BOR BIT2) END
PATCH_IF ("%flag_trap_detectable%" = 1) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BOR BIT3) END
PATCH_IF ("%flag_trap_enemies%" = 1) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BOR BIT4) END
PATCH_IF ("%flag_tutorial%" = 1) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BOR BIT5) END
PATCH_IF ("%flag_trap_npcs%" = 1) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BOR BIT6) END
PATCH_IF ("%flag_silent%" = 1) BEGIN WRITE_BYTE (trig_off + 0x60 + (index * 0xc4)) (THIS BOR BIT7) END
PATCH_IF ("%flag_deactivated%" = 1) BEGIN WRITE_BYTE (trig_off + 0x61 + (index * 0xc4)) (THIS BOR BIT0) END
PATCH_IF ("%flag_impassable_npc%" = 1) BEGIN WRITE_BYTE (trig_off + 0x61 + (index * 0xc4)) (THIS BOR BIT1) END
PATCH_IF ("%flag_activation_point%" = 1) BEGIN WRITE_BYTE (trig_off + 0x61 + (index * 0xc4)) (THIS BOR BIT2) END
PATCH_IF ("%flag_connect_to_door%" = 1) BEGIN WRITE_BYTE (trig_off + 0x61 + (index * 0xc4)) (THIS BOR BIT3) END
PATCH_IF ("%dest_area%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (trig_off + 0x38 + (index * 0xc4)) "%dest_area%" #8 // value from str_var
END
PATCH_IF ("%ent_name%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (trig_off + 0x40 + (index * 0xc4)) "%ent_name%" #32 // value from str_var
END
PATCH_IF ("%door_key%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (trig_off + 0x74 + (index * 0xc4)) "%door_key%" #8 // value from str_var
END
PATCH_IF ("%door_script%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (trig_off + 0x7c + (index * 0xc4)) "%door_script%" #8 // value from str_var
END
END
END
END
DEFINE_PATCH_FUNCTION cd_area_alter_cre
INT_VAR x_coord = "-1"
y_coord = "-1"
orient = "-1"
STR_VAR cre_name = ""
dlg_file = "same"
script_override = "same"
script_general = "same"
script_class = "same"
script_race = "same"
script_default = "same"
script_specifics = "same"
cre_file = "same"
BEGIN
READ_LONG 0x54 cre_off
READ_SHORT 0x58 cre_num
FOR (index = 0 ; index < cre_num ; ++index) BEGIN
READ_ASCII (cre_off + (index * 0x110)) cre_name_file (32) NULL
PATCH_IF ("%cre_name%" STRING_COMPARE_CASE "%cre_name_file%" = 0) BEGIN
PATCH_IF ("%x_coord%" >= 0) BEGIN WRITE_SHORT (cre_off + 0x20 + (index * 0x110)) "%x_coord%"
WRITE_SHORT (cre_off + 0x24 + (index * 0x110)) "%x_coord%" END
PATCH_IF ("%y_coord%" >= 0) BEGIN WRITE_SHORT (cre_off + 0x22 + (index * 0x110)) "%y_coord%"
WRITE_SHORT (cre_off + 0x26 + (index * 0x110)) "%y_coord%" END
PATCH_IF ("%orient%" >= 0) BEGIN WRITE_SHORT (cre_off + 0x34 + (index * 0x110)) "%orient%" END
PATCH_IF ("%dlg_file%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (cre_off + 0x48 + (index * 0x110)) "%dlg_file%" #8 // value from str_var
END
PATCH_IF ("%script_override%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (cre_off + 0x50 + (index * 0x110)) "%script_override%" #8 // value from str_var
END
PATCH_IF ("%script_general%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (cre_off + 0x58 + (index * 0x110)) "%script_general%" #8 // value from str_var
END
PATCH_IF ("%script_race%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (cre_off + 0x68 + (index * 0x110)) "%script_race%" #8 // value from str_var
END
PATCH_IF ("%script_default%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (cre_off + 0x70 + (index * 0x110)) "%script_default%" #8 // value from str_var
END
PATCH_IF ("%script_class%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (cre_off + 0x60 + (index * 0x110)) "%script_class%" #8 // value from str_var
END
PATCH_IF ("%script_specifics%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (cre_off + 0x78 + (index * 0x110)) "%script_specifics%" #8 // value from str_var
END
PATCH_IF ("%cre_file%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (cre_off + 0x80 + (index * 0x110)) "%cre_file%" #8 // value from str_var
END
END
END
END
DEFINE_PATCH_FUNCTION cd_area_alter_container
INT_VAR cont_icon = "-1"
lock_diff = "-1"
flag_locked = "-1"
flag_mlocked = "-1"
flag_resets = "-1"
flag_disabled = "-1"
trap_det_diff = "-1"
trap_rem_diff = "-1"
trapped = "-1"
detected = "-1"
string = "-1"
STR_VAR cont_name = ""
cont_script = "same"
cont_key = "same"
BEGIN
READ_LONG 0x70 cont_off
READ_SHORT 0x74 cont_num
FOR (index = 0 ; index < cont_num ; ++index) BEGIN
READ_ASCII (cont_off + (index * 0xc0)) cont_name_file (32) NULL
PATCH_IF ("%cont_name%" STRING_COMPARE_CASE "%cont_name_file%" = 0) BEGIN
PATCH_IF (cont_icon >= 0) BEGIN WRITE_SHORT (cont_off + 0x24 + (index * 0xc0)) cont_icon END // value from int_var
PATCH_IF (lock_diff >= 0) BEGIN WRITE_SHORT (cont_off + 0x26 + (index * 0xc0)) lock_diff END // value from int_var
PATCH_IF (trap_det_diff >= 0) BEGIN WRITE_SHORT (cont_off + 0x2c + (index * 0xc0)) trap_det_diff END // value from int_var
PATCH_IF (trap_rem_diff >= 0) BEGIN WRITE_SHORT (cont_off + 0x2e + (index * 0xc0)) trap_rem_diff END // value from int_var
PATCH_IF (trapped >= 0) BEGIN WRITE_SHORT (cont_off + 0x30 + (index * 0xc0)) trapped END // value from int_var
PATCH_IF (detected >= 0) BEGIN WRITE_SHORT (cont_off + 0x32 + (index * 0xc0)) detected END // value from int_var
PATCH_IF (string >= 0) BEGIN WRITE_LONG (cont_off + 0x84 + (index * 0xc0)) string END // value from int_var
PATCH_IF (flag_locked = 0) BEGIN WRITE_BYTE (cont_off + 0x28 + (index * 0xc0)) THIS & `BIT0 END
PATCH_IF (flag_mlocked = 0) BEGIN WRITE_BYTE (cont_off + 0x28 + (index * 0xc0)) THIS & `BIT2 END
PATCH_IF (flag_resets = 0) BEGIN WRITE_BYTE (cont_off + 0x28 + (index * 0xc0)) THIS & `BIT3 END
PATCH_IF (flag_disabled = 0) BEGIN WRITE_BYTE (cont_off + 0x28 + (index * 0xc0)) THIS & `BIT5 END
PATCH_IF (flag_locked = 1) BEGIN WRITE_BYTE (cont_off + 0x28 + (index * 0xc0)) THIS | BIT0 END
PATCH_IF (flag_mlocked = 1) BEGIN WRITE_BYTE (cont_off + 0x28 + (index * 0xc0)) THIS | BIT2 END
PATCH_IF (flag_resets = 1) BEGIN WRITE_BYTE (cont_off + 0x28 + (index * 0xc0)) THIS | BIT3 END
PATCH_IF (flag_disabled = 1) BEGIN WRITE_BYTE (cont_off + 0x28 + (index * 0xc0)) THIS | BIT5 END
// update script if matched
PATCH_IF ("%cont_script%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (cont_off + 0x48 + (index * 0xc0)) "%cont_script%" #8 // value from str_var
END
// update script if matched
PATCH_IF ("%cont_key%" STRING_COMPARE_CASE "same") BEGIN // if script not set to same
WRITE_ASCIIE (cont_off + 0x78 + (index * 0xc0)) "%cont_key%" #8 // value from str_var
END
END
END
END
DEFINE_PATCH_FUNCTION cd_area_alter_doors
INT_VAR door_icon = "-1"
trap_detect = "-1"
trap_remove = "-1"
trapped = "-1"
detected = "-1"
door_detect = "-1"
lock_diff = "-1"
STR_VAR door_name = ""
door_key = "same"
door_script = "same"
BEGIN
READ_LONG 0xa4 door_num
READ_LONG 0xa8 door_off
FOR (index = 0 ; index < door_num ; ++index) BEGIN
READ_ASCII (door_off + (index * 0xc8)) door_name_file (32) NULL
PATCH_IF ("%door_name%" STRING_COMPARE_CASE "%door_name_file%" = 0) BEGIN
PATCH_IF ("%door_icon%" >= 0) BEGIN WRITE_LONG (door_off + 0x68 + (index * 0xc8)) "%door_icon%" END
PATCH_IF ("%trap_detect%" >= 0) BEGIN WRITE_SHORT (door_off + 0x6c + (index * 0xc8)) "%trap_detect%" END
PATCH_IF ("%trap_remove%" >= 0) BEGIN WRITE_SHORT (door_off + 0x6e + (index * 0xc8)) "%trap_remove%" END
PATCH_IF ("%trapped%" >= 0) BEGIN WRITE_SHORT (door_off + 0x70 + (index * 0xc8)) "%trapped%" END
PATCH_IF ("%detected%" >= 0) BEGIN WRITE_SHORT (door_off + 0x72 + (index * 0xc8)) "%detected%" END
PATCH_IF ("%door_detect%" >= 0) BEGIN WRITE_LONG (door_off + 0x88 + (index * 0xc8)) "%door_detect%" END
PATCH_IF ("%lock_diff%" >= 0) BEGIN WRITE_LONG (door_off + 0x8c + (index * 0xc8)) "%lock_diff%" END
PATCH_IF ("%door_key%" STRING_COMPARE_CASE "same") BEGIN // if key not set to same
WRITE_ASCIIE (door_off + 0x78 + (index * 0xc8)) "%door_key%" #8 // value from str_var
END
PATCH_IF ("%door_script%" STRING_COMPARE_CASE "same") BEGIN // if key not set to same
WRITE_ASCIIE (door_off + 0x80 + (index * 0xc8)) "%door_script%" #8 // value from str_var
END
END
END
END
///// \\\\\
///// item functions \\\\\
///// \\\\\
DEFINE_PATCH_FUNCTION cd_item_alter_effect
INT_VAR equipped = 0 // check global fx: 0 for no, 1 for yes
headers = 0 // check ability fx; 0 for no, 1 for yes
type = "-1" // -1 is all headers, otherwise of type specified
opcode = "-1" // opcode to match, -1 for all
opcode_new = "-1" // change to this opcode
target = "-1" // for rest, -1 means no change
timing = "-1"
power = "-1"
parameter1 = "-1"
parameter2 = "-1"
power = "-1"
resist_dispel = "-1"
duration = "-1"
duration_high = "-1" // special, only replaces if existing duration is > one round
probability1 = "-1"
probability2 = "-1"
dicenumber = "-1"
dicesize = "-1"
savingthrow = "-1"
savebonus = "-11"
STR_VAR resource = "same" // same means no change, otherwise use this value
BEGIN
READ_LONG 0x6a fx_off
PATCH_IF (equipped = 1) BEGIN
READ_SHORT 0x70 fx_num
FOR (index = 0 ; index < fx_num ; ++index) BEGIN
READ_SHORT (fx_off + (index * 0x30)) opcode_file
PATCH_IF ((opcode = opcode_file) OR (opcode < 0)) BEGIN
PATCH_IF (opcode_new >= 0) BEGIN WRITE_SHORT (fx_off + (index * 0x30)) opcode_new END
PATCH_IF (target >= 0) BEGIN WRITE_BYTE (fx_off + 0x02 + (index * 0x30)) target END
PATCH_IF (power >= 0) BEGIN WRITE_BYTE (fx_off + 0x03 + (index * 0x30)) power END
PATCH_IF (parameter1 >= 0) BEGIN WRITE_LONG (fx_off + 0x04 + (index * 0x30)) parameter1 END
PATCH_IF (parameter2 >= 0) BEGIN WRITE_LONG (fx_off + 0x08 + (index * 0x30)) parameter2 END
PATCH_IF (timing >= 0) BEGIN WRITE_BYTE (fx_off + 0x0c + (index * 0x30)) timing END
PATCH_IF (resist_dispel >= 0) BEGIN WRITE_BYTE (fx_off + 0x0d + (index * 0x30)) resist_dispel END
PATCH_IF (duration >= 0) BEGIN WRITE_LONG (fx_off + 0x0e + (index * 0x30)) duration END
PATCH_IF (probability1 >= 0) BEGIN WRITE_BYTE (fx_off + 0x12 + (index * 0x30)) probability1 END
PATCH_IF (probability2 >= 0) BEGIN WRITE_BYTE (fx_off + 0x13 + (index * 0x30)) probability2 END
PATCH_IF (dicenumber >= 0) BEGIN WRITE_LONG (fx_off + 0x1c + (index * 0x30)) dicenumber END
PATCH_IF (dicesize >= 0) BEGIN WRITE_LONG (fx_off + 0x20 + (index * 0x30)) dicesize END
PATCH_IF (savingthrow >= 0) BEGIN WRITE_LONG (fx_off + 0x24 + (index * 0x30)) savingthrow END
PATCH_IF (savebonus >= "-10") BEGIN WRITE_LONG (fx_off + 0x28 + (index * 0x30)) savebonus END
PATCH_IF (duration_high >= 0) BEGIN
READ_LONG (fx_off + 0x0e + (index * 0x30)) duration_file
PATCH_IF (duration_file > 6) BEGIN
WRITE_LONG (fx_off + 0x0e + (index * 0x30)) duration_high
END
END
PATCH_IF ("%resource%" STRING_COMPARE_CASE "same") BEGIN
WRITE_ASCIIE (fx_off + 0x14 + (index * 0x30)) "%resource%" #8
END
END
END
END
PATCH_IF (headers = 1) BEGIN
READ_LONG 0x64 "abil_off"
READ_SHORT 0x68 "abil_num"
FOR (index2 = 0 ; index2 < abil_num ; ++index2) BEGIN // looks through headers
READ_BYTE (abil_off + (index2 * 0x38)) abil_type
PATCH_IF ((abil_type = type) OR (type < 0)) BEGIN
READ_SHORT (abil_off + 0x1e + (index2 * 0x38)) abil_fx_num
READ_SHORT (abil_off + 0x20 + (index2 * 0x38)) abil_fx_idx
FOR (index = 0 ; index < abil_fx_num ; index = index + 1) BEGIN
READ_SHORT (fx_off + ((abil_fx_idx + index) * 0x30)) opcode_file
PATCH_IF ((opcode = opcode_file) OR (opcode < 0)) BEGIN
PATCH_IF (opcode_new >= 0) BEGIN WRITE_SHORT (fx_off + ((index + abil_fx_idx) * 0x30)) opcode_new END
PATCH_IF (target >= 0) BEGIN WRITE_BYTE (fx_off + 0x02 + ((index + abil_fx_idx) * 0x30)) target END
PATCH_IF (power >= 0) BEGIN WRITE_BYTE (fx_off + 0x03 + ((index + abil_fx_idx) * 0x30)) power END
PATCH_IF (parameter1 >= 0) BEGIN WRITE_LONG (fx_off + 0x04 + ((index + abil_fx_idx) * 0x30)) parameter1 END
PATCH_IF (parameter2 >= 0) BEGIN WRITE_LONG (fx_off + 0x08 + ((index + abil_fx_idx) * 0x30)) parameter2 END
PATCH_IF (timing >= 0) BEGIN WRITE_BYTE (fx_off + 0x0c + ((index + abil_fx_idx) * 0x30)) timing END
PATCH_IF (resist_dispel >= 0) BEGIN WRITE_BYTE (fx_off + 0x0d + ((index + abil_fx_idx) * 0x30)) resist_dispel END
PATCH_IF (duration >= 0) BEGIN WRITE_LONG (fx_off + 0x0e + ((index + abil_fx_idx) * 0x30)) duration END
PATCH_IF (probability1 >= 0) BEGIN WRITE_BYTE (fx_off + 0x12 + ((index + abil_fx_idx) * 0x30)) probability1 END
PATCH_IF (probability2 >= 0) BEGIN WRITE_BYTE (fx_off + 0x13 + ((index + abil_fx_idx) * 0x30)) probability2 END
PATCH_IF (dicenumber >= 0) BEGIN WRITE_LONG (fx_off + 0x1c + ((index + abil_fx_idx) * 0x30)) dicenumber END
PATCH_IF (dicesize >= 0) BEGIN WRITE_LONG (fx_off + 0x20 + ((index + abil_fx_idx) * 0x30)) dicesize END
PATCH_IF (savingthrow >= 0) BEGIN WRITE_LONG (fx_off + 0x24 + ((index + abil_fx_idx) * 0x30)) savingthrow END
PATCH_IF (savebonus >= "-10") BEGIN WRITE_LONG (fx_off + 0x28 + ((index + abil_fx_idx) * 0x30)) savebonus END
PATCH_IF (duration_high >= 0) BEGIN
READ_LONG (fx_off + 0x0e + (index * 0x30)) duration_file
PATCH_IF (duration_file > 6) BEGIN
WRITE_LONG (fx_off + 0x0e + (index * 0x30)) duration_high
END
END
PATCH_IF ("%resource%" STRING_COMPARE_CASE "same") BEGIN
WRITE_ASCIIE (fx_off + 0x14 + ((index + abil_fx_idx) * 0x30)) "%resource%" #8
END
END
END
END
END
END
END
DEFINE_PATCH_FUNCTION cd_item_alter_header
INT_VAR type = "-1" // -1 is all headers, >4 forces icon match, otherwise use value here
header = 0 // 0 matches all headers, otherwise just modify specified header - use with type = -1
type_new = "-1" // for rest, -1 means no change
identify = "-1"
location = "-1"
target = "-1"
range = "-1"
launcher = "-1"
speed = "-1"
thac0_bonus = "-1"
dicesize = "-1"
dicenum = "-1"
damage_bonus = "-1"
damage_type = "-1"
effects_num = "-1"
effects_index = "-1"
charges = "-1"
drained = "-1"
flag_strength = "-1"
flag_break = "-1"
flag_hostile = "-1"
flag_recharge = "-1"
flag_bypass = "-1"
flag_keenedge = "-1"
projectile = "-1"
anim_overhead = "-1"
anim_backhand = "-1"
anim_thrust = "-1"
arrow = "-1"
bolt = "-1"
bullet = "-1"
STR_VAR icon = "same" // same means no change, otherwise use this value; may just be used as match if type is > 4
BEGIN
READ_LONG 0x64 "abil_off"
READ_SHORT 0x68 "abil_num"
PATCH_IF (header = 0) BEGIN SET loop_start = 0 SET loop_end = abil_num END
ELSE BEGIN SET loop_start = (header - 1) SET loop_end = header END
FOR (index = loop_start ; index < loop_end ; ++index) BEGIN
READ_BYTE (abil_off + (index * 0x38)) abil_type
READ_ASCII (abil_off + 0x04 + (index * 0x38)) icon_file
PATCH_IF ((type < 0) OR (abil_type = type) OR ((type > 4) AND ("%icon_file%" STRING_COMPARE_CASE "%icon%" = 0))) BEGIN
PATCH_IF (type_new >= 0) BEGIN WRITE_SHORT (abil_off + (index * 0x38)) type_new END
PATCH_IF (identify >= 0) BEGIN WRITE_BYTE (abil_off + 0x01 + (index * 0x38)) identify END
PATCH_IF (location >= 0) BEGIN WRITE_SHORT (abil_off + 0x02 + (index * 0x38)) location END
PATCH_IF (target >= 0) BEGIN WRITE_SHORT (abil_off + 0x0c + (index * 0x38)) target END
PATCH_IF (range >= 0) BEGIN WRITE_SHORT (abil_off + 0x0e + (index * 0x38)) range END
PATCH_IF (launcher >= 0) BEGIN WRITE_SHORT (abil_off + 0x10 + (index * 0x38)) launcher END
PATCH_IF (speed >= 0) BEGIN WRITE_SHORT (abil_off + 0x12 + (index * 0x38)) speed END
PATCH_IF (thac0_bonus >= 0) BEGIN WRITE_SHORT (abil_off + 0x14 + (index * 0x38)) thac0_bonus END
PATCH_IF (dicesize >= 0) BEGIN WRITE_SHORT (abil_off + 0x16 + (index * 0x38)) dicesize END
PATCH_IF (dicenum >= 0) BEGIN WRITE_SHORT (abil_off + 0x18 + (index * 0x38)) dicenum END
PATCH_IF (damage_bonus >= 0) BEGIN WRITE_SHORT (abil_off + 0x1a + (index * 0x38)) damage_bonus END
PATCH_IF (damage_type >= 0) BEGIN WRITE_SHORT (abil_off + 0x1c + (index * 0x38)) damage_type END
PATCH_IF (effects_num >= 0) BEGIN WRITE_SHORT (abil_off + 0x1e + (index * 0x38)) effects_num END
PATCH_IF (effects_index >= 0) BEGIN WRITE_SHORT (abil_off + 0x20 + (index * 0x38)) effects_index END
PATCH_IF (charges >= 0) BEGIN WRITE_SHORT (abil_off + 0x22 + (index * 0x38)) charges END
PATCH_IF (drained >= 0) BEGIN WRITE_SHORT (abil_off + 0x24 + (index * 0x38)) drained END
PATCH_IF (projectile >= 0) BEGIN WRITE_SHORT (abil_off + 0x2a + (index * 0x38)) projectile END
PATCH_IF (anim_overhead >= 0) BEGIN WRITE_SHORT (abil_off + 0x2c + (index * 0x38)) anim_overhead END
PATCH_IF (anim_backhand >= 0) BEGIN WRITE_SHORT (abil_off + 0x2e + (index * 0x38)) anim_backhand END
PATCH_IF (anim_thrust >= 0) BEGIN WRITE_SHORT (abil_off + 0x30 + (index * 0x38)) anim_thrust END
PATCH_IF (arrow >= 0) BEGIN WRITE_SHORT (abil_off + 0x32 + (index * 0x38)) arrow END
PATCH_IF (bolt >= 0) BEGIN WRITE_SHORT (abil_off + 0x34 + (index * 0x38)) bolt END
PATCH_IF (bullet >= 0) BEGIN WRITE_SHORT (abil_off + 0x36 + (index * 0x38)) bullet END
PATCH_IF (flag_strength = 0) BEGIN WRITE_BYTE (abil_off + 0x26 + (index * 0x38)) THIS & `BIT0 END
PATCH_IF (flag_break = 0) BEGIN WRITE_BYTE (abil_off + 0x26 + (index * 0x38)) THIS & `BIT1 END
PATCH_IF (flag_hostile = 0) BEGIN WRITE_BYTE (abil_off + 0x27 + (index * 0x38)) THIS & `BIT2 END
PATCH_IF (flag_recharge = 0) BEGIN WRITE_BYTE (abil_off + 0x27 + (index * 0x38)) THIS & `BIT3 END
PATCH_IF (flag_bypass = 0) BEGIN WRITE_BYTE (abil_off + 0x28 + (index * 0x38)) THIS & `BIT0 END
PATCH_IF (flag_keenedge = 0) BEGIN WRITE_BYTE (abil_off + 0x28 + (index * 0x38)) THIS & `BIT1 END
PATCH_IF (flag_strength = 1) BEGIN WRITE_BYTE (abil_off + 0x26 + (index * 0x38)) THIS | BIT0 END
PATCH_IF (flag_break = 1) BEGIN WRITE_BYTE (abil_off + 0x26 + (index * 0x38)) THIS | BIT1 END
PATCH_IF (flag_hostile = 1) BEGIN WRITE_BYTE (abil_off + 0x27 + (index * 0x38)) THIS | BIT2 END
PATCH_IF (flag_recharge = 1) BEGIN WRITE_BYTE (abil_off + 0x27 + (index * 0x38)) THIS | BIT3 END
PATCH_IF (flag_bypass = 1) BEGIN WRITE_BYTE (abil_off + 0x28 + (index * 0x38)) THIS | BIT0 END
PATCH_IF (flag_keenedge = 1) BEGIN WRITE_BYTE (abil_off + 0x28 + (index * 0x38)) THIS | BIT1 END
PATCH_IF ("%icon%" STRING_COMPARE_CASE "same") BEGIN
WRITE_ASCIIE (abil_off + 0x04 + (index * 0x38)) "%icon%" #8
END
END
END
END
DEFINE_PATCH_FUNCTION cd_item_delete_header
INT_VAR type = 0 // -1 for all headers, otherwise match type
BEGIN
READ_LONG 0x64 abil_off
READ_SHORT 0x68 abil_num
READ_LONG 0x6a fx_off
READ_SHORT 0x70 fx_num
SET fx_delta = 0
FOR (index = 0 ; index < abil_num ; ++index) BEGIN // looks for default ability header
READ_BYTE (abil_off + (index * 0x38)) type_file
PATCH_IF ((type = type_file) OR (type < 0)) BEGIN // default ability check
READ_SHORT (0x1e + abil_off + (index * 0x38)) abil_fx_num
READ_SHORT (0x20 + abil_off + (index * 0x38)) abil_fx_idx
DELETE_BYTES (fx_off + (0x30 * (abil_fx_idx - fx_delta))) (0x30 * abil_fx_num) // deletes all associated effects
DELETE_BYTES (abil_off + (index * 0x38)) 0x38 // deletes ability itself
SET fx_delta = (fx_delta + abil_fx_num)
SET abil_num = (abil_num - 1)
SET index = (index - 1)
SET fx_off = (fx_off - 0x38)
END ELSE BEGIN // if non-matched ability, need to adjust effect indices
READ_SHORT (0x20 + abil_off + (index * 0x38)) abil_fx_idx
WRITE_SHORT (0x20 + abil_off + (index * 0x38)) (abil_fx_idx - fx_delta)
END
END
WRITE_SHORT 0x68 abil_num
WRITE_LONG 0x6a fx_off
END
///// \\\\\
///// spell functions \\\\\
///// \\\\\
DEFINE_PATCH_FUNCTION cd_spell_alter_effect
INT_VAR header = 0 // 0 for all, otherwise use number
type = "-1" // -1 is all headers, otherwise of type specified
opcode = "-1" // opcode to match, -1 for all
opcode_new = "-1" // change to this opcode
target = "-1" // for rest, -1 means no change
timing = "-1"
power = "-1"
parameter1 = "-1"
parameter2 = "-1"
power = "-1"
resist_dispel = "-1"
duration = "-1"
duration_high = "-1" // special, only replaces if existing duration is > one round
probability1 = "-1"
probability2 = "-1"
dicenumber = "-1"
dicesize = "-1"
savingthrow = "-1"
savebonus = "-11"
STR_VAR resource = "same" // same means no change, otherwise use this value
BEGIN
READ_LONG 0x6a fx_off
READ_LONG 0x64 abil_off
READ_SHORT 0x68 abil_num
PATCH_IF (header = 0) BEGIN SET loop_start = 0 SET loop_end = abil_num END
ELSE BEGIN SET loop_start = (header - 1) SET loop_end = header END
FOR (index2 = loop_start ; index2 < loop_end ; ++index2) BEGIN // looks through headers
READ_BYTE (abil_off + (index2 * 0x28)) abil_type
PATCH_IF ((abil_type = type) OR (type < 0)) BEGIN
READ_SHORT (abil_off + 0x1e + (index2 * 0x28)) abil_fx_num
READ_SHORT (abil_off + 0x20 + (index2 * 0x28)) abil_fx_idx
FOR (index = 0 ; index < abil_fx_num ; index = index + 1) BEGIN
READ_SHORT (fx_off + ((abil_fx_idx + index) * 0x30)) opcode_file
PATCH_IF ((opcode = opcode_file) OR (opcode < 0)) BEGIN
PATCH_IF (opcode_new >= 0) BEGIN WRITE_SHORT (fx_off + ((index + abil_fx_idx) * 0x30)) opcode_new END
PATCH_IF (target >= 0) BEGIN WRITE_BYTE (fx_off + 0x02 + ((index + abil_fx_idx) * 0x30)) target END
PATCH_IF (power >= 0) BEGIN WRITE_BYTE (fx_off + 0x03 + ((index + abil_fx_idx) * 0x30)) power END
PATCH_IF (parameter1 >= 0) BEGIN WRITE_LONG (fx_off + 0x04 + ((index + abil_fx_idx) * 0x30)) parameter1 END
PATCH_IF (parameter2 >= 0) BEGIN WRITE_LONG (fx_off + 0x08 + ((index + abil_fx_idx) * 0x30)) parameter2 END
PATCH_IF (timing >= 0) BEGIN WRITE_BYTE (fx_off + 0x0c + ((index + abil_fx_idx) * 0x30)) timing END
PATCH_IF (resist_dispel >= 0) BEGIN WRITE_BYTE (fx_off + 0x0d + ((index + abil_fx_idx) * 0x30)) resist_dispel END
PATCH_IF (duration >= 0) BEGIN WRITE_LONG (fx_off + 0x0e + ((index + abil_fx_idx) * 0x30)) duration END
PATCH_IF (probability1 >= 0) BEGIN WRITE_BYTE (fx_off + 0x12 + ((index + abil_fx_idx) * 0x30)) probability1 END
PATCH_IF (probability2 >= 0) BEGIN WRITE_BYTE (fx_off + 0x13 + ((index + abil_fx_idx) * 0x30)) probability2 END
PATCH_IF (dicenumber >= 0) BEGIN WRITE_LONG (fx_off + 0x1c + ((index + abil_fx_idx) * 0x30)) dicenumber END
PATCH_IF (dicesize >= 0) BEGIN WRITE_LONG (fx_off + 0x20 + ((index + abil_fx_idx) * 0x30)) dicesize END
PATCH_IF (savingthrow >= 0) BEGIN WRITE_LONG (fx_off + 0x24 + ((index + abil_fx_idx) * 0x30)) savingthrow END
PATCH_IF (savebonus >= "-10") BEGIN WRITE_LONG (fx_off + 0x28 + ((index + abil_fx_idx) * 0x30)) savebonus END
PATCH_IF (duration_high >= 0) BEGIN
READ_LONG (fx_off + 0x0e + (index * 0x30)) duration_file
PATCH_IF (duration_file > 6) BEGIN
WRITE_LONG (fx_off + 0x0e + (index * 0x30)) duration_high
END
END
PATCH_IF ("%resource%" STRING_COMPARE_CASE "same") BEGIN
WRITE_ASCIIE (fx_off + 0x14 + ((index + abil_fx_idx) * 0x30)) "%resource%" #8
END
END
END
END
END
END
DEFINE_PATCH_FUNCTION cd_spell_alter_header
INT_VAR type = "-1" // -1 is all headers, >4 forces icon match, otherwise use value here
header = 0 // 0 matches all headers, otherwise just modify specified header - use with type = -1
type_new = "-1" // for rest, -1 means no change
location = "-1"
target = "-1"
range = "-1"
min_level = "-1"
speed = "-1"
thac0_bonus = "-1"
dicesize = "-1"
dicenum = "-1"
damage_bonus = "-1"
damage_type = "-1"
effects_num = "-1"
effects_index = "-1"
charges = "-1"
projectile = "-1"
STR_VAR icon = "same" // same means no change, otherwise use this value; may just be used as match if type is > 4
BEGIN
READ_LONG 0x64 "abil_off"
READ_SHORT 0x68 "abil_num"
PATCH_IF (header = 0) BEGIN SET loop_start = 0 SET loop_end = abil_num END
ELSE BEGIN SET loop_start = (header - 1) SET loop_end = header END
FOR (index = loop_start ; index < loop_end ; ++index) BEGIN
READ_BYTE (abil_off + (index * 0x28)) abil_type
READ_ASCII (abil_off + 0x04 + (index * 0x28)) icon_file
PATCH_IF ((type < 0) OR (abil_type = type) OR ((type > 4) AND ("%icon_file%" STRING_COMPARE_CASE "%icon%" = 0))) BEGIN
PATCH_IF (type_new >= 0) BEGIN WRITE_SHORT (abil_off + (index * 0x28)) type_new END
PATCH_IF (location >= 0) BEGIN WRITE_SHORT (abil_off + 0x02 + (index * 0x28)) location END
PATCH_IF (target >= 0) BEGIN WRITE_SHORT (abil_off + 0x0c + (index * 0x28)) target END
PATCH_IF (range >= 0) BEGIN WRITE_SHORT (abil_off + 0x0e + (index * 0x28)) range END
PATCH_IF (min_level >= 0) BEGIN WRITE_SHORT (abil_off + 0x10 + (index * 0x28)) min_level END
PATCH_IF (speed >= 0) BEGIN WRITE_SHORT (abil_off + 0x12 + (index * 0x28)) speed END
PATCH_IF (thac0_bonus >= 0) BEGIN WRITE_SHORT (abil_off + 0x14 + (index * 0x28)) thac0_bonus END
PATCH_IF (dicesize >= 0) BEGIN WRITE_SHORT (abil_off + 0x16 + (index * 0x28)) dicesize END
PATCH_IF (dicenum >= 0) BEGIN WRITE_SHORT (abil_off + 0x18 + (index * 0x28)) dicenum END
PATCH_IF (damage_bonus >= 0) BEGIN WRITE_SHORT (abil_off + 0x1a + (index * 0x28)) damage_bonus END
PATCH_IF (damage_type >= 0) BEGIN WRITE_SHORT (abil_off + 0x1c + (index * 0x28)) damage_type END
PATCH_IF (effects_num >= 0) BEGIN WRITE_SHORT (abil_off + 0x1e + (index * 0x28)) effects_num END
PATCH_IF (effects_index >= 0) BEGIN WRITE_SHORT (abil_off + 0x20 + (index * 0x28)) effects_index END
PATCH_IF (charges >= 0) BEGIN WRITE_SHORT (abil_off + 0x22 + (index * 0x28)) charges END
PATCH_IF (projectile >= 0) BEGIN WRITE_SHORT (abil_off + 0x26 + (index * 0x28)) projectile END
PATCH_IF ("%icon%" STRING_COMPARE_CASE "same") BEGIN
WRITE_ASCIIE (abil_off + 0x04 + (index * 0x28)) "%icon%" #8
END
END
END
END
DEFINE_PATCH_FUNCTION cd_spell_delete_header
INT_VAR type = 0 // -1 for all headers, otherwise match type
min_level = "-1" // -1 for all headers, otherwise match
BEGIN
READ_LONG 0x64 abil_off
READ_SHORT 0x68 abil_num
READ_LONG 0x6a fx_off
READ_SHORT 0x70 fx_num
SET fx_delta = 0
FOR (index = 0 ; index < abil_num ; ++index) BEGIN // looks for default ability header
READ_BYTE (abil_off + (index * 0x28)) type_file
READ_SHORT (abil_off + 0x10 + (index * 0x28)) min_level_file
PATCH_IF (((type = type_file) OR (type < 0)) AND
((min_level = min_level_file) OR (min_level < 0))) BEGIN // default ability check
READ_SHORT (0x1e + abil_off + (index * 0x28)) abil_fx_num
READ_SHORT (0x20 + abil_off + (index * 0x28)) abil_fx_idx
DELETE_BYTES (fx_off + (0x30 * (abil_fx_idx - fx_delta))) (0x30 * abil_fx_num) // deletes all associated effects
DELETE_BYTES (abil_off + (index * 0x28)) 0x28 // deletes ability itself
SET fx_delta = (fx_delta + abil_fx_num)
SET abil_num = (abil_num - 1)
SET index = (index - 1)
SET fx_off = (fx_off - 0x28)
END ELSE BEGIN // if non-matched ability, need to adjust effect indices
READ_SHORT (0x20 + abil_off + (index * 0x28)) abil_fx_idx
WRITE_SHORT (0x20 + abil_off + (index * 0x28)) (abil_fx_idx - fx_delta)
END
END
WRITE_SHORT 0x68 abil_num
WRITE_LONG 0x6a fx_off
END