Jump to content
The Dark Mod Forums

New Entity: Teledoor


Dragofer

Recommended Posts

Quote

Can it chase you through?

Nope, that's a size too large for me I believe - would probably have to identify an area with enough pathable space to teleport the AI to. Something that I could possibly get to work is, when there's a level 5 alerted AI chasing the player:

  • stop the door from working. But imo doesn't really make sense that you can't open certain doors because you're being chased.
  • play a silent alarm on the other side of the door that alerts the AIs there. This can mess up something cramped like a ship interior.

I remember a discussion from jarredmitchel's ship, which also has teleports between interior & exterior - one solution I offered was to do nothing, because most players quickload anyway when they get spotted.

Edit: hm, could maybe ask the mapper to place a teleportation entity for chasing AIs. But what if there are 2-3 AIs chasing the player?

Edited by Dragofer
  • Like 1
Link to comment
Share on other sites

Very nice work!

About AI going through, teleports are the answer indeed, Doom 3 has a tons of AI's teleporting into the levels, if i'm recalling well sometimes more than one in the same place.

One way that I think off to make sure multiple AI teleport into the map, in the same spot, is to create the idea of a cue, no need for multiple teleports, just don't teleport another AI in, while one AI or the player, is in the teleporter or very near it. You can give the teleporter a trigger box or a idbound area and test if a AI is within the volume.

Btw i'm using my C++ mind here not sure if possible or as easy with DoomScript...

Edited by HMart
Link to comment
Share on other sites

I'd leave that for all doors, windows, vents etc. that are inaccessible to AI then, at least for now.

On 2/7/2020 at 6:07 PM, Dragofer said:

I remember a discussion from jarredmitchel's ship, which also has teleports between interior & exterior - one solution I offered was to do nothing, because most players quickload anyway when they get spotted.

That's not a good assumption IMO. There are ghosters and perfectionists, sure, but your map should always support "resetting the simulation", running away from AI and waiting for things to calm down. Otherwise it's not really good level design because im-sim part of the equation falls apart every time AI is alerted.

Edited by peter_spy
Link to comment
Share on other sites

You guys rock. :)

Even though I think this kind of thing should be used sparsely. For me, it's much more fun to move around in a connected world, than warp into a different one all the time. I can see its uses, but, I also think that you shouldn't be thrown out of the mission focus, so to speak.

  • Like 2
Link to comment
Share on other sites

Well having thought on it I can probably do something inside Doomscript, given enough input from the mapper:

1) Ask the mapper to draw an inactive trigger_touch brush in front of each teledoor. It should represent the max range from which an AI would pursue the player through the door. Also ask the mapper place a 2nd teleport entity and maybe also a 3rd in case the 1st teleport spot is occupied.

2) Every time the teledoor gets activated its trigger_touch brush runs for one frame to detect all AIs and their alert states.

3) For any alert 5 (chasing) or alert 4 (agitated searching) AI, calculate their distance to the door and assign a time taken to reach it. Alert 4 AIs have to be closer to the door and take more time to reach it.

4) If the player is still on the other side of the door after the time has elapsed, the AI tries to teleport. Prefer the 1st teleport spot, but use the 2nd spot if the 1st spot is occupied. Run the trigger_touch before each teleport to make sure there are no AIs or moveables standing on the targeted spot. If occupied, wait 1s and try again.

5) After teleporting, check the AI's alert level every 3s. If they're back down to alert 1 (idle, but alert), let them walk back to the teledoor and open it. The AI gets teleported back to the other side - Skyrim has them fade out first - if any of the teleportation spots are free. If they're occupied, keep checking every 3s

6) Find what path node the AI was targeting and reassign it so the AI resumes his patrol.

So it's clear this is a larger project than just getting a new kind of teleportation entity, and there's more that can go wrong. I'd probably be better off learning C++ and doing this properly with all the extra commands available in the source code..


And yeah, chakkman makes a good point about physically connected spaces being preferrable, even if teleportation has its uses. My current WIP ship uses these teledoors to get a more spacious interior that has more content and is less prone to the pathing issues seen in one-piece ships. Imo the benefits outweigh the downsides by a good amount in this case.

An alternative that I'm using for another WIP btw is my mass_teleport script: 2 identical areas with a large trigger_touch brush that can be activated to detect & call teleportation on all moving entities except AIs.

  • Like 1
Link to comment
Share on other sites

On 2/7/2020 at 8:36 PM, Dragofer said:

