Jump to content

trigger dialogs by position in area


lsass.exe

Recommended Posts

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

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

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

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

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

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. :rolleyes:

 

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

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...