lsass.exe Posted July 18, 2009 Share Posted July 18, 2009 Hi, the topic title says it all. I'd like to trigger some dialogs on a specific position in an area. For example in the middle of the gnoll fortress. Or behind the inner courtyard in candlekeep. Or while walking down a certain tunnel in the cloakwood mines and so on. I tinkered a little bit with Range() and See(), but didn't get it right. E.g. See("InfoKeep") in Candlekeep triggers correctly if I click on the infobox on the inner wall. But only if I click it... Which is crap and a totally unqualified method for triggering stuff. (and even if it worked I'd be faced with the problem to have stuff in range to trigger off.) Any tips? Link to comment
cmorgan Posted July 19, 2009 Share Posted July 19, 2009 Take a look at bg1npc's .tp2, for adding an area trigger that a talk can fire from within (and only from within). We had a "Coran comments on the big dragon skeleton" thing that was just not working reliably at all, and he came up with this solution: /* Macro adding proximity trigger into FW /ARD013.ARE (for Coran dragon talk) by pro-5 */ DEFINE_PATCH_MACRO ~DRAGON_TRIGGER~ BEGIN READ_LONG 0x54 "actor_off" READ_LONG 0x5c "info_off" READ_SHORT 0x5a "info_num" READ_LONG 0x60 "spawn_off" READ_LONG 0x68 "ent_off" READ_LONG 0x70 "cont_off" READ_LONG 0x78 "item_off" READ_LONG 0x7c "vert_off" READ_SHORT 0x80 "vert_num" READ_LONG 0x84 "amb_off" READ_LONG 0x88 "var_off" READ_LONG 0xa0 "bmp_off" READ_LONG 0xa8 "door_off" READ_LONG 0xb0 "anim_off" READ_LONG 0xb8 "tiled_off" READ_LONG 0xbc "song_off" READ_LONG 0xc0 "rest_off" READ_LONG 0xc4 "note_off" SET "Left" = 1 SET "Top" = 1 SET "Right" = 2800 SET "Bottom" = 1600 WRITE_SHORT 0x5a ("%info_num%" + 1) INSERT_BYTES "%info_off%" 0xC4 // insert new blank info point WRITE_ASCII "%info_off%" ~P5#DragonTrigger~ // name WRITE_SHORT ("%info_off%" + 0x22) "%Left%" WRITE_SHORT ("%info_off%" + 0x24) "%Top%" WRITE_SHORT ("%info_off%" + 0x26) "%Right%" WRITE_SHORT ("%info_off%" + 0x28) "%Bottom%" WRITE_SHORT ("%info_off%" + 0x2A) 4 // # vertices WRITE_LONG ("%info_off%" + 0x2C) "%vert_num%" // first vertex index WRITE_BYTE ("%info_off%" + 0x60) 2 // Flags: Trap Resets=true // WRITE_BYTE ("%info_off%" + 0x60) 10 // Flags: Trap Resets=true, Trap Detectable=true - for testing // WRITE_SHORT ("%info_off%" + 0x68) 1 // Trap det.difficulty - for testing WRITE_SHORT ("%info_off%" + 0x6C) 1 // Trap flag - needed WRITE_ASCII ("%info_off%" + 0x7C) ~P5ARD013~ #8 // Script name PATCH_IF NOT ("%actor_off%" < "%info_off%") BEGIN WRITE_LONG 0x54 ("%actor_off%" + 0xC4) END PATCH_IF NOT ("%spawn_off%" < "%info_off%") BEGIN WRITE_LONG 0x60 ("spawn_off" + 0xC4) END PATCH_IF NOT ("%ent_off%" < "%info_off%") BEGIN WRITE_LONG 0x68 ("ent_off" + 0xC4) END PATCH_IF NOT ("%cont_off%" < "%info_off%") BEGIN WRITE_LONG 0x70 ("cont_off" + 0xC4) END PATCH_IF NOT ("%item_off%" < "%info_off%") BEGIN WRITE_LONG 0x78 ("item_off" + 0xC4) END PATCH_IF NOT ("%vert_off%" < "%info_off%") BEGIN WRITE_LONG 0x7c ("vert_off" + 0xC4) END PATCH_IF NOT ("%amb_off%" < "%info_off%") BEGIN WRITE_LONG 0x84 ("amb_off" + 0xC4) END PATCH_IF NOT ("%var_off%" < "%info_off%") BEGIN WRITE_LONG 0x88 ("var_off" + 0xC4) END PATCH_IF NOT ("%bmp_off%" < "%info_off%") BEGIN WRITE_LONG 0xa0 ("bmp_off" + 0xC4) END PATCH_IF NOT ("%door_off%" < "%info_off%") BEGIN WRITE_LONG 0xa8 ("door_off" + 0xC4) END PATCH_IF NOT ("%anim_off%" < "%info_off%") BEGIN WRITE_LONG 0xb0 ("anim_off" + 0xC4) END PATCH_IF NOT ("%tiled_off%" < "%info_off%") BEGIN WRITE_LONG 0xb8 ("tiled_off" + 0xC4) END PATCH_IF NOT ("%song_off%" < "%info_off%") BEGIN WRITE_LONG 0xbc ("song_off" + 0xC4) END PATCH_IF NOT ("%rest_off%" < "%info_off%") BEGIN WRITE_LONG 0xc0 ("rest_off" + 0xC4) END PATCH_IF NOT ("%note_off%" < "%info_off%") BEGIN WRITE_LONG 0xc4 ("note_off" + 0xC4) END // Add 4 new vertices READ_LONG 0x54 "actor_off" READ_LONG 0x5c "info_off" READ_SHORT 0x5a "info_num" READ_LONG 0x60 "spawn_off" READ_LONG 0x68 "ent_off" READ_LONG 0x70 "cont_off" READ_LONG 0x78 "item_off" READ_LONG 0x7c "vert_off" READ_SHORT 0x80 "vert_num" READ_LONG 0x84 "amb_off" READ_LONG 0x88 "var_off" READ_LONG 0xa0 "bmp_off" READ_LONG 0xa8 "door_off" READ_LONG 0xb0 "anim_off" READ_LONG 0xb8 "tiled_off" READ_LONG 0xbc "song_off" READ_LONG 0xc0 "rest_off" READ_LONG 0xc4 "note_off" WRITE_SHORT 0x80 ("%vert_num%" + 4) INSERT_BYTES ("%vert_off%" + (0x04 * "%vert_num%")) 0x10 WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%") 948 // Vertex1.X WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" + 2) 1588 // Vertex1.Y WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" + 4) 651 // Vertex2.X WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" + 6) 1125 // Vertex2.Y WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" + 8) 2366 // Vertex3.X WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" +10) 351 // Vertex3.Y WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" +12) 2743 // Vertex4.X WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" +14) 618 // Vertex4.Y PATCH_IF NOT ("%actor_off%" < "%vert_off%") BEGIN WRITE_LONG 0x54 ("%actor_off%" + 0x10) END PATCH_IF NOT ("%info_off%" < "%vert_off%") BEGIN WRITE_LONG 0x5c ("info_off" + 0x10) END PATCH_IF NOT ("%spawn_off%" < "%vert_off%") BEGIN WRITE_LONG 0x60 ("spawn_off" + 0x10) END PATCH_IF NOT ("%ent_off%" < "%vert_off%") BEGIN WRITE_LONG 0x68 ("ent_off" + 0x10) END PATCH_IF NOT ("%cont_off%" < "%vert_off%") BEGIN WRITE_LONG 0x70 ("cont_off" + 0x10) END PATCH_IF NOT ("%item_off%" < "%vert_off%") BEGIN WRITE_LONG 0x78 ("item_off" + 0x10) END PATCH_IF NOT ("%amb_off%" < "%vert_off%") BEGIN WRITE_LONG 0x84 ("amb_off" + 0x10) END PATCH_IF NOT ("%var_off%" < "%vert_off%") BEGIN WRITE_LONG 0x88 ("var_off" + 0x10) END PATCH_IF NOT ("%bmp_off%" < "%vert_off%") BEGIN WRITE_LONG 0xa0 ("bmp_off" + 0x10) END PATCH_IF NOT ("%door_off%" < "%vert_off%") BEGIN WRITE_LONG 0xa8 ("door_off" + 0x10) END PATCH_IF NOT ("%anim_off%" < "%vert_off%") BEGIN WRITE_LONG 0xb0 ("anim_off" + 0x10) END PATCH_IF NOT ("%tiled_off%" < "%vert_off%") BEGIN WRITE_LONG 0xb8 ("tiled_off" + 0x10) END PATCH_IF NOT ("%song_off%" < "%vert_off%") BEGIN WRITE_LONG 0xbc ("song_off" + 0x10) END PATCH_IF NOT ("%rest_off%" < "%vert_off%") BEGIN WRITE_LONG 0xc0 ("rest_off" + 0x10) END PATCH_IF NOT ("%note_off%" < "%vert_off%") BEGIN WRITE_LONG 0xc4 ("note_off" + 0x10) END END and then the trap script is: IF %BGT_VAR% Global("P5#DragonTrigger","%DurlagsTower_D3%",0) Name("coran",LastTrigger) InParty("coran") Entered([PC]) THEN RESPONSE #100 Wait(5) SetGlobal("P5#DragonTrigger","%DurlagsTower_D3%",1) END which sets the global, and then Coran's .bcs sets the talk: /* Coran, Sighting The Dragon Skeleton TOTSC, set from Dragon Trigger (trap) */ IF %BGT_VAR% AreaCheck("%DurlagsTower_D3%") Global("P5#DragonTrigger","%DurlagsTower_D3%",1) Global("P#CSTDS","GLOBAL",0) InParty(Myself) !StateCheck(Myself,CD_STATE_NOTVALID) InMyArea(Player1) !StateCheck(Player1,CD_STATE_NOTVALID) CombatCounter(0) !See([ENEMY]) THEN RESPONSE #100 SetGlobal("P#CSTDS","GLOBAL",1) END /* Initiate: Coran, Sighting The Dragon Skeleton TOTSC, set from Dragon Trigger (trap) */ IF %BGT_VAR% Global("P#CSTDS","GLOBAL",1) InParty(Myself) !StateCheck(Myself,CD_STATE_NOTVALID) InMyArea(Player1) !StateCheck(Player1,CD_STATE_NOTVALID) CombatCounter(0) !See([ENEMY]) THEN RESPONSE #100 Dialog(Myself) END Very slick, and very reliable. Link to comment
plainab Posted July 19, 2009 Share Posted July 19, 2009 The region trigger which you referred to is an 'info' trigger. Info triggers are those that when clicked display text on screen. Travel triggers are those that allow the party to travel from one area to another without accessing the world map. Floor triggers are used primarily as traps, they either cause something to happen in the game like advancing the chapter, starting dialog or they are an actual trap. What you want is a floor trigger whose 'trap' script initiates the dialog sequence. You can use the code that cmorgan posted and modify it to add a 'floor' trigger. Or you can use some 'user friendly' code that GeN1e and I have worked on that will utilize some macros and functions allowing you to just enter the data that you want (the functions & macros do all the work, you just provide the data). GeN1e has the more current versions, but I do have an older working set that you could use. I will provide it, along with a working example. Should you choose to use the code I provide, I'll see if GeN1e has anything newer on hand. NOTE: There is an ADD_AREA_REGION_TRIGGER that shipped with weidu 211, but I recommend not using it as when I first coded it I made the mistake of adding the new trigger to the beginning of the list rather than the end (could cause problems with other mods) No matter what style of weidu code you use, you'll probably want to first use DLTCEP to enter the new trigger region(s) and test things out in game. Why? Getting the vertex points correct can be a little tricky if you've not planned out the exact coordinates of the outline before hand. DLTCEP will let you play with the vertex points to get your region trigger outline the exact way that you want it to appear. If you've got cheats/debug enabled, I think you can use ctrl-x to get the coordinates within game. You can also use Infinity Explorer's general map view for the given area to mouse over and get the coordinate points. Here is my 'older' but working code: The following should be put into an external .tph .tpp or .tpa file // ======================= BEGIN Q_AREInitVars 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 // 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 // ======================= END OF Q_ARE_InitVars Macro Definition ========================= // ====================== BEGIN Q_AREAdd_InitVars Macro Definition ======================== DEFINE_PATCH_MACRO ~Q_AREAdd_InitVars~ BEGIN // 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 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 SET "QV_Type" = 0 SET "QV_Offset" = 0 SET "QV_VCount" = 0 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 DEFINE_ACTION_FUNCTION ~ab_Add_Area_Floor_Trigger~ BEGIN COPY_EXISTING ~%ab_file%~ ~override~ LAUNCH_PATCH_MACRO ~Q_ARE_InitVars~ //launch variable initiation macro LAUNCH_PATCH_MACRO ~Q_AREAdd_InitVars~ //launch variable initiation macro for adding new sections SET "Q_New_Trigg" = %ab_new_triggers% //set number of new region triggers to add SET "Q_New_Vertx" = %ab_new_vertex_points% //set number of new vertex/coordinate pairs to add LAUNCH_PATCH_MACRO ~Q_AREAdd_Process~ //launch macro that adds new space for above listed entries SET vert_entry = %Q_Num_Vertx% - %Q_New_Vertx% FOR(index=0;index<%ab_new_triggers%;index+=1) BEGIN SET new_loc = %Q_NewOffset_Trigg% + (%Q_Siz_Trigg% * %index%) WRITE_SHORT (%new_loc% + 0x20) 0 //always 0 for floor triggers //integer writes WRITE_SHORT (%new_loc% + 0x22) $RT_BBOX_LOW_X("%index%") WRITE_SHORT (%new_loc% + 0x24) $RT_BBOX_LOW_Y("%index%") WRITE_SHORT (%new_loc% + 0x26) $RT_BBOX_HIGH_X("%index%") WRITE_SHORT (%new_loc% + 0x28) $RT_BBOX_HIGH_Y("%index%") SET RT_VERTEX_PAIRS = $RT_VERTEX_PAIRS("%index%") WRITE_SHORT (%new_loc% + 0x2a) $RT_VERTEX_PAIRS("%index%") WRITE_SHORT (%new_loc% + 0x68) $RT_TRAP_DET_DIFF("%index%") WRITE_SHORT (%new_loc% + 0x6a) $RT_TRAP_REM_DIFF("%index%") WRITE_SHORT (%new_loc% + 0x6c) $RT_TRAP_IS_SET("%index%") WRITE_SHORT (%new_loc% + 0x63) $RT_TRAP_DETECTED("%index%") WRITE_SHORT (%new_loc% + 0x70) $RT_LAUNCH_POINT_X("%index%") WRITE_SHORT (%new_loc% + 0x72) $RT_LAUNCH_POINT_Y("%index%") WRITE_SHORT (%new_loc% + 0x84) $RT_ALT_USE_POINT_X("%index%") WRITE_SHORT (%new_loc% + 0x86) $RT_ALT_USE_POINT_Y("%index%") //set flags by bit READ_LONG (%new_loc% + 0x60) ~flag_bits~ WRITE_LONG (%new_loc% + 0x60) (%flag_bits% BOR $RT_FLAGS("%index%")) //flags set by bit //string writes SPRINT RT_NAME $RT_NAME(~%index%~) WRITE_EVALUATED_ASCII (%new_loc% + 0) ~%RT_NAME%~ (32) //name SPRINT RT_KEY_ITEM $RT_KEY_ITEM(~%index%~) WRITE_EVALUATED_ASCII (%new_loc% + 0x74) ~%RT_KEY_ITEM%~ //item to use as key SPRINT RT_REGION_SCRIPT $RT_REGION_SCRIPT(~%index%~) WRITE_EVALUATED_ASCII (%new_loc% + 0x7c) ~%RT_REGION_SCRIPT%~ (8) //script for trigger PATCH_IF (GAME_IS ~pst~) BEGIN SPRINT RT_DIALOG_FILE $RT_DIALOG_FILE(~%index%~) WRITE_EVALUATED_ASCII (%new_loc% + 0xbc) ~%RT_DIALOG_FILE%~ (8) //dialog file used only in pst END //enter correct index into vertex pairs WRITE_LONG (%new_loc% + 0x2c) %vert_entry% //index of vertices SET vert_entry = %vert_entry% + %RT_VERTEX_PAIRS% END //end for loop FOR (idx=0;idx<%ab_new_vertex_points%;idx+=1) BEGIN SPRINT ab_VX_X ~ab_VX_X%idx%~ SET ab_VX_X = EVALUATE_BUFFER ~%%ab_VX_X%%~ SPRINT ab_VX_Y ~ab_VX_Y%idx%~ SET ab_VX_Y = EVALUATE_BUFFER ~%%ab_VX_Y%%~ WRITE_SHORT (%Q_NewOffset_Vertx% +(%idx%*4) +0) %ab_VX_X% WRITE_SHORT (%Q_NewOffset_Vertx% +(%idx%*4) +2) %ab_VX_Y% END BUT_ONLY_IF_IT_CHANGES END //end function define Then you can call these up within your tp2 and provide your data as in the following example where 2 triggers and associated vertex points were added all in one shot: //------------------------------------------------------------------------------- // Restore Chapter 5 start to Vanilla BG behaviour //------------------------------------------------------------------------------- BEGIN ~Restore Chapter 5 start to Vanilla BG behaviour~ REQUIRE_COMPONENT ~Setup-BG_FixPack.tp2~ ~0~ ~SKIPPING Required Component not installed~ REQUIRE_PREDICATE (GAME_IS ~totsc~) ~SKIPPING Only for TOTSC~ INCLUDE ~BG_FixPack\tph\endch4.tph~ //compiles script and removes area script reference from area file INCLUDE ~bg_fixpack\tph\Q_AREMacros.tph~ //defines Qwinn's Macros INCLUDE ~bg_fixpack\tph\ab_FlorTrig.tph~ //defines ab_Add_Area_Floor_Trigger function LAUNCH_ACTION_FUNCTION ~ab_Add_Area_Floor_Trigger~ //integers defined INT_VAR ab_new_triggers = 2 //number of new triggers you are adding ab_new_vertex_points = 10 //number of new coordinate points (pairs of vertices) for all your triggers //first trigger entries have _0 added to the variable name RT_BBOX_LOW_X_0 = 380 //bounding box low x value LEFT RT_BBOX_LOW_Y_0 = 1062 //bounding box low y value TOP RT_BBOX_HIGH_X_0 = 541 //bounding box high x value RIGHT RT_BBOX_HIGH_Y_0 = 1277 //bounding box high y value BOTTOM RT_VERTEX_PAIRS_0 = 6 //number of x y coordinate pairs making up new region RT_FLAGS_0 = 0b0000000000000010 //flag values set in bit format from right to left 1 turns on 0 turns off RT_TRAP_DET_DIFF_0 = 100 //trap detection difficulty percentage RT_TRAP_REM_DIFF_0 = 100 //trap removal difficulty percentage RT_TRAP_IS_SET_0 = 1 //Is the region trapped? 0=no;1=yes RT_TRAP_DETECTED_0 = 0 //Is the region trap already detected? 0=no;1=yes RT_LAUNCH_POINT_X_0 = 404 //Main use point x value RT_LAUNCH_POINT_Y_0 = 1300 //Main use point y value RT_ALT_USE_POINT_X_0 = 0 //alternate use point x value RT_ALT_USE_POINT_Y_0 = 0 //alternate use point y value //second trigger entries have _1 added to the variable name RT_BBOX_LOW_X_1 = 1523 RT_BBOX_LOW_Y_1 = 272 RT_BBOX_HIGH_X_1 = 1629 RT_BBOX_HIGH_Y_1 = 356 RT_VERTEX_PAIRS_1 = 4 RT_FLAGS_1 = 0b0000000000000010 RT_TRAP_DET_DIFF_1 = 100 RT_TRAP_REM_DIFF_1 = 100 RT_TRAP_IS_SET_1 = 1 RT_TRAP_DETECTED_1 = 0 RT_LAUNCH_POINT_X_1 = 1620 RT_LAUNCH_POINT_Y_1 = 340 RT_ALT_USE_POINT_X_1 = 0 //alternate use point x value RT_ALT_USE_POINT_Y_1 = 0 //alternate use point y value //vertex entries have incremental numbers attached per pair starting with 0 //vertex entries for trigger 1 ab_VX_X0 = 380 //Point #0 X value ab_VX_Y0 = 1076 //Point #0 Y value ab_VX_X1 = 510 //Point #1 X value ab_VX_Y1 = 1160 //Point #1 Y value ab_VX_X2 = 439 //Point #2 X value ab_VX_Y2 = 1263 //Point #2 Y value ab_VX_X3 = 468 //Point #3 X value ab_VX_Y3 = 1277 //Point #3 Y value ab_VX_X4 = 541 //Point #4 X value ab_VX_Y4 = 1148 //Point #4 Y value ab_VX_X5 = 393 //Point #5 X value ab_VX_Y5 = 1062 //Point #5 Y value //vertex entries for trigger 2 ab_VX_X6 = 1523 //Point #0 X value ab_VX_Y6 = 292 //Point #0 Y value ab_VX_X7 = 1607 //Point #1 X value ab_VX_Y7 = 356 //Point #1 Y value ab_VX_X8 = 1629 //Point #2 X value ab_VX_Y8 = 334 //Point #2 Y value ab_VX_X9 = 1550 //Point #3 X value ab_VX_Y9 = 272 //Point #3 Y value //strings defined STR_VAR ab_file = ~ar1803.are~ //area file to edit requires extension to be included //first trigger entries have _0 added to the variable name RT_NAME_0 = ~Chapter trigger 1~ //name of floor trigger RT_REGION_SCRIPT_0 = ~endch4~ //name of script for trigger RT_KEY_ITEM_0 = ~~ //key item reference if one is required RT_DIALOG_FILE_0 = ~~ //dialog file if the region can talk in pst //second trigger entries have _1 added to the variable name RT_NAME_1 = ~Chapter trigger 2~ //name of floor trigger RT_REGION_SCRIPT_1 = ~endch4~ //name of script for trigger RT_KEY_ITEM_1 = ~~ //key item reference if one is required RT_DIALOG_FILE_1 = ~~ //dialog file if the region can talk in pst END You will note in this example that I had 'my' function code separate from Qwinn's macro code, but you can put them together into one file and use a single INCLUDE to call them all up at once. I know that portions of the functions/macros have been updated, but I do not know if all the 'advancements' have made it into the region trigger functions. The advancements do the same work, but allow for less code and thus smaller file sizes... Link to comment
devSin Posted July 19, 2009 Share Posted July 19, 2009 Sometimes, simple is better. Create an invisible NPC. Modify the area script to have the NPC spawn at the location you want. Have the NPC's script start dialogue when the conditions you want are met. Destroy the NPC. Or you can just run 10 billion lines of TP2 code... ;-) Link to comment
Ardanis Posted July 19, 2009 Share Posted July 19, 2009 Agreed with DevSin. Dialog may be triggered by an invisible creature, without area patching. Unlike the latter, using the former method the mod can be installed whether or not the area was visited (and got stored in a save) Link to comment
lsass.exe Posted July 19, 2009 Author Share Posted July 19, 2009 First: Thanks for your answers! I really appreciate it. But I also have to say, that's all double dutch to me. I honestly can't claim to understand any of that code. But while trying to fall asleep last night I got the idea with that invisble creature too, which could mean I am not as lost with this stuff as I thought. I think I will go with that. Again, thanks for all your efforts. Link to comment
Recommended Posts
Archived
This topic is now archived and is closed to further replies.