play a sound globally via script. However, as far as I'm aware this will loop until you stop it after x amount of time, and I don't know of a way to check how long the sounds in a soundshader are

I think if you start sound from script, it will loop only is the shader has looping keyword.

What happens if you just call startSound? I think you can call it on any entity, not only on the current one. Also, this event returns the duration of the sound.
 

  • Thanks 1
Link to comment
Share on other sites

As for AI: they can use elevators. Elevator is a special multi-station thing such that AIs know how to move between stations. In fact, elevator is even more complicated than teledoor: AI knows how to call it, and how to wait while being on it. It is quite likely that this elevator system can be adapted here, so that guards could chase through teledoors without problem.

If this does not work, then it's better just do nothing. The support for elevators took about 1000-2000 lines of complicated C++ code, I doubt this teledoor feature is valuable enough to spend so much time and effort on it.

Link to comment
Share on other sites

This is a really cool feature, thanks for making it and releasing it Dragofer! I do think that it should be used sparingly, but in some cases such as with ships and smaller interiors it makes sense. I never really felt like the immersion was too badly affected in Skyrim due to their door system, as a caveat TDM is a very different game though. It does make the job a whole lot easier for mappers for those special cases.

  • Thanks 1

My Fan Missions:

   Series:                                                                           Standalone:

Chronicles of Skulduggery 0: To Catch a Thief                     The Night of Reluctant Benefaction

Chronicles of Skulduggery 1: Pearls and Swine                    Langhorne Lodge

Chronicles of Skulduggery 2: A Precarious Position              

Chronicles of Skulduggery 3: Sacricide

 

 

 

Link to comment
Share on other sites

 

10 hours ago, stgatilov said:

What happens if you just call startSound? I think you can call it on any entity, not only on the current one. Also, this event returns the duration of the sound.

Thanks, that's got me on the right track. There's startSound and startSoundShader - the wiki says startSound is to be preferred, but it's been behaving oddly when I was working with it. It also has an odd 3rd parameter called netSync that's never been mentioned anywhere on thedarkmod.com. Seeing that it always returns 0 as the duration caused me to look for another command: startSoundShader, which works flawlessly out of the box.

So, the teledoor has been refined:

  • the teledoor now uses snd_open and snd_close instead of asking for speakers. snd_open gets played on this teledoor, while snd_close plays on the other side's teledoor if the mapper has targeted it, otherwise snd_close plays in the player's head. There are now no more custom spawnargs.
  • the teledoor now identifies up to 2 door handles via their spawnclass, rather than triggering all bound entities (this was after getting blocked by a bug in trying to identify them via their "inherit" property)

Also experimented with making it lockable, but the road got blocked at calling the use_action_script. As I understand the use_action_script should get called when I use any inventory item on it, but the items seem to only use themselves on themselves. I'm guessing when an item is used it checks whether an eligible entity like a mover_door is in your frob highlighter?

 

9 hours ago, stgatilov said:

As for AI: they can use elevators. Elevator is a special multi-station thing such that AIs know how to move between stations. In fact, elevator is even more complicated than teledoor: AI knows how to call it, and how to wait while being on it. It is quite likely that this elevator system can be adapted here, so that guards could chase through teledoors without problem.

If this does not work, then it's better just do nothing. The support for elevators took about 1000-2000 lines of complicated C++ code, I doubt this teledoor feature is valuable enough to spend so much time and effort on it.

For an in-Doomscript solution I'm imagining turning this into a hybrid between a func_mover and an elevator button, which spawns a symbolic elevator that tells the AI to wait x seconds before it can move from its new position. Well.. it sounds like the kind of thing that you can spend ages tweaking & polishing, and as has been said it's mainly for special situations. I'd rather get my spawnarg-controlled func_mover ready before going down this route.

Link to comment
Share on other sites

5 hours ago, Dragofer said:

Thanks, that's got me on the right track. There's startSound and startSoundShader - the wiki says startSound is to be preferred, but it's been behaving oddly when I was working with it. It also has an odd 3rd parameter called netSync that's never been mentioned anywhere on thedarkmod.com. Seeing that it always returns 0 as the duration caused me to look for another command: startSoundShader, which works flawlessly out of the box.

The netSync parameter specifies whether the sound should be started for this player only, or for all players in a multiplayer session. I'm afraid it cannot be removed at this moment. Existing scripts often call it by passing false, although true would work too.

