Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patient glitches if unable to vomit #1614

Open
lewri opened this issue May 22, 2020 · 2 comments
Open

Patient glitches if unable to vomit #1614

lewri opened this issue May 22, 2020 · 2 comments
Assignees

Comments

@lewri
Copy link
Member

lewri commented May 22, 2020

Describe the issue

A weird one here. And very hard to reproduce on command.
If a patient is going to vomit, but can't because it was in the middle of another action; the patient seems to glitch and slide through walls/objects before being reset. Then the patient vomits.

So far during the game I've seen it happen in 2 occasions.

  1. Patient is about to use vending machine and subsequently is about to vomit. As a result the patient slides forwards through the vending machine about 2 tiles then resets. Patient then vomits.

  2. Patient leaves a room and subsequently is about to vomit. As a result the patient slides through the door back into the room, then resets. Patient then vomits.

Steps to Reproduce

  1. Honestly no idea how to reproduce this... It seems like a game of chance to get a patient to vomit on command.

Save Game

Expected Behavior

In original pretty sure this didn't happen. Patient was able to vomit after their current action finished.

System Information

CorsixTH Version: 0.63

Operating System: W10

Theme Hospital Version: GOG

Gamelog.txt

None

Additional Info

@mugmuggy
Copy link
Contributor

This happens on the drinks machine one as the walk action is disable truncate, thus the walk action has to finish, and the vomit action is just queued ahead of the walk, so it just switches the animation, but still ticks for the movement and indeed it does need some finesse.

I can't recall seeing the second one.

@mugmuggy
Copy link
Contributor

mugmuggy commented Sep 8, 2020

Humanoid_startAction, queue action - interrupt_head, humandoid:setNextAction and Patient:interruptAndRequeueAction have snippets of code that call the actions interrupt handler and the latter two also, Humanoid:finishAction.

Say you have a patient that is exiting GP about to head to a room. Seek room starts a walk action to the destination room. In those first few ticks of the walk to the destination room, the room is edited. Through Queue:rerouteAllPatients, setNextAction queues an idle and a new seek room is queued.

setNextAction goes ahead and marks all actions as todo_interrupt that are must happen and interrupts the walk action. This ensures the walk will complete its one tile move still. setNextAction removes the actions interrupt handler preventing it from being called again.

Soon after tick wise, the Patient:tickDay is called and calling Patient:vomit if you are lucky. This correctly queues the action, but at the end of Patient:interruptAndRequeAction, there it checks if the action interrupt handler is set, which it now no longer is, and just calls Humanoid:finishAction in turn calling Humanoid_startAction.

As the timer for the walk hasn't fired (action_walk_tick hasn't run) and reset the patients speed. The vomit animation starts and the patient slides across. Ideally the walk should complete then the vomit occur.

The action interrupt handlers may have had unintended processing in the past. Indeed some of that code goes back years. I haven't fully explored for other consequences as yet, but we could leave those interrupt handlers accessible and have them just return if already called. Note the action_walk_interrupt restores the handler if required and returns preventing the truncation of the path/avoiding finishAction being called etc, or likewise set a flag to indicate the handler has been called and not call finishAction instead.

Humanoid_startAction also clears the todo_interrupt flag. If that is a walk that should now not process, it would appear possible to have a vomit action for example, requeue a walk action that shouldn't occur, due to the nature of that walk starting in the first place.

You can manipulate a humanoids action queue: queue an IdleAction():setMustHappen(true), queue a WalkAction(x,y):setMustHappen(true) and then setNextAction another IdleAction. When the walk starts, call Patient:vomit(). They vomit and the action completes, even though it technically shouldn't as setNextAction wanted to abort. This would be more similar to the drinks machine scenario where it may or may not be desired for the patient to abort whatever walk they are performing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants