Jump to content

Add a new door to the area (with tiles!)


Recommended Posts

Your tools made it super easy to add the closed door tiles to the end of the TIS, too.

Spoiler
	// Add closed door tiles to end of TIS
	LPF ps_tileset_add_tiles INT_VAR MaxCount = 1 PVRz_Page = "%strt_idx%" PVRz_X = 0 PVRz_Y = 448 STR_VAR Method = "Push" RET Count END
	LPF ps_tileset_add_tiles INT_VAR MaxCount = 1 PVRz_Page = "%strt_idx%" PVRz_X = 64 PVRz_Y = 448 STR_VAR Method = "Push" RET Count END
	LPF ps_tileset_add_tiles INT_VAR MaxCount = 1 PVRz_Page = "%strt_idx%" PVRz_X = 0 PVRz_Y = 512 STR_VAR Method = "Push" RET Count END
	LPF ps_tileset_add_tiles INT_VAR MaxCount = 1 PVRz_Page = "%strt_idx%" PVRz_X = 64 PVRz_Y = 512 STR_VAR Method = "Push" RET Count END

 

 

Link to comment

I did a function that adds a door.  It's not generic, but it's a start.  It should help folks get over some hurdles at least.

It's a lot of code...feel free to rip into it.  Everything can always be better.

Spoiler
////////////////////////////////////////////////////
// ADD A DOOR TO AN AREA AND ITS ASSOCIATED FILES //
// PVRz are compressed graphic files              //
// TIS are a series of indices pointing to        //
//   sections (tiles) in the PVRz files           //
// An area can have two TIS/WED files associated  //
//   with it. One for day, one for night.         //
// If the area has a day and night version, then  //
//   this will need to be called twice - once     //
//   for each TIS/WED                             //
//                                                //
// THIS IS NOT A GENERIC FUNCTION                 //
// IT WAS BUILT FOR A VERY SPECIFIC CASE          //
// MUCH WORK WOULD NEED TO BE DONE TO MAKE IT     //
//   FIT ALL USE CASES                            //
////////////////////////////////////////////////////
// To get the x/y of the open and closed tiles (g_closed_... and g_open_...) use:
// COPY_EXISTING ~<your source tis file>.tis~ ~override~
//   LPF ps_tileset_info INT_VAR Verbose = 2 Log = 1 END // Log verbose output of PVRz-based tileset to file
// BUT_ONLY
// Then open up the log file it generates, search for your tile #s and it'll list and the X/Ys needed to use in his other functions
// I could probably automate that process...but I don't feel much inclined to do so
DEFINE_ACTION_FUNCTION ADD_DOOR
	INT_VAR
		is_day = 0
		g_closed_x1 = 0			// X,Y coordinates of the graphic within the source PVRz file (use ps_tileset_info to determine)
		g_closed_x2 = 0
		g_closed_y1 = 0
		g_closed_y2 = 0
		g_open_x1 = 0
		g_open_x2 = 0
		g_open_y1 = 0
		g_open_y2 = 0
		t_open_pos1 = 0			// The tile # in the target TIS to be replaced (closed are added to the end of the file, not replaced)
		t_open_pos2 = 0
		t_open_pos3 = 0
		t_open_pos4 = 0
		v_closed_x0 = 0			// X/Y pairs (vertices) of the actual door object - only allowing 4 per door state
		v_closed_y0 = 0			// Must be given in clockwise order starting with the one furthest to the right
		v_closed_x1 = 0			// If 2 tie for rightmost - use the lower of the two
		v_closed_y1 = 0
		v_closed_x2 = 0
		v_closed_y2 = 0
		v_closed_x3 = 0
		v_closed_y3 = 0
		v_open_x0 = 0
		v_open_y0 = 0
		v_open_x1 = 0
		v_open_y1 = 0
		v_open_x2 = 0
		v_open_y2 = 0
		v_open_x3 = 0
		v_open_y3 = 0
	STR_VAR
		source_open_pvrz = ""
		source_closed_pvrz = ""
		target_tis = ""
		target_wed = ""
		target_are = ""
		door_name = ""
		door_id = ""
	RET 
		open_pvrz
		closed_pvrz
