View Issue Details

IDProjectCategoryView StatusLast Update
0003989The Dark ModAIpublic29.05.2020 11:49
Reportergrayman Assigned Tograyman  
Status resolvedResolutionfixed 
Product VersionTDM 2.03 
Target VersionTDM 2.08Fixed in VersionTDM 2.08 
Summary0003989: Examine returning to sitting position after interruption
DescriptionThere's a fellow in NHAT/Forest in the barracks who sits down at the start of the mission, and has no instruction to get up. If you put out the floor candle next to the sleeping guard near him, the sitter will get up and relight the candle.

Because of the angle at which he now approaches his chair, to reseat himself, the code considers him "at his goal" when he's near enough to the spot where he was when he was sitting.

Unfortunately, this places him next to the back of the chair, and when he turns and sits, he's impaled on the back of the chair.

Examine this situation and see if smaller granularity on the return trip can be isolated to this situation (so as not to disturb ALL returning situations) so that he ends up in the correct place for sitting on the chair.
TagsNo tags attached.


related to 0004936 resolvedgrayman Sykes not sitting properly when using 2.07 
related to 0004940 resolvedgrayman Various AI get dead/unconscious before you get to them 
related to 0005156 resolvedgrayman Physics failures: Huge translation 
related to 0005265 resolvedgrayman Problem with allowing sitting/sleeping when AI is far away. 




09.10.2017 15:05

developer   ~0009431

I have come to the conclusion that this is more generalized issue with path locations. There should be no step at the end where we "figure out" the original position. We know where the AI was seated "a priori" and we should be able to poll that info and use it when concluding the seating process. The same problem happens when AI return to sleep and will levitate in strange locations. We already have the sleep position where they started, we need to either use that info as a lerp factor when returning to it or (worst case) hard jump to that position at the end of the animation.


03.12.2018 18:20

viewer   ~0010815

It appears that the upgrade to 'forest' removed any guards told to sit at the beginning of the mission.

So I can't replicate exactly what I saw nearly 4 years ago when I filed this.

I'll make a new test map.


04.12.2018 01:30

viewer   ~0010816

Last edited: 04.12.2018 01:35

Use cases:

1. Use the "sitting" or "sleeping" spawnarg on an AI who doesn't patrol, and starts the mission sitting or sleeping, and stays there, unless interrupted. When interrupted, he should go do what he needs to do, then return to his initial starting spot and sit back down or go back to sleep.

