The mouse state machine and SCP

The mouse has several behaviours:

These are handled both by the state machine (in code) and the SCP (in data).

What's the difference between the SCP and the state machine?

The mouse's state machine holds the actual logic of behaviours. There are eight states, as can be seen in MouseSprite::Dispatch. There's also a global mouse state machine with three states, in GlobalMouseStateMachine::Dispatch.

The corresponding state names (in alphabetical, not id, order) are:

These states contain logic like "if you're holding a piece of cheese or fleeing, play the fast run action; if not, play the normal run animation" (DoMouseLocomote); checks to see if the mouse holes are open/closed; checks to see if the mouse is falling; checks to see if other sprites are too close for comfort (like a pet or the cursor); and tons of other things.

It seems like generally the state is pushed directly via NewState. I'm not sure if there's anything that triggers a state change automatically.

These states DO NOT correspond to the states in the SCP. There are 11 states in the mouse SCP.

The SCP provides information about what animations and sounds to play during certain actions. The mouse's state machine logic directly pushes certain actions defined in the SCP. For example, DoMouseLookAround can push actions 29, 32 and 43. These are all 'container' actions which call other actions. If 29 is pushed, then action 16 and action 11 are called via the SCP script. Action 16 is lifting a paw, action 11 is sitting up.

When an action is pushed by the state machine, the game tries to build a transition from the current SCP state to start state of the desired SCP action. The SCP action then pushes a new state after running.

Here is the SCP state machine of the mouse.

Let's say the mouse is running (SCP state 7). The state machine pushes action 29. Action 29's SCP script wants to play action 16. Action 16's start state is defined as SCP state 4. There is a valid path from state 7 to state 4 via state 9. Action 2 goes from state 7 to state 9, playing animation frames 190-193 on the way. These are the final 3 frames of the running animation, i.e. a short stopping animation. Now the game can go from state 9 to state 4 using action 15, playing animation frames 94-97 on the way (the start of the paw lift animation). This pathing logic is done in BuildTransition when attempting to push a new action.

Once action 15 has played, we are now in state 4, so action 16 (4->4) can successfully execute, playing the middle frames of the grooming animation. Then we can pop back to our original action, action 29, and continue forward in that script to play action 11 (which requires a start state of state 2, which means the SCP state machine will have to go via state 9 again, calling transitionary actions 17 (4->9) and 42 (9->2) on the way...)

(Also note state 0 has no links. Several actions fired from the state machine live in state 0, and they trigger other actions in their scripts. Maybe state 0 is a special case, I don't know.)

I don't get it. Summarise pls.

The state machine's responsibility is controlling behavioural state. The mouse is either looking around, or it's locomoting, or it's dangling, or whatever. The state machine doesn't know or care about the previous state. It just says "hey SCP, make the mouse look around. You figure out how to get there and what the 'looking around' animations are."

The SCP's responsibility is controlling animation state. The SCP is the thing that knows the mouse is currently in a running animation, and that we want to transition it to a grooming animation. It can make the decision to animate the mouse stopping, then animate the mouse sitting up, then animate the mouse grooming itself. Alternatively, if the mouse is currently standing with one paw up, then it knows to animate the mouse putting that paw down, then sitting up, then grooming itself. The SCP knows how to transition from the current animation to another animation.

The SCP is equivalent to an animation controller in Unity. The code state machine is the actual mouse behaviour code. People commonly say that SCP controls behaviour but this isn't the whole story.

Demonstration

The mouse has an unused exploding animation similar to the Oddballz grub. Let's add the possibiity for the mouse to explode in DoMouseLookAround.

Action 43 is one possible action that can be fired from DoMouseLookAround. It has 6 scripts. We could just replace one of these scripts, but then we'd lose existing behaviour.

Most of the mouse's states (lifting paw, grooming, walking, sniffing) can be transitioned to directly from state 9, and only lead back to state 9. Let's add a new state (state 11, exploding) that transitions to/from state 9 (actions 44 and 45), playing the first/last half of the frames of the explode animation to transition. This ensures that when the mouse is going to go from running, sitting up, etc to exploding, it will nicely finish its current animation before beginning to explode.

(You can try to use cuecode hidelinez to make the explosion better, but it seems like this does nothing in Petz.)

Then we add an 11-11 transition which contains the middle few frames of the exploding animation (action 46).

At this point we must also update the number of states at the start of the SCP.

As it is, state 11 will never be transitioned to, because nothing in the state machine calls any actions that lead to it. So, let's add a new script to action 43 which just plays action 46. This will make the game figure out the necessary transition to state 11 via state 9.

Action 43 only has a small chance to trigger in DoMouseLookAround, and there are 7 scripts on action 43. So the mouse only has a very slight chance to explode. You can speed up the game and use a debugger to make it fire more often.

The script size and number of scripts related to action 43 must be updated too.

Now the mouse has had no behaviour removed, only added. Animation transitions work correctly - the mouse will unexplode itself before going on to another action.

Boom! You can download the modified SCP at the end of this page.

Do pets work the same way?

Kind of. Pets also have SCPs for animation control, but their code side is more complex. See The pet state machine and SCP page.

What does this mean for adding new actions?

We still generally can't add complex behavioural logic. This is because you would have to define complex behaviour in the state machine, not in the SCP.

If the SCP is set up to allow it, you can add new SCP states and actions using the existing verbs and cues. But if nothing in the state machine triggers them, nothing will happen.

The only way to add new behavoural logic (i.e. new goals/states/plans) is via PetzHeaders, and support for that is currently limited.

An explanation for Kalium's findings

Kalium changed action 1 (normal run animation) to be a 1->7 transition instead of a 7->7 transition. They found that the mouse rose up into the air as if it was being picked up, on a regular interval. Why?

When the mouse is in DoMouseLocomote state, the state machine pushes action 1 (unless the mouse is fleeing). Action 1 is normally a 7-7 transition. When Kalium changed it to 1-7, the first thing the game sees is now "I need to be in SCP state 1 in order to execute action 1 like the state machine is telling me to". So it tries to find a valid transition from its current SCP state (probably state 7, locomoting, or state 9, the 'transitional' state between most other states) to state 1. State 1 is the dangling state.

State 1 normally only transitions back to state 9 via a dropping animation. Kalium's change means that action 1 is now a valid transition between 1 and 7. But action 1's animation frames are the running animation.

So - the sequence of events is:

When Kalium changed it to a 7->1 transition the mouse appeared to fall instead of rise:

When Kalium changed it to a 1->1 transition, the mouse apparently rose up with a lesser frequency. Why?

Credits

Kalium for SCP info and the SCP parser
Reflet for SCP and mouse animation info, and the verb/cue lists

Edited mouse SCP

Download here and replace mouse.scp in Petz 4.exe using Resource Hacker. Use Kalium's SCP reader and my Kaitai scp to inspect.