BEGIN
	// There are 2 versions of the door, opened and closed
	// Copy their respective PVRZ (source graphic) files to the override folder using
	// names that can be associated with the target TIS file (if necessary)
	LAF COPY_PVRZ_FILE_TO_OVERRIDE
		STR_VAR 
			tis_file = EVAL ~%target_tis%~
			source_pvrz = EVAL ~%source_open_pvrz%~
		RET 
			open_pvrz = pvrz_file
			open_pvrz_page = pvrz_suffix
	END
	ACTION_IF (~%source_closed_pvrz%~ STRING_EQUAL ~%source_open_pvrz%~) = 1 BEGIN
		// Open and closed day sources are the same file
		OUTER_SPRINT closed_pvrz ~%open_pvrz%~
		OUTER_SPRINT closed_pvrz_page ~%open_pvrz_page%~
	END ELSE BEGIN
		LAF COPY_PVRZ_FILE_TO_OVERRIDE
			STR_VAR 
				tis_file = EVAL ~%target_tis%~
				source_pvrz = EVAL ~%source_closed_pvrz%~
			RET 
				closed_pvrz = pvrz_file
				closed_pvrz_page = pvrz_suffix
		END
	END
	
	// Update the target TIS file
	COPY_EXISTING ~%target_tis%.tis~ ~override~
		// Will need to know where the closed tiles were added in order to update the WED
		READ_LONG 0x0008 new_closed_tile // The count of the current tiles will be the index to the new one

		PATCH_IF (STRING_LENGTH ~%closed_pvrz%~ > 1) BEGIN
			// Add closed door tiles to end of TIS first
			LPF ps_tileset_add_tiles 
				INT_VAR MaxCount = 1 
					PVRz_Page = "%closed_pvrz_page%" 
					PVRz_X = "%g_closed_x1%"
					PVRz_Y = "%g_closed_y1%" 
				STR_VAR 
					Method = "Push" 
				RET Count
			END
			LPF ps_tileset_add_tiles 
				INT_VAR MaxCount = 1 
					PVRz_Page = "%closed_pvrz_page%" 
					PVRz_X = "%g_closed_x2%"
					PVRz_Y = "%g_closed_y1%" 
				STR_VAR 
					Method = "Push" 
				RET Count
			END
			LPF ps_tileset_add_tiles 
				INT_VAR MaxCount = 1 
					PVRz_Page = "%closed_pvrz_page%" 
					PVRz_X = "%g_closed_x1%"
					PVRz_Y = "%g_closed_y2%" 
				STR_VAR 
					Method = "Push" 
				RET Count
			END
			LPF ps_tileset_add_tiles 
				INT_VAR MaxCount = 1 
					PVRz_Page = "%closed_pvrz_page%" 
					PVRz_X = "%g_closed_x2%"
					PVRz_Y = "%g_closed_y2%" 
				STR_VAR 
					Method = "Push" 
				RET Count
			END
		END
		
		PATCH_IF (STRING_LENGTH ~%open_pvrz%~ > 1) BEGIN
			// These replace tiles currently in the file
			LPF ps_tileset_add_tiles 
				INT_VAR MaxCount = 1 
					Pos = "%t_open_pos1%"
					PVRz_Page = "%open_pvrz_page%" 
					PVRz_X = "%g_open_x1%"
					PVRz_Y = "%g_open_y1%" 
				STR_VAR 
					Method = "Replace" 
				RET Count
			END
			LPF ps_tileset_add_tiles 
				INT_VAR MaxCount = 1 
					Pos = "%t_open_pos2%"
					PVRz_Page = "%open_pvrz_page%" 
					PVRz_X = "%g_open_x2%"
					PVRz_Y = "%g_open_y1%" 
				STR_VAR 
					Method = "Replace" 
				RET Count
			END
			LPF ps_tileset_add_tiles 
				INT_VAR MaxCount = 1 
					Pos = "%t_open_pos3%"
					PVRz_Page = "%open_pvrz_page%" 
					PVRz_X = "%g_open_x1%"
					PVRz_Y = "%g_open_y2%" 
				STR_VAR 
					Method = "Replace" 
				RET Count
			END
			LPF ps_tileset_add_tiles 
				INT_VAR MaxCount = 1 
					Pos = "%t_open_pos4%"
					PVRz_Page = "%open_pvrz_page%" 
					PVRz_X = "%g_open_x2%"
					PVRz_Y = "%g_open_y2%" 
				STR_VAR 
					Method = "Replace" 
				RET Count
			END
		END
	BUT_ONLY_IF_IT_CHANGES
	
	// WED file changes
	COPY_EXISTING ~%target_wed%.WED~ ~override~
		LPF ADD_WED_DOOR
			INT_VAR
				v_open_x0 = %v_open_x0%			// X/Y pairs (vertices) of the actual door object - only allowing 4 per door state
				v_open_y0 = %v_open_y0%			// Must be given in clockwise order starting with the one furthest to the right
				v_open_x1 = %v_open_x1%			// Start with the lowest if two are tied for the rightmost
				v_open_y1 = %v_open_y1%
				v_open_x2 = %v_open_x2%
				v_open_y2 = %v_open_y2%
				v_open_x3 = %v_open_x3%
				v_open_y3 = %v_open_y3%
				v_closed_x0 = %v_closed_x0%
				v_closed_y0 = %v_closed_y0%
				v_closed_x1 = %v_closed_x1%
				v_closed_y1 = %v_closed_y1%
				v_closed_x2 = %v_closed_x2%
				v_closed_y2 = %v_closed_y2%
				v_closed_x3 = %v_closed_x3%
				v_closed_y3 = %v_closed_y3%
				t_open_pos1 = %t_open_pos1%			// The tile # in the target TIS that was replaced
				t_open_pos2 = %t_open_pos2%
				t_open_pos3 = %t_open_pos3%
				t_open_pos4 = %t_open_pos4%
				t_closed_pos1 = %new_closed_tile%	// The tile # of the first new closed graphic that was added to the target TIS ... rest are sequential
			STR_VAR 
				door_id = EVAL ~%door_id%~			// Called name in NI, but it's the ID used in the ARE file
		END
	BUT_ONLY_IF_IT_CHANGES
	
	// I'm just putting it in to connect it to the WED
	// Any details like scripts, flags, travel regions, keys, etc will have to be done elsewhere
	ACTION_IF is_day = 1 BEGIN
		COPY_EXISTING ~%target_are%.ARE~ ~override~
			// Set defaults
			SET door_cursor = 30
			
			// Calculate the min/max x/y for both open/closed
			LPF GET_BOUNDING_BOX
				INT_VAR
					v_x0 = %v_open_x0%
					v_y0 = %v_open_y0%
					v_x1 = %v_open_x1%
					v_y1 = %v_open_y1%
					v_x2 = %v_open_x2%
					v_y2 = %v_open_y2%
					v_x3 = %v_open_x3%
					v_y3 = %v_open_y3%
				RET
					min_open_x = min_x
					max_open_x = max_x
					min_open_y = min_y
					max_open_y = max_y
			END
			LPF GET_BOUNDING_BOX
				INT_VAR
					v_x0 = %v_closed_x0%
					v_y0 = %v_closed_y0%
					v_x1 = %v_closed_x1%
					v_y1 = %v_closed_y1%
					v_x2 = %v_closed_x2%
					v_y2 = %v_closed_y2%
					v_x3 = %v_closed_x3%
					v_y3 = %v_closed_y3%
				RET
					min_closed_x = min_x
					max_closed_x = max_x
					min_closed_y = min_y
					max_closed_y = max_y
			END
			
			LPF fj_are_structure
				INT_VAR
					fj_open_box_left       = min_open_x
					fj_open_box_top        = min_open_y
					fj_open_box_right      = max_open_x
					fj_open_box_bottom     = max_open_y
					fj_closed_box_left     = min_closed_x
					fj_closed_box_top      = min_closed_y
					fj_closed_box_right    = max_closed_x
					fj_closed_box_bottom   = max_closed_y
					fj_cursor_idx          = door_cursor
					fj_door_open_vert_0    = v_open_x0 + (v_open_y0 << 16)
					fj_door_open_vert_1    = v_open_x1 + (v_open_y1 << 16)
					fj_door_open_vert_2    = v_open_x2 + (v_open_y2 << 16)
					fj_door_open_vert_3    = v_open_x3 + (v_open_y3 << 16)
					fj_door_closed_vert_0  = v_closed_x0 + (v_closed_y0 << 16)
					fj_door_closed_vert_1  = v_closed_x1 + (v_closed_y1 << 16)
					fj_door_closed_vert_2  = v_closed_x2 + (v_closed_y2 << 16)
					fj_door_closed_vert_3  = v_closed_x3 + (v_closed_y3 << 16)
				STR_VAR
					fj_structure_type = ~door~
					fj_name = EVAL ~%door_name%~
					fj_door_wed_id = EVAL ~%door_id%~
			END
		BUT_ONLY_IF_IT_CHANGES
	END
