# Checking the distance to a point

## 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...?

Uh...sorry wrong forum. Could someone move this to the Q&A forum, please?

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).

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.

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).

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 ).

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.

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)
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
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```

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.

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.

There is also a WalkedToTrigger trigger, but i think it requires clicking on it

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.

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```

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.

Trigger scripts run always

As you can see in my previous post.

Door scripts start running when the door was first accessed (after a reload).

Container scripts also run always (i think).