I cannot understand why startSound returns zero for you. Looking at the code, startSound internally calls startSoundShader and returns the value it gets from it. Moreover, I put breakpoint into startSound and verified that it returns some positive numbers.

Link to comment
Share on other sites

@stgatilov thanks for finding that out, this kind of thing can go on the wiki later on.

Quote

I cannot understand why startSound returns zero for you. Looking at the code, startSound internally calls startSoundShader and returns the value it gets from it. Moreover, I put breakpoint into startSound and verified that it returns some positive numbers.

Neither do I. I've made a simple map script yesterday that should automatically play the start, loop and end sound of an elevator at the location of player1 and prints sound durations to the console. If I use the thread with startSound, no sound is played and it returns 0 as the duration of the start sound, while if I use the thread with startSoundShader everything works smoothly:

Spoiler

void test_startSound()		//doesn't work: no sound is heard, sound_duration1 is 0 and script stops at sys.wait(sound_duration1);
{
float	sound_duration1 = $player1.startSound("elevator03_start", SND_CHANNEL_ANY, 0);
	sys.println("sound duration1 is " + sound_duration1 + "s");
	sys.wait(sound_duration1);

float	sound_duration2 = $player1.startSound("elevator03_loop", SND_CHANNEL_ANY, 0);
	sys.println("sound duration2 is " + sound_duration2 + "s");
	sys.wait(sound_duration2);
	$player1.stopSound(SND_CHANNEL_ANY, 0);

float	sound_duration3 = $player1.startSound("elevator03_end", SND_CHANNEL_ANY, 0);
	sys.println("sound duration3 is " + sound_duration3 + "s");
	sys.wait(sound_duration3);
}


void test_startSoundShader()		//works
{
float	sound_duration1 = $player1.startSoundShader("elevator03_start", SND_CHANNEL_ANY);
	sys.println("sound duration1 is " + sound_duration1 + "s");
	sys.wait(sound_duration1);

float	sound_duration2 = $player1.startSoundShader("elevator03_loop", SND_CHANNEL_ANY);
	sys.println("sound duration2 is " + sound_duration2 + "s");
	sys.wait(sound_duration2);
	$player1.stopSound(SND_CHANNEL_ANY, 0);

float	sound_duration3 = $player1.startSoundShader("elevator03_end", SND_CHANNEL_ANY);
	sys.println("sound duration3 is " + sound_duration3 + "s");
	sys.wait(sound_duration3);
}


void main()
{
	sys.waitFrame();
//	thread test_startSound();		//doesn't work
	thread test_startSoundShader();		//works
}

 

Now I'm no longer sure if I ever managed to get startSound to play a sound. Been experimenting with netSync 0/1 as well as alternative channels. You can specify a channel either with text or a number: tried channel 0, 1, 5, 9, 11, SND_CHANNEL_UNUSED, _UNUSED_2 and _ANY, I never hear anything and duration is 0.

Link to comment
Share on other sites

This startSound, you must pass name of spawnarg in the entity which you call it on. The name must also start with snd_, because for any such spawnarg the engine preloads sound file on map load. You cannot pass name of sound shader directly. By the way, a good approach to see how a function actually works is to find its usages in the core scripts, e.g.:

    if ( vine.getKey( "snd_grow" ) != "" )
        vine.startSound( "snd_grow", SND_CHANNEL_BODY, false );

 

The serious downside of startSound is that you cannot play a sound on entity B if you have it in a spawnarg of entity A. Which seems to be your case.

I guess it won't a problem if you use startSoundShader on a sound shader which is specified as snd_open or snd_close in some already spawned entity. It should be preloaded anyway, and already available at the moment when you use it. But in general, if you use startSoundShader, then you should do cacheSoundShader before that, preferably during initialization.

  • Thanks 1
Link to comment
Share on other sites

Ah, that clears up why I was having such a rough/inconsistent experience with scripting sounds. Turns out I've been missing theory.

So, I've switched to startSound for snd_open without problems now. Will still keep startSoundShader for snd_close because I want to run that on a different entity which may have a different/missing snd_close spawnarg, but added a line to cache snd_close in initialisation.

Also fixed a bug: turns out I can't check multiple conditionals side by side in the same for(), so the teledoor was missing some target assignments. Moved them into each their own for() and they catch everything now. Broken & working versions:

Spoiler