END

////////////////////////////////////////////////////
// Gets the name of the PVRz file and copies it   //
// to the override folder if it's new             //
// Returns the name of the PVRz file as well      //
// as it's associated parts (prefix and suffix)   //
// The PVRz file name is the TIS file name        //
// with the 2nd letter of the file name dropped   //
// and then a sequential number added as a suffix //
////////////////////////////////////////////////////
DEFINE_ACTION_FUNCTION COPY_PVRZ_FILE_TO_OVERRIDE
	STR_VAR
		tis_file = ~~		// target tis file name without the extension
		source_pvrz = ~~ 	// source of the graphic without the extension
	RET
		pvrz_file
		pvrz_prefix
		pvrz_suffix
BEGIN
	// Set default return values
	OUTER_SPRINT pvrz_file ~~
	OUTER_SPRINT pvrz_prefix ~~
	OUTER_SPRINT pvrz_suffix ~~
	
	ACTION_IF (STRING_LENGTH ~%tis_file%~ > 1) BEGIN
		OUTER_INNER_PATCH_SAVE pvrz_prefix ~%tis_file%~ BEGIN DELETE_BYTES 1 1 END
		
		ACTION_IF ((~%source_pvrz%~ STRING_CONTAINS_REGEXP ~%pvrz_prefix%~) = 0) AND ((STRING_LENGTH ~%pvrz_prefix%~) = ((STRING_LENGTH ~%source_pvrz%~) - 2)) BEGIN
			// The source of the graphic is already one of the TIS file's PVRz files
			OUTER_INNER_PATCH_SAVE pvrz_suffix ~%source_pvrz%~ BEGIN DELETE_BYTES 0 ((STRING_LENGTH ~%source_pvrz%~) - 2) END
			OUTER_SPRINT pvrz_file ~%source_pvrz%~
			
		END ELSE BEGIN
			// The source of the graphic will need to be copied to a new PVRz that can be associated with the TIS
			OUTER_SPRINT pvrz_suffix ~-1~
			OUTER_SET file_ok = 0
			OUTER_SET strt_idx = 0
			ACTION_IF GAME_IS ~eet~ THEN BEGIN
				OUTER_SET strt_idx = 50
			END

			OUTER_FOR (idx = strt_idx; idx < 99 && file_ok = 0; idx = idx + 1) BEGIN
				ACTION_IF idx < 10 THEN BEGIN
					OUTER_SPRINT pvrz_suffix ~0%idx%~
				END ELSE BEGIN
					OUTER_SPRINT pvrz_suffix ~%idx%~
				END
				ACTION_IF NOT FILE_EXISTS_IN_GAME ~%pvrz_prefix%%pvrz_suffix%.pvrz~ THEN BEGIN
					OUTER_SET file_ok = 1
					OUTER_SPRINT pvrz_file ~%pvrz_prefix%%pvrz_suffix%~
					COPY_EXISTING ~%source_pvrz%.PVRZ~ ~override\%pvrz_file%.pvrz~
				END
			END
		END
	END