2. Use a path_corner next to a chair or bed which points to a sequence of path_nodes that puts him into a sitting or sleeping state. If he is interrupted from sitting or sleeping, he should return (I'll need to check this) to finish his sit or sleep. (Maybe he aborts the sit/sleep and moves on to the next path_node; need to check.)

3. Sometimes a sitting or sleeping AI, when interrupted, will be told to start a patrol. (I.e. he was playing cards, and some alert aborted the card game and put him on a patrol route.) Make sure any changes to solve cases 1 and 2 don't disturb that behavior.



04.12.2018 01:32

viewer   ~0010817

1. The first use case is solved, but when I find a solution for the second use case, I may have to make it general enough to also cover the first use case, tossing the solution I found for that.


04.12.2018 15:42

viewer   ~0010818

2. The second use case is solved. Its solution is different than the one for the first use case, because it requires knowledge of the path_corner that kicks off the sitting/sleeping sequence.


09.12.2018 20:22

viewer   ~0010854

1 – Fixed problem of non-patrolling sitters and sleepers not returning to their initial starting points after waking up and walking around to search.

2 – Fixed problem of sitters and sleepers descending into the floor or floating above beds (as far as I can tell).

3 – Made sitters and sleepers who use path_nodes always end up at the same place on the chair or bed.

Rev 7795:


Rev. 15423:



16.02.2020 13:24

administrator   ~0012207

I'm afraid the story of dying AIs is not over.
See the new issue 0005156. It is similar to 0004940.
I think that snap-into-position idea is good in general, but with the way how it is implemented currently it is a disaster.

The "ideal sitting position" must be statically determined by the mapper, not determined in runtime.
The wiki page:
clearly says:
  "You must place the path_sit next to the chair, angled away from the direction you want him to sit."
So the "ideal sitting location" should be where the used path_sit entity is.
Another approach would be using the location of path entity which targets the path_sit entity. But this is very dangerous, because it may be something different from path_corner, in which case it can have pretty random location.

Another problem is that the snapping happens always, without any limitations.
Even if the snap-location happens to be on the other side of the map, the script would simply drag AI to there, killing him with all the obstacles in the way.
There should be sane limit on the translation done this way, so that AIs don't teleport, be thrown away and killed.

So my opinion is that AIs should snap into the location/orientation of path_sit entity.
If this is not an option due to breaking maps, then it's better to revert all the changes, declare all sitting bugs features and hope no one dies in process.


16.02.2020 14:04

viewer   ~0012208

Last edited: 16.02.2020 14:06

There's a lot of material here, and I need to find time to review it and see if there's a simple solution to the new problems that cropped up. From a quick read-through, I see there's no mention of initially sitting w/o using a path_sit entity, so that has to be factored in.

Don't revert any of the "snapping to original position" code until I've had time to report back.

It'll prolly be a few days, possibly a week.




16.02.2020 16:42

administrator   ~0012211

Another possibility is to save "ideal sitting position" only when guard first starts the "sit" task (or ends it).
So the behavior would be:
1. Record sitting position on first sit-down.
2. Once recorded, always used the same sit-location for the whole game, no matter what.
This will ensure that the sitting-down process will always be the same. And also AIs would hopefully sit down in a way which was tested by the mapper.

As a general idea, I think it would be great if sitting-down was predetermined. I.e. so that a guard always moves along same one path, as if he is "on rails".
It probably lacks a bit of realism, but removes the chance of problems like this one.


16.02.2020 19:32

viewer   ~0012212

Last edited: 17.02.2020 01:06

SVN: atdm_ai_thief02_3 died after 5 mins at timescale 2.

2.07 hot fix: he didn't die, but after 30 mins at timescale 2, I found him patrolling normally. A minute later, he started tread-milling, stuck in a wall.

2.07: he died after 2 mins at timescale 2.

2.06: he didn't die, but after 2.5 hours at timescale 2, I found him stuck (in a different place than he was in 2.07 hot fix), tread-milling.

The tread-milling problem might not have anything to do with the dying problem, since the theory is that the dying problem is the result of changes made for this issue, back in 2.07.


17.02.2020 01:04

viewer   ~0012215

Looking at path node linkages and "move to" instructions being given to the AI just before he dies.

No eureka moment yet.

For the record, I'm building with MSVS2017.


17.02.2020 04:58

administrator   ~0012217

I have described what causes the problem with this guard in 0005157:
The core problem is: when an AI sits down, your new code drags him to "startSitLocation". Which is assigned quite erratically and is often in some random distant places. For this particular guard, it might end up in at least three different wrong places, causing him to die/teleport outdoors in two of the cases.


17.02.2020 07:14

viewer   ~0012219

Last edited: 17.02.2020 12:49

I agree with adding the missing line in the prediction area.

The reason he sits at the bottom of the stairs has to do with the closeness of 316 and 300. When he comes down the stairs, he does a prediction when he gets close to 316, and when he picks the next path node as 300, 300 is close enough to 316 that he decides he has also arrived at 300.

Once he "arrives" at 300, he sits down on the stairs.

I've been reviewing the interleave thinking code, because the player is so far away from this guy most of the time. That might be a factor in his decisions as he gets close to 316 and 300.

Btw, I disagree that startSitLocation is set "erratically". All settings made during a patrol are correct. I think the confusion is in its name. (Edit: see following note.) <del>It started life as the place where AI return to when all they do is sit or sleep in the same place. I probably overloaded its meaning when I extended it to handle interruptions anywhere during an AI's patrol. I will probably rename it to something more general, like "HeresWhereIReturnOnceImDoneWithAnInterruption".</del>

Also, btw, the origins of any path nodes other than path_corners are meaningless, since they are "action" nodes, and not "location" nodes. So storing a path_sit origin at mission start does nothing.


17.02.2020 12:38

viewer   ~0012220

Last edited: 17.02.2020 12:50

After further review of how startSitLocation is used, I realized it's only used by the sitting animation to slide a nearby AI into the same location prior to running the "sit down" animation, for both sitting and sleeping.

With that in mind, I renamed startSitLocation to returnSitPosition.

In addition to any initial "sitting" or "sleeping" AI spawnargs (not using an initial path_corner), this position is saved for all visited path_corners, even though nearly all will not lead to sitting/sleeping. This is simpler than always looking forward for path_sit or path_sleep nodes.


17.02.2020 12:54

administrator   ~0012221

Last edited: 17.02.2020 12:55

But the guy in question is never interrupted. And interleaved thinking does not apply. I simply teleport to him with notarget and observe him patrolling. Should I assume that something in his patrol schedule is considered an "interruption"?
Also, I did not get it: do you want to say that sitting on the stairs is the normal behavior for this guy?

It is sad that path_sit location is ignored. I think a better decision would be to snap AI into the location+orientation of the path_sit entity, and return him back to where he was before that when he finishes. All those issues would never happen if mappers were forced to specify exactly where AI should sit.


17.02.2020 13:22

viewer   ~0012222

Last edited: 17.02.2020 13:31

We (unfortunately) need to support the methods available to mappers over the years so we don't break released missions.

He'll be interrupted during future tests. Atm I'm trying to straighten out and verify the code that becomes important when he _is_ interrupted.

Since there are a variety of ways mappers can set up sitting/sleeping, we need to accommodate them all. Returning an AI to the settings he used when he sat/slept for the first time allows these various ways to continue to work.


As for sitting on the stairs...

Interleaved thinking increases the number of frames between "thinks" for an AI when he's far away from the player. This was introduced for performance reasons, before I joined the team. In 1.04 (IIRC), I made improvements to stop unplanned AI deaths that the original code would sometimes cause. The Alchemist mission was where folks started noticing the phantom deaths, which killed off probably half the AI before the player could meet them.

If you get anywhere near our guy, the delay between "thinks" decreases, so his movements look more natural.

If you teleport near him or start near him, he will not behave as he does when you're far away. You can observe what he does when he's far away by setting the tdm_ai_opt_interleavethinkskipPVS cvar to "1" in your cfg file. This causes him to skip the "am I in the player's PVS" check and make use of longer "think" delays. His animations will become choppy, for instance.

As mentioned above, he sits on the stairs because he's already processed the 316 node, and via the prediction code, he's also processed the 300 node. He then processes the path_sit node, but does so w/o moving over to the bench. He just sits down where he is at that frame, which happens to be at the bottom of the stairs.

Once I get into the prediction code and account for these situations where the mapper has placed path_corner nodes very close to one another (this map is probably full of this stuff, if these narrow halls our guy traverses are any indication) (again--damn those mappers!), he'll make his way over to the 300 node, invoke the path_sit, and plop himself properly onto the bench.


17.02.2020 13:51

viewer   ~0012224

Last edited: 17.02.2020 13:53

In a note above ...

"The "ideal sitting position" must be statically determined by the mapper, not determined in runtime.
The wiki page:
clearly says:
  "You must place the path_sit next to the chair, angled away from the direction you want him to sit."
So the "ideal sitting location" should be where the used path_sit entity is."

This is Fake News. I corrected the wiki page. The path_sit can be anywhere (its location is not used because it isn't important. I could put it into the mission's "blue room" if I wanted). The sitting location is provided by the path_corner that precedes the path_sit, even if there are a number of action nodes (like turning your head, scratching your arm, a path_wait, etc.) that might be stuck between the path_corner and the path_sit.


18.02.2020 14:06

viewer   ~0012225

Last edited: 18.02.2020 14:08

Found the root cause for the AI sitting on the stairs (and sometimes sitting in front of the nearby door).

The problem is that the mappers didn't extend the monsterclip on the bench up to the ceiling, so an AAS area is created by dmap on the top of the bench, and it extends off the bench top to cover the floor in front of it,

path_corner_300 sits inside that AAS area, so when the guy is standing on the floor, he can't step up onto the bench, because the bench top (AAS area) is 23 units off the floor, and AI can't step higher than 13 units.

When I carry the m/c up to the ceiling and push back the front of the m/c to be > 17 from 300's origin, he sits on the bench. I also had to add an "angle/0" spawnarg to path_sit_2 so he sits at the correct angle. (When the map starts, he's facing away from the bench, but he can't get to 300 from there, so he just sits down in front of the bench.)

So unless the map is corrected and re-issued, the AI will never be able to get back to 300, and will sit down at the point where the failure occurs.

There's one other path_sit in the map, and it might need similar corrections.

I'm afraid there's nothing we can do code-wise to correct this, since pathfinding depends on AAS areas to move the AI around, and there's no AAS area sitting on the floor where 300 sits.


18.02.2020 14:10

viewer   ~0012226

Plan at this point:

1. Test with other maps that I originally tested with back when I made the original fix to this issue.

2. Commit changes.

3. Finished.


19.02.2020 02:25

viewer   ~0012228


See my commit note in issue 0005156.


19.02.2020 16:18

administrator   ~0012230

What about adding a safeguard against pulling guards too much?
I.e. check in script that vecToIdealPosition is not greater than one meter, and do nothing otherwise.
Or maybe better abort sitting/sleeping process and continue with next patrol task.


19.02.2020 16:31

viewer   ~0012231

"Pulling" guards?

Do you mean don't let them sit or sleep if they're too far away from where they're supposed to be sitting/sleeping?


19.02.2020 16:36

administrator   ~0012232

Because if this happens and they are allowed to do so, that would be an awful thing to do (probably resulting in death or getting to unexpected place).


19.02.2020 16:37

viewer   ~0012233

The only thing that happens is that they sit/sleep in their present location.

They don't go flying off or die; we just fixed that.


22.02.2020 12:15

viewer   ~0012235

I just posted a thread about sitting & sleeping in the wrong place.


16.05.2020 07:35

administrator   ~0012521

How about this:

"I don't know if this beta test is an opportunity to look at this, but there seems to have been a map breaking regression, probably introduced in 2.07, which makes it impossible to complete The King of Diamonds without resorting to noclip. Specifically, there is an key character in an upstairs room who is scripted to wake up and walk out of the room at some point in play, but he is stuck against the chair he is trying to walk away from. Looking at reports of this problem in the forum (and on a posted playthrough on youtube) I'm pretty sure this started around the time 2.07 came out."

Almost surely caused by these changes.
I must admit that I did not play this FM, so I don't know how to reproduce the issue.


17.05.2020 07:28

viewer   ~0012522

I will look at the Ai problems cited. (I also found one in my WIP.)

While the solutions to the problems might lie in the map, it's not nice to force a mapper to re-issue his work (i.e. try to have the code work around the problem).

However, the computer I use for code work died yesterday with a suspected memory error. I need time to fix it before I look at any bugs.


17.05.2020 07:32

viewer   ~0012523

Builders' Forge:

1. Why does Jacob stay awake after sitting?

2. If you remove the wait node before the sleep node, why does the code warn about Jacob not being near enough to his path_corner to sleep, when he's already sitting in the chair?


23.05.2020 05:38

viewer   ~0012542

Instructions on King of Diamonds problem:


23.05.2020 05:53

viewer   ~0012543

Well, it's no wonder the AI has problems in that area:

1. His path_corner is right up next to monsterclip, when it should be at least 17 units away.

2. In spite of constant suggestions over the years, the monsterclip brush doesn't extend up to the ceiling, providing a nice surface for pathfinding to think the AI can climb up on the desk. AI that are allowed to do that usually get stuck.

I'm going to go back before 2.07 and see if he gets stuck. There's been no report of anyone testing this with 2.06 or earlier.


23.05.2020 15:01

viewer   ~0012546

Unfortunately, I'm unable to reproduce this problem.I'm testing with beta6, and the AI is able to sit down at the desk and subsequently stand up and walk away w/no problem.

I tested this 5x in a row, and he was ok each time.

By whatever means, I'm going to need someone to create a savegame showing the problem, using beta6.


24.05.2020 02:31

developer   ~0012551

Save file. (2,680,641 bytes)


24.05.2020 02:31

developer   ~0012552

Save from just before the issue. (2,678,944 bytes)


27.05.2020 01:23

viewer   ~0012564

Both of these savegames abort during loading under beta6.


27.05.2020 02:15

developer   ~0012565


I tested with the mission dmap-ed under 2.08.

I try to replicate on the original FM.

I hope these failed load issues are not indicative of some sort of memory leak or pointer issue...


27.05.2020 03:25

developer   ~0012566

Original DMAP. All advanced options off.

Before the door. (2,617,458 bytes)


27.05.2020 03:26

developer   ~0012567

Noclip into the room (2,614,568 bytes)


28.05.2020 03:43

developer   ~0012569

Last edited: 28.05.2020 03:43

SVN 8741


28.05.2020 03:44

developer   ~0012570 (2,609,851 bytes)


28.05.2020 03:44

developer   ~0012571 (2,611,182 bytes)


28.05.2020 10:29

viewer   ~0012572

Parkins is stuck on the chair behind him.

So this is a matter of getting him to recognize that the chair is not in the way of his forward motion.


29.05.2020 03:52

developer   ~0012576

Test with the new test build:

Saves inside the zip (before and after door). (4,324,180 bytes)

Issue History

Date Modified Username Field Change
27.12.2014 18:09 grayman New Issue
09.10.2017 14:21 nbohr1more Target Version => TDM 2.07
09.10.2017 15:05 nbohr1more Note Added: 0009431
03.12.2018 17:49 grayman Assigned To => grayman
03.12.2018 17:49 grayman Status new => assigned
03.12.2018 18:20 grayman Note Added: 0010815
04.12.2018 01:30 grayman Note Added: 0010816
04.12.2018 01:32 grayman Note Added: 0010817
04.12.2018 01:32 grayman Note Edited: 0010816
04.12.2018 01:35 grayman Note Edited: 0010816
04.12.2018 15:42 grayman Note Added: 0010818
09.12.2018 20:22 grayman Note Added: 0010854
09.12.2018 20:22 grayman Status assigned => resolved
09.12.2018 20:22 grayman Resolution open => fixed
09.12.2018 20:22 grayman Fixed in Version => TDM 2.07
03.01.2019 15:58 grayman Relationship added related to 0004936
03.01.2019 15:58 grayman Relationship added related to 0004940
16.02.2020 12:48 stgatilov Relationship added related to 0005156
16.02.2020 13:24 stgatilov Note Added: 0012207
16.02.2020 14:04 grayman Note Added: 0012208
16.02.2020 14:06 grayman Note Edited: 0012208
16.02.2020 16:42 stgatilov Note Added: 0012211
16.02.2020 19:32 grayman Note Added: 0012212
16.02.2020 19:33 grayman Status resolved => assigned
16.02.2020 19:33 grayman Fixed in Version TDM 2.07 =>
16.02.2020 19:33 grayman Target Version TDM 2.07 => TDM 2.08
17.02.2020 01:04 grayman Note Added: 0012215
17.02.2020 01:06 grayman Note Edited: 0012212
17.02.2020 04:58 stgatilov Note Added: 0012217
17.02.2020 07:14 grayman Note Added: 0012219
17.02.2020 07:16 grayman Note Edited: 0012219
17.02.2020 12:38 grayman Note Added: 0012220
17.02.2020 12:46 grayman Note Edited: 0012219
17.02.2020 12:46 grayman Note Edited: 0012219
17.02.2020 12:47 grayman Note Edited: 0012219
17.02.2020 12:49 grayman Note Edited: 0012219
17.02.2020 12:50 grayman Note Edited: 0012220
17.02.2020 12:54 stgatilov Note Added: 0012221
17.02.2020 12:55 stgatilov Note Edited: 0012221
17.02.2020 13:22 grayman Note Added: 0012222
17.02.2020 13:29 grayman Note Edited: 0012222
17.02.2020 13:31 grayman Note Edited: 0012222
17.02.2020 13:51 grayman Note Added: 0012224
17.02.2020 13:52 grayman Note Edited: 0012224
17.02.2020 13:53 grayman Note Edited: 0012224
18.02.2020 14:06 grayman Note Added: 0012225
18.02.2020 14:07 grayman Note Edited: 0012225
18.02.2020 14:08 grayman Note Edited: 0012225
18.02.2020 14:10 grayman Note Added: 0012226
19.02.2020 02:25 grayman Note Added: 0012228
19.02.2020 02:57 grayman Status assigned => resolved
19.02.2020 02:57 grayman Fixed in Version => TDM 2.08
19.02.2020 16:18 stgatilov Note Added: 0012230
19.02.2020 16:31 grayman Note Added: 0012231
19.02.2020 16:36 stgatilov Note Added: 0012232
19.02.2020 16:37 grayman Note Added: 0012233
22.02.2020 12:15 grayman Note Added: 0012235
16.05.2020 07:35 stgatilov Note Added: 0012521
17.05.2020 07:28 grayman Status resolved => assigned
17.05.2020 07:28 grayman Resolution fixed => reopened
17.05.2020 07:28 grayman Note Added: 0012522
17.05.2020 07:32 grayman Note Added: 0012523
23.05.2020 05:38 grayman Note Added: 0012542
23.05.2020 05:53 grayman Note Added: 0012543
23.05.2020 15:01 grayman Note Added: 0012546
24.05.2020 02:31 nbohr1more Note Added: 0012551
24.05.2020 02:31 nbohr1more File Added:
24.05.2020 02:31 nbohr1more Note Added: 0012552
24.05.2020 02:31 nbohr1more File Added:
27.05.2020 01:23 grayman Note Added: 0012564
27.05.2020 02:15 nbohr1more Note Added: 0012565
27.05.2020 03:25 nbohr1more Note Added: 0012566
27.05.2020 03:25 nbohr1more File Added:
27.05.2020 03:26 nbohr1more Note Added: 0012567
27.05.2020 03:26 nbohr1more File Added:
27.05.2020 15:01 grayman Relationship added related to 0005265
28.05.2020 03:43 nbohr1more Note Added: 0012569
28.05.2020 03:43 nbohr1more Note Edited: 0012569
28.05.2020 03:44 nbohr1more Note Added: 0012570
28.05.2020 03:44 nbohr1more File Added:
28.05.2020 03:44 nbohr1more Note Added: 0012571
28.05.2020 03:44 nbohr1more File Added:
28.05.2020 10:29 grayman Note Added: 0012572
29.05.2020 03:52 nbohr1more Note Added: 0012576
29.05.2020 03:52 nbohr1more File Added:
29.05.2020 11:49 grayman Status assigned => resolved
29.05.2020 11:49 grayman Resolution reopened => fixed