Jump to content

Checking the distance to a point


Ieldra

Recommended Posts

I've been looking for a way to check the distance to a certain point in an area. Since the Range() trigger only checks the distance to objects, I've been thinking of using an invisible creature. Some questions about this:

 

(1) What I want to do is to start a cutscene at the entrance point of an area, after the PC enters that area, and once (s)he is a certain distance away from this (only) entrance point. I don't want it to happen immediately, I don't want it to happen on top of the PC (NPCs aren't a consideration at this point), and I don't want it to happen when the PC is too far away to see the place. Is there a better way to do this than using an invisible creature for distance checking?

 

(2) Is there a pre-existing invisible creature I can use in the game, preferrably of rabbit size or even smaller, or must I create one?

 

(3) This will happen in a confined space, so is there a chance that stumbling over the invisible creature will influence the PC's movements - such as making it impossible to walk along a narrow corridor if the invisible creature is present - or will that not be a problem?

 

(4) I've been thinking of using fixed coordinates as an alternative. The problem with is this that the area to check would be an approximate circle. It could be simplified to rhombus-shaped one, but since math functions seem not to be implemented in the scripting language, both would get rather complicated.

 

I'll appreciate any advice. How can such a simple task get so complicated...?

Link to comment

If it is your own area, I'd suggest implementing a trigger - just the way it happens with Jaheira over Khalid's death. See DLTCEP tutorials(downloaded with DLTCEP - PPG modlist has the links) for instructions.

 

If you are trying this in an existing area, writing a trigger in via WeiDU could work, as well. I recall CamDawg posting some examples in Q&A recently. (I definitely recall there was something like this, 'cause I remember jcompton's "It's so much easier in WeiNGINE!" post).

Link to comment

As Kulyok already said, it would be easier to simply draw an Info Trigger and then assign the appropriate script to it. You can either use DLTCEP to do this, or you can patch the trigger into the area via WeiDU which is slightly more complicated. As for the script, I guess you'll need something along these lines:

 

IF
Global("SomeGlobal","GLOBAL",0)  // If the cutscene didn't already occur
Range(Player1,12) // and the protagonist is nearby
!Range(Player1,4) // but (s)he is not on top of the trigger
THEN
RESPONSE #100
	SetGlobal("SomeGlobal","GLOBAL",1) // set the global indicating that the cutscene has triggered
	StartCutSceneMode()
	.
	.
	.
	.
	<some cutscene commands>
	.
	.
	.
	EndCutSceneMode()
END

 

EDIT - I just noticed that you didn't actually ask for two cutscenes (as I had hastily assumed :)) so I've shortened the code.

Link to comment

Thanks. Yes, my script would look like that. Unfortunately, it is in existing game area, so I'll need to use the patch in method. I'll have a look into IESDP and then try it.

 

BTW: I have to say I consider myself lucky for actually understanding that tp2 code, but if this is "slightly more complicated", I'm beginning to wonder what "considerably more complicated" might be... 50+ lines of code for nothing but a range check... and all this for an as-yet simple mod NPC making a dramatic entrance (I'll post something more about it once it's at least playable).

Link to comment

Heh, don't worry. It may seem a bit intimidating at first, but once you start experimenting and actually using the code it all comes together quite nicely. If you'd like, I could post some of the modified code which I'll be using for RR v3.8. It has much more comments which make things somewhat more understandable and easier to remember (well, for me at least :)).

Link to comment
If you'd like, I could post some of the modified code which I'll be using for RR v3.8. It has much more comments which make things somewhat more understandable and easier to remember (well, for me at least :)).

I would appreciate that. There's never too much commented sample code if you're trying a new programming language (for all practical purposes, WeiDU is exactly that).

 

EDIT: I've looked into the file format description and it's all very straightforward. It's only the tp2 code that looks complicated. I'd still like to see your code.

Link to comment

Ok, here you go then. :)

 

// Modifying AR0800 to include the new CoC ambush triggers (code based on pro5's Dragon Trigger from the BG1 NPC project)

COPY_EXISTING ~AR0800.ARE~ ~override~									  // Graveyard district CoC trigger 1 (bottom exit)
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" = 1675
SET "Top" = 2125
SET "Right" = 1968
SET "Bottom" = 2175
WRITE_SHORT 0x5a ("%info_num%" + 1)
INSERT_BYTES "%info_off%" 0xC4						  // Insert new blank info point
  WRITE_ASCII "%info_off%" ~RR#COC01~				   // Trigger name
  WRITE_SHORT ("%info_off%" + 0x20) 1				   // Trigger type (trap, info or travel)
  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				   // Number of vertices
  WRITE_LONG ("%info_off%" + 0x2C) "%vert_num%"		 // First vertex index
  WRITE_SHORT ("%info_off%" + 0x34) 34				  // Cursor type
  WRITE_SHORT ("%info_off%" + 0x60) 256				 // Flags (i.e. trigger is initially deactivated)
  WRITE_ASCII ("%info_off%" + 0x7C) ~RR#CGRAV~ #8	   // Trigger 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%") 1675	// Vertex1.X
	WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" + 2) 2175 // Vertex1.Y
	WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" + 4) 1700  // Vertex2.X
	WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" + 6) 2125 // Vertex2.Y
	WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" + 8) 1968 // Vertex3.X
	WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" +10) 2132  // Vertex3.Y
	WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" +12) 1957 // Vertex4.X
	WRITE_SHORT ("%vert_off%" + 0x04 * "%vert_num%" +14) 2175  // 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