for(...)
	{
		target = getTarget(i);
		if(target.getKey("classname") == "info_player_teleport")
			{works}

		else if(target.getKey("classname") == "atdm:teledoor")
			{doesn't occur}
	}

 

Spoiler

for(...)
	{
		target = getTarget(i);
		if(target.getKey("classname") == "info_player_teleport")
			{works}
	}

for(...)
	{
		target = getTarget(i);
		if(target.getKey("classname") == "atdm:teledoor")
			{works}
	}

 

 

Link to comment
Share on other sites

  • 3 years later...
On 2/7/2020 at 2:36 PM, Dragofer said:

This is a Skyrim-style door which opens just a bit into a black_matt "void" before teleporting the player to a different area of the map, which may represent the other side of the door.

Is it possible to teleport the player to different areas depending on a condition? For example a gui selection.

It would be nice to have a gui-selection menu opened up when you click on the door. You only get teleported after making a selection in the gui.

Link to comment
Share on other sites

On 6/5/2023 at 10:17 AM, datiswous said:

Is it possible to teleport the player to different areas depending on a condition? For example a gui selection.

It would be nice to have a gui-selection menu opened up when you click on the door. You only get teleported after making a selection in the gui.

Yes. You would modify the function that gets called when the player frobs a teledoor to offer the player a GUI selection, wait for his input and then update the entity variable for which teledoor it's paired to, before the teleportation begins.

Link to comment
Share on other sites

  • 4 months later...

Is it possible to have a different style of door? For example a window or a trapdoor. I mean is the animation of door opening and screen fading to black easy to implement on other type of doors?

Edit: Nevermind. I figured it out. Answer is yes.

Edited by datiswous
Link to comment
Share on other sites

  • 3 weeks later...
6 hours ago, datiswous said:

I was just thinking, is it possible to make it behave as a normal door for ai but when the player interact with the door it behaves as a teledoor?

Something to try out...

Not with the current scripting, right now frobbing causes the door to open and close a little bit to simulate Skyrim-style opening of a closed door to another map section. This would conflict with the stock door opening effects. Apart from that I don't see a technical issue with adding new script effects to an existing door.

Conceptually, the teledoor script is designed for permanently closed doors. If the door can be used normally by AI you might find it fully opened. It would be odd if AIs and the player can walk through at will but if the player frobs it he gets teleported somewhere else.

Link to comment
Share on other sites

Well the original reason I came up with it was to have the possibly of an alternative regular door. When the player opens it, they get teleported right behind the door, like as if they entered through it. This means the door never has to be auto-closed (for performance) and you don't bump into it when opening. But I guess ai will have an issue with teleportation so wouldn't be able to use that teledoor.

Btw. what happens if there's an ai patrol route in the location the player gets teleported to and the player ends in the place where the ai is at that moment?

Edited by datiswous
Link to comment
Share on other sites

51 minutes ago, datiswous said:

Btw. what happens if there's an ai patrol route in the location the player gets teleported to and the player ends in the place where the ai is at that moment?

I guess you'll have a horrible teleportation accident on your hands, then. I don't think the setOrigin code checks whether the destination is free and applies an offset.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recent Status Updates

    • Ansome

      Finally got my PC back from the shop after my SSD got corrupted a week ago and damaged my motherboard. Scary stuff, but thank goodness it happened right after two months of FM development instead of wiping all my work before I could release it. New SSD, repaired Motherboard and BIOS, and we're ready to start working on my second FM with some added version control in the cloud just to be safe!
      · 1 reply
    • Petike the Taffer  »  DeTeEff

      I've updated the articles for your FMs and your author category at the wiki. Your newer nickname (DeTeEff) now comes first, and the one in parentheses is your older nickname (Fieldmedic). Just to avoid confusing people who played your FMs years ago and remember your older nickname. I've added a wiki article for your latest FM, Who Watches the Watcher?, as part of my current updating efforts. Unless I overlooked something, you have five different FMs so far.
      · 0 replies
    • Petike the Taffer

      I've finally managed to log in to The Dark Mod Wiki. I'm back in the saddle and before the holidays start in full, I'll be adding a few new FM articles and doing other updates. Written in Stone is already done.
      · 4 replies
    • nbohr1more

      TDM 15th Anniversary Contest is now active! Please declare your participation: https://forums.thedarkmod.com/index.php?/topic/22413-the-dark-mod-15th-anniversary-contest-entry-thread/
       
      · 0 replies
    • JackFarmer

      @TheUnbeholden
      You cannot receive PMs. Could you please be so kind and check your mailbox if it is full (or maybe you switched off the function)?
      · 1 reply
×
×
  • Create New...