One macro provides a lot of the offsets and stuff you generally need to look up in NI or IESDP and provides their values for you in consistently named variables for your use.
Another two macros will redo all the offsets and counters for you when adding any combination of new sections to a .ARE file with very very little work on your part.
Feel free to cut and paste this entire file and use it as an include in your programs. The comments within the file explain what it does and how it works.
Keep an eye here, because I hope to be adding a couple of macros that will allow you to edit the vertexes in an existing door, container or trigger, or add items to an existing container, hopefully within a day or two after I've worked the kinks out.
Enjoy!
EDIT: 05/28/09. Significant update. Now updated to work with any IE game, hopefully... only tested for PS:T, but now takes into account fields used by other IE games like Map Notes and Projectile Traps (exclusive to BG2). If you're using it for a game other than PS:T, make sure to adjust the value of the variable "Q_Game" set in the first macro, Q_AREInitVars.
Also note, these macros will not work with IWD2, the area file is significantly different.
EDIT 2: 05/30/09: Attached a downloadable version of these macros at the end of this post, to save the trouble of cutting and pasting.
EDIT 3: 06/01/09: Tweaked to account for adding to empty sections sharing the same offset with a non-empty section.
EDIT 4: 06/11/09: Added Sasha's GAME_IS logic to replace manual SET Q_Game, thanks to Sasha.
// ======================= BEGIN Q_ARE_InitVars Macro Definition =========================
DEFINE_PATCH_MACRO ~Q_ARE_InitVars~ BEGIN
PATCH_IF (GAME_IS ~PST~) BEGIN //only pst games
SET Q_Game = 1
END
PATCH_IF (GAME_IS ~soa tob bgt tutu tutu_totsc~) BEGIN //all bg2 engine games
SET Q_Game = 2
END
PATCH_IF !(GAME_IS ~PST soa tob bgt tutu tutu_totsc IWD2~) BEGIN //any other ie game but pst, bg2 variants and iwd2
SET Q_Game = 3
END
// WEIDU AREA MAPPING TOOL #1, by Qwinn
// This macro initializes variables to be used by the other WAMT macros. They are also highly useful
// for the coder him/herself to use, and even if none of the other macros are installed or used,
// inserting the include in order to use this macro can save a lot of referring back and forth
// to NI and IESDP.
// OVERVIEW/TUTORIAL ON THE AREA FILE
// An Area file is comprised of 1 main section and 15 subsections. The main section contains
// basic information about the area, and also stores information about each of the 15 subsections.
// Each of the subsections can hold a varying number of records, and thus the main section stores
// offsets and counts which are used to map the rest of file.
//
// The 15 subsections are referred to in these tools with the following 5 letter codes:
//
// "Actor" = Actors
// "Trigg" = Info Triggers
// "Spawn" = Spawn Points
// "Entra" = Entrances
// "Conta" = Containers
// "Items" = Items
// "Ambie" = Ambients
// "Varia" = Variables - not used in PS:T
// "Doors" = Doors
// "Tiled" = Tiled Objects - not used in PS:T
// "Vertx" = Vertexes
// "Explo" = Explored Bitmap - not used in PS:T. no count, offset only
// "Anima" = Animations
// "Songs" = Songs - no count, offset only
// "RestS" = Rest Spawns - no count, offset only
// "MapNo" = Map Notes - not used in PS:T
// "ProTr" = Projectile Traps - BG2 only
// This macro sets up variables pointing to all the useful information about each subsection.
// To use those variables, use these variable names, replacing the XXXXX with the code above
// for the section you want to work with:
// SHORT DESCRIPTION OF STATIC VARIABLES:
// Q_Siz_XXXXX = Size of the description of XXXXX in any area file. Constant.
// Q_Num_XXXXX = Count of XXXXX records in current area file. Varies.
// Q_SoL_XXXXX = Whether the Q_Num_XXXXX field is a Short or Long. 2 = short, 4 = long. Needed for the WRITE.
// Q_OoN_XXXXX = Offset where value in Q_Num_XXXXX is stored in any area file. Constant.
// Q_Off_XXXXX = Offset where records of type XXXXX start in current area file. Varies.
// Q_OoO_XXXXX = Offset of the offset - where value in Q_Off_XXXXX is stored in any area file. Constant.
// LONG DESCRIPTION OF STATIC VARIABLES:
// Q_Siz_XXXXX = the size, in bytes, of one instance of section XXXXX in any area file.
// For example, Q_Siz_Items has the value 0x14, which is hexidecimal for 20 bytes, the
// size of one Item record. I got these values from referring to both Near Infinity and
// IESDP. These values are constant for any area file.
// Q_Num_XXXXX = the count of how many XXXXX records are in this area. For example, Q_Num_Doors
// is the number of Doors set up in this area. These values depend on the .ARE you're editing.
// Q_SoL_XXXXX = whether the Count field of a given section is a short or long. It varies. Unfortunately.
// 2 = short, 4 = long.
// Q_OoN_XXXXX = the offset where the previous value, Q_Num_XXXXX, is stored in the main section
// of any area file. (OoN = Offset Of Number). For example, if you do READ_SHORT "Q_OoN_Conta"
// "NumOfContainers", your NumOfContainers variable will get the same value as Q_Num_Conta. Why
// store the offsets if I already have the values stored in variables? So I know where to
// write back to when I need to at the end of my editing. These values are the same for any
// area file.
// Q_Off_XXXXX = the offset, from the beginning of the file, where records of the subsection in
// question start being stored in this particular area file. These values depend on the area
// you're editing.
// Q_OoO_XXXXX = the offset where the previous value, Q_Off_XXXXX, is stored in the main section
// of any area file. (OoO = Offset Of Offset). For example, if you do READ_LONG "Q_OoO_Conta"
// "FirstContainerDescriptionInTheFileStartsHere", that variable will get the same value as
// Q_OffConta. Why store the offsets of the offset? Because I may have to write to that offset,
// as adding to sections earlier in the file will require a change to the position/offset of
// subsections deeper into the file. These values are constant for any area file.
// If you want instructions on how to use the tool to have it remap an area file for you,
// see the other macro sections.
// ============================== STATIC VARIABLES ===========================
// Size of one instance of each type of record
SET "Q_Siz_Actor" = 0x110 // Size of Actor Section
SET "Q_Siz_Trigg" = 0xc4 // Size of Trigger Section
SET "Q_Siz_Spawn" = 0xc8 // Size of Spawn Points Section
SET "Q_Siz_Entra" = 0x68 // Size of Entrances Section
SET "Q_Siz_Conta" = 0xc0 // Size of Containers Section
SET "Q_Siz_Items" = 0x14 // Size of Items Section
SET "Q_Siz_Ambie" = 0xd4 // Size of Ambients Section
SET "Q_Siz_Varia" = 0x54 // Size of Variables Section - not used in PS:T
SET "Q_Siz_Doors" = 0xc8 // Size of Doors Section
SET "Q_Siz_Tiled" = 0x6c // Size of Tiled Objects Section 0 - not used in PS:T
SET "Q_Siz_Vertx" = 0x4 // Size of Vertexes Section - size of one set of X, Y coordinates
SET "Q_Siz_Explo" = 0x0 // Size of Explored Bitmap Section - not applicable
SET "Q_Siz_Anima" = 0x4c // Size of Animations Section
SET "Q_Siz_Songs" = 0x90 // Size of Songs Section
SET "Q_Siz_RestS" = 0xe4 // Size of Rest Spawn Section
SET "Q_Siz_MapNo" = 0x34 // Size of Map Notes Section - not used in PS:T
SET "Q_Siz_ProTr" = 0x1A // Size of Projectile Traps Section - only used in BG2?
// Sets the offsets where count of each type of record is stored in any area file
SET "Q_OoN_Actor" = 0x58 // Offset of Number Of Actors
SET "Q_OoN_Trigg" = 0x5a // Offset of Number Of Trigger
SET "Q_OoN_Spawn" = 0x64 // Offset of Number Of Spawn Points
SET "Q_OoN_Entra" = 0x6c // Offset of Number Of Entrances
SET "Q_OoN_Conta" = 0x74 // Offset of Number Of Containers
SET "Q_OoN_Items" = 0x76 // Offset of Number Of Items
SET "Q_OoN_Ambie" = 0x82 // Offset of Number Of Ambients
SET "Q_OoN_Varia" = 0x8c // Offset of Number Of Variables
SET "Q_OoN_Doors" = 0xa4 // Offset of Number Of Doors
SET "Q_OoN_Tiled" = 0xb4 // Offset of Number Of Tiled Objects
SET "Q_OoN_Vertx" = 0x80 // Offset of Number Of Vertexes
SET "Q_OoN_Explo" = 0x0 // Offset of Number Of Explored Bitmap - not applicable
SET "Q_OoN_Anima" = 0xac // Offset of Number Of Animations
SET "Q_OoN_Songs" = 0x0 // Offset of Number Of Songs - not applicable
SET "Q_OoN_RestS" = 0x0 // Offset of Number Of Rest Spawn - not applicable
PATCH_IF "Q_Game" = 1 THEN BEGIN SET "Q_OoN_MapNo" = 0xcc // Offset of Number of Map Notes in PS:T
END ELSE BEGIN SET "Q_OoN_MapNo" = 0xc8 // Offset of Number of Map Notes in all other IE games
END
PATCH_IF "Q_Game" = 2 THEN BEGIN SET "Q_OoN_ProTr" = 0xcc // Offset of Number of Projectile Traps in BG2
END ELSE BEGIN SET "Q_OoN_ProTr" = 0 // Not Applicable
END
// Using those offsets, load the actual count of each type
// of record from the area file currently loaded.
READ_SHORT "Q_OoN_Actor" "Q_Num_Actor" // Number of Actors
READ_SHORT "Q_OoN_Trigg" "Q_Num_Trigg" // Number of Triggers
READ_LONG "Q_OoN_Spawn" "Q_Num_Spawn" // Number of Spawn Points
READ_LONG "Q_OoN_Entra" "Q_Num_Entra" // Number of Entrances
READ_SHORT "Q_OoN_Conta" "Q_Num_Conta" // Number of Containers
READ_SHORT "Q_OoN_Items" "Q_Num_Items" // Number of Items
READ_SHORT "Q_OoN_Ambie" "Q_Num_Ambie" // Number of Ambients
READ_LONG "Q_OoN_Varia" "Q_Num_Varia" // Number of Variables
READ_LONG "Q_OoN_Doors" "Q_Num_Doors" // Number of Doors
READ_LONG "Q_OoN_Tiled" "Q_Num_Tiled" // Number of Tiled Objects
READ_SHORT "Q_OoN_Vertx" "Q_Num_Vertx" // Number of Vertexes
SET "Q_Num_Explo" = 1 // Only 1 Explored Bitmap section per area. This isn't really needed.
READ_LONG "Q_OoN_Anima" "Q_Num_Anima" // Number of Animations
SET "Q_Num_Songs" = 1 // Only 1 song section per area. This isn't really needed.
SET "Q_Num_RestS" = 1 // Only 1 rest section per area. This isn't really needed.
READ_LONG "Q_OoN_MapNo" "Q_Num_MapNo" // Number of Mapnotes
PATCH_IF "Q_Game" = 2 THEN BEGIN READ_LONG "Q_OoN_ProTr" "Q_Num_ProTr" // Number of Projectile Traps in BG2
END ELSE BEGIN SET "Q_Num_ProTr" = 0 // Not Applicable
END
// Whether the "Number of" field is a long or a short field. Long = 4, Short = 2
SET "Q_SoL_Actor" = 2
SET "Q_SoL_Trigg" = 2
SET "Q_SoL_Spawn" = 4
SET "Q_SoL_Entra" = 4
SET "Q_SoL_Conta" = 2
SET "Q_SoL_Items" = 2
SET "Q_SoL_Ambie" = 2
SET "Q_SoL_Varia" = 4
SET "Q_SoL_Doors" = 4
SET "Q_SoL_Tiled" = 4
SET "Q_SoL_Vertx" = 2
SET "Q_SoL_Explo" = 0 // Not applicable
SET "Q_SoL_Anima" = 4
SET "Q_SoL_Songs" = 0 // Not applicable
SET "Q_SoL_RestS" = 0 // Not applicable
SET "Q_SoL_MapNo" = 4
SET "Q_SoL_ProTr" = 4
// The offsets at which each subsection's offset in any .ARE file is stored
SET "Q_OoO_Actor" = 0x54 // Offset of Actors Offset
SET "Q_OoO_Trigg" = 0x5c // Offset of Trigger Offset
SET "Q_OoO_Spawn" = 0x60 // Offset of Spawn Points Offset
SET "Q_OoO_Entra" = 0x68 // Offset of Entrances Offset
SET "Q_OoO_Conta" = 0x70 // Offset of Containers Offset
SET "Q_OoO_Items" = 0x78 // Offset of Items Offset
SET "Q_OoO_Ambie" = 0x84 // Offset of Ambients Offset
SET "Q_OoO_Varia" = 0x88 // Offset of Variables Offset
SET "Q_OoO_Doors" = 0xa8 // Offset of Doors Offset
SET "Q_OoO_Tiled" = 0xb8 // Offset of Tiled Objects Offset
SET "Q_OoO_Vertx" = 0x7c // Offset of Vertexes Offset
SET "Q_OoO_Explo" = 0xa0 // Offset of Explored Bitmap Offset
SET "Q_OoO_Anima" = 0xb0 // Offset of Animations Offset
SET "Q_OoO_Songs" = 0xbc // Offset of Songs Offset
SET "Q_OoO_RestS" = 0xc0 // Offset of Rest Spawn Offset
PATCH_IF "Q_Game" = 1 THEN BEGIN SET "Q_OoO_MapNo" = 0xc8 // Offset of Map Notes Offset in PS:T
END ELSE BEGIN SET "Q_OoO_MapNo" = 0xc4 // Offset of Map Notes Offset in all other IE games
END
PATCH_IF "Q_Game" = 2 THEN BEGIN SET "Q_OoO_ProTr" = 0xcc // Offset of Projectile Traps section in BG2
END ELSE BEGIN SET "Q_OoO_ProTr" = 0 // Not Applicable
END
// Using those offsets, load the actual offsets as they exist in this specific area file
READ_LONG "Q_OoO_Actor" "Q_Off_Actor" // Actors Offset
READ_LONG "Q_OoO_Trigg" "Q_Off_Trigg" // Trigger Offset
READ_LONG "Q_OoO_Spawn" "Q_Off_Spawn" // Spawn Points Offset
READ_LONG "Q_OoO_Entra" "Q_Off_Entra" // Entrances Offset
READ_LONG "Q_OoO_Conta" "Q_Off_Conta" // Containers Offset
READ_LONG "Q_OoO_Items" "Q_Off_Items" // Items Offset
READ_LONG "Q_OoO_Ambie" "Q_Off_Ambie" // Ambients Offset
READ_LONG "Q_OoO_Varia" "Q_Off_Varia" // Variables Offset
READ_LONG "Q_OoO_Doors" "Q_Off_Doors" // Doors Offset
READ_LONG "Q_OoO_Tiled" "Q_Off_Tiled" // Tiled Objects Offset
READ_LONG "Q_OoO_Vertx" "Q_Off_Vertx" // Vertexes Offset
READ_LONG "Q_OoO_Explo" "Q_Off_Explo" // Explored Bitmap Offset
READ_LONG "Q_OoO_Anima" "Q_Off_Anima" // Animations Offset
READ_LONG "Q_OoO_Songs" "Q_Off_Songs" // Songs Offset
READ_LONG "Q_OoO_RestS" "Q_Off_RestS" // Rest Spawn Offset
READ_LONG "Q_OoO_MapNo" "Q_Off_MapNo" // Map Notes Offset
PATCH_IF "Q_Game" = 2 THEN BEGIN READ_LONG "Q_OoO_ProTr" "Q_Off_ProTr" // Projectile Trap Offset in BG2
END ELSE BEGIN SET "Q_Off_ProTr" = 0 // Not Applicable. Value of 0 will keep it from ever updating in inner S2 loop of Process macro.
END
END
// ====================== BEGIN Q_AREAdd_InitVars Macro Definition ========================
DEFINE_PATCH_MACRO ~Q_AREAdd_InitVars~
BEGIN
// Use this macro in conjunction with macro ~Q_AREAdd_Process~ if you are adding entirely
// new records to any of the subsections. This macro will reset all of the offsets, indexes
// and counts in your .ARE record to match your additions with very little work on your
// part, as well as supply you with variables storing the offsets where you should start
// writing your new records.
// Best of all, it does so in a dynamic manner which should not interfere with any other
// mods that come before or after yours, always assuming they take similar care to be
// compatible with other mods, of course.
// Do NOT use this macro if you need to modify the vertexes in an existing trigger, door
// or container, or adding items to an existing container. You CAN use it to add room for
// both new triggers/doors/containers and the new vertexes that go along with them.
// Another two macros, named Q_AREVertex_InitVars and Q_AREVertex_Process will be provided
// in the case that you need to modify the vertexes in an existing door/trigger/container.
// Another two macros, Q_AREItem_InitVars and Q_AREItem_Process will be provided if you need
// to add items to an existing container.
// INSTRUCTIONS FOR USE:
// All you need to do is include these macro definitions somewhere in your .tp2 (near the top,
// preferably.) Then when ready to use them, use your COPY or COPY_EXISTING statement to grab the
// .ARE file you're working with, run -this- macro, like this:
// LAUNCH_PATCH_MACRO ~Q_AREAdd_InitVars~
// ... then set your Q_New_XXXXX variables... what do you set your Q_NewXXXXX variable to?
// Just how many records of each type you want to add. Say you need to add 3 actors,
// 2 containers (each containing 5 vertexes and 2 items), and two triggers (each containing
// 10 vertexes). Here's all you need to do:
// SET Q_NewActor = 3
// SET Q_NewConta = 2
// SET Q_NewItems = 4
// SET Q_NewVertx = 30
// ... and then run the Q_AREAdd_Process macro, like this:
// LAUNCH_PATCH_MACRO ~Q_AREAdd_Process~
// That macro will insert bytes into each subsection in the file to accomodate the new records
// you want to add, and all offsets and counts will be updated for you.
// So, putting it all together, and assuming you included this file somewhere in your tp2,
// the whole process for prepping your file for the addition of 3 actors,
// 2 containers (each containing 5 vertexes and 2 items), and two triggers (each containing
// 10 vertexes), is this:
// LAUNCH_PATCH_MACRO ~Q_AREAdd_InitVars~
// SET Q_NewActor = 3
// SET Q_NewConta = 2
// SET Q_NewItems = 4
// SET Q_NewVertx = 30
// LAUNCH_PATCH_MACRO ~Q_AREAdd_Process~
// That's it. The right amount of bytes needed to write in your actors, containers,
// items and vertexes is now available in the file, with all the various offsets
// and counts updated to match.
// But how do you know where to actually write your records? You can find the offset
// at which the new space was inserted at the variables Q_NewOffset_XXXXX, which the
// tool has filled in for you.
// It is recommended that you immediately start writing to the fields you want to write
// to. In this example, you would start writing your new actors at Q_NewOffset_Actor,
// your new containers at Q_NewOffset_Conta, your new items at Q_NewOffset_Items
// and your new vertexes at Q_NewOffset_Vertx.
// If you plan to use this or any of the other macros included with the WAMT tool more,
// than once in your tp2, you should always rerun the _InitVars macro associated with
// the _Process macro you intend to use to clear any old values. That's why I recommend
// immediately doing your writes, so that you don't forget and rerun this tool somewhere
// else, does wiping out all your NewOffset values telling you where you can write your
// new subsections.
// This macro will initialize all of the Q_New_XXXXX variables and the output variables
// (i.e. Q_NewOffset_XXXXX).
SET "Q_New_Actor" = 0 // Number of New Actors
SET "Q_New_Trigg" = 0 // Number of New Triggers
SET "Q_New_Spawn" = 0 // Number of New Spawn Points
SET "Q_New_Entra" = 0 // Number of New Entrances
SET "Q_New_Conta" = 0 // Number of New Containers
SET "Q_New_Items" = 0 // Number of New Items
SET "Q_New_Ambie" = 0 // Number of New Ambients
SET "Q_New_Varia" = 0 // Number of New Variables
SET "Q_New_Doors" = 0 // Number of New Doors
SET "Q_New_Tiled" = 0 // Number of New Tiled Objects
SET "Q_New_Vertx" = 0 // Number of New Vertexes
SET "Q_New_Anima" = 0 // Number of New Animations
SET "Q_New_MapNo" = 0 // Number of Map Notes
SET "Q_New_ProTr" = 0 // Number of Projectile Traps
// Initializing the variables that return the offset where the new areas have been created
SET "Q_NewOffset_Actor" = 0 // Begin writing your new actors here.
SET "Q_NewOffset_Trigg" = 0 // Begin writing your new triggers here.
SET "Q_NewOffset_Spawn" = 0 // Etc.
SET "Q_NewOffset_Entra" = 0
SET "Q_NewOffset_Conta" = 0
SET "Q_NewOffset_Items" = 0
SET "Q_NewOffset_Ambie" = 0
SET "Q_NewOffset_Varia" = 0
SET "Q_NewOffset_Doors" = 0
SET "Q_NewOffset_Tiled" = 0
SET "Q_NewOffset_Vertx" = 0
SET "Q_NewOffset_Anima" = 0
SET "Q_NewOffset_MapNo" = 0
SET "Q_NewOffset_ProTr" = 0
SET "Q_NewOffset_Explo" = 0 // These 3 cannot have new records created, but need variables to compile
SET "Q_NewOffset_Songs" = 0
SET "Q_NewOffset_RestS" = 0
SET "Q_ManualInsert" = 0 // If you want to handle the INSERT_BYTES (or DELETE_BYTES, potentially)
// by yourself, set this flag to 1
END
// ====================== END Q_AREAdd_InitVars Macro Definition ========================
// ===================== BEGIN Q_AREAdd_Process Macro Definition ========================
DEFINE_PATCH_MACRO ~Q_AREAdd_Process~
BEGIN
// DO NOT use this macro without first running Q_AREAdd_InitVars.
// Documentation for the use of this macro is contained within that macro definition.
PATCH_FOR_EACH "S1" IN
~Actor~ ~Trigg~ ~Spawn~ ~Entra~ ~Conta~ ~Items~ ~Ambie~ ~Varia~ ~Doors~
~Tiled~ ~Vertx~ ~Anima~ ~MapNo~ ~ProTr~
BEGIN
SET "Q_NewSect" = $Q_New("%S1%") // How many new sections user has asked for
PATCH_IF !("Q_NewSect" = 0) THEN
BEGIN
// WRITE_ASCII 0x33c ~%S1%~ #32 // DEBUG
SET "Q_OoNSect" = $Q_OoN("%S1%") // Offset where count of each section is stored
SET "Q_NumSect" = $Q_Num("%S1%") // Original count for that section
SET "Q_SoLSect" = $Q_SoL("%S1%") // Whether original count is stored as long or short
SET "Q_OoOSect1" = $Q_OoO("%S1%") // Offset of offset for the section
SET "Q_Offset1" = $Q_Off("%S1%") // Offset of the section being added to
SET "Q_SizSect" = $Q_Siz("%S1%") // The size of one new section
PATCH_FOR_EACH "S2" IN
~Actor~ ~Trigg~ ~Spawn~ ~Entra~ ~Conta~ ~Items~ ~Ambie~ ~Varia~ ~Doors~
~Tiled~ ~Vertx~ ~Explo~ ~Anima~ ~Songs~ ~RestS~ ~MapNo~ ~ProTr~
BEGIN
// WRITE_ASCII 0x33c ~%S1% %S2%~ #32 // DEBUG
SET "Q_Offset2" = $Q_Off("%S2%") // Offset of each other section
SET "Q_OoOSect2" = $Q_OoO("%S2%") // Offset of that offset
SET "Q_OldInsert" = $Q_NewOffset("%S2%") // Previous insert offsets need to be updated too
PATCH_IF ("Q_Offset2" >= "Q_Offset1") AND NOT ("%S1%" STRING_EQUAL "%S2%") THEN
BEGIN
WRITE_LONG "Q_OoOSect2" ("Q_Offset2" + ("Q_NewSect" * "Q_SizSect"))
END
PATCH_IF ("Q_OldInsert" >= "Q_Offset1") AND NOT ("%S1%" STRING_EQUAL "%S2%") THEN
BEGIN
SET $Q_NewOffset("%S2%") = $Q_NewOffset("%S2%") + ("Q_NewSect" * "Q_SizSect")
END
END
SET $Q_NewOffset("%S1%") = "Q_Offset1" + ("Q_NumSect" * "Q_SizSect")
SET "Q_InsertOffset" = $Q_NewOffset("%S1%")
PATCH_IF "Q_ManualInsert" = 0 THEN
BEGIN
INSERT_BYTES "Q_InsertOffset" ("Q_NewSect" * "Q_SizSect")
END
PATCH_IF "Q_SoLSect" = 2 THEN BEGIN WRITE_SHORT "Q_OoNSect" ("Q_NumSect" + "Q_NewSect") END
ELSE BEGIN WRITE_LONG "Q_OoNSect" ("Q_NumSect" + "Q_NewSect") END
LAUNCH_PATCH_MACRO ~Q_ARE_InitVars~ // Reset all our variables to their new values
END
END
END
// ====================== END Q_AREAdd_Process Macro Definition ========================
// ==================== BEGIN Q_AREVertex_InitVars Macro Definition ====================
DEFINE_PATCH_MACRO ~Q_AREVertex_InitVars~
BEGIN
// This macro initializes some constant variables for use by the Q_AREVertex_Process macro,
// and also the variables that the user will set to make the macro work.
// First, the variables the tool will use. This basically sets the variables defining
// the "First Vertex Index" and count fields within doors, trigger and containers in much
// the same way the Q_AREInitVars does it for the offsets in the main section of the .ARE
// file. These offsets are from the beginning of a door/trigger/container definition, btw,
// not the beginning of the .ARE file. You can ignore this part. Instructions continue below.
// The key to the fields in this file, by the way, are:
// "Trigg" - Vertex list for triggers
// "Conta" - Vertex list for containers
// "DoorO" - Vertex list for door in Open position
// "DoorC" - Vertex list for door in Closed position
// "DoorOI" - Vertex list for door in Open, Impeded position
// "DoorCI" - Vertex list for door in Closed, Impeded position
// Note: The IESDP and Near Infinity disagree on these offsets. IESDP has definite errors
// in theirs though, so I'm going with the values in NI. If someone finds out NI is wrong
// too, please let me know.
SET "QV_OffFVI_Trigg" = 0x2c
SET "QV_OffFVI_Conta" = 0x50
SET "QV_OffFVI_DoorO" = 0x2c
SET "QV_OffFVI_DoorC" = 0x34
SET "QV_OffFVI_DoorOI" = 0x50
SET "QV_OffFVI_DoorCI" = 0x48
SET "QV_OffNumV_Trigg" = 0x2a
SET "QV_OffNumV_Conta" = 0x54
SET "QV_OffNumV_DoorO" = 0x30
SET "QV_OffNumV_DoorC" = 0x32
SET "QV_OffNumV_DoorOI" = 0x4e
SET "QV_OffNumV_DoorCI" = 0x4c
// INSTRUCTIONS FOR USE:
// To remap the vertexes of an existing trigger, door or container, you must supply 3
// different values - the type of record you're changing, the offset to the definition of that
// record, and the new number of vertexes attached to that record.
// The three variables the user must fill in are:
// QV_Offset - The offset of the Item, Door or Container definition whose vertexes are being remapped
// QV_Count - The new number of vertexes attached to this item, door or container
// QV_Type - This must be an integer value from 1 to 6:
// 1 - Trigger
// 2 - Container
// 3 - Door, Open
// 4 - Door, Closed
// 5 - Door, Open Impeded
// 6 - Door, Closed Impeded
// Initializing those variables now:
SET "QV_Type" = 0
SET "QV_Offset" = 0
SET "QV_VCount" = 0
// COMPATIBILITY NOTE: I strongly suggest NOT hardcoding the value of QV_Offset. Doing so will
// likely make your mod incompatible with other mods. If you want to modify the vertexes of the
// third trigger in your area, set the value of QV_Offset dynamically like this:
// "QV_Offset" = "Q_Off_Trigg" + ("Q_Siz_Trigg" * 2)
// You should have run the macro Q_ARE_InitVars prior to even thinking about using these macros
// anyway, so those two Q_ variables will already be filled in for you at this point.
// Also be aware that, when I say "third trigger", I don't mean the third trigger listed in NI,
// which lists them alphabetically by assigned name. I mean the third one sequentially in the
// file. Look at the starting offset of each trigger to get the actual order they are sequenced
// in in the file.
// Here's an example of how to use this macro. Say you want to change the "Open" vertex of
// the fifth door in your file. It originally had 6 vertexes, and your new map has 9 vertexes.
// INCLUDE Q_AREMacros.tph
// ...
// COPY_EXISTING ~AR0400.ARE~ ~override~
// LAUNCH_PATCH_MACRO Q_ARE_InitVars
// LAUNCH_PATCH_MACRO Q_AREVertex_InitVars // this macro
// SET "QV_Type" = ~DoorO~
// SET "QV_Offset" = "Q_Off_Doors + (Q_Siz_Doors * 4)
// SET "QV_VCount = 9
// LAUNCH_PATCH_MACRO Q_AREVertex_Process
// That code will first delete the bytes where the vertexes for that door record are mapped, and then
// reinsert bytes to the size you need. Thus, expect 0's in all the vertexes, you'll need to remap
// them all (which, when it comes to vertex mapping, generally needs to be done anyway). It will
// also update all the "First Vertex Index" fields in -all- items, doors and containers that need it
// to match their new positions within the vertex pool.
// That's it. Oh, and you'd get the offset at which you can start writing your new vertexes
// in the variable QV_NewVertexOffset. Start writing your new vertexes there. Don't worry
// about pointing your Door file's First Vertex Index to them, that's already done for you.
SET "QV_NewVertexOffset" = 0
END
// ==================== END Q_AREVertex_InitVars Macro Definition ====================
// ==================== BEGIN Q_AREVertex_Process Macro Definition ====================
DEFINE_PATCH_MACRO ~Q_AREVertex_Process~
BEGIN
// DO NOT use this macro without first running Q_AREVertex_InitVars.
// Documentation for the use of this macro is contained within that macro definition.
PATCH_IF "QV_Type" > 0 AND "QV_Type" < 7 THEN
BEGIN
PATCH_IF "QV_Type" = 1 THEN
BEGIN
SET "QV_OffFVI" = "QV_OffFVI_Trigg"
SET "QV_OffNumV" = "QV_OffNumV_Trigg"
END
PATCH_IF "QV_Type" = 2 THEN
BEGIN
SET "QV_OffFVI" = "QV_OffFVI_Conta"
SET "QV_OffNumV" = "QV_OffNumV_Conta"
END
PATCH_IF "QV_Type" = 3 THEN
BEGIN
SET "QV_OffFVI" = "QV_OffFVI_DoorO"
SET "QV_OffNumV" = "QV_OffNumV_DoorO"
END
PATCH_IF "QV_Type" = 4 THEN
BEGIN
SET "QV_OffFVI" = "QV_OffFVI_DoorC"
SET "QV_OffNumV" = "QV_OffNumV_DoorC"
END
PATCH_IF "QV_Type" = 5 THEN
BEGIN
SET "QV_OffFVI" = "QV_OffFVI_DoorOI"
SET "QV_OffNumV" = "QV_OffNumV_DoorOI"
END
PATCH_IF "QV_Type" = 6 THEN
BEGIN
SET "QV_OffFVI" = "QV_OffFVI_DoorCI"
SET "QV_OffNumV" = "QV_OffNumV_DoorCI"
END
READ_LONG ("QV_Offset" + "QV_OffFVI") "QV_OldFVI"
READ_SHORT ("QV_Offset" + "QV_OffNumV") "QV_OldCount"
SET "QV_Delta" = "QV_VCount" - "QV_OldCount"
FOR ("i2" = 1; "i2" <= "Q_Num_Trigg"; "i2" += 1)
BEGIN
READ_LONG ("Q_Off_Trigg" + ("Q_Siz_Trigg" * ("i2" - 1)) + "QV_OffFVI_Trigg") "QV_EachFVI"
PATCH_IF "QV_EachFVI" > "QV_OldFVI" THEN
BEGIN
WRITE_LONG ("Q_Off_Trigg" + ("Q_Siz_Trigg" * ("i2" - 1)) + "QV_OffFVI_Trigg")
"QV_EachFVI" + "QV_Delta"
END
END
FOR ("i2" = 1; "i2" <= "Q_Num_Conta"; "i2" += 1)
BEGIN
READ_LONG ("Q_Off_Conta" + ("Q_Siz_Conta" * ("i2" - 1)) + "QV_OffFVI_Conta") "QV_EachFVI"
PATCH_IF "QV_EachFVI" > "QV_OldFVI" THEN
BEGIN
WRITE_LONG ("Q_Off_Conta" + ("Q_Siz_Conta" * ("i2" - 1)) + "QV_OffFVI_Conta")
"QV_EachFVI" + "QV_Delta"
END
END
FOR ("i2" = 1; "i2" <= "Q_Num_Doors"; "i2" += 1)
BEGIN
READ_LONG ("Q_Off_Doors" + ("Q_Siz_Doors" * ("i2" - 1)) + "QV_OffFVI_DoorO") "QV_EachFVI"
PATCH_IF "Q_EachFVI" > "QV_OldFVI" THEN
BEGIN
WRITE_LONG ("Q_Off_Doors" + ("Q_Siz_Doors" * ("i2" - 1)) + "QV_OffFVI_DoorO")
"QV_EachFVI" + "QV_Delta"
END
READ_LONG ("Q_Off_Doors" + ("Q_Siz_Doors" * ("i2" - 1)) + "QV_OffFVI_DoorC") "QV_EachFVI"
PATCH_IF "Q_EachFVI" > "QV_OldFVI" THEN
BEGIN
WRITE_LONG ("Q_Off_Doors" + ("Q_Siz_Doors" * ("i2" - 1)) + "QV_OffFVI_DoorC")
"QV_EachFVI" + "QV_Delta"
END
READ_LONG ("Q_Off_Doors" + ("Q_Siz_Doors" * ("i2" - 1)) + "QV_OffFVI_DoorOI") "QV_EachFVI"
PATCH_IF "Q_EachFVI" > "QV_OldFVI" THEN
BEGIN
WRITE_LONG ("Q_Off_Doors" + ("Q_Siz_Doors" * ("i2" - 1)) + "QV_OffFVI_DoorOI")
"QV_EachFVI" + "QV_Delta"
END
READ_LONG ("Q_Off_Doors" + ("Q_Siz_Doors" * ("i2" - 1)) + "QV_OffFVI_DoorOC") "QV_EachFVI"
PATCH_IF "Q_EachFVI" > "QV_OldFVI" THEN
BEGIN
WRITE_LONG ("Q_Off_Doors" + ("Q_Siz_Doors" * ("i2" - 1)) + "QV_OffFVI_DoorOC")
"QV_EachFVI" + "QV_Delta"
END
END
WRITE_SHORT ("QV_Offset" + "QV_OffNumV") "QV_VCount"
WRITE_SHORT "Q_OoN_Vertx" ("Q_Num_Vertx" + "QV_Delta")
DELETE_BYTES ("Q_Off_Vertx" + ("QV_OldFVI" * "Q_Siz_Vertx"))
("QV_OldCount" * "Q_Siz_Vertx")
INSERT_BYTES ("Q_Off_Vertx" + ("QV_OldFVI" * "Q_Siz_Vertx"))
("QV_VCount" * "Q_Siz_Vertx")
SET "QV_NewVertexOffset" = ("Q_Off_Vertx" + ("QV_OldFVI" * "Q_Siz_Vertx"))
LAUNCH_PATCH_MACRO ~Q_AREAdd_InitVars~
SET "Q_ManualInsert" = 1
SET "Q_New_Vertx" = "QV_Delta"
LAUNCH_PATCH_MACRO ~Q_AREAdd_Process~
END
END
Attached Files
Edited by Qwinn, 11 June 2009 - 11:44 AM.