Link to comment

Great. I think I've got it. Now, to another question. What I really need is something like a distance trigger - something is supposed to happen if the party is *off* a certain circumscribed area they appear in when they enter the map. I suppose I could instead set the trigger area to the rest of the room, but the shape of the area would be, well, interesting. I wonder if I could use an octagonal trigger area and to script it like this:

 

Trigger script does:

IF 
  !Global("IxCutsceneTrigger","ARnnnn",0) // global exists, and
  !Global("IxCutsceneTrigger","ARnnnn",9) // cutscene hasn't yet happened
THEN
  RESPONSE #100
  IncrementGlobal"(IxCutsceneTrigger","ARnnnn",-1)
END

 

Area Script does:

IF 
  Global("IxCutsceneTrigger","ARnnnn",2) // trigger script has done nothing for one or two cycles
THEN
  RESPONSE #100
  SetGlobal("IxCutsceneTrigger","ARnnnn",9) // set "cutscene happened" indicator and start the scene
  (Cutscene Code)
END
/* Increment the global - I don't know what IncrementGlobal does if its argument
variable doesn't exist, so I need to check for non-existence first */
IF 
  Global("IxCutsceneTrigger","ARnnnn",0)
THEN
  RESPONSE #100
  SetGlobal("IxCutsceneTrigger","ARnnnn",1)
END
IF 
  GlobalLT("IxCutsceneTrigger","ARnnnn",9)
THEN
  RESPONSE #100
  IncrementGlobal("IxCutsceneTrigger","ARnnnn",1)
END

 

I presuppose that the trigger fires once per cycle if any party member is in the area (i.e. not twice if two are, for instance).

 

Does this look as if it could work? As for the situation involved: the party appears as if per Teleport, similar to the way you appear in the Planar Sphere using the Planar Sphere Return mod, only you appear near to the center. Suppose I would want something to happen once the party is far enough away from the center of the room, but at least one party member is still in it and can see what happens. Thus the need for an "off" trigger.

Link to comment
I suppose I could instead set the trigger area to the rest of the room, but the shape of the area would be, well, interesting.

 

You can use IsOverMe() or Entered() for determining when a PC has stepped on the trigger. I'm not 100% sure, but the trigger may have to be of the Trap type for this to work.

Link to comment

Thanks, Avenger and aVENGER_[RR], but these triggers won't work for my purpose, because they can only be used in trigger scripts. The kind of check I need would be:

IF
  Global("IxCutsceneTrigger","ARnnnn",0)
  !IsOverMe(Player1)
  !IsOverMe(PartyMember2)
  ....etc.
THEN
 RESPONSE #100
 SetGlobal("IxCutsceneTrigger","ARnnnn",1)
END

(and then check the global in the area script for starting the cutscene)

But the condition will never become true, since it would only do so if no party members are in the trigger region, which means that the trigger won't fire and this piece of code will not be reached. There would only be a way around this if the active object could be set to the trigger region for a block of code. So far I have only seen this in cutscenes with CutsceneId. For actions there is ActionOverride. But I don't suppose something similar exists for conditions - at least I have found nothing in IESDP.

Link to comment

Invisible invulnerable rats or birds are useful, they don't have personal space.

 

Why can't you use trigger scripts?

 

if
 IsOverMe([PC])
then
...

 

Something similar was implemented in DLTC, there are trigger regions which don't need to be entered but their script runs and detects if someone goes near them (causing an autosave before the ogre encounter).

 

IF
 Global("InitSave","DL0100",0)
 Range([PC],10)
THEN
 RESPONSE #100
SetGlobal("InitSave","DL0100",1)
SaveGame(0)
END

Link to comment
Invisible invulnerable rats or birds are useful, they don't have personal space.

Ah, very good to know to know that.

 

Why can't you use trigger scripts?

If you've read what I'd like to do, you'll notice that this does not work for triggers where something is supposed to happen when all party members have left the area. I assume, of course, that trigger scripts only start running if anyone is on the trigger. If they actually run all the time, like area scripts, then it would work, but that would be very inefficient, since every trap in an area would have its script running all the time. But hey, I don't know the game engine...do trigger scripts run all the time or do they only start running if, well, triggered.

Link to comment

Archived

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

×
×
  • Create New...