END

/////////////////////////////////////////////////////
// Determine the bounding box for polygon vertices //
// Expects there to be four                        //
/////////////////////////////////////////////////////
DEFINE_PATCH_FUNCTION GET_BOUNDING_BOX
	INT_VAR
		v_x0 = 0
		v_y0 = 0
		v_x1 = 0
		v_y1 = 0
		v_x2 = 0
		v_y2 = 0
		v_x3 = 0
		v_y3 = 0
	RET
		min_x
		max_x
		min_y
		max_y
BEGIN
	SET min_x = v_x0
	SET max_x = v_x0
	SET min_y = v_y0
	SET max_y = v_y0
	
	// Calculate the min/max x/y
	PATCH_IF v_x1 < min_x BEGIN
		SET min_x = v_x1
	END
	PATCH_IF v_x2 < min_x BEGIN
		SET min_x = v_x2
	END
	PATCH_IF v_x3 < min_x BEGIN
		SET min_x = v_x3
	END

	PATCH_IF v_x1 > max_x BEGIN
		SET max_x = v_x1
	END
	PATCH_IF v_x2 > max_x  BEGIN
		SET max_x = v_x2
	END
	PATCH_IF v_x3 > max_x  BEGIN
		SET max_x = v_x3
	END
	
	PATCH_IF v_y1 < min_y  BEGIN
		SET min_y = v_y1
	END
	PATCH_IF v_y2 < min_y  BEGIN
		SET min_y = v_y2
	END
	PATCH_IF v_y3 < min_y  BEGIN
		SET min_y = v_y3
	END

	PATCH_IF v_y1 > max_y  BEGIN
		SET max_y = v_y1
	END
	PATCH_IF v_y2 > max_y  BEGIN
		SET max_y = v_y2
	END
	PATCH_IF v_y3 > max_y  BEGIN
		SET max_y = v_y3
	END
END

//////////////////////////////////////////
// ADD A DOOR TO THE WED FILE           //
// It'll be easier to insert bytes at   //
//   the proper places starting from    //
//   the bottom of the file, recalc all //
//   the offsets, then add objects that //
//   reference those offsets.           //
// Those sections that don't reference  //
//   offsets can be written right away. //
//////////////////////////////////////////
DEFINE_PATCH_FUNCTION ADD_WED_DOOR
	INT_VAR
		v_open_x0 = 0			// X/Y pairs (vertices) of the actual door object - only allowing 4 per door state
		v_open_y0 = 0			// Must be given in clockwise order starting with the one furthest to the right
		v_open_x1 = 0			// Start with the lowest if two are tied for the rightmost
		v_open_y1 = 0
		v_open_x2 = 0
		v_open_y2 = 0
		v_open_x3 = 0
		v_open_y3 = 0
		v_closed_x0 = 0
		v_closed_y0 = 0
		v_closed_x1 = 0
		v_closed_y1 = 0
		v_closed_x2 = 0
		v_closed_y2 = 0
		v_closed_x3 = 0
		v_closed_y3 = 0
		t_open_pos1 = 0			// The tile # in the target TIS that was replaced (closed were added to the end of the file, not replaced)
		t_open_pos2 = 0
		t_open_pos3 = 0
		t_open_pos4 = 0
		t_closed_pos1 = 0		// The tile # of the first new closed graphic that was added to the target TIS ... rest are sequential
	STR_VAR 
		door_id = ""			// Called name in NI, but it's the ID used in the ARE file
