Area structure function
#1 -Guest-
Posted 24 September 2010 - 05:25 AM
set fj_delete_mode to the count-from-zero index of the structure to delete, and fj_structure type as usual. Single structures (bitmask, songlist, rest interrupts) still need fj_delete_mode = 1.
the aforementioned bitmask, songlist, and rest interrupt table can now be deleted or added, and if you add another the function will simply replace the preexisting. don't use.
embedded creatures are now supported; if fj_loaded & 1 == 0 when adding a new actor, the function will try fj_cre_embedded = ~path/to/file.cre~. failing that, it'll try fj_cre_resref. failing that, it'll mark the the actor not embedded. don't use this either.
embedded projectiles are now supported. set fj_embedded_eff0, fj_embedded_eff1... = ~path/to/v2.eff~ or eff resref if adding new ones. none of this will work correctly on the mac port. don't use it.
the unzeroing header offsets now requires a fj_unzero_header_off = 1 toggle. shouldn't matter.
fj_debug = 1 dumps even more useless "info" into your debug file. maybe it'll help someone debug an area or this function sometime. probably not.
you might need to set the linebreaks back to *nix.
no warranty is expressed or implied in this post.
[codebox]
DEFINE_PATCH_FUNCTION fj_are_structure
// let's set up our variables! i++++ 4eva
INT_VAR
// these are internal variables, not to be used as input
is_bg2 = ENGINE_IS ~soa tob~
is_pst = ENGINE_IS pst
is_id2 = ENGINE_IS iwd2
fj_position = 0x11c
fj_itm_idx = 0
fj_vertex_idx = 0
off = 0
num = 0
off1 = 0
num1 = 0
key = 0
value = 0
key1 = 0
value1 = 0
fj_return_offset = 0
fj_deleted = 0
// instead of adding fj_structure_type, delete if num == fj_delete_mode
fj_delete_mode = ` 0
// offsets to various structures unpointed at zero
fj_unzero_header_off = 0
// spams your console with psuedoinformative nonsense
fj_debug = 0
// actors
fj_loc_x = 0
fj_loc_y = 0
fj_dest_x = 0
fj_dest_y = 0
fj_loading = 1
fj_spawned = 0
fj_animation = 0
fj_orientation = 0
fj_expiry = ` 0
fj_wander_dist_actor = 0
fj_mvmt_dist_actor = 0
fj_schedule = ` 0
fj_num_talked = 0
// regions
fj_type = 0
fj_box_left = 0
fj_box_top = 0
fj_box_right = 0
fj_box_bottom = 0
fj_cursor_idx = 0
fj_flags = 0
fj_info_point_strref = ` 0
fj_trap_detect = 0
fj_trap_remove = 0
fj_trap_active = 0
fj_trap_status = 0
fj_alt_x = 0
fj_alt_y = 0
// spawns
fj_spawn_num = 0
fj_difficulty = 0
fj_delay = 10
fj_method = 0
fj_duration = 1000
fj_wander_dist_spawn = 1000
fj_mvmt_dist_spawn = 1000
fj_max_num = 0
fj_enable = 1
fj_day_prob = 100
fj_night_prob = 100
// containers
fj_con_itm_idx = ` 0
fj_lock_diff = 100
fj_trap_remove_diff = 100
fj_trap_loc_x = 0
fj_trap_loc_y = 0
fj_lockpick_strref = ` 0
// items
fj_itm_expiry = 0
fj_charge0 = 0
fj_charge1 = 0
fj_charge2 = 0
// ambients
fj_radius = 500
fj_loc_z = 0
fj_volume = 80
fj_sound_num = 0
fj_delay = 0
fj_variation = 0
// variables
fj_variable_value = 0
// doors
fj_open_box_left = 0
fj_open_box_top = 0
fj_open_box_right = 0
fj_open_box_bottom = 0
fj_closed_box_left = 0
fj_closed_box_top = 0
fj_closed_box_right = 0
fj_closed_box_bottom = 0
fj_detect_diff = 0
fj_locked_diff = 0
fj_open_loc_x = 0
fj_open_loc_y = 0
fj_closed_loc_x = 0
fj_closed_loc_y = 0
fj_dlg_strref = ` 0
// animations
fj_bam_seq = 0
fj_bam_frame = 0
fj_transparent = 0
fj_init_frame = 0
fj_loop_chance = 0
fj_skip_cycles = 0
// songs
fj_song_day = 0
fj_song_night = 0
fj_song_victory = 0
fj_song_battle = 0
fj_song_defeat = 0
fj_song_day_vol = 100
fj_song_night_vol = 100
fj_song_reverb = 0
// rest interrupts
fj_cre_strref0 = ` 0
fj_cre_strref1 = ` 0
fj_cre_strref2 = ` 0
fj_cre_strref3 = ` 0
fj_cre_strref4 = ` 0
fj_cre_strref5 = ` 0
fj_cre_strref6 = ` 0
fj_cre_strref7 = ` 0
fj_cre_strref8 = ` 0
fj_cre_strref9 = ` 0
// map notes
fj_note_strref = ` 0
fj_strref_loc = 1
fj_color = 0
fj_note_id = 0
// embedded projectiles
fj_missile_num = ` 0
fj_frequency = 0
fj_target = 0
STR_VAR
// variables
fj_structure_type = ~~
fj_name = ~~
// actors
fj_dlg_resref = ~~
fj_bcs_override = ~~
fj_bcs_general = ~~
fj_bcs_class = ~~
fj_bcs_race = ~~
fj_bcs_default = ~~
fj_bcs_specific = ~~
fj_cre_resref = ~~
fj_cre_embedded = ~~
// regions
fj_destination_area = ~~
fj_destination_name = ~~
fj_key_resref = ~~
fj_reg_script = ~~
// spawns
fj_cre_resref0 = ~~
fj_cre_resref1 = ~~
fj_cre_resref2 = ~~
fj_cre_resref3 = ~~
fj_cre_resref4 = ~~
fj_cre_resref5 = ~~
fj_cre_resref6 = ~~
fj_cre_resref7 = ~~
fj_cre_resref8 = ~~
fj_cre_resref9 = ~~
// containers
fj_trap_script = ~~
// ambients
fj_wav_resref0 = ~~
fj_wav_resref1 = ~~
fj_wav_resref2 = ~~
fj_wav_resref3 = ~~
fj_wav_resref4 = ~~
fj_wav_resref5 = ~~
fj_wav_resref6 = ~~
fj_wav_resref7 = ~~
fj_wav_resref8 = ~~
fj_wav_resref9 = ~~
// doors
fj_door_wed_id = ~~
fj_door_open_wav = ~~
fj_door_close_wav = ~~
fj_door_script = ~~
fj_travel_trigger = ~~
// animations
fj_bam_resref = ~~
fj_bmp_resref = ~~
//bitmask
fj_bitmask = ~~
// songs
fj_song_day0 = ~~
fj_song_day1 = ~~
fj_song_night0 = ~~
fj_song_night1 = ~~
// map notes
fj_note_text = ~~ // only for PST
RET
fj_return_offset
BEGIN
// we must set $num(0) == num_0 when using function input
// otherwise WeiDU won't recognize that they're synonymous
PATCH_FOR_EACH value IN
vertex door_open_vert door_closed_vert cell_open_vert cell_closed_vert
BEGIN
FOR( num = 0 ; VARIABLE_IS_SET EVAL ~fj_%value%_%num%~ ; ++num )BEGIN
SET $EVAL ~fj_%value%~(~%num%~) = EVAL ~fj_%value%_%num%~
END
END
FOR( num = 0 ; VARIABLE_IS_SET EVAL ~fj_embedded_eff_%num%~ ; ++num )BEGIN
TEXT_SPRINT $fj_embedded_eff(~%num%~) EVAL ~%fj_embedded_eff_%num%%~
END
// php over this array rather than an explicit list to reduce code length and typos
CLEAR_ARRAY struct
TEXT_SPRINT $struct(0x54 0x58 0x02 0x110) actor
TEXT_SPRINT $struct(0x5c 0x5a 0x02 0x0c4) region
TEXT_SPRINT $struct(0x60 0x64 0x04 0x0c8) spawn
TEXT_SPRINT $struct(0x68 0x6c 0x04 0x068) entrance
TEXT_SPRINT $struct(0x70 0x74 0x02 0x0c0) container
TEXT_SPRINT $struct(0x78 0x76 0x02 0x014) itm
TEXT_SPRINT $struct(0x84 0x82 0x02 0x0d4) ambient
TEXT_SPRINT $struct(0x88 0x8c 0x02 0x054) variable
TEXT_SPRINT $struct(0xa8 0xa4 0x04 0x0c8) door
TEXT_SPRINT $struct(0xb8 0xb4 0x04 0x06c) tiled
TEXT_SPRINT $struct(0x7c 0x80 0x02 0x004) vertex
TEXT_SPRINT $struct(0xb0 0xac 0x04 0x04c) animation
TEXT_SPRINT $struct(0xa0 0x9c 0x04 0x000) bitmask
TEXT_SPRINT $struct(0xbc 0x00 0x00 0x090) songs
TEXT_SPRINT $struct(0xc0 0x00 0x00 0x0e4) interrupts
PATCH_IF is_pst BEGIN
TEXT_SPRINT $struct(0xc8 0xcc 0x04 0x214) note
END ELSE BEGIN
TEXT_SPRINT $struct(0xc4 0xc8 0x04 0x034) note
END
TEXT_SPRINT $struct(0xcc 0xd0 0x02 0x01c) projectile
PHP_EACH struct AS key => value BEGIN
PATCH_IF ~%value%~ STRING_EQUAL_CASE ~%fj_structure_type%~ BEGIN
SET fj_structure_type = key_0
END
END
// Icewind Dale II decided to be uselessly special
PATCH_IF is_id2 BEGIN
READ_ASCII 0x54 id2_header (0x10)
DELETE_BYTES 0x54 0x10
PATCH_FOR_EACH off IN
0x54 0x5c 0x60 0x68 0x70 0x78 0x7c 0x84 0x88 0xa0 0xa8 0xb0 0xb8 0xbc 0xc0
BEGIN
PATCH_IF LONG_AT off BEGIN
WRITE_LONG off THIS - 0x10
END
END
END
PATCH_IF fj_unzero_header_off BEGIN
// a small courtesy to fix areas missing obligatory structures
PATCH_IF fj_delete_mode == ` 0 BEGIN
PATCH_IF !LONG_AT 0xbc && fj_structure_type != 0xbc BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Offset to songlist points to 0! Adding empty songlist.~ END
WRITE_LONG 0xbc BUFFER_LENGTH
INSERT_BYTES BUFFER_LENGTH 0x90
END
PATCH_IF !LONG_AT 0xc0 && fj_structure_type != 0xc0 BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Offset to rest interrupts points to 0! Adding empty rest interrupt table.~ END
WRITE_LONG 0xc0 BUFFER_LENGTH
INSERT_BYTES BUFFER_LENGTH 0xe4
END
END
// offsets to valid structures should not point to 0
PATCH_FOR_EACH off IN
0x54 0x5c 0x60 0x68 0x70 0x78 0x7c 0x84 0x88 0xa0 0xa8 0xb0 0xb8
BEGIN
PATCH_IF !LONG_AT off BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Header offset %off% points to 0, setting to 0x11c.~ END
WRITE_LONG off 0x11c
END
END
PATCH_IF is_pst BEGIN
PATCH_IF !LONG_AT 0xc8 BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Header offset 0xc8 points to 0, setting to 0x11c.~ END
WRITE_LONG 0xc8 0x11c
END
END ELSE PATCH_IF is_bg2 BEGIN
PATCH_FOR_EACH off IN 0xc4 0xcc BEGIN
PATCH_IF !LONG_AT off BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Header offset %off% points to 0, setting to 0x11c.~ END
WRITE_LONG off 0x11c
END
END
END
END
// long block to read all the existing data
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Beginning unmarshalling.~ END
PHP_EACH struct AS key => value BEGIN
PATCH_IF( LONG_AT key_0 )BEGIN // skip it if the header offset points at 0
CLEAR_ARRAY EVAL ~%value%~
GET_OFFSET_ARRAY EVAL ~%value%~ key_0 0x04 key_1 key_2 0x00 0x00 key_3 // e.g. $region
PHP_EACH ~%value%~ AS num => off BEGIN
CLEAR_ARRAY array
PATCH_IF( key_0 == 0x54 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading actor %num%.~ END
PATCH_IF!( LONG_AT (off + 0x28) & 0x01 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~ Associating embedded creature.~ END
READ_ASCII LONG_AT (off + 0x88) $are_embedded_cre(~%num%~) (LONG_AT (off + 0x8c))
END
WRITE_LONG off + 0x88 0
READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3)
END ELSE
PATCH_IF( key_0 == 0x5c )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading region %num%.~ END
PATCH_IF( fj_debug && SHORT_AT ( off + 0x2a ) )BEGIN PATCH_PRINT ~ Associating vertices.~ END
GET_OFFSET_ARRAY array 0x7c 0x04 (off + 0x2a) 0x02 (off + 0x2c) 0x04 0x04
PHP_EACH array AS num1 => off1 BEGIN
READ_LONG off1 $EVAL ~are_region_%num%_vertex~(~%num1%~)
END
CLEAR_ARRAY array
WRITE_LONG off + 0x2c 0x00
READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3)
END ELSE
PATCH_IF( key_0 == 0x60 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading spawn %num%~ END
READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3)
END ELSE
PATCH_IF( key_0 == 0x68 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading entrance %num%~ END
READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3)
END ELSE
PATCH_IF( key_0 == 0x70 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading container %num%.~ END
// load container vertices
GET_OFFSET_ARRAY array 0x7c 0x04 (off + 0x54) 0x04 (off + 0x50) 0x04 0x04
PATCH_IF( fj_debug && LONG_AT 0x54 )BEGIN PATCH_PRINT ~ Associating vertices.~ END
PHP_EACH array AS num1 => off1 BEGIN
READ_LONG off1 $EVAL ~are_container_%num%_vertex~(~%num1%~)
END
CLEAR_ARRAY array
// load container items
GET_OFFSET_ARRAY array 0x78 0x04 (off + 0x44) 0x04 (off + 0x40) 0x04 0x14
PATCH_IF( fj_debug && LONG_AT 0x44 )BEGIN PATCH_PRINT ~ Associating items.~ END
PHP_EACH array AS num1 => off1 BEGIN
READ_ASCII off1 $EVAL ~are_container_%num%_itm~(~%num1%~) (0x14)
END
CLEAR_ARRAY array
// read container structure
WRITE_LONG off + 0x40 0x00 // wipe item index
WRITE_LONG off + 0x44 0x00 // wipe item count
WRITE_LONG off + 0x50 0x00 // wipe vertex index
READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3)
END ELSE
// items are read off with their associated containers
PATCH_IF( key_0 == 0x78 )BEGIN
END ELSE
PATCH_IF( key_0 == 0x84 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading ambient %num%~ END
READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3)
END ELSE
PATCH_IF( key_0 == 0x88 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading variable %num%~ END
READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3)
END ELSE
PATCH_IF( key_0 == 0xa8 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading door %num% and associated vertices.~ END
// load door open vertices
GET_OFFSET_ARRAY array 0x7c 0x04 (off + 0x30) 0x02 (off + 0x2c) 0x04 0x04
PHP_EACH array AS num1 => off1 BEGIN
READ_LONG off1 $EVAL ~are_door_open_%num%_vertex~(~%num1%~)
END
CLEAR_ARRAY array
WRITE_LONG off + 0x2c 0x00
// load door closed vertices
GET_OFFSET_ARRAY array 0x7c 0x04 (off + 0x32) 0x02 (off + 0x34) 0x04 0x04
PHP_EACH array AS num1 => off1 BEGIN
READ_LONG off1 $EVAL ~are_door_closed_%num%_vertex~(~%num1%~)
END
CLEAR_ARRAY array
WRITE_LONG off + 0x34 0x00
// load cell open vertices
GET_OFFSET_ARRAY array 0x7c 0x04 (off + 0x4c) 0x02 (off + 0x48) 0x04 0x04
PHP_EACH array AS num1 => off1 BEGIN
READ_LONG off1 $EVAL ~are_cell_open_%num%_vertex~(~%num1%~)
END
CLEAR_ARRAY array
WRITE_LONG off + 0x48 0x00
// load cell closed vertices
GET_OFFSET_ARRAY array 0x7c 0x04 (off + 0x4e) 0x02 (off + 0x50) 0x04 0x04
PHP_EACH array AS num1 => off1 BEGIN
READ_LONG off1 $EVAL ~are_cell_closed_%num%_vertex~(~%num1%~)
END
CLEAR_ARRAY array
WRITE_LONG off + 0x50 0x00
// read the door structure itself
READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3)
END ELSE
PATCH_IF( key_0 == 0xb8 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading tiled object %num% (something is probably very wrong).~ END
READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3)
END ELSE
// vertices, these are read off with their associated regions/containers/doors
PATCH_IF( key_0 == 0x78 )BEGIN
END ELSE
PATCH_IF( key_0 == 0xb0 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading animation %num%.~ END
READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3)
END ELSE
PATCH_IF(
( key_0 == 0xc4 && is_bg2 ) ||
( key_0 == 0xc8 && is_pst)
)BEGIN //
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading map note %num%.~ END
READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3)
END ELSE
PATCH_IF( key_0 == 0xcc && is_bg2 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading projectile %num%.~ END
READ_ASCII off $are_projectile(~%num%~) (key_3)
PATCH_IF SHORT_AT (off + 0x0c) BEGIN
PATCH_IF( fj_debug )BEGIN PATCH_PRINT ~ Associating v2 embedded effects.~ END
READ_ASCII LONG_AT (off + 0x08) $are_embedded_eff(~%num%~) (SHORT_AT (off + 0x0c))
END
END
END // php_each ~%value%~
CLEAR_ARRAY array
CLEAR_ARRAY EVAL ~%value%~
// single structures
// bitmask
PATCH_IF( key_0 == 0xa0 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading bitmask (should only exist in saved game areas).~ END
READ_ASCII LONG_AT 0xa0 $are_bitmask(0) (LONG_AT 0x9c)
END ELSE
// songs
PATCH_IF( key_0 == 0xbc )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading songs (obligatory structure).~ END
READ_ASCII LONG_AT 0xbc $are_songs(0) (0x90)
END ELSE
// rest interrupts
PATCH_IF( key_0 == 0xc0 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading rest interrupt table (obligatory structure).~ END
READ_ASCII LONG_AT 0xc0 $are_interrupts(0) (0xe4)
END
END // skip if key_0 points to 0
END // end php_each $structure: all extended structures now loaded in buffer
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Trimming %SOURCE_FILE% down to the header.~ END
DELETE_BYTES 0x11c BUFFER_LENGTH - 0x11c
PHP_EACH struct AS key => value BEGIN
PATCH_IF( key_2 == 0x02 )BEGIN
WRITE_SHORT key_1 0x00
END ELSE
PATCH_IF( key_2 == 0x04 )BEGIN
WRITE_LONG key_1 0x00
END
END
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassembling %SOURCE_FILE%.~ END
PHP_EACH struct AS key => value BEGIN
WRITE_LONG key_0 fj_position
PHP_EACH ~are_%value%~ AS key1 => value1 BEGIN
PATCH_IF( key_0 != 0xa0 && key_0 != 0xbc && key_0 != 0xc0 )BEGIN
PATCH_IF( key1 != fj_delete_mode || fj_structure_type != key_0 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reinserting %value% number %key1%.~ END
PATCH_IF( key_2 == 0x02 )BEGIN
WRITE_SHORT key_1 THIS + 0x01
END ELSE
PATCH_IF( key_2 == 0x04 )BEGIN
WRITE_LONG key_1 THIS + 0x01
END
INSERT_BYTES fj_position key_3
WRITE_ASCIIE fj_position ~%value1%~
SET fj_position += key_3
END
END ELSE
PATCH_IF( key_0 == 0xa0 && fj_structure_type != key_0 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reinserting %value% number %key1%.~ END
TEXT_SPRINT value1 $are_bitmask(0)
WRITE_LONG 0x9c STRING_LENGTH EVAL ~%value1%~
INSERT_BYTES fj_position LONG_AT 0x9c
WRITE_ASCIIE fj_position ~%value1%~
SET fj_position += LONG_AT 0x9c
END ELSE
PATCH_IF( key_0 == 0xbc && fj_structure_type != key_0 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reinserting %value% number %key1%.~ END
INSERT_BYTES fj_position key_3
WRITE_ASCIIE fj_position ~%value1%~
SET fj_position += key_3
END ELSE
PATCH_IF( key_0 == 0xc0 && fj_structure_type != key_0 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reinserting %value% number %key1%.~ END
INSERT_BYTES fj_position key_3
WRITE_ASCIIE fj_position ~%value1%~
SET fj_position += key_3
END
END // PHP_EACH $EVAL ~are_%value%~
// add new structure
PATCH_IF( key_0 == fj_structure_type && fj_delete_mode == ` 0 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Adding new %value% structure.~ END
PATCH_IF( key_2 == 0x02 )BEGIN
WRITE_SHORT key_1 THIS + 0x01
END ELSE PATCH_IF( key_2 == 0x04 )BEGIN
WRITE_LONG key_1 THIS + 0x01
END
SET fj_return_offset = fj_position
INSERT_BYTES fj_position key_3
SET fj_position += key_3
// actor
PATCH_IF( fj_structure_type == 0x54 )BEGIN
WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~
WRITE_SHORT fj_return_offset + 0x20 fj_loc_x
WRITE_SHORT fj_return_offset + 0x22 fj_loc_y
WRITE_SHORT fj_return_offset + 0x24 fj_dest_x
WRITE_SHORT fj_return_offset + 0x26 fj_dest_y
WRITE_LONG fj_return_offset + 0x28 fj_loading
WRITE_LONG fj_return_offset + 0x2c fj_spawned
WRITE_LONG fj_return_offset + 0x30 fj_animation
WRITE_LONG fj_return_offset + 0x34 fj_orientation
WRITE_LONG fj_return_offset + 0x38 fj_expiry
WRITE_SHORT fj_return_offset + 0x3c fj_wander_dist_actor
WRITE_SHORT fj_return_offset + 0x3e fj_mvmt_dist_actor
WRITE_LONG fj_return_offset + 0x40 fj_schedule
WRITE_LONG fj_return_offset + 0x44 fj_num_talked
WRITE_ASCIIE fj_return_offset + 0x48 ~%fj_dlg_resref%~
WRITE_ASCIIE fj_return_offset + 0x50 ~%fj_bcs_override%~
WRITE_ASCIIE fj_return_offset + 0x58 ~%fj_bcs_general%~
WRITE_ASCIIE fj_return_offset + 0x60 ~%fj_bcs_class%~
WRITE_ASCIIE fj_return_offset + 0x68 ~%fj_bcs_race%~
WRITE_ASCIIE fj_return_offset + 0x70 ~%fj_bcs_default%~
WRITE_ASCIIE fj_return_offset + 0x78 ~%fj_bcs_specific%~
WRITE_ASCIIE fj_return_offset + 0x80 ~%fj_cre_resref%~
END ELSE
// region
PATCH_IF( fj_structure_type == 0x5c )BEGIN
WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32
WRITE_SHORT fj_return_offset + 0x20 fj_type
WRITE_SHORT fj_return_offset + 0x22 fj_box_left
WRITE_SHORT fj_return_offset + 0x24 fj_box_top
WRITE_SHORT fj_return_offset + 0x26 fj_box_right
WRITE_SHORT fj_return_offset + 0x28 fj_box_bottom
WRITE_LONG fj_return_offset + 0x34 fj_cursor_idx
WRITE_ASCIIE fj_return_offset + 0x38 ~%fj_destination_area%~ #8
WRITE_ASCIIE fj_return_offset + 0x40 ~%fj_destination_name%~ #32
WRITE_LONG fj_return_offset + 0x60 fj_flags
WRITE_LONG fj_return_offset + 0x64 fj_info_point_strref
WRITE_SHORT fj_return_offset + 0x68 fj_trap_detect
WRITE_SHORT fj_return_offset + 0x6a fj_trap_remove
WRITE_SHORT fj_return_offset + 0x6c fj_trap_active
WRITE_SHORT fj_return_offset + 0x6e fj_trap_status
WRITE_SHORT fj_return_offset + 0x70 fj_loc_x
WRITE_SHORT fj_return_offset + 0x72 fj_loc_y
WRITE_ASCIIE fj_return_offset + 0x74 ~%fj_key_resref%~ #8
WRITE_ASCIIE fj_return_offset + 0x7c ~%fj_reg_script%~ #8
WRITE_SHORT fj_return_offset + 0x84 fj_alt_x
WRITE_SHORT fj_return_offset + 0x86 fj_alt_y
PHP_EACH fj_vertex AS key1 => value1 BEGIN
WRITE_SHORT fj_return_offset + 0x2a THIS + 0x01
END
END ELSE
// spawn
PATCH_IF( fj_structure_type == 0x60 )BEGIN
WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32
WRITE_SHORT fj_return_offset + 0x20 fj_loc_x
WRITE_SHORT fj_return_offset + 0x22 fj_loc_y
WRITE_ASCIIE fj_return_offset + 0x24 ~%fj_cre_resref0%~ #8
WRITE_ASCIIE fj_return_offset + 0x2c ~%fj_cre_resref1%~ #8
WRITE_ASCIIE fj_return_offset + 0x34 ~%fj_cre_resref2%~ #8
WRITE_ASCIIE fj_return_offset + 0x3c ~%fj_cre_resref3%~ #8
WRITE_ASCIIE fj_return_offset + 0x44 ~%fj_cre_resref4%~ #8
WRITE_ASCIIE fj_return_offset + 0x4c ~%fj_cre_resref5%~ #8
WRITE_ASCIIE fj_return_offset + 0x54 ~%fj_cre_resref6%~ #8
WRITE_ASCIIE fj_return_offset + 0x5c ~%fj_cre_resref7%~ #8
WRITE_ASCIIE fj_return_offset + 0x64 ~%fj_cre_resref8%~ #8
WRITE_ASCIIE fj_return_offset + 0x6c ~%fj_cre_resref9%~ #8
WRITE_SHORT fj_return_offset + 0x74 fj_spawn_num
WRITE_SHORT fj_return_offset + 0x76 fj_difficulty
WRITE_SHORT fj_return_offset + 0x78 fj_delay
WRITE_SHORT fj_return_offset + 0x7a fj_method
WRITE_LONG fj_return_offset + 0x7c fj_duration
WRITE_SHORT fj_return_offset + 0x80 fj_wander_distance
WRITE_SHORT fj_return_offset + 0x82 fj_mvmt_distance
WRITE_SHORT fj_return_offset + 0x84 fj_max_num
WRITE_SHORT fj_return_offset + 0x86 fj_enable
WRITE_LONG fj_return_offset + 0x88 fj_schedule
WRITE_SHORT fj_return_offset + 0x8c fj_day_prob
WRITE_SHORT fj_return_offset + 0x8e fj_night_prob
END ELSE
// entrance
PATCH_IF( fj_structure_type == 0x68 )BEGIN
WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32
WRITE_SHORT fj_return_offset + 0x20 fj_loc_x
WRITE_SHORT fj_return_offset + 0x22 fj_loc_y
WRITE_SHORT fj_return_offset + 0x24 fj_orientation
END ELSE
// container
PATCH_IF( fj_structure_type == 0x70 )BEGIN
WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32
WRITE_SHORT fj_return_offset + 0x20 fj_loc_x
WRITE_SHORT fj_return_offset + 0x22 fj_loc_y
WRITE_SHORT fj_return_offset + 0x24 fj_type
WRITE_SHORT fj_return_offset + 0x26 fj_lock_diff
WRITE_LONG fj_return_offset + 0x28 fj_flags
WRITE_SHORT fj_return_offset + 0x2c fj_trap_detect
WRITE_SHORT fj_return_offset + 0x2e fj_trap_remove_diff
WRITE_SHORT fj_return_offset + 0x30 fj_trap_active
WRITE_SHORT fj_return_offset + 0x32 fj_trap_status
WRITE_SHORT fj_return_offset + 0x34 fj_trap_loc_x
WRITE_SHORT fj_return_offset + 0x36 fj_trap_loc_y
WRITE_SHORT fj_return_offset + 0x38 fj_box_left
WRITE_SHORT fj_return_offset + 0x3a fj_box_top
WRITE_SHORT fj_return_offset + 0x3c fj_box_right
WRITE_SHORT fj_return_offset + 0x3e fj_box_bottom
WRITE_ASCIIE fj_return_offset + 0x48 ~%fj_trap_script%~ #8
WRITE_ASCIIE fj_return_offset + 0x78 ~%fj_key_resref%~ #8
WRITE_LONG fj_return_offset + 0x84 fj_lockpick_strref
PHP_EACH fj_vertex AS key1 => value1 BEGIN
WRITE_LONG fj_return_offset + 0x54 THIS + 0x01
END
END ELSE
// itm
PATCH_IF( fj_structure_type == 0x78 )BEGIN
WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #8
WRITE_SHORT fj_return_offset + 0x08 fj_itm_expiry
WRITE_SHORT fj_return_offset + 0x0a fj_charge0
WRITE_SHORT fj_return_offset + 0x0c fj_charge1
WRITE_SHORT fj_return_offset + 0x0e fj_charge2
WRITE_LONG fj_return_offset + 0x10 fj_flags
END ELSE
// ambient
PATCH_IF( fj_structure_type == 0x84 )BEGIN
WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32
WRITE_SHORT fj_return_offset + 0x20 fj_loc_x
WRITE_SHORT fj_return_offset + 0x22 fj_loc_y
WRITE_SHORT fj_return_offset + 0x24 fj_radius
WRITE_SHORT fj_return_offset + 0x26 fj_loc_z
WRITE_SHORT fj_return_offset + 0x2e fj_volume
WRITE_ASCIIE fj_return_offset + 0x30 ~%fj_wav_resref0%~ #8
WRITE_ASCIIE fj_return_offset + 0x38 ~%fj_wav_resref1%~ #8
WRITE_ASCIIE fj_return_offset + 0x40 ~%fj_wav_resref2%~ #8
WRITE_ASCIIE fj_return_offset + 0x48 ~%fj_wav_resref3%~ #8
WRITE_ASCIIE fj_return_offset + 0x50 ~%fj_wav_resref4%~ #8
WRITE_ASCIIE fj_return_offset + 0x58 ~%fj_wav_resref5%~ #8
WRITE_ASCIIE fj_return_offset + 0x60 ~%fj_wav_resref6%~ #8
WRITE_ASCIIE fj_return_offset + 0x68 ~%fj_wav_resref7%~ #8
WRITE_ASCIIE fj_return_offset + 0x70 ~%fj_wav_resref8%~ #8
WRITE_ASCIIE fj_return_offset + 0x78 ~%fj_wav_resref9%~ #8
WRITE_SHORT fj_return_offset + 0x80 fj_sound_num
WRITE_LONG fj_return_offset + 0x84 fj_delay
WRITE_LONG fj_return_offset + 0x88 fj_variation
WRITE_LONG fj_return_offset + 0x8c fj_schedule
WRITE_LONG fj_return_offset + 0x90 fj_flags
END ELSE
// variable
PATCH_IF( fj_structure_type == 0x88 )BEGIN
WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32
WRITE_LONG fj_return_offset + 0x28 fj_variable_value
END ELSE
// door
PATCH_IF( fj_structure_type == 0xa8 )BEGIN
WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32
WRITE_ASCIIE fj_return_offset + 0x20 ~%fj_door_wed_id%~
WRITE_LONG fj_return_offset + 0x28 fj_flags
WRITE_SHORT fj_return_offset + 0x38 fj_open_box_left
WRITE_SHORT fj_return_offset + 0x3a fj_open_box_top
WRITE_SHORT fj_return_offset + 0x3c fj_open_box_right
WRITE_SHORT fj_return_offset + 0x3e fj_open_box_bottom
WRITE_SHORT fj_return_offset + 0x40 fj_closed_box_left
WRITE_SHORT fj_return_offset + 0x42 fj_closed_box_top
WRITE_SHORT fj_return_offset + 0x44 fj_closed_box_right
WRITE_SHORT fj_return_offset + 0x46 fj_closed_box_bottom
WRITE_ASCIIE fj_return_offset + 0x58 ~%fj_door_open_wav%~
WRITE_ASCIIE fj_return_offset + 0x60 ~%fj_door_close_wav%~
WRITE_LONG fj_return_offset + 0x68 fj_cursor_idx
WRITE_SHORT fj_return_offset + 0x6c fj_trap_detect
WRITE_SHORT fj_return_offset + 0x6e fj_trap_remove
WRITE_SHORT fj_return_offset + 0x70 fj_trap_active
WRITE_SHORT fj_return_offset + 0x72 fj_trap_status
WRITE_SHORT fj_return_offset + 0x74 fj_trap_loc_x
WRITE_SHORT fj_return_offset + 0x76 fj_trap_loc_y
WRITE_ASCIIE fj_return_offset + 0x78 ~%fj_key_resref%~
WRITE_ASCIIE fj_return_offset + 0x80 ~%fj_door_script%~
WRITE_LONG fj_return_offset + 0x88 fj_detect_diff
WRITE_LONG fj_return_offset + 0x8c fj_locked_diff
WRITE_SHORT fj_return_offset + 0x90 fj_open_loc_x
WRITE_SHORT fj_return_offset + 0x92 fj_open_loc_y
WRITE_SHORT fj_return_offset + 0x94 fj_closed_loc_x
WRITE_SHORT fj_return_offset + 0x96 fj_closed_loc_y
WRITE_LONG fj_return_offset + 0x98 fj_lockpick_strref
WRITE_ASCIIE fj_return_offset + 0x9c ~%fj_travel_trigger%~ #24
WRITE_LONG fj_return_offset + 0xb4 fj_dlg_strref
WRITE_ASCIIE fj_return_offset + 0xb8 ~%fj_dlg_resref%~
PHP_EACH fj_door_open_vert AS key1 => value1 BEGIN
WRITE_SHORT fj_return_offset + 0x30 THIS + 0x01
END
PHP_EACH fj_door_closed_vert AS key1 => value1 BEGIN
WRITE_SHORT fj_return_offset + 0x32 THIS + 0x01
END
PHP_EACH fj_cell_open_vert AS key1 => value1 BEGIN
WRITE_SHORT fj_return_offset + 0x4c THIS + 0x01
END
PHP_EACH fj_cell_closed_vert AS key1 => value1 BEGIN
WRITE_SHORT fj_return_offset + 0x4e THIS + 0x01
END
END ELSE
// animation
PATCH_IF( fj_structure_type == 0xb0 )BEGIN
WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32
WRITE_SHORT fj_return_offset + 0x20 fj_loc_x
WRITE_SHORT fj_return_offset + 0x22 fj_loc_y
WRITE_LONG fj_return_offset + 0x24 fj_schedule
WRITE_ASCIIE fj_return_offset + 0x28 ~%fj_bam_resref%~ #8
WRITE_SHORT fj_return_offset + 0x30 fj_bam_seq
WRITE_SHORT fj_return_offset + 0x32 fj_bam_frame
WRITE_LONG fj_return_offset + 0x34 fj_flags
WRITE_SHORT fj_return_offset + 0x38 fj_loc_z
WRITE_SHORT fj_return_offset + 0x3a fj_transparent
WRITE_SHORT fj_return_offset + 0x3c fj_init_frame
WRITE_BYTE fj_return_offset + 0x3e fj_loop_chance
WRITE_BYTE fj_return_offset + 0x3f fj_skip_cycles
WRITE_ASCIIE fj_return_offset + 0x40 ~%fj_bmp_resref%~ #8
END ELSE
// bitmask
PATCH_IF( fj_structure_type == 0xa0 )BEGIN
PATCH_IF( FILE_EXISTS ~%fj_bitmask%~ )BEGIN
SET key1 = BUFFER_LENGTH
APPEND_FILE_EVALUATE ~%fj_bitmask%~
WRITE_LONG 0x9c BUFFER_LENGTH - key1
END ELSE BEGIN
WRITE_LONG 0x9c 0x00
END
SET fj_position += LONG_AT 0x9c
END ELSE
// songs
PATCH_IF( fj_structure_type == 0xbc )BEGIN
WRITE_LONG fj_return_offset + 0x00 fj_song_day
WRITE_LONG fj_return_offset + 0x04 fj_song_night
WRITE_LONG fj_return_offset + 0x08 fj_song_victory
WRITE_LONG fj_return_offset + 0x0c fj_song_battle
WRITE_LONG fj_return_offset + 0x10 fj_song_defeat
WRITE_LONG fj_return_offset + 0x14 0xffffffff
WRITE_LONG fj_return_offset + 0x18 0xffffffff
WRITE_LONG fj_return_offset + 0x1c 0xffffffff
WRITE_LONG fj_return_offset + 0x20 0xffffffff
WRITE_LONG fj_return_offset + 0x24 0xffffffff
WRITE_ASCIIE fj_return_offset + 0x28 ~%fj_song_day0%~ #8
WRITE_ASCIIE fj_return_offset + 0x30 ~%fj_song_day1%~ #8
WRITE_LONG fj_return_offset + 0x38 fj_song_day_vol
WRITE_ASCIIE fj_return_offset + 0x3c ~%fj_song_night0%~ #8
WRITE_ASCIIE fj_return_offset + 0x44 ~%fj_song_night1%~ #8
WRITE_LONG fj_return_offset + 0x4c fj_song_night_vol
WRITE_LONG fj_return_offset + 0x50 fj_song_reverb
END ELSE
// rest interrupts
PATCH_IF( fj_structure_type == 0xc0 )BEGIN
WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32
WRITE_LONG fj_return_offset + 0x20 fj_cre_strref0
WRITE_LONG fj_return_offset + 0x24 fj_cre_strref1
WRITE_LONG fj_return_offset + 0x28 fj_cre_strref2
WRITE_LONG fj_return_offset + 0x2c fj_cre_strref3
WRITE_LONG fj_return_offset + 0x30 fj_cre_strref4
WRITE_LONG fj_return_offset + 0x34 fj_cre_strref5
WRITE_LONG fj_return_offset + 0x38 fj_cre_strref6
WRITE_LONG fj_return_offset + 0x3c fj_cre_strref7
WRITE_LONG fj_return_offset + 0x40 fj_cre_strref8
WRITE_LONG fj_return_offset + 0x44 fj_cre_strref9
WRITE_ASCIIE fj_return_offset + 0x48 ~%fj_cre_resref0%~ #8
WRITE_ASCIIE fj_return_offset + 0x50 ~%fj_cre_resref1%~ #8
WRITE_ASCIIE fj_return_offset + 0x58 ~%fj_cre_resref2%~ #8
WRITE_ASCIIE fj_return_offset + 0x60 ~%fj_cre_resref3%~ #8
WRITE_ASCIIE fj_return_offset + 0x68 ~%fj_cre_resref4%~ #8
WRITE_ASCIIE fj_return_offset + 0x70 ~%fj_cre_resref5%~ #8
WRITE_ASCIIE fj_return_offset + 0x78 ~%fj_cre_resref6%~ #8
WRITE_ASCIIE fj_return_offset + 0x80 ~%fj_cre_resref7%~ #8
WRITE_ASCIIE fj_return_offset + 0x88 ~%fj_cre_resref8%~ #8
WRITE_ASCIIE fj_return_offset + 0x90 ~%fj_cre_resref9%~ #8
WRITE_SHORT fj_return_offset + 0x98 fj_spawn_num
WRITE_SHORT fj_return_offset + 0x9a fj_difficulty
WRITE_LONG fj_return_offset + 0x9c fj_duration
WRITE_SHORT fj_return_offset + 0xa0 fj_wander_distance
WRITE_SHORT fj_return_offset + 0xa2 fj_mvmt_distance
WRITE_SHORT fj_return_offset + 0xa4 fj_max_num
WRITE_SHORT fj_return_offset + 0xa6 fj_enable
WRITE_SHORT fj_return_offset + 0xa8 fj_day_prob
WRITE_SHORT fj_return_offset + 0xaa fj_night_prob
END ELSE
// map note (BGII)
PATCH_IF( fj_structure_type == 0xc4 )BEGIN
WRITE_SHORT fj_return_offset + 0x00 fj_loc_x
WRITE_SHORT fj_return_offset + 0x02 fj_loc_y
WRITE_LONG fj_return_offset + 0x04 fj_note_strref
WRITE_SHORT fj_return_offset + 0x08 fj_strref_loc
WRITE_SHORT fj_return_offset + 0x0a fj_color
WRITE_LONG fj_return_offset + 0x0c fj_note_id
END ELSE
// map note (PST)
PATCH_IF( fj_structure_type == 0xc8 )BEGIN
WRITE_LONG fj_return_offset + 0x000 fj_loc_x
WRITE_LONG fj_return_offset + 0x004 fj_loc_y
WRITE_ASCIIE fj_return_offset + 0x008 ~%fj_note_text%~
WRITE_LONG fj_return_offset + 0x1fc fj_color
END ELSE
// embedded projectile
PATCH_IF( fj_structure_type == 0xcc )BEGIN
PATCH_IF( fj_missile_num == ` 0 )BEGIN
SET fj_missile_num = IDS_OF_SYMBOL ( projectl ~%fj_name%~ )
PATCH_IF( fj_missile_num > ` 0 )BEGIN
SET fj_missile_num -= 0x01
END
END
WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #8
WRITE_SHORT fj_return_offset + 0x0e fj_missile_num
WRITE_SHORT fj_return_offset + 0x10 fj_frequency
WRITE_SHORT fj_return_offset + 0x12 fj_duration
WRITE_SHORT fj_return_offset + 0x14 fj_loc_x
WRITE_SHORT fj_return_offset + 0x16 fj_loc_y
WRITE_SHORT fj_return_offset + 0x18 fj_loc_z
WRITE_SHORT fj_return_offset + 0x1a fj_target
END
END
// add items and index to their containers
PATCH_IF( key_0 == 0x78 )BEGIN
PHP_EACH are_container AS num => structure BEGIN
PATCH_IF( fj_structure_type == 0x70 && num == fj_delete_mode && fj_deleted == 0x00 )BEGIN
SET fj_deleted = 0x01
END ELSE BEGIN
WRITE_LONG LONG_AT 0x70 + 0xc0 * ( num - fj_deleted ) + 0x40 fj_itm_idx
PHP_EACH ~are_container_%num%_itm~ AS num1 => value1 BEGIN
PATCH_IF(
( fj_structure_type != 0x78 ) ||
( fj_delete_mode != num1 + LONG_AT ( LONG_AT 0x70 + 0xc0 * ( num - fj_deleted ) + 0x40 ) )
)BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassociating item %num1% to container %num%.~ END
WRITE_LONG LONG_AT 0x70 + 0xc0 * ( num - fj_deleted ) + 0x44 THIS + 0x01
INSERT_BYTES fj_position 0x14
WRITE_ASCIIE fj_position ~%value1%~
WRITE_SHORT 0x76 THIS + 0x01
SET ++fj_itm_idx
SET fj_position += key_3
END
END
END
PATCH_IF( fj_con_itm_idx == num && fj_structure_type == 0x78 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Adding new item to container %num%.~ END
WRITE_LONG LONG_AT 0x70 + 0xc0 * num + 0x44 THIS + 0x01
WRITE_SHORT 0x76 THIS + 0x01
INSERT_BYTES fj_position key_3
WRITE_ASCIIE fj_position + 0x00 ~%fj_name%~ #8
WRITE_SHORT fj_position + 0x08 fj_itm_expiry
WRITE_SHORT fj_position + 0x0a fj_charge0
WRITE_SHORT fj_position + 0x0c fj_charge1
WRITE_SHORT fj_position + 0x0e fj_charge2
WRITE_LONG fj_position + 0x10 fj_flags
SET ++fj_itm_idx
SET fj_position += key_3
END
END// php $are_container
SET fj_deleted = 0x00
PHP_EACH are_container AS key => value BEGIN
CLEAR_ARRAY EVAL ~are_container_%key%_itm~
END
END ELSE
// add vertices
PATCH_IF( key_0 == 0x7c )BEGIN
// vertices associated with regions
PHP_EACH are_region AS num => structure BEGIN
PATCH_IF( fj_structure_type == 0x5c && num == fj_delete_mode && fj_deleted == 0x00 )BEGIN
SET fj_deleted = 0x01
END ELSE BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassociating vertices to region %num%.~ END
WRITE_LONG LONG_AT 0x5c + 0xc4 * ( num - fj_deleted ) + 0x2c fj_vertex_idx
PHP_EACH ~are_region_%num%_vertex~ AS num1 => value1 BEGIN
INSERT_BYTES fj_position 0x04
WRITE_LONG fj_position value1
WRITE_SHORT 0x80 THIS + 0x01
SET ++fj_vertex_idx
SET fj_position += key_3
END
END
END
SET fj_deleted = 0x00
PATCH_IF( fj_structure_type == 0x5c && fj_delete_mode == ` 0 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Adding vertices to new region.~ END
WRITE_LONG fj_return_offset + 0x2c fj_vertex_idx
PHP_EACH fj_vertex AS num => off BEGIN
INSERT_BYTES fj_position 0x04
WRITE_SHORT 0x80 THIS + 0x01
SET ++fj_vertex_idx
END
PHP_EACH fj_vertex AS num => off BEGIN
WRITE_LONG fj_position off
SET fj_position += 0x04
END
END
PHP_EACH are_region AS num => structure BEGIN
CLEAR_ARRAY EVAL ~are_region_%num%_vertex~
END
// vertices associated with containers
PHP_EACH are_container AS num => structure BEGIN
PATCH_IF( fj_structure_type == 0x70 && num == fj_delete_mode && fj_deleted == 0x00 )BEGIN
SET fj_deleted = 0x01
END ELSE BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassociating vertices to container %num%.~ END
WRITE_LONG LONG_AT 0x70 + 0xc0 * ( num - fj_deleted ) + 0x50 fj_vertex_idx
PHP_EACH ~are_container_%num%_vertex~ AS num1 => value1 BEGIN
INSERT_BYTES fj_position 0x04
WRITE_LONG fj_position value1
WRITE_SHORT 0x80 THIS + 0x01
SET ++fj_vertex_idx
SET fj_position += 0x04
END
END
END
SET fj_deleted = 0x00
PATCH_IF fj_structure_type == 0x70 && fj_delete_mode == ` 0 BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Adding vertices to new container.~ END
WRITE_LONG fj_return_offset + 0x50 fj_vertex_idx
PHP_EACH fj_vertex AS num => off BEGIN
SET ++fj_vertex_idx
INSERT_BYTES fj_position 0x04
WRITE_SHORT 0x80 THIS + 0x01
END
PHP_EACH fj_vertex AS num => off BEGIN
WRITE_LONG fj_position off
SET fj_position += 0x04
END
END
PHP_EACH are_container AS num => structure BEGIN
CLEAR_ARRAY EVAL ~are_container_%num%_vertex~
END
// vertices associated with doors
PHP_EACH are_door AS num => structure BEGIN
PATCH_IF( fj_structure_type == 0xa8 && num == fj_delete_mode && fj_deleted == 0x00 )BEGIN
SET fj_deleted = 0x01
END ELSE BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassociating vertices to door %num%.~ END
WRITE_LONG LONG_AT 0xa8 + 0xc8 * ( num - fj_deleted ) + 0x2c fj_vertex_idx
PHP_EACH ~are_door_open_%num%_vertex~ AS num1 => value1 BEGIN
INSERT_BYTES fj_position 0x04
WRITE_LONG fj_position value1
SET ++fj_vertex_idx
SET fj_position += 0x04
WRITE_SHORT 0x80 THIS + 0x01
END
WRITE_LONG LONG_AT 0xa8 + 0xc8 * ( num - fj_deleted ) + 0x34 fj_vertex_idx
PHP_EACH ~are_door_closed_%num%_vertex~ AS num1 => value1 BEGIN
INSERT_BYTES fj_position 0x04
WRITE_LONG fj_position value1
SET ++fj_vertex_idx
SET fj_position += 0x04
WRITE_SHORT 0x80 THIS + 0x01
END
WRITE_LONG LONG_AT 0xa8 + 0xc8 * ( num - fj_deleted ) + 0x48 fj_vertex_idx
PHP_EACH ~are_cell_open_%num%_vertex~ AS num1 => value1 BEGIN
INSERT_BYTES fj_position 0x04
WRITE_LONG fj_position value1
SET ++fj_vertex_idx
SET fj_position += 0x04
WRITE_SHORT 0x80 THIS + 0x01
END
WRITE_LONG LONG_AT 0xa8 + 0xc8 * ( num - fj_deleted ) + 0x50 fj_vertex_idx
PHP_EACH ~are_cell_closed_%num%_vertex~ AS num1 => value1 BEGIN
INSERT_BYTES fj_position 0x04
WRITE_LONG fj_position value1
SET ++fj_vertex_idx
SET fj_position += 0x04
WRITE_SHORT 0x80 THIS + 0x01
END
END
END
SET fj_deleted = 0x00
PATCH_FOR_EACH value1 IN
door_open door_closed cell_open cell_closed
BEGIN
CLEAR_ARRAY EVAL ~are_%value1%_%num%_vertex~
END
PATCH_IF( fj_structure_type == 0xa8 && fj_delete_mode == ` 0 )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Adding vertices to new door.~ END
WRITE_LONG fj_return_offset + 0x2c fj_vertex_idx
WRITE_LONG fj_return_offset + 0x34
LONG_AT (fj_return_offset + 0x2c) + SHORT_AT (fj_return_offset + 0x30)
WRITE_LONG fj_return_offset + 0x48
LONG_AT (fj_return_offset + 0x34) + SHORT_AT (fj_return_offset + 0x32)
WRITE_LONG fj_return_offset + 0x50
LONG_AT (fj_return_offset + 0x48) + SHORT_AT (fj_return_offset + 0x4c)
PATCH_FOR_EACH vertex_type IN
door_open door_closed cell_open cell_closed
BEGIN
PHP_EACH ~fj_%vertex_type%_vert~ AS num => off BEGIN
INSERT_BYTES fj_position 0x04
WRITE_SHORT 0x80 THIS + 0x01
END
PHP_EACH ~fj_%vertex_type%_vert~ AS num => off BEGIN
WRITE_LONG fj_position off
SET fj_position += 0x04
END
CLEAR_ARRAY EVAL ~fj_%vertex_type%_vert~
END
END
END // adding vertices
// reinsert embedded creatures
PATCH_IF( key_0 == 0x54 )BEGIN
PHP_EACH are_embedded_cre AS num => value1 BEGIN
PATCH_IF( fj_structure_type == 0x54 && num == fj_delete_mode && fj_deleted == 0x00 )BEGIN
SET fj_deleted = 0x01
END ELSE BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassociating embedded creature to actor %num%.~ END
WRITE_LONG LONG_AT 0x54 + ( num - fj_deleted ) * 0x110 + 0x88 fj_position
INSERT_BYTES fj_position LONG_AT (LONG_AT 0x54 + ( num - fj_deleted ) * 0x110 + 0x8c)
WRITE_ASCIIE fj_position ~%value1%~
SET fj_position += LONG_AT (LONG_AT 0x54 + ( num - fj_deleted ) * 0x110 + 0x8c)
END
END
CLEAR_ARRAY are_embedded_cre
SET fj_deleted = 0x00
PATCH_IF( fj_structure_type == 0x54 && fj_delete_mode == ` 0 && !( fj_loading & 0x01 ) )BEGIN
PATCH_IF( FILE_EXISTS ~%fj_cre_embedded%~ )BEGIN
SET off = BUFFER_LENGTH // we do a stupid dance here to avoid INNER_ACTION
APPEND_FILE_EVALUATE ~%fj_cre_embedded%~
READ_ASCII off fj_cre_embedded (BUFFER_LENGTH - off)
DELETE_BYTES off STRING_LENGTH EVAL ~%fj_cre_embedded%~
END ELSE PATCH_IF( FILE_EXISTS_IN_GAME ~%fj_cre_resref%.cre~ ) BEGIN
INNER_PATCH_FILE ~%fj_cre_resref%.cre~ BEGIN
READ_ASCII 0x00 fj_cre_embedded (BUFFER_LENGTH)
END
END
PATCH_IF( ~%fj_cre_embedded%~ STR_CMP ~~ )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Embedding creature to new actor.~ END
WRITE_LONG fj_return_offset + 0x88 fj_position
WRITE_LONG fj_return_offset + 0x8c STRING_LENGTH EVAL ~%fj_cre_embedded%~
INSERT_BYTES fj_position LONG_AT (fj_return_offset + 0x8c)
WRITE_ASCIIE fj_position ~%fj_cre_embedded%~
SET fj_position += LONG_AT (fj_return_offset + 0x8c)
END ELSE BEGIN
WRITE_LONG fj_return_offset + 0x28 THIS | 0x01 // if we didn't find a .cre, mark it unembedded
END
END
END ELSE
// reinsert embedded projectile effects
PATCH_IF( key_0 == 0xcc )BEGIN
PHP_EACH are_embedded_eff AS num => value1 BEGIN
PATCH_IF( fj_structure_type == 0xcc && fj_delete_mode == num && fj_deleted == 0x00 )BEGIN
SET fj_deleted = 0x01
END ELSE BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassociating embedded effects to projectile %num%.~ END
WRITE_LONG LONG_AT 0xcc + ( num - fj_deleted ) * 0x1c + 0x08 fj_position
INSERT_BYTES fj_position SHORT_AT (LONG_AT 0xcc + ( num - fj_deleted ) * 0x1c + 0x0c)
WRITE_ASCIIE fj_position ~%value1%~
SET fj_position += SHORT_AT (LONG_AT 0xcc + ( num - fj_deleted ) * 0x1c + 0x0c)
END
END
SET fj_deleted = 0x00
CLEAR_ARRAY are_embedded_eff
PATCH_IF( fj_structure_type == 0xcc && fj_delete_mode == ` 0 )BEGIN
WRITE_LONG fj_return_offset + 0x08 fj_position
PHP_EACH fj_embedded_eff AS num => value1 BEGIN
PATCH_IF( FILE_EXISTS ~%value1%~ )BEGIN
SET off = BUFFER_LENGTH
APPEND_FILE_EVALUATE ~%value1%~
READ_ASCII off + 0x08 value1 (0x108)
DELETE_BYTES off 0x110
END ELSE PATCH_IF( FILE_EXISTS_IN_GAME ~%value1%.eff~ )BEGIN
INNER_PATCH_FILE ~%value1%.eff~ BEGIN
READ_ASCII 0x08 value1 (0x108)
END
END ELSE BEGIN
TEXT_SPRINT value1 ~~
END
PATCH_IF( ~%value1%~ STR_CMP ~~ )BEGIN
PATCH_IF fj_debug BEGIN PATCH_PRINT ~Adding effect %num% to new embedded projectile.~ END
WRITE_SHORT fj_return_offset + 0x0c THIS + 0x108
INSERT_BYTES fj_position 0x108
WRITE_ASCIIE fj_position ~%value1%~
SET fj_position += 0x108
END
END
END
CLEAR_ARRAY fj_embedded_eff
END
END // php $struct: everything added
// restoring Icewind Dale II's special snowflakiness
PATCH_IF is_id2 BEGIN
PATCH_FOR_EACH off IN
0x54 0x5c 0x60 0x68 0x70 0x78 0x7c 0x84
0x88 0xa0 0xa8 0xb0 0xb8 0xbc 0xc0
BEGIN
PATCH_IF LONG_AT off BEGIN
WRITE_LONG off THIS + 0x10
END
END
INSERT_BYTES 0x54 0x10
WRITE_ASCIIE 0x54 ~%id2_header%~
SET fj_return_offset += 0x10
END
// wipedown remaining arrays
PHP_EACH struct AS key => value BEGIN
CLEAR_ARRAY EVAL ~are_%value%~
END
CLEAR_ARRAY struct
END
// EOF
[/codebox]
[codebox]
\verb+fj_add_are_structure+: adds a structure to an area file. All variables are zero or blank by default unless otherwise indicated. Fields designated by an asterisk are typically required; all others are optional.
This is a PATCH function.
Universal structure variables:
\begin{itemize}
\item STR_VAR \verb+fj_structure_type+ to the type of area structure to be added (actor, region, spawn, entrance, container, itm, ambient, variable, door, animation, explored bitmask, songlist, rest interrupt table, note or projectile)*;
\item INT_VAR \verb+fj_delete_mode+ to the index of the structure to be deleted (if deleting rather than adding a new structure);
\item INT_VAR \verb+fj_delete+ to 1 to enable feedback
\item RET \verb+fj_return_offset+ returns the position of the structure in the area file;
\end{itemize}
Actor structure variables:
\begin{itemize}
\item STR_VAR \verb+fj_name+ to the actor's name*;
\item INT_VAR \verb+fj_loc_x+ to the starting X (horizontal) coordinate*;
\item INT_VAR \verb+fj_loc_y+ to the starting Y (vertical) coordinate*;
\item INT_VAR \verb+fj_dest_x+ to the destination X coordinate (normally the same as fj_loc_x)*;
\item INT_VAR \verb+fj_dest_y+ to the destination Y coordinate (normally the same as fj_loc_y)*;
\item INT_VAR \verb+fj_loading+ to whether the .cre file is loaded (0=attached, 1=loaded, default 1);
\item INT_VAR \verb+fj_spawned+ to whether the creature has been spawned (0=no, 1=yes);
\item INT_VAR \verb+fj_animation+ to the actor's animation number (from animate.ids, though the engine uses the animation set on the .cre file);
\item INT_VAR \verb+fj_orientation+ to the facing direction (0-15 where 0=south, 4=west, 8=north, 12=east)*;
\item INT_VAR \verb+fj_expiry+ to the actor removal timer in absolute ticks (default -1 to avoid removal);
\item INT_VAR \verb+fj_wander_dist_actor+ to the actor's random walk distance limit;
\item INT_VAR \verb+fj_mvmt_dist_actor+ to the actor's movement distance limit;
\item INT_VAR \verb+fj_schedule+ to the hourly appearance schedule (bits 0-23, default -1 or always);
\item INT_VAR \verb+fj_num_talked+ to the NumTimesTalkedTo (in .sav files);
\item STR_VAR \verb+fj_dlg_resref+ to the actor's dialogue file (normally obtained from .cre files);
\item STR_VAR \verb+fj_bcs_override+ to the actor's override script (normally obtained from .cre files);
\item STR_VAR \verb+fj_bcs_general+ to the actor's general script (normally obtained from .cre files);
\item STR_VAR \verb+fj_bcs_class+ to the actor's class script (normally obtained from .cre files);
\item STR_VAR \verb+fj_bcs_race+ to the actor's race script (normally obtained from .cre files);
\item STR_VAR \verb+fj_bcs_default+ to the actor's default script (normally obtained from .cre files);
\item STR_VAR \verb+fj_bcs_specific+ to the actor's specific script (normally obtained from .cre files);
\item STR_VAR \verb+fj_cre_resref+ to the actor's resource reference (creature filename)*;
\item STR_VAR \verb+fj_cre_embedded+ to ~path/to/file.cre~ if embedding a new creature (defaults to fj_cre_resref if not set);
\end{itemize}
Region structure variables:
\begin{itemize}
\item STR_VAR \verb+fj_name+ to the region's name*;
\item INT_VAR \verb+fj_type+ to the region type (0=trap, 1=info, 2=travel)*;
\item INT_VAR \verb+fj_box_left+ to the leftmost X coordinate of the region's bounding box*;
\item INT_VAR \verb+fj_box_top+ to the topmost Y coordinate of the region's bounding box*;
\item INT_VAR \verb+fj_box_right+ to the rightmost X coordinate of the region's bounding box*;
\item INT_VAR \verb+fj_box_bottom+ to the bottommost Y coordinate of the region's bounding box*;
\item INT_VAR \verb+fj_cursor_idx+ to the region's mouse cursor index (from cursors.bam)*;
\item STR_VAR \verb+fj_destination_area+ to the destination area resource reference (for travel regions);
\item STR_VAR \verb+fj_destination_name+ to the entrance name in the destination area (for travel regions);
\item INT_VAR \verb+fj_flags+ to the bitwise region flags;
\item INT_VAR \verb+fj_info_point_strref+ to the information text string reference (for info points, default -1);
\item INT_VAR \verb+fj_trap_detect+ to the trap detection difficulty percentage;
\item INT_VAR \verb+fj_trap_remove+ to the trap removal difficulty percentage;
\item INT_VAR \verb+fj_trap_active+ to whether the region is trapped (0=no, 1=yes);
\item INT_VAR \verb+fj_trap_status+ to whether the trap is detected (0=no, 1=yes);
\item INT_VAR \verb+fj_loc_x+ to the trap launch X coordinate*;
\item INT_VAR \verb+fj_loc_y+ to the trap launch Y coordinate*;
\item STR_VAR \verb+fj_key_resref+ to the filename of the region's key;
\item STR_VAR \verb+fj_reg_script+ to the region script;
\item INT_VAR \verb+fj_alt_x+ to the activation point X coordinate;
\item INT_VAR \verb+fj_alt_y+ to the activation point Y coordinate;
\item INT_VAR \verb+fj_vertex_0+ to (X coordinate + (Y coordinate << 16)) for each vertex pair*;
\end{itemize}
Spawn structure variables:
\begin{itemize}
\item STR_VAR \verb+fj_name+ to the spawn point's name*;
\item INT_VAR \verb+fj_loc_x+ to the spawning X coordinate*;
\item INT_VAR \verb+fj_loc_y+ to the spawning Y coordinate*;
\item STR_VAR \verb+fj_cre_resref0+ to the resource reference of each creature spawned (0-9)*;
\item INT_VAR \verb+fj_spawn_num+ to the count of spawn creatures*;
\item INT_VAR \verb+fj_base_num+ to the base number of creatures to spawn (encounter difficulty)*;
\item INT_VAR \verb+fj_delay+ to the number of seconds between spawning (default 10);
\item INT_VAR \verb+fj_method+ to the spawn method;
\item INT_VAR \verb+fj_duration+ to the creature duration (default 1000);
\item INT_VAR \verb+fj_wander_dist_spawn+ to the creature's random walk distance limit (default 1000);
\item INT_VAR \verb+fj_mvmt_dist_spawn+ to the creature's movement distance limit (default 1000);
\item INT_VAR \verb+fj_max_num+ to the maximum number of creatures to spawn*;
\item INT_VAR \verb+fj_enable+ to the spawn point status (0=inactive, 1=active, default 1);
\item INT_VAR \verb+fj_schedule+ to the hourly appearance schedule (bits 0-23, default -1 or always);
\item INT_VAR \verb+fj_day_prob+ to the spawn point daytime probability (default 100);
\item INT_VAR \verb+fj_night_prob+ to the spawn point nighttime probability (default 100);
\end{itemize}
Entrance structure variables:
\begin{itemize}
\item STR_VAR \verb+fj_name+ to the entrance's name*;
\item INT_VAR \verb+fj_loc_x+ to the X coordinate*;
\item INT_VAR \verb+fj_loc_y+ to the Y coordinate*;
\item INT_VAR \verb+fj_orientation+ to the facing direction (0-15 where 0=south, 4=west, 8=north, 12=east)*;
\end{itemize}
Container structure variables:
\begin{itemize}
\item STR_VAR \verb+fj_name+ to the container's name*;
\item INT_VAR \verb+fj_loc_x+ to the X coordinate*;
\item INT_VAR \verb+fj_loc_y+ to the Y coordinate*;
\item INT_VAR \verb+fj_type+ to the container type (1=bag, 2=chest, 3=drawer, 4=pile, 5=table, 6=shelf, 7=altar, 8=nonvisible, 9=spellbook, 10=body, 11=barrel, 12=crate)*;
\item INT_VAR \verb+fj_lock_diff+ to the lock difficulty (default 100);
\item INT_VAR \verb+fj_flags+ to the bitwise container flags (bit0=locked, bit3=trap resets, bit5=disabled);
\item INT_VAR \verb+fj_trap_detect+ to the trap detection difficulty percentage;
\item INT_VAR \verb+fj_trap_remove_diff+ to the trap removal difficulty percentage (default 100);
\item INT_VAR \verb+fj_trap_active+ to whether the container is trapped (0=no, 1=yes);
\item INT_VAR \verb+fj_trap_status+ to whether the trap is detected (0=no, 1=yes);
\item INT_VAR \verb+fj_trap_loc_x+ to the trap launch X coordinate*;
\item INT_VAR \verb+fj_trap_loc_y+ to the trap launch Y coordinate*;
\item INT_VAR \verb+fj_box_left+ to the leftmost X coordinate of the trap's bounding box;
\item INT_VAR \verb+fj_box_top+ to the topmost Y coordinate of the trap's bounding box;
\item INT_VAR \verb+fj_box_right+ to the rightmost X coordinate of the trap's bounding box;
\item INT_VAR \verb+fj_box_bottom+ to the bottommost Y coordinate of the trap's bounding box;
\item STR_VAR \verb+fj_trap_script+ to the trap's script;
\item INT_VAR \verb+fj_vertex_0+ to (X coordinate + (Y coordinate << 16)) for each vertex pair*;
\item STR_VAR \verb+fj_key_resref+ to the filename of the container's key;
\item INT_VAR \verb+fj_lockpick_strref+ to the lockpick string reference (default -1);
\end{itemize}
Item structure variables:
\begin{itemize}
\item STR_VAR \verb+fj_name+ to the item's resource reference (filename)*;
\item INT_VAR \verb+fj_con_itm_idx+ to the index of the container to which the item is added;
\item INT_VAR \verb+fj_itm_expiry+ to the item expiration time;
\item INT_VAR \verb+fj_charge0+ to the charges of the 1st ability (item quantity for stackables);
\item INT_VAR \verb+fj_charge1+ to the charges of the 2nd ability;
\item INT_VAR \verb+fj_charge1+ to the charges of the 3rd ability;
\item INT_VAR \verb+fj_flags+ to the bitwise item flags (bit0=identified, bit1=unstealable, bit2=stolen, bit3=undroppable);
\end{itemize}
Ambient structure variables:
\begin{itemize}
\item STR_VAR \verb+fj_name+ to the ambient's name*;
\item INT_VAR \verb+fj_loc_x+ to the X coordinate*;
\item INT_VAR \verb+fj_loc_y+ to the Y coordinate*;
\item INT_VAR \verb+fj_radius+ to the sound radius (default 500);
\item INT_VAR \verb+fj_loc_z+ to the Z coordinate (height);
\item INT_VAR \verb+fj_volume+ to the volume percentage (default 80);
\item STR_VAR \verb+fj_wav_resref0+ to the resource reference of each sound (0-9)*;
\item INT_VAR \verb+fj_sound_num+ to the number of sounds*;
\item INT_VAR \verb+fj_delay+ to the base interval in seconds between sounds from this ambient list;
\item INT_VAR \verb+fj_variation+ to the base deviation from the base interval;
\item INT_VAR \verb+fj_schedule+ to the hourly appearance schedule (bits 0-23, default -1 or always);
\item INT_VAR \verb+fj_flags+ to the bitwise ambient flags*;
\end{itemize}
Variable structure variables:
\begin{itemize}
\item STR_VAR \verb+fj_name+ to the variable's name*;
\item INT_VAR \verb+fj_variable_value+ to the variable's value*;
\end{itemize}
Door structure variables:
\begin{itemize}
\item STR_VAR \verb+fj_name+ to the door's name*;
\item STR_VAR \verb+fj_door_wed_id+ to the door ID linked to the .wed file*;
\item INT_VAR \verb+fj_flags+ to the bitwise door flags*;
\item INT_VAR \verb+fj_open_box_left+ to the leftmost X coordinate of the open door's bounding box*;
\item INT_VAR \verb+fj_open_box_top+ to the topmost Y coordinate of the open door's bounding box*;
\item INT_VAR \verb+fj_open_box_right+ to the rightmost X coordinate of the open door's bounding box*;
\item INT_VAR \verb+fj_open_box_bottom+ to the bottommost Y coordinate of the open door's bounding box*;
\item INT_VAR \verb+fj_closed_box_left+ to the leftmost X coordinate of the closed door's bounding box*;
\item INT_VAR \verb+fj_closed_box_top+ to the topmost Y coordinate of the closed door's bounding box*;
\item INT_VAR \verb+fj_closed_box_right+ to the rightmost X coordinate of the closed door's bounding box*;
\item INT_VAR \verb+fj_closed_box_bottom+ to the bottommost Y coordinate of the closed door's bounding box*;
\item INT_VAR \verb+fj_door_open_vert_0+ to (X coordinate + (Y coordinate << 16)) for each vertex pair of the open door*;
\item INT_VAR \verb+fj_door_closed_vert_0+ to (X coordinate + (Y coordinate << 16)) for each vertex pair of the closed door*;
\item INT_VAR \verb+fj_cell_open_vert_0+ to (X coordinate + (Y coordinate << 16)) for each impeded search map cell of the open door*;
\item INT_VAR \verb+fj_cell_closed_vert_0+ to (X coordinate + (Y coordinate << 16)) for each impeded search map cell of the closed door*;
\item STR_VAR \verb+fj_door_open_wav+ to the door open sound;
\item STR_VAR \verb+fj_door_close_wav+ to the door closed sound;
\item INT_VAR \verb+fj_cursor_idx+ to the door's mouse cursor index (from cursors.bam)*;
\item INT_VAR \verb+fj_trap_detect+ to the trap detection difficulty percentage;
\item INT_VAR \verb+fj_trap_remove+ to the trap removal difficulty percentage;
\item INT_VAR \verb+fj_trap_active+ to whether the door is trapped (0=no, 1=yes);
\item INT_VAR \verb+fj_trap_status+ to whether the trap is detected (0=no, 1=yes);
\item INT_VAR \verb+fj_trap_loc_x+ to the trap launch X coordinate*;
\item INT_VAR \verb+fj_trap_loc_y+ to the trap launch Y coordinate*;
\item STR_VAR \verb+fj_key_resref+ to the filename of the door's key;
\item STR_VAR \verb+fj_door_script+ to the door script;
\item INT_VAR \verb+fj_detect_diff+ to the detection difficulty (for secret doors);
\item INT_VAR \verb+fj_locked_diff+ to the lock difficulty;
\item INT_VAR \verb+fj_open_loc_x+ to the X coordinate for toggling the door's open state*;
\item INT_VAR \verb+fj_open_loc_y+ to the Y coordinate for toggling the door's open state*;
\item INT_VAR \verb+fj_closed_loc_x+ to the X coordinate for toggling the door's closed state*;
\item INT_VAR \verb+fj_closed_loc_y+ to the Y coordinate for toggling the door's closed state*;
\item INT_VAR \verb+fj_lockpick_strref+ to the lockpick string reference (default -1);
\item STR_VAR \verb+fj_travel_trigger+ to the travel region name*;
\item INT_VAR \verb+fj_dlg_strref+ to the dialogue string reference (default -1);
\item STR_VAR \verb+fj_dlg_resref+ to the door's dialogue file;
\end{itemize}
Animation structure variables:
\begin{itemize}
\item STR_VAR \verb+fj_name+ to the animation name*;
\item INT_VAR \verb+fj_loc_x+ to the X coordinate*;
\item INT_VAR \verb+fj_loc_y+ to the Y coordinate*;
\item INT_VAR \verb+fj_schedule+ to the hourly appearance schedule (bits 0-23, default -1 or always);
\item STR_VAR \verb+fj_bam_resref+ to the animation resource reference (filename)*;
\item INT_VAR \verb+fj_bam_seq+ to the BAM sequence number;
\item INT_VAR \verb+fj_bam_frame+ to the BAM frame number;
\item INT_VAR \verb+fj_flags+ to the bitwise animation flags*;
\item INT_VAR \verb+fj_loc_z+ to the height;
\item INT_VAR \verb+fj_transparent+ to the BAM transparency;
\item INT_VAR \verb+fj_init_frame+ to the starting frame;
\item INT_VAR \verb+fj_loop_chance+ to the chance of looping;
\item INT_VAR \verb+fj_skip_cycles+ to start delay in frames;
\item STR_VAR \verb+fj_bmp_resref+ to the palette bitmap;
\end{itemize}
Bitmask structure variables:
\begin{itemize}
\item STR_VAR \verb+fj_bitmask+ to ~path/to/binary.file~*;
\end{itemize}
Songlist structure variables:
\begin{itemize}
\item INT_VAR \verb+fj_song_day+ to the day SONGLIST.2DA entry;
\item INT_VAR \verb+fj_song_night+ to the night SONGLIST.2DA entry;
\item INT_VAR \verb+fj_song_victory+ to the victory SONGLIST.2DA entry;
\item INT_VAR \verb+fj_song_battle+ to the battle SONGLIST.2DA entry;
\item INT_VAR \verb+fj_song_defeat+ to the defeat SONGLIST.2DA entry;
\item STR_VAR \verb+fj_song_day0+ to the day song WAV resref;
\item STR_VAR \verb+fj_song_day1+ to the night song WAV resref;
\item INT_VAR \verb+fj_song_day_vol+ to the day songs volume (default 100);
\item STR_VAR \verb+fj_song_night0+ to the night song WAV resref;
\item STR_VAR \verb+fj_song_night1+ to the second night song WAV resref;
\item INT_VAR \verb+fj_song_night_vol+ to the night songs volume (default 100);
\end{itemize}
Rest interrupt structure variables
\begin{itemize}
\item STR_VAR \verb+fj_name+ to the name of the rest interrupts (for editor use only);
\item INT_VAR \verb+fj_cre_strref0...fj_cre_strref9+ to string displayed upon party ambush (default -1);
\item STR_VAR \verb+fj_cre_resref0...fj_cre_resref9+ to creature resref;
\item STR_VAR \verb+fj_spawn_num+ to the number of spawned attackers;
\item STR_VAR \verb+fj_difficulty+ to the difficulty of the encounter;
\item STR_VAR \verb+fj_duration+ to the creature's duration (default 1000);
\item STR_VAR \verb+fj_wander_distance+ to the creature's random walk distance limit (default 1000);
\item STR_VAR \verb+fj_mvmt_distance+ to the creature's movement distance limit (default 1000);
\item STR_VAR \verb+fj_max_num+ to maximum number of spawned creatures;
\item STR_VAR \verb+fj_enable+ to whether rest interrupts are enabled (0=no, 1=yes);
\item STR_VAR \verb+fj_day_prob+ to probability of daytime ambush;
\item STR_VAR \verb+fj_night_prob+ to probability of nightime ambush;
\end{itemize}
Map note structure variables:
\begin{itemize}
\item INT_VAR \verb+fj_loc_x+ to the X coordinate*;
\item INT_VAR \verb+fj_loc_y+ to the Y coordinate*;
\item INT_VAR \verb+fj_note_strref+ to the note string reference (default -1, BGII only)*;
\item STR_VAR \verb+fj_note_text+ to the note text (PST only)*;
\item INT_VAR \verb+fj_strref_loc+ to the strref location (0=external, 1=dialog.tlk, default 1);
\item INT_VAR \verb+fj_color+ to the map marker color (0-7);
\item INT_VAR \verb+fj_note_id+ to the note ID;
\end{itemize}
Projectile trap structure variables:
\begin{itemize}
\item STR_VAR \verb+fj_name+ to the projectile filename*;
\item INT_VAR \verb+fj_eff_off+ to the effect block offset;
\item INT_VAR \verb+fj_eff_size+ to the effect block size;
\item INT_VAR \verb+fj_missile_num+ to the missile.ids reference (projectl.ids - 1);
\item INT_VAR \verb+fj_frequency to the explosion length (in frames);
\item INT_VAR \verb+fj_duration+ to the number of explosions;
\item INT_VAR \verb+fj_loc_x+ to the X coordinate*;
\item INT_VAR \verb+fj_loc_y+ to the Y coordinate*;
\item INT_VAR \verb+fj_loc_z+ to the height;
\item INT_VAR \verb+fj_target+ to the target ID;
\item STR_VAR \verb+fj_embedded_eff0+ to ~path/to/v2.eff~ or eff resref containing to projectile's effects*;
\end{itemize}
A few examples best illustrate the use of this function.
Example 1: add an actor to an area
\begin{verbatim}
COPY_EXISTING ar0500.are override
LPF fj_are_structure
INT_VAR
fj_loc_x = 2780
fj_loc_y = 1955
fj_dest_x = 2780
fj_dest_y = 1955
fj_animation = 0x6110 //fighter female human
fj_orientation = 15 //SSE
STR_VAR
fj_structure_type = actor
fj_name = Aurora
fj_cre_resref = agaurora
END
\end{verbatim}
Example 2: add a region to an area (in this case, a travel trigger to another area)
\begin{verbatim}
LPF fj_are_structure
INT_VAR
fj_type = 2 //travel
fj_box_left = 3415
fj_box_top = 625
fj_box_right = 3450
fj_box_bottom = 700
fj_cursor_idx = 30 //door
fj_vertex_0 = 3415 + (625 << 16)
fj_vertex_1 = 3450 + (650 << 16)
fj_vertex_2 = 3450 + (700 << 16)
fj_vertex_3 = 3415 + (676 << 16)
STR_VAR
fj_structure_type = region
fj_name = Tran0540
fj_destination_area = ag0540
fj_destination_name = Exit0500
END
\end{verbatim}
Example 3: add an entrance (from another area) to an area
\begin{verbatim}
LPF fj_are_structure
INT_VAR
fj_loc_x = 3490
fj_loc_y = 655
fj_orientation = 10 //NE
STR_VAR
fj_structure_type = entrance
fj_name = Exit0540
END
\end{verbatim}
Example 4: add a container to an area, then add an item to the new container
\begin{verbatim}
LPF fj_are_structure
INT_VAR
fj_type = 8 //nonvisible
fj_loc_x = 4388
fj_loc_y = 2876
fj_box_left = 4372
fj_box_top = 2826
fj_box_right = 4420
fj_box_bottom = 2858
fj_trap_loc_x = 4380
fj_trap_loc_y = 2870
fj_vertex_0 = 4411 + (2858 << 16)
fj_vertex_1 = 4372 + (2845 << 16)
fj_vertex_2 = 4382 + (2826 << 16)
fj_vertex_3 = 4420 + (2839 << 16)
STR_VAR
fj_structure_type = container
fj_name = ~Cornerstone~
END
LPF fj_are_structure
INT_VAR
fj_con_itm_idx = SHORT_AT 0x74 - 1 // a new container will be last in the file
fj_flags = 1 // identified
STR_VAR
fj_name = c6lantho
fj_structure_type = itm
END
\end{verbatim}
Example 5: add a door to an area
\begin{verbatim}
LPF fj_are_structure
INT_VAR
fj_flags = 0b100000000
fj_open_box_left = 520
fj_open_box_top = 724
fj_open_box_right = 545
fj_open_box_bottom = 830
fj_closed_box_left = 507
fj_closed_box_top = 761
fj_closed_box_right = 562
fj_closed_box_bottom = 869
fj_cursor_idx = 30
fj_trap_loc_x = 500
fj_trap_loc_y = 852
fj_open_loc_x = 517
fj_open_loc_y = 881
fj_closed_loc_x = 562
fj_closed_loc_y = 814
fj_door_open_vert_0 = 520 + (826 << 16)
fj_door_open_vert_1 = 527 + (830 << 16)
fj_door_open_vert_2 = 545 + (798 << 16)
fj_door_open_vert_3 = 545 + (727 << 16)
fj_door_open_vert_4 = 539 + (724 << 16)
fj_door_open_vert_5 = 520 + (750 << 16)
fj_door_closed_vert_0 = 507 + (831 << 16)
fj_door_closed_vert_1 = 562 + (869 << 16)
fj_door_closed_vert_2 = 562 + (799 << 16)
fj_door_closed_vert_3 = 507 + (761 << 16)
fj_cell_open_vert_0 = 32 + (68 << 16)
fj_cell_open_vert_1 = 33 + (67 << 16)
fj_cell_open_vert_2 = 32 + (67 << 16)
fj_cell_closed_vert_0 = 32 + (70 << 16)
fj_cell_closed_vert_1 = 33 + (71 << 16)
fj_cell_closed_vert_2 = 34 + (72 << 16)
fj_cell_closed_vert_3 = 34 + (71 << 16)
fj_cell_closed_vert_4 = 33 + (70 << 16)
fj_cell_closed_vert_5 = 32 + (69 << 16)
fj_cell_closed_vert_6 = 32 + (68 << 16)
fj_cell_closed_vert_7 = 33 + (69 << 16)
fj_cell_closed_vert_8 = 34 + (70 << 16)
STR_VAR
fj_structure_type = door
fj_name = Door10
fj_door_wed_id = DOOR10
END
\end{verbatim}
Example 6: add an animation to an area
\begin{verbatim}
LPF fj_are_structure
INT_VAR
fj_loc_x = 2785
fj_loc_y = 949
fj_flags = 0b00000000000000000001000110000101
//visible, not illuminated, invisible in dark, covered by actors, shown in combat
STR_VAR
fj_structure_type = animation
fj_name = Cave1
fj_bam_resref = ag1100c1
END
\end{verbatim}
Example 7: delete all ambients from an area
\begin{verbatim}
FOR( i = SHORT_AT 0x82 ; i ; --i )BEGIN
LPF fj_are_structure
INT_VAR fj_delete_mode = i - 1
STR_VAR fj_structure_type = ambient
END
END
\end{verbatim}
[/codebox]
#2 -Guest-
Posted 24 September 2010 - 05:37 AM
#3
Posted 24 September 2010 - 05:49 AM
Infinity Engine Contributions
Aurora * BG1 NPC * BG1 Fixpack * Haiass * Infinity Animations * Level 1 NPCs * P5Tweaks
PnP Free Action * Thrown Hammers * Unique Containers * BG:EE * BGII:EE * IWD:EE
================================================================
Player & Modder Resources
BAM Batcher * Creature Lister * Creature Checker * Creature Fixer * Tutu/BGT Area Map & List * Tutu Mod List
================================================================
"Infinity turns out to be the opposite of what people say it is. It is not 'that which has nothing beyond itself' that is infinite, but 'that which always has something beyond itself'." -Aristotle
#4
Posted 25 September 2010 - 11:08 AM
#5
Posted 04 October 2010 - 12:31 PM
Regarding adding CREs, is there any point in having the animation variable or not setting it to 0? Looking at a number of identical CREs in a ARE with NI, this offset is often 0 or something seemingly random.
#6
Posted 04 October 2010 - 07:56 PM
I have not had a chance to test it yet (which is maybe where you can help out ) but it would seem to take a number according to this:I have added CREs with this function (which was not terribly difficult considering the detailed example) but I was hoping someone could write an example of how to remove one actor from an area, since I clearly cannot. I am not even sure if it is supposed to target the actor by # or resref or whatever.
Meaning that you should only need to do this for example:set fj_delete_mode to the count-from-zero index of the structure to delete, and fj_structure type as usual. Single structures (bitmask, songlist, rest interrupts) still need fj_delete_mode = 1.
COPY_EXISTING fw2602.are override LPF fj_are_structure INT_VAR fj_delete_mode = 0 (should delete "Shank" in the Tutu Candlekeep Priest's Quarters) STR_VAR fj_structure_type = actor END BUT_ONLYBecause Shank is the first and only actor (starting from 0). Of course it would be useful if you could actually match it against numeric index *and* resource name, in case someone has inserted another actor before the one you want to delete. Maybe it does that already, though I'd think our "Guest" would have said so.
Not really - you don't really need to set it at all, since the default is 0. It gets the animation from the .cre files. (However, I think it *might* need to be set for areas with embedded creatures, like those in saved games.) I always set it so I have some idea of what kind of creatures are in my areas without necessarily having to dig up the .cre files separately.Regarding adding CREs, is there any point in having the animation variable or not setting it to 0? Looking at a number of identical CREs in a ARE with NI, this offset is often 0 or something seemingly random.
Infinity Engine Contributions
Aurora * BG1 NPC * BG1 Fixpack * Haiass * Infinity Animations * Level 1 NPCs * P5Tweaks
PnP Free Action * Thrown Hammers * Unique Containers * BG:EE * BGII:EE * IWD:EE
================================================================
Player & Modder Resources
BAM Batcher * Creature Lister * Creature Checker * Creature Fixer * Tutu/BGT Area Map & List * Tutu Mod List
================================================================
"Infinity turns out to be the opposite of what people say it is. It is not 'that which has nothing beyond itself' that is infinite, but 'that which always has something beyond itself'." -Aristotle
#7
Posted 04 October 2010 - 11:31 PM
#8 -Guest-
Posted 09 October 2010 - 05:42 AM
DEFINE_PATCH_FUNCTION fj_are_structure // let's set up our variables! i++++ 4eva INT_VAR // these are internal variables, not to be used as input is_bg2 = ENGINE_IS ~soa tob~ is_pst = ENGINE_IS pst is_id2 = ENGINE_IS iwd2 fj_position = 0x11c fj_itm_idx = 0 fj_vertex_idx = 0 off = 0 num = 0 off1 = 0 num1 = 0 key = 0 value = 0 key1 = 0 value1 = 0 fj_return_offset = 0 fj_deleted = 0 // instead of adding fj_structure_type, delete if num == fj_delete_mode fj_delete_mode = ` 0 // offsets to various structures unpointed at zero fj_unzero_header_off = 0 // spams your console with psuedoinformative nonsense fj_debug = 0 // actors fj_loc_x = 0 fj_loc_y = 0 fj_dest_x = 0 fj_dest_y = 0 fj_loading = 1 fj_spawned = 0 fj_animation = 0 fj_orientation = 0 fj_expiry = ` 0 fj_wander_dist_actor = 0 fj_mvmt_dist_actor = 0 fj_schedule = ` 0 fj_num_talked = 0 // regions fj_type = 0 fj_box_left = 0 fj_box_top = 0 fj_box_right = 0 fj_box_bottom = 0 fj_cursor_idx = 0 fj_flags = 0 fj_info_point_strref = ` 0 fj_trap_detect = 0 fj_trap_remove = 0 fj_trap_active = 0 fj_trap_status = 0 fj_alt_x = 0 fj_alt_y = 0 // spawns fj_spawn_num = 0 fj_difficulty = 0 fj_delay = 10 fj_method = 0 fj_duration = 1000 fj_wander_dist_spawn = 1000 fj_mvmt_dist_spawn = 1000 fj_max_num = 0 fj_enable = 1 fj_day_prob = 100 fj_night_prob = 100 // containers fj_lock_diff = 100 fj_trap_remove_diff = 100 fj_trap_loc_x = 0 fj_trap_loc_y = 0 fj_lockpick_strref = ` 0 // items fj_con_itm_idx = ` 0 fj_itm_expiry = 0 fj_charge0 = 0 fj_charge1 = 0 fj_charge2 = 0 // ambients fj_radius = 500 fj_loc_z = 0 fj_volume = 80 fj_sound_num = 0 fj_delay = 0 fj_variation = 0 // variables fj_variable_value = 0 // doors fj_open_box_left = 0 fj_open_box_top = 0 fj_open_box_right = 0 fj_open_box_bottom = 0 fj_closed_box_left = 0 fj_closed_box_top = 0 fj_closed_box_right = 0 fj_closed_box_bottom = 0 fj_detect_diff = 0 fj_locked_diff = 0 fj_open_loc_x = 0 fj_open_loc_y = 0 fj_closed_loc_x = 0 fj_closed_loc_y = 0 fj_dlg_strref = ` 0 // animations fj_bam_seq = 0 fj_bam_frame = 0 fj_transparent = 0 fj_init_frame = 0 fj_loop_chance = 0 fj_skip_cycles = 0 // songs fj_song_day = 0 fj_song_night = 0 fj_song_victory = 0 fj_song_battle = 0 fj_song_defeat = 0 fj_song_day_vol = 100 fj_song_night_vol = 100 fj_song_reverb = 0 // rest interrupts fj_cre_strref0 = ` 0 fj_cre_strref1 = ` 0 fj_cre_strref2 = ` 0 fj_cre_strref3 = ` 0 fj_cre_strref4 = ` 0 fj_cre_strref5 = ` 0 fj_cre_strref6 = ` 0 fj_cre_strref7 = ` 0 fj_cre_strref8 = ` 0 fj_cre_strref9 = ` 0 // map notes fj_note_strref = ` 0 fj_strref_loc = 1 fj_color = 0 fj_note_id = 0 // embedded projectiles fj_missile_num = ` 0 fj_frequency = 0 fj_target = 0 STR_VAR // variables fj_structure_type = ~~ fj_name = ~~ // actors fj_dlg_resref = ~~ fj_bcs_override = ~~ fj_bcs_general = ~~ fj_bcs_class = ~~ fj_bcs_race = ~~ fj_bcs_default = ~~ fj_bcs_specific = ~~ fj_cre_resref = ~~ fj_cre_embedded = ~~ // regions fj_destination_area = ~~ fj_destination_name = ~~ fj_key_resref = ~~ fj_reg_script = ~~ // spawns fj_cre_resref0 = ~~ fj_cre_resref1 = ~~ fj_cre_resref2 = ~~ fj_cre_resref3 = ~~ fj_cre_resref4 = ~~ fj_cre_resref5 = ~~ fj_cre_resref6 = ~~ fj_cre_resref7 = ~~ fj_cre_resref8 = ~~ fj_cre_resref9 = ~~ // containers fj_trap_script = ~~ // ambients fj_wav_resref0 = ~~ fj_wav_resref1 = ~~ fj_wav_resref2 = ~~ fj_wav_resref3 = ~~ fj_wav_resref4 = ~~ fj_wav_resref5 = ~~ fj_wav_resref6 = ~~ fj_wav_resref7 = ~~ fj_wav_resref8 = ~~ fj_wav_resref9 = ~~ // doors fj_door_wed_id = ~~ fj_door_open_wav = ~~ fj_door_close_wav = ~~ fj_door_script = ~~ fj_travel_trigger = ~~ // animations fj_bam_resref = ~~ fj_bmp_resref = ~~ //bitmask fj_bitmask = ~~ // songs fj_song_day0 = ~~ fj_song_day1 = ~~ fj_song_night0 = ~~ fj_song_night1 = ~~ // map notes fj_note_text = ~~ // only for PST RET fj_return_offset BEGIN // we must set $num(0) == num_0 when using function input // otherwise WeiDU won't recognize that they're synonymous PATCH_FOR_EACH value IN vertex door_open_vert door_closed_vert cell_open_vert cell_closed_vert BEGIN FOR( num = 0 ; VARIABLE_IS_SET EVAL ~fj_%value%_%num%~ ; ++num )BEGIN SET $EVAL ~fj_%value%~(~%num%~) = EVAL ~fj_%value%_%num%~ END END FOR( num = 0 ; VARIABLE_IS_SET EVAL ~fj_embedded_eff_%num%~ ; ++num )BEGIN TEXT_SPRINT $fj_embedded_eff(~%num%~) EVAL ~%fj_embedded_eff_%num%%~ END // php over this array rather than an explicit list to reduce code length and typos CLEAR_ARRAY struct TEXT_SPRINT $struct(0x54 0x58 0x02 0x110) actor TEXT_SPRINT $struct(0x5c 0x5a 0x02 0x0c4) region TEXT_SPRINT $struct(0x60 0x64 0x04 0x0c8) spawn TEXT_SPRINT $struct(0x68 0x6c 0x04 0x068) entrance TEXT_SPRINT $struct(0x70 0x74 0x02 0x0c0) container TEXT_SPRINT $struct(0x78 0x76 0x02 0x014) itm TEXT_SPRINT $struct(0x84 0x82 0x02 0x0d4) ambient TEXT_SPRINT $struct(0x88 0x8c 0x02 0x054) variable TEXT_SPRINT $struct(0xa8 0xa4 0x04 0x0c8) door TEXT_SPRINT $struct(0xb8 0xb4 0x04 0x06c) tiled TEXT_SPRINT $struct(0x7c 0x80 0x02 0x004) vertex TEXT_SPRINT $struct(0xb0 0xac 0x04 0x04c) animation TEXT_SPRINT $struct(0xa0 0x9c 0x04 0x000) bitmask TEXT_SPRINT $struct(0xbc 0x00 0x00 0x090) songs TEXT_SPRINT $struct(0xc0 0x00 0x00 0x0e4) interrupts PATCH_IF is_pst BEGIN TEXT_SPRINT $struct(0xc8 0xcc 0x04 0x214) note END ELSE BEGIN TEXT_SPRINT $struct(0xc4 0xc8 0x04 0x034) note END TEXT_SPRINT $struct(0xcc 0xd0 0x02 0x01c) projectile PHP_EACH struct AS key => value BEGIN PATCH_IF ~%value%~ STRING_EQUAL_CASE ~%fj_structure_type%~ BEGIN SET fj_structure_type = key_0 END END // Icewind Dale II decided to be uselessly special PATCH_IF is_id2 BEGIN READ_ASCII 0x54 id2_header (0x10) DELETE_BYTES 0x54 0x10 PATCH_FOR_EACH off IN 0x54 0x5c 0x60 0x68 0x70 0x78 0x7c 0x84 0x88 0xa0 0xa8 0xb0 0xb8 0xbc 0xc0 BEGIN PATCH_IF LONG_AT off BEGIN WRITE_LONG off THIS - 0x10 END END END PATCH_IF fj_unzero_header_off BEGIN // a small courtesy to fix areas missing obligatory structures PATCH_IF fj_delete_mode == ` 0 BEGIN PATCH_IF !LONG_AT 0xbc && fj_structure_type != 0xbc BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Offset to songlist points to 0! Adding empty songlist.~ END WRITE_LONG 0xbc BUFFER_LENGTH INSERT_BYTES BUFFER_LENGTH 0x90 END PATCH_IF !LONG_AT 0xc0 && fj_structure_type != 0xc0 BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Offset to rest interrupts points to 0! Adding empty rest interrupt table.~ END WRITE_LONG 0xc0 BUFFER_LENGTH INSERT_BYTES BUFFER_LENGTH 0xe4 END END // offsets to valid structures should not point to 0 PATCH_FOR_EACH off IN 0x54 0x5c 0x60 0x68 0x70 0x78 0x7c 0x84 0x88 0xa0 0xa8 0xb0 0xb8 BEGIN PATCH_IF !LONG_AT off BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Header offset %off% points to 0, setting to 0x11c.~ END WRITE_LONG off 0x11c END END PATCH_IF is_pst BEGIN PATCH_IF !LONG_AT 0xc8 BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Header offset 0xc8 points to 0, setting to 0x11c.~ END WRITE_LONG 0xc8 0x11c END END ELSE PATCH_IF is_bg2 BEGIN PATCH_FOR_EACH off IN 0xc4 0xcc BEGIN PATCH_IF !LONG_AT off BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Header offset %off% points to 0, setting to 0x11c.~ END WRITE_LONG off 0x11c END END END END // long block to read all the existing data PATCH_IF fj_debug BEGIN PATCH_PRINT ~Beginning unmarshalling.~ END PHP_EACH struct AS key => value BEGIN PATCH_IF( LONG_AT key_0 )BEGIN // skip it if the header offset points at 0 CLEAR_ARRAY EVAL ~%value%~ GET_OFFSET_ARRAY EVAL ~%value%~ key_0 0x04 key_1 key_2 0x00 0x00 key_3 // e.g. $region PHP_EACH ~%value%~ AS num => off BEGIN CLEAR_ARRAY array PATCH_IF( key_0 == 0x54 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading actor %num%.~ END PATCH_IF!( LONG_AT (off + 0x28) & 0x01 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~ Associating embedded creature.~ END READ_ASCII LONG_AT (off + 0x88) $are_embedded_cre(~%num%~) (LONG_AT (off + 0x8c)) END WRITE_LONG off + 0x88 0 READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3) END ELSE PATCH_IF( key_0 == 0x5c )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading region %num%.~ END PATCH_IF( fj_debug && SHORT_AT ( off + 0x2a ) )BEGIN PATCH_PRINT ~ Associating vertices.~ END GET_OFFSET_ARRAY array 0x7c 0x04 (off + 0x2a) 0x02 (off + 0x2c) 0x04 0x04 PHP_EACH array AS num1 => off1 BEGIN READ_LONG off1 $EVAL ~are_region_%num%_vertex~(~%num1%~) END CLEAR_ARRAY array WRITE_LONG off + 0x2c 0x00 READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3) END ELSE PATCH_IF( key_0 == 0x60 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading spawn %num%~ END READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3) END ELSE PATCH_IF( key_0 == 0x68 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading entrance %num%~ END READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3) END ELSE PATCH_IF( key_0 == 0x70 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading container %num%.~ END // load container vertices GET_OFFSET_ARRAY array 0x7c 0x04 (off + 0x54) 0x04 (off + 0x50) 0x04 0x04 PATCH_IF( fj_debug && LONG_AT 0x54 )BEGIN PATCH_PRINT ~ Associating vertices.~ END PHP_EACH array AS num1 => off1 BEGIN READ_LONG off1 $EVAL ~are_container_%num%_vertex~(~%num1%~) END CLEAR_ARRAY array // load container items GET_OFFSET_ARRAY array 0x78 0x04 (off + 0x44) 0x04 (off + 0x40) 0x04 0x14 PATCH_IF( fj_debug && LONG_AT 0x44 )BEGIN PATCH_PRINT ~ Associating items.~ END PHP_EACH array AS num1 => off1 BEGIN READ_ASCII off1 $EVAL ~are_container_%num%_itm~(~%num1%~) (0x14) END CLEAR_ARRAY array // read container structure WRITE_LONG off + 0x40 0x00 // wipe item index WRITE_LONG off + 0x44 0x00 // wipe item count WRITE_LONG off + 0x50 0x00 // wipe vertex index READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3) END ELSE // items are read off with their associated containers PATCH_IF( key_0 == 0x78 )BEGIN END ELSE PATCH_IF( key_0 == 0x84 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading ambient %num%~ END READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3) END ELSE PATCH_IF( key_0 == 0x88 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading variable %num%~ END READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3) END ELSE PATCH_IF( key_0 == 0xa8 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading door %num% and associated vertices.~ END // load door open vertices GET_OFFSET_ARRAY array 0x7c 0x04 (off + 0x30) 0x02 (off + 0x2c) 0x04 0x04 PHP_EACH array AS num1 => off1 BEGIN READ_LONG off1 $EVAL ~are_door_open_%num%_vertex~(~%num1%~) END CLEAR_ARRAY array WRITE_LONG off + 0x2c 0x00 // load door closed vertices GET_OFFSET_ARRAY array 0x7c 0x04 (off + 0x32) 0x02 (off + 0x34) 0x04 0x04 PHP_EACH array AS num1 => off1 BEGIN READ_LONG off1 $EVAL ~are_door_closed_%num%_vertex~(~%num1%~) END CLEAR_ARRAY array WRITE_LONG off + 0x34 0x00 // load cell open vertices GET_OFFSET_ARRAY array 0x7c 0x04 (off + 0x4c) 0x02 (off + 0x48) 0x04 0x04 PHP_EACH array AS num1 => off1 BEGIN READ_LONG off1 $EVAL ~are_cell_open_%num%_vertex~(~%num1%~) END CLEAR_ARRAY array WRITE_LONG off + 0x48 0x00 // load cell closed vertices GET_OFFSET_ARRAY array 0x7c 0x04 (off + 0x4e) 0x02 (off + 0x50) 0x04 0x04 PHP_EACH array AS num1 => off1 BEGIN READ_LONG off1 $EVAL ~are_cell_closed_%num%_vertex~(~%num1%~) END CLEAR_ARRAY array WRITE_LONG off + 0x50 0x00 // read the door structure itself READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3) END ELSE PATCH_IF( key_0 == 0xb8 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading tiled object %num% (something is probably very wrong).~ END READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3) END ELSE // vertices, these are read off with their associated regions/containers/doors PATCH_IF( key_0 == 0x78 )BEGIN END ELSE PATCH_IF( key_0 == 0xb0 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading animation %num%.~ END READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3) END ELSE PATCH_IF( ( key_0 == 0xc4 && is_bg2 ) || ( key_0 == 0xc8 && is_pst) )BEGIN // PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading map note %num%.~ END READ_ASCII off $EVAL ~are_%value%~(~%num%~) (key_3) END ELSE PATCH_IF( key_0 == 0xcc && is_bg2 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading projectile %num%.~ END READ_ASCII off $are_projectile(~%num%~) (key_3) PATCH_IF SHORT_AT (off + 0x0c) BEGIN PATCH_IF( fj_debug )BEGIN PATCH_PRINT ~ Associating v2 embedded effects.~ END READ_ASCII LONG_AT (off + 0x08) $are_embedded_eff(~%num%~) (SHORT_AT (off + 0x0c)) END END END // php_each ~%value%~ CLEAR_ARRAY array CLEAR_ARRAY EVAL ~%value%~ // single structures // bitmask PATCH_IF( key_0 == 0xa0 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading bitmask (should only exist in saved game areas).~ END READ_ASCII LONG_AT 0xa0 $are_bitmask(0) (LONG_AT 0x9c) END ELSE // songs PATCH_IF( key_0 == 0xbc )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading songs (obligatory structure).~ END READ_ASCII LONG_AT 0xbc $are_songs(0) (0x90) END ELSE // rest interrupts PATCH_IF( key_0 == 0xc0 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reading rest interrupt table (obligatory structure).~ END READ_ASCII LONG_AT 0xc0 $are_interrupts(0) (0xe4) END END // skip if key_0 points to 0 END // end php_each $structure: all extended structures now loaded in buffer PATCH_IF fj_debug BEGIN PATCH_PRINT ~Trimming %SOURCE_FILE% down to the header.~ END DELETE_BYTES 0x11c BUFFER_LENGTH - 0x11c PHP_EACH struct AS key => value BEGIN PATCH_IF( key_2 == 0x02 )BEGIN WRITE_SHORT key_1 0x00 END ELSE PATCH_IF( key_2 == 0x04 )BEGIN WRITE_LONG key_1 0x00 END END PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassembling %SOURCE_FILE%.~ END PHP_EACH struct AS key => value BEGIN WRITE_LONG key_0 fj_position PHP_EACH ~are_%value%~ AS key1 => value1 BEGIN PATCH_IF( key_0 != 0xa0 && key_0 != 0xbc && key_0 != 0xc0 )BEGIN PATCH_IF( key1 != fj_delete_mode || fj_structure_type != key_0 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reinserting %value% number %key1%.~ END PATCH_IF( key_2 == 0x02 )BEGIN WRITE_SHORT key_1 THIS + 0x01 END ELSE PATCH_IF( key_2 == 0x04 )BEGIN WRITE_LONG key_1 THIS + 0x01 END INSERT_BYTES fj_position key_3 WRITE_ASCIIE fj_position ~%value1%~ SET fj_position += key_3 END END ELSE PATCH_IF( key_0 == 0xa0 && fj_structure_type != key_0 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reinserting %value% number %key1%.~ END TEXT_SPRINT value1 $are_bitmask(0) WRITE_LONG 0x9c STRING_LENGTH EVAL ~%value1%~ INSERT_BYTES fj_position LONG_AT 0x9c WRITE_ASCIIE fj_position ~%value1%~ SET fj_position += LONG_AT 0x9c END ELSE PATCH_IF( key_0 == 0xbc && fj_structure_type != key_0 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reinserting %value% number %key1%.~ END INSERT_BYTES fj_position key_3 WRITE_ASCIIE fj_position ~%value1%~ SET fj_position += key_3 END ELSE PATCH_IF( key_0 == 0xc0 && fj_structure_type != key_0 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reinserting %value% number %key1%.~ END INSERT_BYTES fj_position key_3 WRITE_ASCIIE fj_position ~%value1%~ SET fj_position += key_3 END END // PHP_EACH $EVAL ~are_%value%~ // add new structure PATCH_IF( key_0 == fj_structure_type && fj_delete_mode == ` 0 && key_0 != 0x78 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Adding new %value% structure.~ END PATCH_IF( key_2 == 0x02 )BEGIN WRITE_SHORT key_1 THIS + 0x01 END ELSE PATCH_IF( key_2 == 0x04 )BEGIN WRITE_LONG key_1 THIS + 0x01 END SET fj_return_offset = fj_position INSERT_BYTES fj_position key_3 SET fj_position += key_3 // actor PATCH_IF( fj_structure_type == 0x54 )BEGIN WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ WRITE_SHORT fj_return_offset + 0x20 fj_loc_x WRITE_SHORT fj_return_offset + 0x22 fj_loc_y WRITE_SHORT fj_return_offset + 0x24 fj_dest_x WRITE_SHORT fj_return_offset + 0x26 fj_dest_y WRITE_LONG fj_return_offset + 0x28 fj_loading WRITE_LONG fj_return_offset + 0x2c fj_spawned WRITE_LONG fj_return_offset + 0x30 fj_animation WRITE_LONG fj_return_offset + 0x34 fj_orientation WRITE_LONG fj_return_offset + 0x38 fj_expiry WRITE_SHORT fj_return_offset + 0x3c fj_wander_dist_actor WRITE_SHORT fj_return_offset + 0x3e fj_mvmt_dist_actor WRITE_LONG fj_return_offset + 0x40 fj_schedule WRITE_LONG fj_return_offset + 0x44 fj_num_talked WRITE_ASCIIE fj_return_offset + 0x48 ~%fj_dlg_resref%~ WRITE_ASCIIE fj_return_offset + 0x50 ~%fj_bcs_override%~ WRITE_ASCIIE fj_return_offset + 0x58 ~%fj_bcs_general%~ WRITE_ASCIIE fj_return_offset + 0x60 ~%fj_bcs_class%~ WRITE_ASCIIE fj_return_offset + 0x68 ~%fj_bcs_race%~ WRITE_ASCIIE fj_return_offset + 0x70 ~%fj_bcs_default%~ WRITE_ASCIIE fj_return_offset + 0x78 ~%fj_bcs_specific%~ WRITE_ASCIIE fj_return_offset + 0x80 ~%fj_cre_resref%~ END ELSE // region PATCH_IF( fj_structure_type == 0x5c )BEGIN WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32 WRITE_SHORT fj_return_offset + 0x20 fj_type WRITE_SHORT fj_return_offset + 0x22 fj_box_left WRITE_SHORT fj_return_offset + 0x24 fj_box_top WRITE_SHORT fj_return_offset + 0x26 fj_box_right WRITE_SHORT fj_return_offset + 0x28 fj_box_bottom WRITE_LONG fj_return_offset + 0x34 fj_cursor_idx WRITE_ASCIIE fj_return_offset + 0x38 ~%fj_destination_area%~ #8 WRITE_ASCIIE fj_return_offset + 0x40 ~%fj_destination_name%~ #32 WRITE_LONG fj_return_offset + 0x60 fj_flags WRITE_LONG fj_return_offset + 0x64 fj_info_point_strref WRITE_SHORT fj_return_offset + 0x68 fj_trap_detect WRITE_SHORT fj_return_offset + 0x6a fj_trap_remove WRITE_SHORT fj_return_offset + 0x6c fj_trap_active WRITE_SHORT fj_return_offset + 0x6e fj_trap_status WRITE_SHORT fj_return_offset + 0x70 fj_loc_x WRITE_SHORT fj_return_offset + 0x72 fj_loc_y WRITE_ASCIIE fj_return_offset + 0x74 ~%fj_key_resref%~ #8 WRITE_ASCIIE fj_return_offset + 0x7c ~%fj_reg_script%~ #8 WRITE_SHORT fj_return_offset + 0x84 fj_alt_x WRITE_SHORT fj_return_offset + 0x86 fj_alt_y PHP_EACH fj_vertex AS key1 => value1 BEGIN WRITE_SHORT fj_return_offset + 0x2a THIS + 0x01 END END ELSE // spawn PATCH_IF( fj_structure_type == 0x60 )BEGIN WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32 WRITE_SHORT fj_return_offset + 0x20 fj_loc_x WRITE_SHORT fj_return_offset + 0x22 fj_loc_y WRITE_ASCIIE fj_return_offset + 0x24 ~%fj_cre_resref0%~ #8 WRITE_ASCIIE fj_return_offset + 0x2c ~%fj_cre_resref1%~ #8 WRITE_ASCIIE fj_return_offset + 0x34 ~%fj_cre_resref2%~ #8 WRITE_ASCIIE fj_return_offset + 0x3c ~%fj_cre_resref3%~ #8 WRITE_ASCIIE fj_return_offset + 0x44 ~%fj_cre_resref4%~ #8 WRITE_ASCIIE fj_return_offset + 0x4c ~%fj_cre_resref5%~ #8 WRITE_ASCIIE fj_return_offset + 0x54 ~%fj_cre_resref6%~ #8 WRITE_ASCIIE fj_return_offset + 0x5c ~%fj_cre_resref7%~ #8 WRITE_ASCIIE fj_return_offset + 0x64 ~%fj_cre_resref8%~ #8 WRITE_ASCIIE fj_return_offset + 0x6c ~%fj_cre_resref9%~ #8 WRITE_SHORT fj_return_offset + 0x74 fj_spawn_num WRITE_SHORT fj_return_offset + 0x76 fj_difficulty WRITE_SHORT fj_return_offset + 0x78 fj_delay WRITE_SHORT fj_return_offset + 0x7a fj_method WRITE_LONG fj_return_offset + 0x7c fj_duration WRITE_SHORT fj_return_offset + 0x80 fj_wander_distance WRITE_SHORT fj_return_offset + 0x82 fj_mvmt_distance WRITE_SHORT fj_return_offset + 0x84 fj_max_num WRITE_SHORT fj_return_offset + 0x86 fj_enable WRITE_LONG fj_return_offset + 0x88 fj_schedule WRITE_SHORT fj_return_offset + 0x8c fj_day_prob WRITE_SHORT fj_return_offset + 0x8e fj_night_prob END ELSE // entrance PATCH_IF( fj_structure_type == 0x68 )BEGIN WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32 WRITE_SHORT fj_return_offset + 0x20 fj_loc_x WRITE_SHORT fj_return_offset + 0x22 fj_loc_y WRITE_SHORT fj_return_offset + 0x24 fj_orientation END ELSE // container PATCH_IF( fj_structure_type == 0x70 )BEGIN WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32 WRITE_SHORT fj_return_offset + 0x20 fj_loc_x WRITE_SHORT fj_return_offset + 0x22 fj_loc_y WRITE_SHORT fj_return_offset + 0x24 fj_type WRITE_SHORT fj_return_offset + 0x26 fj_lock_diff WRITE_LONG fj_return_offset + 0x28 fj_flags WRITE_SHORT fj_return_offset + 0x2c fj_trap_detect WRITE_SHORT fj_return_offset + 0x2e fj_trap_remove_diff WRITE_SHORT fj_return_offset + 0x30 fj_trap_active WRITE_SHORT fj_return_offset + 0x32 fj_trap_status WRITE_SHORT fj_return_offset + 0x34 fj_trap_loc_x WRITE_SHORT fj_return_offset + 0x36 fj_trap_loc_y WRITE_SHORT fj_return_offset + 0x38 fj_box_left WRITE_SHORT fj_return_offset + 0x3a fj_box_top WRITE_SHORT fj_return_offset + 0x3c fj_box_right WRITE_SHORT fj_return_offset + 0x3e fj_box_bottom WRITE_ASCIIE fj_return_offset + 0x48 ~%fj_trap_script%~ #8 WRITE_ASCIIE fj_return_offset + 0x78 ~%fj_key_resref%~ #8 WRITE_LONG fj_return_offset + 0x84 fj_lockpick_strref PHP_EACH fj_vertex AS key1 => value1 BEGIN WRITE_LONG fj_return_offset + 0x54 THIS + 0x01 END END ELSE // ambient PATCH_IF( fj_structure_type == 0x84 )BEGIN WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32 WRITE_SHORT fj_return_offset + 0x20 fj_loc_x WRITE_SHORT fj_return_offset + 0x22 fj_loc_y WRITE_SHORT fj_return_offset + 0x24 fj_radius WRITE_SHORT fj_return_offset + 0x26 fj_loc_z WRITE_SHORT fj_return_offset + 0x2e fj_volume WRITE_ASCIIE fj_return_offset + 0x30 ~%fj_wav_resref0%~ #8 WRITE_ASCIIE fj_return_offset + 0x38 ~%fj_wav_resref1%~ #8 WRITE_ASCIIE fj_return_offset + 0x40 ~%fj_wav_resref2%~ #8 WRITE_ASCIIE fj_return_offset + 0x48 ~%fj_wav_resref3%~ #8 WRITE_ASCIIE fj_return_offset + 0x50 ~%fj_wav_resref4%~ #8 WRITE_ASCIIE fj_return_offset + 0x58 ~%fj_wav_resref5%~ #8 WRITE_ASCIIE fj_return_offset + 0x60 ~%fj_wav_resref6%~ #8 WRITE_ASCIIE fj_return_offset + 0x68 ~%fj_wav_resref7%~ #8 WRITE_ASCIIE fj_return_offset + 0x70 ~%fj_wav_resref8%~ #8 WRITE_ASCIIE fj_return_offset + 0x78 ~%fj_wav_resref9%~ #8 WRITE_SHORT fj_return_offset + 0x80 fj_sound_num WRITE_LONG fj_return_offset + 0x84 fj_delay WRITE_LONG fj_return_offset + 0x88 fj_variation WRITE_LONG fj_return_offset + 0x8c fj_schedule WRITE_LONG fj_return_offset + 0x90 fj_flags END ELSE // variable PATCH_IF( fj_structure_type == 0x88 )BEGIN WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32 WRITE_LONG fj_return_offset + 0x28 fj_variable_value END ELSE // door PATCH_IF( fj_structure_type == 0xa8 )BEGIN WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32 WRITE_ASCIIE fj_return_offset + 0x20 ~%fj_door_wed_id%~ WRITE_LONG fj_return_offset + 0x28 fj_flags WRITE_SHORT fj_return_offset + 0x38 fj_open_box_left WRITE_SHORT fj_return_offset + 0x3a fj_open_box_top WRITE_SHORT fj_return_offset + 0x3c fj_open_box_right WRITE_SHORT fj_return_offset + 0x3e fj_open_box_bottom WRITE_SHORT fj_return_offset + 0x40 fj_closed_box_left WRITE_SHORT fj_return_offset + 0x42 fj_closed_box_top WRITE_SHORT fj_return_offset + 0x44 fj_closed_box_right WRITE_SHORT fj_return_offset + 0x46 fj_closed_box_bottom WRITE_ASCIIE fj_return_offset + 0x58 ~%fj_door_open_wav%~ WRITE_ASCIIE fj_return_offset + 0x60 ~%fj_door_close_wav%~ WRITE_LONG fj_return_offset + 0x68 fj_cursor_idx WRITE_SHORT fj_return_offset + 0x6c fj_trap_detect WRITE_SHORT fj_return_offset + 0x6e fj_trap_remove WRITE_SHORT fj_return_offset + 0x70 fj_trap_active WRITE_SHORT fj_return_offset + 0x72 fj_trap_status WRITE_SHORT fj_return_offset + 0x74 fj_trap_loc_x WRITE_SHORT fj_return_offset + 0x76 fj_trap_loc_y WRITE_ASCIIE fj_return_offset + 0x78 ~%fj_key_resref%~ WRITE_ASCIIE fj_return_offset + 0x80 ~%fj_door_script%~ WRITE_LONG fj_return_offset + 0x88 fj_detect_diff WRITE_LONG fj_return_offset + 0x8c fj_locked_diff WRITE_SHORT fj_return_offset + 0x90 fj_open_loc_x WRITE_SHORT fj_return_offset + 0x92 fj_open_loc_y WRITE_SHORT fj_return_offset + 0x94 fj_closed_loc_x WRITE_SHORT fj_return_offset + 0x96 fj_closed_loc_y WRITE_LONG fj_return_offset + 0x98 fj_lockpick_strref WRITE_ASCIIE fj_return_offset + 0x9c ~%fj_travel_trigger%~ #24 WRITE_LONG fj_return_offset + 0xb4 fj_dlg_strref WRITE_ASCIIE fj_return_offset + 0xb8 ~%fj_dlg_resref%~ PHP_EACH fj_door_open_vert AS key1 => value1 BEGIN WRITE_SHORT fj_return_offset + 0x30 THIS + 0x01 END PHP_EACH fj_door_closed_vert AS key1 => value1 BEGIN WRITE_SHORT fj_return_offset + 0x32 THIS + 0x01 END PHP_EACH fj_cell_open_vert AS key1 => value1 BEGIN WRITE_SHORT fj_return_offset + 0x4c THIS + 0x01 END PHP_EACH fj_cell_closed_vert AS key1 => value1 BEGIN WRITE_SHORT fj_return_offset + 0x4e THIS + 0x01 END END ELSE // animation PATCH_IF( fj_structure_type == 0xb0 )BEGIN WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32 WRITE_SHORT fj_return_offset + 0x20 fj_loc_x WRITE_SHORT fj_return_offset + 0x22 fj_loc_y WRITE_LONG fj_return_offset + 0x24 fj_schedule WRITE_ASCIIE fj_return_offset + 0x28 ~%fj_bam_resref%~ #8 WRITE_SHORT fj_return_offset + 0x30 fj_bam_seq WRITE_SHORT fj_return_offset + 0x32 fj_bam_frame WRITE_LONG fj_return_offset + 0x34 fj_flags WRITE_SHORT fj_return_offset + 0x38 fj_loc_z WRITE_SHORT fj_return_offset + 0x3a fj_transparent WRITE_SHORT fj_return_offset + 0x3c fj_init_frame WRITE_BYTE fj_return_offset + 0x3e fj_loop_chance WRITE_BYTE fj_return_offset + 0x3f fj_skip_cycles WRITE_ASCIIE fj_return_offset + 0x40 ~%fj_bmp_resref%~ #8 END ELSE // bitmask PATCH_IF( fj_structure_type == 0xa0 )BEGIN PATCH_IF( FILE_EXISTS ~%fj_bitmask%~ )BEGIN SET key1 = BUFFER_LENGTH APPEND_FILE_EVALUATE ~%fj_bitmask%~ WRITE_LONG 0x9c BUFFER_LENGTH - key1 END ELSE BEGIN WRITE_LONG 0x9c 0x00 END SET fj_position += LONG_AT 0x9c END ELSE // songs PATCH_IF( fj_structure_type == 0xbc )BEGIN WRITE_LONG fj_return_offset + 0x00 fj_song_day WRITE_LONG fj_return_offset + 0x04 fj_song_night WRITE_LONG fj_return_offset + 0x08 fj_song_victory WRITE_LONG fj_return_offset + 0x0c fj_song_battle WRITE_LONG fj_return_offset + 0x10 fj_song_defeat WRITE_LONG fj_return_offset + 0x14 0xffffffff WRITE_LONG fj_return_offset + 0x18 0xffffffff WRITE_LONG fj_return_offset + 0x1c 0xffffffff WRITE_LONG fj_return_offset + 0x20 0xffffffff WRITE_LONG fj_return_offset + 0x24 0xffffffff WRITE_ASCIIE fj_return_offset + 0x28 ~%fj_song_day0%~ #8 WRITE_ASCIIE fj_return_offset + 0x30 ~%fj_song_day1%~ #8 WRITE_LONG fj_return_offset + 0x38 fj_song_day_vol WRITE_ASCIIE fj_return_offset + 0x3c ~%fj_song_night0%~ #8 WRITE_ASCIIE fj_return_offset + 0x44 ~%fj_song_night1%~ #8 WRITE_LONG fj_return_offset + 0x4c fj_song_night_vol WRITE_LONG fj_return_offset + 0x50 fj_song_reverb END ELSE // rest interrupts PATCH_IF( fj_structure_type == 0xc0 )BEGIN WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #32 WRITE_LONG fj_return_offset + 0x20 fj_cre_strref0 WRITE_LONG fj_return_offset + 0x24 fj_cre_strref1 WRITE_LONG fj_return_offset + 0x28 fj_cre_strref2 WRITE_LONG fj_return_offset + 0x2c fj_cre_strref3 WRITE_LONG fj_return_offset + 0x30 fj_cre_strref4 WRITE_LONG fj_return_offset + 0x34 fj_cre_strref5 WRITE_LONG fj_return_offset + 0x38 fj_cre_strref6 WRITE_LONG fj_return_offset + 0x3c fj_cre_strref7 WRITE_LONG fj_return_offset + 0x40 fj_cre_strref8 WRITE_LONG fj_return_offset + 0x44 fj_cre_strref9 WRITE_ASCIIE fj_return_offset + 0x48 ~%fj_cre_resref0%~ #8 WRITE_ASCIIE fj_return_offset + 0x50 ~%fj_cre_resref1%~ #8 WRITE_ASCIIE fj_return_offset + 0x58 ~%fj_cre_resref2%~ #8 WRITE_ASCIIE fj_return_offset + 0x60 ~%fj_cre_resref3%~ #8 WRITE_ASCIIE fj_return_offset + 0x68 ~%fj_cre_resref4%~ #8 WRITE_ASCIIE fj_return_offset + 0x70 ~%fj_cre_resref5%~ #8 WRITE_ASCIIE fj_return_offset + 0x78 ~%fj_cre_resref6%~ #8 WRITE_ASCIIE fj_return_offset + 0x80 ~%fj_cre_resref7%~ #8 WRITE_ASCIIE fj_return_offset + 0x88 ~%fj_cre_resref8%~ #8 WRITE_ASCIIE fj_return_offset + 0x90 ~%fj_cre_resref9%~ #8 WRITE_SHORT fj_return_offset + 0x98 fj_spawn_num WRITE_SHORT fj_return_offset + 0x9a fj_difficulty WRITE_LONG fj_return_offset + 0x9c fj_duration WRITE_SHORT fj_return_offset + 0xa0 fj_wander_distance WRITE_SHORT fj_return_offset + 0xa2 fj_mvmt_distance WRITE_SHORT fj_return_offset + 0xa4 fj_max_num WRITE_SHORT fj_return_offset + 0xa6 fj_enable WRITE_SHORT fj_return_offset + 0xa8 fj_day_prob WRITE_SHORT fj_return_offset + 0xaa fj_night_prob END ELSE // map note (BGII) PATCH_IF( fj_structure_type == 0xc4 )BEGIN WRITE_SHORT fj_return_offset + 0x00 fj_loc_x WRITE_SHORT fj_return_offset + 0x02 fj_loc_y WRITE_LONG fj_return_offset + 0x04 fj_note_strref WRITE_SHORT fj_return_offset + 0x08 fj_strref_loc WRITE_SHORT fj_return_offset + 0x0a fj_color WRITE_LONG fj_return_offset + 0x0c fj_note_id END ELSE // map note (PST) PATCH_IF( fj_structure_type == 0xc8 )BEGIN WRITE_LONG fj_return_offset + 0x000 fj_loc_x WRITE_LONG fj_return_offset + 0x004 fj_loc_y WRITE_ASCIIE fj_return_offset + 0x008 ~%fj_note_text%~ WRITE_LONG fj_return_offset + 0x1fc fj_color END ELSE // embedded projectile PATCH_IF( fj_structure_type == 0xcc )BEGIN PATCH_IF( fj_missile_num == ` 0 )BEGIN SET fj_missile_num = IDS_OF_SYMBOL ( projectl ~%fj_name%~ ) PATCH_IF( fj_missile_num > ` 0 )BEGIN SET fj_missile_num -= 0x01 END END WRITE_ASCIIE fj_return_offset + 0x00 ~%fj_name%~ #8 WRITE_SHORT fj_return_offset + 0x0e fj_missile_num WRITE_SHORT fj_return_offset + 0x10 fj_frequency WRITE_SHORT fj_return_offset + 0x12 fj_duration WRITE_SHORT fj_return_offset + 0x14 fj_loc_x WRITE_SHORT fj_return_offset + 0x16 fj_loc_y WRITE_SHORT fj_return_offset + 0x18 fj_loc_z WRITE_SHORT fj_return_offset + 0x1a fj_target END END // add items and index to their containers PATCH_IF( key_0 == 0x78 )BEGIN PHP_EACH are_container AS num => structure BEGIN PATCH_IF( fj_structure_type == 0x70 && num == fj_delete_mode && fj_deleted == 0x00 )BEGIN SET fj_deleted = 0x01 END ELSE BEGIN WRITE_LONG LONG_AT 0x70 + 0xc0 * ( num - fj_deleted ) + 0x40 fj_itm_idx PHP_EACH ~are_container_%num%_itm~ AS num1 => value1 BEGIN PATCH_IF( ( fj_structure_type != 0x78 ) || ( fj_delete_mode != num1 + LONG_AT ( LONG_AT 0x70 + 0xc0 * ( num - fj_deleted ) + 0x40 ) ) )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassociating item %num1% to container %num%.~ END WRITE_LONG LONG_AT 0x70 + 0xc0 * ( num - fj_deleted ) + 0x44 THIS + 0x01 INSERT_BYTES fj_position 0x14 WRITE_ASCIIE fj_position ~%value1%~ WRITE_SHORT 0x76 THIS + 0x01 SET ++ fj_itm_idx SET fj_position += key_3 END END END PATCH_IF( fj_con_itm_idx == num && fj_structure_type == 0x78 )BEGIN READ_LONG LONG_AT 0x70 + 0xc0 * num + 0x44 cnt PATCH_IF fj_debug BEGIN PATCH_PRINT ~Adding new item to container %num%.~ END WRITE_LONG LONG_AT 0x70 + 0xc0 * num + 0x44 THIS + 0x01 WRITE_SHORT 0x76 THIS + 0x01 INSERT_BYTES fj_position key_3 WRITE_ASCIIE fj_position + 0x00 ~%fj_name%~ #8 WRITE_SHORT fj_position + 0x08 fj_itm_expiry WRITE_SHORT fj_position + 0x0a fj_charge0 WRITE_SHORT fj_position + 0x0c fj_charge1 WRITE_SHORT fj_position + 0x0e fj_charge2 WRITE_LONG fj_position + 0x10 fj_flags SET ++ fj_itm_idx SET fj_position += key_3 END END // php $are_container SET fj_deleted = 0x00 PHP_EACH are_container AS key => value BEGIN CLEAR_ARRAY EVAL ~are_container_%key%_itm~ END END ELSE // add vertices PATCH_IF( key_0 == 0x7c )BEGIN // vertices associated with regions PHP_EACH are_region AS num => structure BEGIN PATCH_IF( fj_structure_type == 0x5c && num == fj_delete_mode && fj_deleted == 0x00 )BEGIN SET fj_deleted = 0x01 END ELSE BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassociating vertices to region %num%.~ END WRITE_LONG LONG_AT 0x5c + 0xc4 * ( num - fj_deleted ) + 0x2c fj_vertex_idx PHP_EACH ~are_region_%num%_vertex~ AS num1 => value1 BEGIN INSERT_BYTES fj_position 0x04 WRITE_LONG fj_position value1 WRITE_SHORT 0x80 THIS + 0x01 SET ++fj_vertex_idx SET fj_position += key_3 END END END SET fj_deleted = 0x00 PATCH_IF( fj_structure_type == 0x5c && fj_delete_mode == ` 0 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Adding vertices to new region.~ END WRITE_LONG fj_return_offset + 0x2c fj_vertex_idx PHP_EACH fj_vertex AS num => off BEGIN INSERT_BYTES fj_position 0x04 WRITE_SHORT 0x80 THIS + 0x01 SET ++fj_vertex_idx END PHP_EACH fj_vertex AS num => off BEGIN WRITE_LONG fj_position off SET fj_position += 0x04 END END PHP_EACH are_region AS num => structure BEGIN CLEAR_ARRAY EVAL ~are_region_%num%_vertex~ END // vertices associated with containers PHP_EACH are_container AS num => structure BEGIN PATCH_IF( fj_structure_type == 0x70 && num == fj_delete_mode && fj_deleted == 0x00 )BEGIN SET fj_deleted = 0x01 END ELSE BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassociating vertices to container %num%.~ END WRITE_LONG LONG_AT 0x70 + 0xc0 * ( num - fj_deleted ) + 0x50 fj_vertex_idx PHP_EACH ~are_container_%num%_vertex~ AS num1 => value1 BEGIN INSERT_BYTES fj_position 0x04 WRITE_LONG fj_position value1 WRITE_SHORT 0x80 THIS + 0x01 SET ++fj_vertex_idx SET fj_position += 0x04 END END END SET fj_deleted = 0x00 PATCH_IF fj_structure_type == 0x70 && fj_delete_mode == ` 0 BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Adding vertices to new container.~ END WRITE_LONG fj_return_offset + 0x50 fj_vertex_idx PHP_EACH fj_vertex AS num => off BEGIN SET ++fj_vertex_idx INSERT_BYTES fj_position 0x04 WRITE_SHORT 0x80 THIS + 0x01 END PHP_EACH fj_vertex AS num => off BEGIN WRITE_LONG fj_position off SET fj_position += 0x04 END END PHP_EACH are_container AS num => structure BEGIN CLEAR_ARRAY EVAL ~are_container_%num%_vertex~ END // vertices associated with doors PHP_EACH are_door AS num => structure BEGIN PATCH_IF( fj_structure_type == 0xa8 && num == fj_delete_mode && fj_deleted == 0x00 )BEGIN SET fj_deleted = 0x01 END ELSE BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassociating vertices to door %num%.~ END WRITE_LONG LONG_AT 0xa8 + 0xc8 * ( num - fj_deleted ) + 0x2c fj_vertex_idx PHP_EACH ~are_door_open_%num%_vertex~ AS num1 => value1 BEGIN INSERT_BYTES fj_position 0x04 WRITE_LONG fj_position value1 SET ++fj_vertex_idx SET fj_position += 0x04 WRITE_SHORT 0x80 THIS + 0x01 END WRITE_LONG LONG_AT 0xa8 + 0xc8 * ( num - fj_deleted ) + 0x34 fj_vertex_idx PHP_EACH ~are_door_closed_%num%_vertex~ AS num1 => value1 BEGIN INSERT_BYTES fj_position 0x04 WRITE_LONG fj_position value1 SET ++fj_vertex_idx SET fj_position += 0x04 WRITE_SHORT 0x80 THIS + 0x01 END WRITE_LONG LONG_AT 0xa8 + 0xc8 * ( num - fj_deleted ) + 0x48 fj_vertex_idx PHP_EACH ~are_cell_open_%num%_vertex~ AS num1 => value1 BEGIN INSERT_BYTES fj_position 0x04 WRITE_LONG fj_position value1 SET ++fj_vertex_idx SET fj_position += 0x04 WRITE_SHORT 0x80 THIS + 0x01 END WRITE_LONG LONG_AT 0xa8 + 0xc8 * ( num - fj_deleted ) + 0x50 fj_vertex_idx PHP_EACH ~are_cell_closed_%num%_vertex~ AS num1 => value1 BEGIN INSERT_BYTES fj_position 0x04 WRITE_LONG fj_position value1 SET ++fj_vertex_idx SET fj_position += 0x04 WRITE_SHORT 0x80 THIS + 0x01 END END END SET fj_deleted = 0x00 PATCH_FOR_EACH value1 IN door_open door_closed cell_open cell_closed BEGIN CLEAR_ARRAY EVAL ~are_%value1%_%num%_vertex~ END PATCH_IF( fj_structure_type == 0xa8 && fj_delete_mode == ` 0 )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Adding vertices to new door.~ END WRITE_LONG fj_return_offset + 0x2c fj_vertex_idx WRITE_LONG fj_return_offset + 0x34 LONG_AT (fj_return_offset + 0x2c) + SHORT_AT (fj_return_offset + 0x30) WRITE_LONG fj_return_offset + 0x48 LONG_AT (fj_return_offset + 0x34) + SHORT_AT (fj_return_offset + 0x32) WRITE_LONG fj_return_offset + 0x50 LONG_AT (fj_return_offset + 0x48) + SHORT_AT (fj_return_offset + 0x4c) PATCH_FOR_EACH vertex_type IN door_open door_closed cell_open cell_closed BEGIN PHP_EACH ~fj_%vertex_type%_vert~ AS num => off BEGIN INSERT_BYTES fj_position 0x04 WRITE_SHORT 0x80 THIS + 0x01 END PHP_EACH ~fj_%vertex_type%_vert~ AS num => off BEGIN WRITE_LONG fj_position off SET fj_position += 0x04 END CLEAR_ARRAY EVAL ~fj_%vertex_type%_vert~ END END END // adding vertices // reinsert embedded creatures PATCH_IF( key_0 == 0x54 )BEGIN PHP_EACH are_embedded_cre AS num => value1 BEGIN PATCH_IF( fj_structure_type == 0x54 && num == fj_delete_mode && fj_deleted == 0x00 )BEGIN SET fj_deleted = 0x01 END ELSE BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassociating embedded creature to actor %num%.~ END WRITE_LONG LONG_AT 0x54 + ( num - fj_deleted ) * 0x110 + 0x88 fj_position INSERT_BYTES fj_position LONG_AT ( LONG_AT 0x54 + ( num - fj_deleted ) * 0x110 + 0x8c ) WRITE_ASCIIE fj_position ~%value1%~ SET fj_position += LONG_AT (LONG_AT 0x54 + ( num - fj_deleted ) * 0x110 + 0x8c) END END CLEAR_ARRAY are_embedded_cre SET fj_deleted = 0x00 PATCH_IF( fj_structure_type == 0x54 && fj_delete_mode == ` 0 && !( fj_loading & 0x01 ) )BEGIN PATCH_IF( FILE_EXISTS ~%fj_cre_embedded%~ )BEGIN SET off = BUFFER_LENGTH // we do a stupid dance here to avoid INNER_ACTION APPEND_FILE_EVALUATE ~%fj_cre_embedded%~ READ_ASCII off fj_cre_embedded ( BUFFER_LENGTH - off ) DELETE_BYTES off STRING_LENGTH EVAL ~%fj_cre_embedded%~ END ELSE PATCH_IF( FILE_EXISTS_IN_GAME ~%fj_cre_resref%.cre~ ) BEGIN INNER_PATCH_FILE ~%fj_cre_resref%.cre~ BEGIN READ_ASCII 0x00 fj_cre_embedded ( BUFFER_LENGTH ) END END PATCH_IF( ~%fj_cre_embedded%~ STR_CMP ~~ )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Embedding creature to new actor.~ END WRITE_LONG fj_return_offset + 0x88 fj_position WRITE_LONG fj_return_offset + 0x8c STRING_LENGTH EVAL ~%fj_cre_embedded%~ INSERT_BYTES fj_position LONG_AT (fj_return_offset + 0x8c) WRITE_ASCIIE fj_position ~%fj_cre_embedded%~ SET fj_position += LONG_AT ( fj_return_offset + 0x8c ) END ELSE BEGIN WRITE_LONG fj_return_offset + 0x28 THIS | 0x01 // if we didn't find a .cre, mark it unembedded END END END ELSE // reinsert embedded projectile effects PATCH_IF( key_0 == 0xcc )BEGIN PHP_EACH are_embedded_eff AS num => value1 BEGIN PATCH_IF( fj_structure_type == 0xcc && fj_delete_mode == num && fj_deleted == 0x00 )BEGIN SET fj_deleted = 0x01 END ELSE BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Reassociating embedded effects to projectile %num%.~ END WRITE_LONG LONG_AT 0xcc + ( num - fj_deleted ) * 0x1c + 0x08 fj_position INSERT_BYTES fj_position SHORT_AT (LONG_AT 0xcc + ( num - fj_deleted ) * 0x1c + 0x0c) WRITE_ASCIIE fj_position ~%value1%~ SET fj_position += SHORT_AT (LONG_AT 0xcc + ( num - fj_deleted ) * 0x1c + 0x0c) END END SET fj_deleted = 0x00 CLEAR_ARRAY are_embedded_eff PATCH_IF( fj_structure_type == 0xcc && fj_delete_mode == ` 0 )BEGIN WRITE_LONG fj_return_offset + 0x08 fj_position PHP_EACH fj_embedded_eff AS num => value1 BEGIN PATCH_IF( FILE_EXISTS ~%value1%~ )BEGIN SET off = BUFFER_LENGTH APPEND_FILE_EVALUATE ~%value1%~ READ_ASCII off + 0x08 value1 (0x108) DELETE_BYTES off 0x110 END ELSE PATCH_IF( FILE_EXISTS_IN_GAME ~%value1%.eff~ )BEGIN INNER_PATCH_FILE ~%value1%.eff~ BEGIN READ_ASCII 0x08 value1 (0x108) END END ELSE BEGIN TEXT_SPRINT value1 ~~ END PATCH_IF( ~%value1%~ STR_CMP ~~ )BEGIN PATCH_IF fj_debug BEGIN PATCH_PRINT ~Adding effect %num% to new embedded projectile.~ END WRITE_SHORT fj_return_offset + 0x0c THIS + 0x108 INSERT_BYTES fj_position 0x108 WRITE_ASCIIE fj_position ~%value1%~ SET fj_position += 0x108 END END END CLEAR_ARRAY fj_embedded_eff END END // php $struct: everything added // restoring Icewind Dale II's special snowflakiness PATCH_IF is_id2 BEGIN PATCH_FOR_EACH off IN 0x54 0x5c 0x60 0x68 0x70 0x78 0x7c 0x84 0x88 0xa0 0xa8 0xb0 0xb8 0xbc 0xc0 BEGIN PATCH_IF LONG_AT off BEGIN WRITE_LONG off THIS + 0x10 END END INSERT_BYTES 0x54 0x10 WRITE_ASCIIE 0x54 ~%id2_header%~ SET fj_return_offset += 0x10 GET_OFFSET_ARRAY fj_id_actor 0x54 0x04 0x58 0x02 0 0 0x110 PHP_EACH fj_id_actor AS key => value BEGIN PATCH_IF( LONG_AT( value + 0x88 ) > 0x00 && LONG_AT( value + 0x28 ) & 0x01 == 0x00 )BEGIN WRITE_LONG value + 0x88 THIS + 0x10 END END END END // EOF
#9 -Guest-
Posted 09 October 2010 - 07:02 AM
GET_OFFSET_ARRAY fj_id_actor 0x54 0x04 0x58 0x02 0 0 0x110
must be
GET_OFFSET_ARRAY fj_id_actor 0x64 0x04 0x58 0x02 0 0 0x110
#10
Posted 09 October 2010 - 09:37 AM
EDIT: confirmed - doing this works as expected, and in-game test as well as recheck via DLTCEP and NI shows this working just fine.
/* Existing Promenade edits */ COPY_EXISTING ar0700.are override LPF fj_are_structure INT_VAR fj_loc_x = 3183 fj_loc_y = 983 fj_orientation = 8 // s STR_VAR fj_structure_type = entrance fj_name = Exitc-ar01 END /* new area added */ /* delete original travel trigger */ COPY_EXISTING c-ar01.are override LPF fj_are_structure INT_VAR fj_delete_mode = 0 // (only one region) STR_VAR fj_structure_type = region END BUT_ONLY
I am checking on whether or not the animation sets properly, though - I can't seem to apply the animations.
<<snip for lack-of-reading-the-full-text-before-trying-it-out...>>
results in the original noblewoman animation for the .cre in-game.
Edited by cmorgan, 09 October 2010 - 12:34 PM.
#11
Posted 09 October 2010 - 10:43 AM
\item INT_VAR \verb+fj_animation+ to the actor's animation number (from animate.ids, though the engine uses the animation set on the .cre file);
OK, I'd better shelve this until tomorrow. The docs are clear, and I missed it completely.
#12
Posted 09 October 2010 - 12:33 PM
/* Existing Promenade edits */ /* delete original info trigger */ COPY_EXISTING ar0700.are override LPF fj_are_structure INT_VAR fj_delete = 1 // give me feedback fj_delete_mode = 24 // (#25 in NI, but count starts at 0 not one...) STR_VAR fj_structure_type = region fj_type = 1 // info END BUT_ONLY /* add entrance target, add travel region back to c-ar01.are matching original info trigger */ COPY_EXISTING ar0700.are override LPF fj_are_structure INT_VAR fj_loc_x = 3183 fj_loc_y = 983 fj_orientation = 0 // s STR_VAR fj_structure_type = entrance fj_name = Exitc-ar01 END LPF fj_are_structure INT_VAR fj_type = 2 // travel fj_box_left = 3175 fj_box_top = 857 fj_box_right = 3261 fj_box_bottom = 919 fj_cursor_idx = 30 // door fj_vertex_0 = 3175 + (917 << 16) fj_vertex_1 = 3261 + (919 << 16) fj_vertex_2 = 3260 + (882 << 16) fj_vertex_3 = 3255 + (871 << 16) fj_vertex_4 = 3246 + (864 << 16) fj_vertex_5 = 3226 + (858 << 16) fj_vertex_6 = 3213 + (857 << 16) fj_vertex_7 = 3189 + (863 << 16) fj_vertex_8 = 3178 + (868 << 16) fj_vertex_9 = 3175 + (883 << 16) STR_VAR fj_structure_type = region fj_name = Trancar01 fj_destination_area = c-ar01 fj_destination_name = Trancar01 END /* new area added */ COPY_EXISTING c-ar01.are override LPF fj_are_structure INT_VAR fj_loc_x = 1170 fj_loc_y = 910 fj_orientation = 7 STR_VAR fj_structure_type = entrance fj_name = Trancar01 END LPF fj_are_structure INT_VAR fj_loc_x = 897 fj_loc_y = 934 fj_orientation = 15 // SSE STR_VAR fj_structure_type = actor fj_name = c-test1 fj_cre_resref = c-test1 END LPF fj_are_structure INT_VAR fj_loc_x = 597 fj_loc_y = 516 fj_orientation = 11 // NEE STR_VAR fj_structure_type = actor fj_name = c-test2 fj_cre_resref = c-test2 END LPF fj_are_structure INT_VAR fj_loc_x = 367 fj_loc_y = 729 fj_animation = 0x6110 // fighter female human fj_orientation = 15 //SSE STR_VAR fj_structure_type = actor fj_name = c-test3 fj_cre_resref = c-test3 END LPF fj_are_structure INT_VAR fj_loc_x = 478 fj_loc_y = 528 fj_animation = 0x6110 // fighter female human fj_orientation = 15 //SSE STR_VAR fj_structure_type = actor fj_name = c-test4 fj_cre_resref = c-test4 END LPF fj_are_structure INT_VAR fj_loc_x = 713 fj_loc_y = 398 fj_dest_x = 1128 fj_dest_y = 926 fj_orientation = 15 // SSE STR_VAR fj_structure_type = actor fj_name = c-test5 fj_cre_resref = c-test5 END
(blast. This works well enough that even I can use it... which means I guess I need to learn how to patch .wed and .tis files as well.)
Edited by cmorgan, 09 October 2010 - 01:43 PM.
#13
Posted 13 October 2010 - 06:53 AM
You'll need to patch the .wed to have separate open/closed states for the door. There's an example of that in Gavin-BG1 for Beregost. There's no function for it yet though - maybe a job for "Guest" to do an fj_wed_structure function .I guess I need to learn how to patch .wed and .tis files as well.)
I'm not sure if you can do separate open/closed states via adding a .bam but I suppose it's possible in theory. If it's flickering try messing with the flags on the animation - the nasty binary ones, like cover actors, visible in darkness, etc. I had to use different flags to get those to work in different areas - even ones that looked otherwise similar.
I think it'd be practically impossible to patch a .tis, hence why we need these workarounds with adding BAMs for doors etc. I tried it but DLTCEP stores imported BMPs using a different method than the game's, so I wasn't able to determine a working diff to patch it. Even importing the same identical .tis resulted in a completely different hexadecimal file.
Infinity Engine Contributions
Aurora * BG1 NPC * BG1 Fixpack * Haiass * Infinity Animations * Level 1 NPCs * P5Tweaks
PnP Free Action * Thrown Hammers * Unique Containers * BG:EE * BGII:EE * IWD:EE
================================================================
Player & Modder Resources
BAM Batcher * Creature Lister * Creature Checker * Creature Fixer * Tutu/BGT Area Map & List * Tutu Mod List
================================================================
"Infinity turns out to be the opposite of what people say it is. It is not 'that which has nothing beyond itself' that is infinite, but 'that which always has something beyond itself'." -Aristotle
#14
Posted 17 December 2010 - 07:34 PM
Follow up question, please-
Map note structure variables: \begin{itemize} \item INT_VAR \verb+fj_loc_x+ to the X coordinate*; \item INT_VAR \verb+fj_loc_y+ to the Y coordinate*;
[font="Verdana"]\item INT_VAR \verb+fj_note_strref+ to the note string reference (default -1, BGII only)*;
\item STR_VAR \verb+fj_note_text+ to the note text (PST only)*;
\item INT_VAR \verb+fj_strref_loc+ to the strref location (0=external, 1=dialog.tlk, default 1);
\item INT_VAR \verb+fj_color+ to the map marker color (0-7);
\item INT_VAR \verb+fj_note_id+ to the note ID;
I can't see a way of adding a not-yet-existing sttref. Unless it can take a tra ref - For BG2,
fj_loc_x = 3218 fj_loc_y = 898 fj_note_strref] = @9999 // setup.tra "The Broken Sword" fj_strref_loc = 0 fj_color = 0 fj_note_id = // ??? no reference that I can find...
I can experiment, but if someone knows it will save a good bit of time. I test slowly!
Edited by cmorgan, 17 December 2010 - 09:08 PM.
#15
Posted 17 December 2010 - 08:54 PM
The variable takes string references only. the_bigg added RESOLVE_STR_REF to handle this type of situation more easily.I can't see a way of adding a not-yet-existing sttref. Unless it can take a tra ref - For BG2,
fj_loc_x = 3218 fj_loc_y = 898 fj_note_strref = @9999 // setup.tra "The Broken Sword" fj_strref_loc = 0 fj_color = 0 fj_note_id = // ??? no reference that I can find...
I can experiment, but if someone knows it will save a good bit of time. I test slowly!
fj_note_strref = RESOLVE_STR_REF (@9999)
You can put a tra reference or an actual string inside the brackets there, and RESOLVE_STR_REF will return the reference to that string from dialog.tlk (after adding it if need be).
#16
Posted 17 December 2010 - 09:18 PM
So for an un-traified mod (and for testing), I attempted
/* add entrance target, add travel region back to c-ar01.are matching original info trigger , and map note */ COPY_EXISTING ar0700.are override /* LPF fj_are_structure INT_VAR fj_loc_x = 3216 fj_loc_y = 927 fj_note_strref = RESOLVE_STR_REF (~The Broken Sword~) fj_strref_loc = 0 fj_color = 0 END */ LPF fj_are_structure INT_VAR fj_loc_x = 3183 fj_loc_y = 983 fj_orientation = 0 // s STR_VAR fj_structure_type = entrance fj_name = Exitc-ar01 END LPF fj_are_structure INT_VAR fj_type = 2 // travel fj_box_left = 3175 fj_box_top = 857 fj_box_right = 3261 fj_box_bottom = 919 fj_cursor_idx = 30 // door fj_vertex_0 = 3175 + (917 << 16) fj_vertex_1 = 3261 + (919 << 16) fj_vertex_2 = 3260 + (882 << 16) fj_vertex_3 = 3255 + (871 << 16) fj_vertex_4 = 3246 + (864 << 16) fj_vertex_5 = 3226 + (858 << 16) fj_vertex_6 = 3213 + (857 << 16) fj_vertex_7 = 3189 + (863 << 16) fj_vertex_8 = 3178 + (868 << 16) fj_vertex_9 = 3175 + (883 << 16) STR_VAR fj_structure_type = region fj_name = Trancar01 fj_destination_area = c-ar01 fj_destination_name = Trancar01 END
...with the comment in place, everything is fine. But when uncommented, I get
ERROR: cannot convert fj_structure_type or %fj_structure_type% to an integer
ERROR: [ar0700.are] -> [override] Patching Failed (COPY) (Not_found)
Stopping installation because of error.
I must be missing something. Hey - no defined fj_structure_type defined - i must not have understood the "universal structure variable" thing - adding
STR_VAR
fj_structure_type = note
so
LPF fj_are_structure INT_VAR fj_loc_x = 3216 fj_loc_y = 927 fj_note_strref = RESOLVE_STR_REF (~The Broken Sword~) fj_strref_loc = 0 fj_color = 0 STR_VAR fj_structure_type = note ENDand, success!
So, I just need to work out if I really, really want to make a working door, or if I am ok with just having the door cursor on mouseover.
(Thanks, Mike1072...)
Edited by cmorgan, 17 December 2010 - 09:38 PM.
#17
Posted 18 December 2010 - 06:25 PM
Um yeah, I guess you figured out you need to STR_VAR that...Hey - no defined fj_structure_type defined - i must not have understood the "universal structure variable" thing - adding
STR_VAR
fj_structure_type = note
I recommend the latter. It probably works just fine that way, and is not worth the effort of trying to patch in a door BAM that you can somehow toggle and patching the WED. All that might not even work, or could look crappy. However, if the door is not *visible* (because it's on the north side of a building for example) then you can get away with patching the WED to make an open/closeable (and lockable) door. See Gavin BG1 for an example of that (there isn't a function for it yet).So, I just need to work out if I really, really want to make a working door, or if I am ok with just having the door cursor on mouseover.
The latest version of the function is in the WeiDU source code (tph/include/fj_are_struct.tpa) and the latest documentation is in the WeiDU doc, along with examples for adding animations and other common structures.
Note you can also SPRINT 9999 @9999 and then fj_note_strref = %9999% or so I would guess anyway, but I guess RESOLVE_STR_REF is probably easier.
Infinity Engine Contributions
Aurora * BG1 NPC * BG1 Fixpack * Haiass * Infinity Animations * Level 1 NPCs * P5Tweaks
PnP Free Action * Thrown Hammers * Unique Containers * BG:EE * BGII:EE * IWD:EE
================================================================
Player & Modder Resources
BAM Batcher * Creature Lister * Creature Checker * Creature Fixer * Tutu/BGT Area Map & List * Tutu Mod List
================================================================
"Infinity turns out to be the opposite of what people say it is. It is not 'that which has nothing beyond itself' that is infinite, but 'that which always has something beyond itself'." -Aristotle
#18
Posted 19 December 2010 - 07:24 AM
I'll take a look at the weidu docs on it - I then can strip out the macro from the .tp2 and just use the weidu distributed one.
I have to recheck, but so far, I haven't found any conflicting mods. I am a happy dude.
#19
Posted 19 December 2010 - 09:23 AM
I use this code to remove an info trigger and add a replacement travel trigger. It assumes that the entry I want is 24.
I am pretty sure that as long as stuff is added (like Fishing for Trouble entrances/exits/etc.) everything will be fine, as the structures are added at the end of the sequence. I may need to check that.... but the big question is what if I (or another modder) wants to do the same thing "upstream"?
My mod looks for "Abandon02" (mode 24) and deletes it. Another mod wants to use "Abandon07" and do the same thing.
Aran:
/* delete original info trigger */ COPY_EXISTING ar0700.are override LPF fj_are_structure INT_VAR fj_delete = 1 // give me feedback fj_delete_mode = 24 // (#25 in NI, but count starts at 0 not one...) STR_VAR fj_structure_type = region fj_type = 1 // info END BUT_ONLY
Now the follow-on mod has a problem, because "Abandon07" is now #29 in DLTCEP instead of #30 (count starts from 0 so in this code mode is now 28 instead of 29 ). So...
is there a simple way I can make this an "iterate through the region names, find the correct one, read its mode #, use this information to sprint the correct variables, and delete the correct one if it exists ELSE fail" so that the next person can use the same code on the same area and not hose the area?
(I am playing about to figure it out myself, but not likely to get anything done in the nexxt week or so, and the question has come up more pressing in terms of timeframe).
Edited by cmorgan, 19 December 2010 - 09:44 AM.
#20 -guest-
Posted 19 December 2010 - 12:27 PM
/* delete original info trigger */ COPY_EXISTING ar0700.are override SET region = 0xffffffff READ_LONG 0x5c off READ_SHORT 0x5a num FOR( i = 0 ; i < num && region == 0xffffffff ; ++ i )BEGIN READ_ASCII( off + 0xc4 * i ) name (32) NULL PATCH_IF!( ~%name%~ STRING_CONTAINS_REGEXP ~Abandon07~ )BEGIN SET region = i END END PATCH_IF( region != 0xffffffff )BEGIN LPF fj_are_structure INT_VAR fj_delete_mode = region fj_debug = 1 STR_VAR fj_structure_type = region END END ELSE BEGIN PATCH_FAIL ~Couldn't find region "Abandon07" in ar0700.are~ END BUT_ONLY
or some such thing.
i didn't include any automated way to scan for this data because you may not always want to filter existing structures by the same parameter.