BEGIN
	///////////////////////////////////////////
	// Read in offsets and counts from the headers
	///////////////////////////////////////////
	READ_LONG 0x0008 num_overlays
	READ_LONG 0x000c num_doors
	READ_LONG 0x0010 offset_overlays
	READ_LONG 0x0014 offset_header2
	READ_LONG 0x0018 offset_doors
	READ_LONG 0x001c offset_door_tile_cells
	READ_LONG (offset_header2) num_polygons
	READ_LONG (offset_header2 + 0x0004) offset_polygons
	READ_LONG (offset_header2 + 0x0008) offset_vertices
	READ_LONG (offset_header2 + 0x000c) offset_wallgroups
	READ_LONG (offset_header2 + 0x0010) offset_polygon_indices
	READ_LONG (offset_overlays + 0x0010) offset_overlay_tilemap	// if it's not the first overlay - this will need to change
	
	///////////////////////////////////////////
	// Set up the size of objects
	///////////////////////////////////////////
	SET size_overlay = 0x0018
	SET size_door = 0x001a
	SET size_tilemap = 0x000a
	SET size_door_tile_cell = 0x0002
	SET size_polygon = 0x0012
	SET size_index = 0x0002
	SET size_vertex = 0x0004			// X,Y
	
	//////////////////////////////////
	//                              //
	//  ******** VERTICES ********  //
	//                              //
	//////////////////////////////////
	// Only allowing for 8 new vertices, 4 for the open door and 4 for the closed
	SET new_vertices_open = 4
	SET new_vertices_closed = 4
	
	// New vertices can just be added at the end of the file (hopefully)
	// We'll add the open ones first then the closed ones
	SET new_open_vertices_offset = SOURCE_SIZE
	SET new_closed_vertices_offset = new_open_vertices_offset + (new_vertices_open * size_vertex)
	
	// Insert bytes at the end of the file for our new vertices
	INSERT_BYTES new_open_vertices_offset (size_vertex * (new_vertices_open + new_vertices_closed))
	
	// Add the vertices to our new vertices section
	// These define the door polygons
	WRITE_SHORT new_open_vertices_offset %v_open_x0%
	WRITE_SHORT (new_open_vertices_offset + 0x0002) %v_open_y0%
	WRITE_SHORT (new_open_vertices_offset + 0x0004) %v_open_x1%
	WRITE_SHORT (new_open_vertices_offset + 0x0006) %v_open_y1%
	WRITE_SHORT (new_open_vertices_offset + 0x0008) %v_open_x2%
	WRITE_SHORT (new_open_vertices_offset + 0x000a) %v_open_y2%
	WRITE_SHORT (new_open_vertices_offset + 0x000c) %v_open_x3%
	WRITE_SHORT (new_open_vertices_offset + 0x000e) %v_open_y3%
	WRITE_SHORT new_closed_vertices_offset %v_closed_x0%
	WRITE_SHORT (new_closed_vertices_offset + 0x0002) %v_closed_y0%
	WRITE_SHORT (new_closed_vertices_offset + 0x0004) %v_closed_x1%
	WRITE_SHORT (new_closed_vertices_offset + 0x0006) %v_closed_y1%
	WRITE_SHORT (new_closed_vertices_offset + 0x0008) %v_closed_x2%
	WRITE_SHORT (new_closed_vertices_offset + 0x000a) %v_closed_y2%
	WRITE_SHORT (new_closed_vertices_offset + 0x000c) %v_closed_x3%
	WRITE_SHORT (new_closed_vertices_offset + 0x000e) %v_closed_y3%
	
	////////////////////////////////////////////////////
	//                                                //
	//  ******** POLYGON INDEX LOOKUP TABLE ********  //
	//                                                //
	////////////////////////////////////////////////////
	// I think this is only used for walls - not doors
	
	//////////////////////////////////
	//                              //
	//  ******** POLYGONS ********  //
	//                              //
	//////////////////////////////////
	// Need to add polygons for both open and closed doors in the polygon section
	// the offset to and count of these will be added to the door object
	// only allowing for 1 open and 1 closed polygon at the moment
	SET new_polygons_open = 1			
	SET new_polygons_closed = 1
	SET new_open_polygon_flags = 129 // Shade wall + door
	SET new_closed_polygon_flags = 129
	
	// New entries will go at the bottom of the current section
	SET new_polygons_open_offset = offset_polygons + (num_polygons * size_polygon)
	SET new_polygons_closed_offset = new_polygons_open_offset + (new_polygons_open * size_polygon)
	
	// Determine the next vertex index to use
	READ_LONG (offset_polygons + ((num_polygons - 1) * size_polygon)) last_vertex_index
	READ_LONG (offset_polygons + ((num_polygons - 1) * size_polygon) + 0x0004) num_last_vertices_used
	SET new_vertex_index = last_vertex_index + num_last_vertices_used
	
	// Calculate the min/max x/y for both open/closed
	LPF GET_BOUNDING_BOX
		INT_VAR
			v_x0 = %v_open_x0%
			v_y0 = %v_open_y0%
			v_x1 = %v_open_x1%
			v_y1 = %v_open_y1%
			v_x2 = %v_open_x2%
			v_y2 = %v_open_y2%
			v_x3 = %v_open_x3%
			v_y3 = %v_open_y3%
		RET
			min_open_x = min_x
			max_open_x = max_x
			min_open_y = min_y
			max_open_y = max_y
	END
	LPF GET_BOUNDING_BOX
		INT_VAR
			v_x0 = %v_closed_x0%
			v_y0 = %v_closed_y0%
			v_x1 = %v_closed_x1%
			v_y1 = %v_closed_y1%
			v_x2 = %v_closed_x2%
			v_y2 = %v_closed_y2%
			v_x3 = %v_closed_x3%
			v_y3 = %v_closed_y3%
		RET
			min_closed_x = min_x
			max_closed_x = max_x
			min_closed_y = min_y
			max_closed_y = max_y
	END
	
	// Insert bytes at the end of the current section for our new polygons
	INSERT_BYTES new_polygons_open_offset (size_polygon * (new_polygons_open + new_polygons_closed))
	
	// Can add polygons now since they only reference indices, not offsets
	WRITE_LONG new_polygons_open_offset %new_vertex_index%
	WRITE_LONG (new_polygons_open_offset + 0x0004) %new_vertices_open%
	WRITE_BYTE (new_polygons_open_offset + 0x0008) %new_open_polygon_flags%
	WRITE_BYTE (new_polygons_open_offset + 0x0009) 0xff
	WRITE_SHORT (new_polygons_open_offset + 0x000a) %min_open_x%
	WRITE_SHORT (new_polygons_open_offset + 0x000c) %max_open_x%
	WRITE_SHORT (new_polygons_open_offset + 0x000e) %min_open_y%
	WRITE_SHORT (new_polygons_open_offset + 0x0010) %max_open_y%
	
	WRITE_LONG new_polygons_closed_offset (%new_vertex_index% + %new_vertices_open%)
	WRITE_LONG (new_polygons_closed_offset + 0x0004) %new_vertices_closed%
	WRITE_BYTE (new_polygons_closed_offset + 0x0008) %new_closed_polygon_flags%
	WRITE_BYTE (new_polygons_closed_offset + 0x0009) 0xff
	WRITE_SHORT (new_polygons_closed_offset + 0x000a) %min_closed_x%
	WRITE_SHORT (new_polygons_closed_offset + 0x000c) %max_closed_x%
	WRITE_SHORT (new_polygons_closed_offset + 0x000e) %min_closed_y%
	WRITE_SHORT (new_polygons_closed_offset + 0x0010) %max_closed_y%

	/////////////////////////////////////
	//                                 //
	//  ******** WALL GROUPS ********  //
	//                                 //
	/////////////////////////////////////
	// I don't think I need to do anything here

	/////////////////////////////////////////////////
	//                                             //
	//  ******** TILE INDEX LOOKUP TABLE ********  //
	//                                             //
	/////////////////////////////////////////////////
	// I don't think I need to do anything with these
	
	/////////////////////////////////////////
	//                                     //
	//  ******** DOOR TILE CELLS ********  //
	//                                     //
	/////////////////////////////////////////
	// Need to add 4 entries into this table for the 4 graphic tiles used by the open door
	// It'll point to tiles defined in the Tile Map Structure and will also associate them with their closed graphics
	SET new_door_tile_cells = 4

	// Find the last tilemap index to calculate the next and determine the offset to the next
	SET last_door_tile_index = 0
	SET last_door_tile_count = 0
	PATCH_IF num_doors > 0 BEGIN
		SET last_door_offset  = offset_doors + ((num_doors - 1) * size_door)
		READ_SHORT (last_door_offset + 0x000a) last_door_tile_index
		READ_SHORT (last_door_offset + 0x000c) last_door_tile_count
	END
	SET new_door_tile_index = (last_door_tile_index + last_door_tile_count)
	
	// Calculate where the new door tile cells are inserted
	SET new_door_tile_cell_offset = offset_door_tile_cells + (new_door_tile_index * size_door_tile_cell)
	
	// Insert bytes at the end of the current section for our new door tile cells
	INSERT_BYTES new_door_tile_cell_offset (size_door_tile_cell * new_door_tile_cells)
	
	// Door tile cells only reference indices, not offsets, so we can add them right away
	WRITE_SHORT new_door_tile_cell_offset %t_open_pos1%
	WRITE_SHORT (new_door_tile_cell_offset + size_door_tile_cell) %t_open_pos2%
	WRITE_SHORT (new_door_tile_cell_offset + (2 * size_door_tile_cell)) %t_open_pos3%
	WRITE_SHORT (new_door_tile_cell_offset + (3 * size_door_tile_cell)) %t_open_pos4%
	
	/////////////////////////////////////////////
	//                                         //
	//  ******** TILE MAP STRUCTURES ********  //
	//                                         //
	/////////////////////////////////////////////
	// Need to find and update the tiles associated with the open door
	// and update their secondary values to point to the new closed door graphics
	WRITE_SHORT (offset_overlay_tilemap + (t_open_pos1 * size_tilemap) + 0x0004) %t_closed_pos1%
	WRITE_SHORT (offset_overlay_tilemap + (t_open_pos2 * size_tilemap) + 0x0004) (%t_closed_pos1% + 1)
	WRITE_SHORT (offset_overlay_tilemap + (t_open_pos3 * size_tilemap) + 0x0004) (%t_closed_pos1% + 2)
	WRITE_SHORT (offset_overlay_tilemap + (t_open_pos4 * size_tilemap) + 0x0004) (%t_closed_pos1% + 3)

	///////////////////////////////
	//                           //
	//  ******** DOORS ********  //
	//                           //
	///////////////////////////////
	// Calculate the start of our new door object
	SET new_door_offset = offset_doors + (num_doors * size_door)
	
	// Only allowing for 4 door tiles (per state) at the moment
	// Only the open ones need to be linked to the door structure
	SET new_tilemap_tiles = 4
	
	// Insert bytes at the start of our new door section
	INSERT_BYTES new_door_offset size_door
	
	// Write the door section after all offsets are updated
	
	/////////////////////////////////////////////
	//                                         //
	//  ******** RECALCULATE OFFSETS ********  //
	//                                         //
	/////////////////////////////////////////////
	SET add_size = size_door
	SET offset_door_tile_cells = offset_door_tile_cells + add_size
	
	SET add_size = add_size + (size_door_tile_cell * new_door_tile_cells)
	SET offset_wallgroups = offset_wallgroups + add_size	
	SET offset_polygons = offset_polygons + add_size
	SET new_polygons_open_offset = new_polygons_open_offset + add_size
	SET new_polygons_closed_offset = new_polygons_open_offset + (size_polygon * new_polygons_open)
	
	SET add_size = add_size + (size_polygon * (new_polygons_open + new_polygons_closed))
	SET offset_polygon_indices = offset_polygon_indices + add_size
	SET offset_vertices = offset_vertices + add_size
	SET new_open_vertices_offset = new_open_vertices_offset + add_size
	SET new_closed_vertices_offset = new_closed_vertices_offset + add_size

	///////////////////////////////////////////////////////////////
	//                                                           //
	//  ******** WRITE TO SECTIONS REFERENCING OFFSETS ********  //
	//                                                           //
	///////////////////////////////////////////////////////////////
	// VERTICES - already written

	// POLYGON INDEX LOOKUP TABLE - no changes
	
	// POLYGONS - already written

	// WALL GROUPS - no changes
	
	// TILE INDEX LOOKUP TABLE - no changes
	
	// DOOR TILE CELLS - already written

	// TILE MAP STRUCTURES - already written

	// DOORS
	WRITE_ASCIIE new_door_offset ~%door_id%~ (8)
	WRITE_SHORT (new_door_offset + 0x0008) 1					// Is door?
	WRITE_SHORT (new_door_offset + 0x000a) %new_door_tile_index%
	WRITE_SHORT (new_door_offset + 0x000c) %new_tilemap_tiles%
	WRITE_SHORT (new_door_offset + 0x000e) %new_polygons_open%
	WRITE_SHORT (new_door_offset + 0x0010) %new_polygons_closed%
	WRITE_LONG (new_door_offset + 0x0012) %new_polygons_open_offset%
	WRITE_LONG (new_door_offset + 0x0016) %new_polygons_closed_offset%

	// SECONDARY HEADER
	WRITE_LONG (offset_header2) (num_polygons + new_polygons_open + new_polygons_closed)
	WRITE_LONG (offset_header2 + 0x0004) %offset_polygons%
	WRITE_LONG (offset_header2 + 0x0008) %offset_vertices%
	WRITE_LONG (offset_header2 + 0x000c) %offset_wallgroups%
	WRITE_LONG (offset_header2 + 0x0010) %offset_polygon_indices%

	// OVERLAYS - offset to this section doesn't change
	// Update offsets to tilemaps and tile index lookups referenced by the overlays
	FOR (idx = 0; idx < num_overlays; idx = idx + 1) BEGIN
		READ_LONG (offset_overlays + (idx * size_overlay) + 0x0010) offset_overlay_tilemap
		READ_LONG (offset_overlays + (idx * size_overlay) + 0x0014) offset_overlay_tile_lookup
		SET add_size = size_door
		SET new_offset_overlay_tilemap = offset_overlay_tilemap + add_size
		SET add_size = add_size + (new_door_tile_cells * size_door_tile_cell)
		SET new_offset_overlay_tile_lookup = offset_overlay_tile_lookup + add_size
		WRITE_LONG (offset_overlays + (idx * size_overlay) + 0x0010) %new_offset_overlay_tilemap%
		WRITE_LONG (offset_overlays + (idx * size_overlay) + 0x0014) %new_offset_overlay_tile_lookup%
	END

	// HEADER
	// Update the header section with new number of doors and offset to door tile cell indices
	WRITE_LONG (0x000c) (num_doors + 1)
	WRITE_LONG (0x001c) %offset_door_tile_cells%
END

 

 

It's called like this:

Spoiler
		// Add a door to the PC's residence in the SoD areas
		// Will take the graphic for the open door from the BG1 area PVRz files
		// There are 4 versions of every exterior door - open and closed during the day and night
		OUTER_SPRINT open_source_day "A020008"
		OUTER_SPRINT open_source_night "A0200N08"
		OUTER_SPRINT closed_source_day "B001000"
		OUTER_SPRINT closed_source_night "B0010N00"
		ACTION_IF GAME_IS ~eet~ THEN BEGIN
			OUTER_SPRINT open_source_day "B020008"
			OUTER_SPRINT open_source_night "B0200N08"
			OUTER_SPRINT closed_source_day "B001050"
			OUTER_SPRINT closed_source_night "B0010N50"
		END

		// Daytime door
		LAF ADD_DOOR
			INT_VAR
				is_day = 1
				g_closed_x1 = 0		// X,Y coordinates from within the source PVRz file
				g_closed_x2 = 64
				g_closed_y1 = 448
				g_closed_y2 = 512
				g_open_x1 = 128
				g_open_x2 = 192
				g_open_y1 = 704
				g_open_y2 = 768
				t_open_pos1 = 140		// The tile # in the target TIS to be replaced
				t_open_pos2 = 141
				t_open_pos3 = 160
				t_open_pos4 = 161
				v_closed_x0 = 39				// X/Y pairs (vertices) of the actual door object - only allowing 4 per door state
				v_closed_y0 = 524				// Must be given in clockwise order starting with the one furthest to the right
				v_closed_x1 = 87				// If 2 tie for rightmost - use the lower of the two
				v_closed_y1 = 535
				v_closed_x2 = 87
				v_closed_y2 = 469
				v_closed_x3 = 39
				v_closed_y3 = 457
				v_open_x0 = 16			
				v_open_y0 = 553			
				v_open_x1 = 39			
				v_open_y1 = 552
				v_open_x2 = 39
				v_open_y2 = 455
				v_open_x3 = 16
				v_open_y3 = 484
			STR_VAR
				source_open_pvrz = EVAL "%open_source_day%"
				source_closed_pvrz = EVAL "%closed_source_day%"
				target_tis = ~BD0010~
				target_wed = ~BD0010~
				target_are = ~BD0010~
				door_name = "Port0006"
				door_id = "door0006"
			RET 
				pvrzOpenDay = open_pvrz
				pvrzClosedDay = closed_pvrz
		END
		
		// Nighttime door
		LAF ADD_DOOR
			INT_VAR
				is_day = 0
				g_closed_x1 = 0			// X,Y coordinates from within the source PVRz file (use DLTCEP to determine)
				g_closed_x2 = 64
				g_closed_y1 = 448
				g_closed_y2 = 512
				g_open_x1 = 128		
				g_open_x2 = 192
				g_open_y1 = 704
				g_open_y2 = 768
				t_open_pos1 = 140			// The tile # in the target TIS to be replaced
				t_open_pos2 = 141
				t_open_pos3 = 160
				t_open_pos4 = 161
				v_closed_x0 = 39				// X/Y pairs (vertices) of the actual door object - only allowing 4 per door state
				v_closed_y0 = 524				// Must be given in clockwise order starting with the one furthest to the right
				v_closed_x1 = 87				// If 2 tie for rightmost - use the lower of the two
				v_closed_y1 = 535
				v_closed_x2 = 87
				v_closed_y2 = 469
				v_closed_x3 = 39
				v_closed_y3 = 457
				v_open_x0 = 16			
				v_open_y0 = 553			
				v_open_x1 = 39			
				v_open_y1 = 552
				v_open_x2 = 39
				v_open_y2 = 455
				v_open_x3 = 16
				v_open_y3 = 484
			STR_VAR
				source_open_pvrz = EVAL "%open_source_night%"
				source_closed_pvrz = EVAL "%closed_source_night%"
				target_tis = ~BD0010N~
				target_wed = ~BD0010N~
				target_are = ~BD0010~
				door_name = "Port0006"
				door_id = "door0006"
			RET 
				pvrzOpenNight = open_pvrz
				pvrzClosedNight = closed_pvrz
		END

 

 

Edited by Lauriel
Removed redundant code and fixed a comment
Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

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

×   Your previous content has been restored.   Clear editor

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

×
×
  • Create New...