PlayerState
This page uses Vector3, Quaternion, Transform from Unity. The glossary says what each one is.
This is the full list of what the API gives you, one section for each part. Text in brackets at the end of a note is extra detail for experienced modders, and you can skip it on a first read.
PlayerState reads the player’s state and changes some of it: health, position, name, sleeping and waiting, and two cheat flags. Its name is PlayerState because the game already has a different class called Player (a card-game player).
Basics: health, position and names
PlayerState the player's health, position and name
Use these to read the player’s health, position and name, and to hurt, heal or move the player.
public static partial class PlayerState
{
public static bool IsAvailable { get; }
public static Vector3 Position { get; }
public static Quaternion Rotation { get; }
public static bool IsAlive { get; }
public static float Health { get; }
public static string FirstName { get; }
public static string LastName { get; }
public static bool Damage(float amount, DamageReason reason);
public static bool Heal(float amount);
public static bool Teleport(Transform target);
}
| Property | Type | What it means |
|---|---|---|
IsAvailable | bool | false when one of the sleep, wait or wake-up events could not be set up. |
Position | Vector3 | Where the player is. (0, 0, 0) when there is no player. |
Rotation | Quaternion | Which way the player is turned. No rotation when there is no player. |
IsAlive | bool | true when there is a player and they are not dead. |
Health | float | The player’s health, from 0 to 100. |
FirstName | string | The player’s first name. null when there is none. |
LastName | string | The player’s last name. null when there is none. |
| Method | Returns | What it does |
|---|---|---|
Damage(amount, reason) | bool | Hurts the player. Returns true when the game took the call. |
Heal(amount) | bool | Heals the player over a short time. Returns true when accepted. |
Teleport(target) | bool | Moves the player to a spot. Returns true when it was done. |
DamageReason the kinds of damage you can deal
PlayerState.Damage takes one of these as its reason. Each value is one of the game’s damage types, and Damage hurts the player the normal way for that type.
public enum DamageReason
{
Unspecified,
Violence,
Hunger,
Thirst,
Seizure,
Smv,
Drown,
Fire,
Radiation,
Fall,
Poison,
Withdrawal,
Suicide,
Bleed,
Mushrooms,
Explosion,
Gun,
Gas,
Force,
Liquid,
Electric
}
| Value | Meaning |
|---|---|
Unspecified | The game’s Unspecified damage type. |
Violence | The game’s Violence damage type. |
Hunger | The game’s Hunger damage type. |
Thirst | The game’s Thirst damage type. |
Seizure | The game’s ShitSeizure damage type. |
Smv | The game’s SMV damage type. |
Drown | The game’s Drown damage type. |
Fire | The game’s Fire damage type. |
Radiation | The game’s Radiation damage type. |
Fall | The game’s Fall damage type. |
Poison | The game’s Poison damage type. |
Withdrawal | The game’s Withdrawal damage type. |
Suicide | The game’s Suicide damage type. |
Bleed | The game’s Bleed damage type. |
Mushrooms | The game’s Mushrooms damage type. |
Explosion | The game’s Explosion damage type. |
Gun | The game’s Gun damage type. |
Gas | The game’s Gass damage type. |
Force | The game’s Force damage type. |
Liquid | The game’s Liquid damage type. |
Electric | The game’s Electric damage type. |
Things to know
Damagehurts the player the normal way, with the game’s sounds, camera shake and protection rules. Masks and mushroom protection work as usual. It returnstruewhen the game took the call, even if the game then ignores the damage. (It calls the game’sPlayerStatsHealth.Damageon the normal (not silent) path.)Damagereturnsfalsewhen there is no living player or a save is loading or being written.amountmust be a real number above 0, or it throws anArgumentException. An unknownreasonalso throws.Healadds health that comes back gradually, not at once. The game gives it back over a short time, the same way it does for food and medicine.amountmust be a real number above 0, or it throws. It returnsfalsewhen there is no living player or a save is loading or being written. (It adds toPlayerStatsHealth.HealthToRegenerate, the field the game’s consumable items add to (seePlayerStatsHealth.UpdateValues).)Teleportmoves the player to thetargettransform. It also turns the third-person camera to face the target, and it copies the target’s scale onto the player, so pass a transform whose scale is (1, 1, 1). It returnsfalsewhen there is no player or camera. (It uses the game’s ownPlayerLocator.Teleport, which is whatTeleport.TeleportPlayerToTargetStaticcalls.)IsAliveisfalsewhen there is no player.Healthis the same number thatSurvival.Getreads for the health stat. To set health, bleeding and other stats, useSurvival.GetandSurvival.Set. (HealthisPlayerStats.health.currentStatus.IsAliveusesPlayerStatsandDeath. The names come fromPlayerIdentity.identity.)IsAvailableisfalsewhen one of the sleep, wait or wake-up events could not be set up. The reads and writes keep working when it isfalse. See If something fails to set up.
Limits
Teleportalso returnsfalse, and moves nothing, while the world is busy: a save is loading or being written, the loading screen is up, the player is dead, a wait or sleep is running, a level change is running, an arrest is happening, a sleep event is running, or a dialogue is on.
Sleeping and waiting
The player can sleep in a bed, or wait (while working, reading or watching TV, for example). These calls start a sleep or a wait, and these events tell you when one starts and ends.
PlayerState sleep, wait and their events
Use Sleep and Wait to start a sleep or a wait, IsSleeping and IsWaiting to check, and the events to hear when they start and end.
public static partial class PlayerState
{
public static bool IsSleeping { get; }
public static bool IsWaiting { get; }
public static bool Sleep(int setTime);
public static bool Wait(int seconds, WaitKind kind);
public static bool Wait(string modId, int seconds, WaitKind kind, WaitOptions options, Action<int> onDone);
public static event Action<SleepStartedArgs> SleepStarted;
public static event Action<WaitKind> WaitStarted;
public static event Action WokeUp;
}
| Property | Type | What it means |
|---|---|---|
IsSleeping | bool | true when the player is asleep. Passing out counts. |
IsWaiting | bool | true when the player is waiting. |
| Method | Returns | What it does |
|---|---|---|
Sleep(setTime) | bool | Puts the player to bed. Returns true when they went to sleep. |
Wait(seconds, kind) | bool | Starts a wait. Returns true when it started. |
Wait(modId, seconds, kind, options, onDone) | bool | Starts a wait with settings, and tells you when it ends. |
| Event | Gives you | When it fires |
|---|---|---|
SleepStarted | SleepStartedArgs | The player goes to bed. args.SetTime is the alarm in game seconds, or -1 for no alarm. |
WaitStarted | WaitKind | It fires when a wait begins. |
WokeUp | Nothing | A sleep, a pass-out or a wait ends. |
WaitKind the kinds of wait
PlayerState.Wait takes one of these to choose the word on the wait clock, and WaitStarted gives you the kind of the wait that began.
public enum WaitKind
{
Waiting,
Working,
HavingFun,
Reading,
Playing,
StaringWall,
WatchingTV,
Talking,
Studying
}
| Value | Meaning |
|---|---|
Waiting | The wait clock shows “Waiting”. |
Working | The wait clock shows “Working”. |
HavingFun | The wait clock shows “Having fun”. |
Reading | The wait clock shows “Reading”. |
Playing | The wait clock shows “Playing”. |
StaringWall | The wait clock shows “Staring wall”. |
WatchingTV | The wait clock shows “Watching television”. |
Talking | The wait clock shows “Talking”. |
Studying | The wait clock shows “Studying”. |
WaitOptions extra settings for a wait
Pass one of these to the five-argument Wait to change how the wait treats needs, passing out and the clock label.
public sealed class WaitOptions
{
public bool IgnoreNeeds { get; set; }
public bool NoPassOut { get; set; }
public string Label { get; set; }
}
| Property | Type | What it means |
|---|---|---|
IgnoreNeeds | bool | true: no need wakes the player, and most needs stop ticking. Default false. |
NoPassOut | bool | true: the player does not pass out during the wait. Default false. |
Label | string | Text on the wait clock instead of “Working”, “Waiting” and so on. null keeps the game’s word. |
Things to know
IsSleepingistruewhile the player is asleep, and that includes passing out.IsWaitingistruewhile the player is waiting.Sleep(setTime)puts the player to bed the same way the bed’s time screen does.setTimeis the alarm in game seconds, the same units as the bed’s slider: 600 to 86400, with 600 as the default.-1means no alarm.0and values below-1throw an error. (It calls the game’sWaitingController.Sleep, which is what the bed’s time screen calls.)- A refused
Sleepreturnsfalse. The game refuses when the player is not tired enough (tiredness above 10, or alcohol above 75), when sleep is blocked, when the player is already asleep or waiting, and when a level change is running. It also refuses while aPickTimepanel is open. A refused call leaves the alarm setting as it was. (The tiredness check isPlayerStatsTiredness.CheckTiredness. The sleep uses the quality, arrest and event settings the last bed set (WaitingController.ShowTimeSetUI).) Wait(seconds, kind)starts a wait the way the game’s timed actions do. The time is in game seconds, so a wait of 10 game minutes is 600. It returnsfalsewhen the player is already asleep or waiting, when waiting is blocked, or when the game’s screen or clock is not there yet. (It callsWaitingController.Wait, which the game’s timed actions call with minutes times 60.)Wait(modId, seconds, kind, options, onDone)is the same wait, and it callsonDone(minutes)once when the wait ends. It has the same reasons to returnfalse.modIdmust be a valid mod id, or it throws anArgumentException. AnulloptionsoronDonethrows anArgumentNullException.minutesis how many game minutes passed, rounded down. (The minutes are counted from the wait’s minute ticks (WaitingController.OnWait), divided by 60. The game changes behind this overload have their own feature group,obenseuer.moddingframework.player.waitresult. If one of them fails, only this overload is turned off and it returnsfalse.)- The wait ends in one of these ways: its planned time runs out; a need ends it (unless you set
IgnoreNeeds); another caller wakes the player, for example a talk, a logic event or a sleep event; a pass-out replaces it; a game wait starts over it, for example the two-argumentWaitor a work station; or a new scene loads in place of the old one. onDoneruns at the moment the wait ends, and it may start another wait. An arrest or a pass-out can still be in progress when it runs, so do not start a sleep from it. (It runs inside the game call that ended the wait.)- If tiredness goes above 100 during a wait, the game makes the player pass out. The wait ends at once and
onDoneruns with the minutes so far, while the pass-out sleep starts. SetNoPassOutto stop this, and the wait keeps its planned length. (The game callsWaitingController.PassOut.) WaitOptions.IgnoreNeedsstops needs from waking the player, and it pauses most need ticks for this wait only. Hunger, thirst, bladder, bowel, mental health and hygiene stop changing during it, and tiredness keeps only the wait clock. Health (bleeding and recovery), alcohol, mushrooms, addictions, radiation and conditions keep running, so a bleed still hurts.IgnoreNeedsis not the same asNeedsFrozen.NeedsFrozenwould also stop the clock that makes the wait end, so a wait would never finish. (IgnoreNeedspasses the game’signorePlayerNeedsflag.PlayerStatsHungerAndThirst.UpdateStats,PlayerStatsMentalHealth.UpdateStatsandPlayerStatsHygiene.UpdateStatsdo not run during the wait.PlayerStatsTiredness.UpdateStatskeeps only the wait clock.StatsProgressDisabled(NeedsFrozen) also stops the minute tick that drives the wait clock.)WaitOptions.NoPassOutstops the player from passing out during the wait. The pass-out then happens after the wait, as in the game, if tiredness is still above 100. It covers the tiredness pass-out and the drunk pass-out. (The framework skips the originalPassOut(withType.Passout) while the wait runs. It chose blocking over ending the wait early, because blocking changes no game state and the wait keeps its planned length.)WaitOptions.Labelreplaces the game’s word on the wait clock, so the clock readsLabel: HH:MM.nullor empty keeps the game’s word. The label is copied when the wait starts. If this part fails to set up, only the label is turned off. (It is a postfix on the game’s privateWaitingUI.GetTypeString, in its own feature group,obenseuer.moddingframework.player.waitresult.label.)- Both options default to
false, which is the game’s own wait. Every end of a wait clears the waiting state, the need pause and the pass-out block. An error while a wait starts clears them too. If a new scene loads,onDoneruns with the minutes so far. (The game clears its ownignoreNeedsForCurrentWaitinWakeup.) SleepStartedfires when the player goes to bed.WaitStartedfires when a wait begins, andWokeUpfires when a sleep, a pass-out or a wait ends. They are separate events, each with its own feature group (see If something fails to set up).
Limits
- An arrest is not a pass-out, so it still ends a wait that has
NoPassOutset. - The label is cleared when the wait ends, when an arrest or a pass-out happens, and when a new scene loads. While the player is passing out or asleep, the clock shows the game’s word. A pass-out that
NoPassOutblocked keeps the label.
Choosing a time (PickTime)
PickTime opens the same time panel that a bed shows, with the orange slider, so your mod can ask the player how long to do something. It does not start a sleep. When the player confirms, your code gets the number of minutes.
PlayerState the time picker
PickTime opens the bed’s time panel so the player can choose a number of minutes. It starts no sleep; your code gets the minutes and decides what to do with them.
public static partial class PlayerState
{
public static bool PickTime(string modId, string title, int minMinutes, int maxMinutes, int startMinutes, string confirmLabel, Action<int> onConfirm, Action onCancel);
public static bool PickTime(string modId, string title, int minMinutes, int maxMinutes, int startMinutes, int stepMinutes, Func<int, string> validate, string confirmLabel, Action<int> onConfirm, Action onCancel);
}
| Method | Returns | What it does |
|---|---|---|
PickTime(modId, title, minMinutes, maxMinutes, startMinutes, confirmLabel, onConfirm, onCancel) | bool | Opens the time panel. Returns true when it opened. |
PickTime(modId, title, minMinutes, maxMinutes, startMinutes, stepMinutes, validate, confirmLabel, onConfirm, onCancel) | bool | The same, with steps and a live check. |
Putting it together
Pick a time, then wait for it with a result and no pass-out.
PlayerState.PickTime("com.example.mymod", "Work", 30, 480, 60, "Start", minutes =>
{
PlayerState.Wait("com.example.mymod", minutes * 60, WaitKind.Working, new WaitOptions { NoPassOut = true }, passed =>
{
});
}, () =>
{
});
| Step | What it does |
|---|---|
PlayerState.PickTime("com.example.mymod", "Work", 30, 480, 60, "Start", ...) | Opens the time panel from 30 to 480 minutes, starting at 60, with a Start button. |
minutes => ... | Runs when the player confirms, with the minutes they picked. |
WaitKind.Working with NoPassOut = true | Waits that many game minutes as work, with no pass-out. |
passed => ... | Gets the game minutes that passed. |
() => ... | Runs if the player cancels. |
Things to know
PickTimeopens the bed’s own time panel. The panel shows its slider, a Sleep button that usesconfirmLabelas its text, and a Cancel button. The panel’s time line readstitle: HH:MMinstead of “Sleeping”. The slider runs fromminMinutestomaxMinutes, andstartMinutesis clamped into that range.- The longer overload adds a step and a live check. The slider snaps to whole steps counted from
minMinutes, andstartMinutessnaps the same way. The top of the range is the last whole step at or belowmaxMinutes: with a minimum of 0, a maximum of 100 and a step of 60, the slider stops at 60. The shorter overload is the longer one with a step of 1 and no check. validate(minutes)lets you refuse some times. It runs each time the time changes, when Sleep is pressed, and when a refused Sleep is pressed. Returnnullor an empty string to allow the time. A non-empty text refuses it: the text shows in red under the time line and the Sleep button turns off. A controller Interact press does nothing while the time is refused. It may run several times in one frame while an arrow key is held, so keep it quick and free of side effects.validatecan benull, which means no check. Ifvalidatethrows an error, the error is logged once and the time counts as refused, with no text.- Wrong arguments throw errors. An invalid
modId(empty, longer than 64 characters, or with other characters) throws anArgumentException. Anulltitle,confirmLabel,onConfirmoronCancelthrows anArgumentNullException. It also throws anArgumentExceptionunless0 <= minMinutes <= maxMinutes <= 1440.stepMinutesbelow 1 throws anArgumentException. - Confirming gives you the minutes and starts no sleep. The Sleep button and a controller Interact press both confirm.
minutesis the slider value rounded to whole minutes and clamped to the range. The panel is put back and closed first, so the bed’s controls come back, and thenonConfirmruns. (While a picker is open, the framework skips the game’sStartSleepand callsonConfirm(minutes)instead. Then it restores the panel and closes it withCloseTimeSetUI.) - Cancelling calls
onCancel. A keyboard Interact press, the Menu key, the Cancel button, Escape, and any close of the panel by the game all cancel. A controller Interact press confirms, and a keyboard Interact press cancels. (All of these reachWaitingUI.CloseTimeSetUI. Escape is the pause menu key, and the pause menu callsCloseAllMenus, which closes the panel the same way.) - Before either callback runs, the panel goes back to how the bed had it. The slider’s range and value, the Sleep label, the Sleep button’s state and the time line are restored. The bed’s own listeners are not replaced, so the bed works normally after the picker closes.
- A new scene load cancels an open picker.
onCancelruns, and the panel is not restored because it goes away with the scene. PlayerState.Sleepand the five-argumentWaitrefuse while a picker is open. The two-argumentWait,WaitStations.Useand the game’s own waits do not refuse: they close the picker and runonCancel. A pass-out also closes the picker first, so the pass-out happens as normal. (Those callers useHideGameMenu(forceHide: true).)
Limits
PickTimereturnsfalsewhen the panel can’t open. That happens when a picker is already open (only one at a time), when a wait or sleep is running, while a save is loading or being written, when the bed panel is already showing, during a level change, when the panel or one of its buttons is missing, or when the picker’s feature group is turned off. It finds the buttons by the game method each one calls, and if it does not find the expected ones, it refuses rather than guess. (The Sleep button must callWaitingUI.StartSleep, and a button must callWaitingUI.CloseTimeSetUI. The feature group isobenseuer.moddingframework.player.pick.)- With a step, holding an arrow key moves the slider in whole steps, but reversing direction may need extra presses. The bed keeps its own stored time, and that drifts away from the slider.
- The bed stores a slider value under 600 seconds as 0. The picker reads the slider, so the minutes you get are right. The arrow keys step from the bed’s stored value, so below 10 minutes the first arrow step starts from 0.
God mode and frozen needs
These are two cheat flags that the game’s console also uses.
PlayerState god mode and frozen needs
SetGodMode and SetNeedsFrozen turn two cheat flags on or off for the player, and the versions with an owner keep one claim per mod id.
public static partial class PlayerState
{
public static bool GodMode { get; }
public static bool SetGodMode(bool on);
public static bool SetGodMode(string owner, bool on);
public static bool NeedsFrozen { get; }
public static bool SetNeedsFrozen(bool on);
public static bool SetNeedsFrozen(string owner, bool on);
}
| Property | Type | What it means |
|---|---|---|
GodMode | bool | true when the player can’t die. |
NeedsFrozen | bool | true when the player’s stats do not change. |
| Method | Returns | What it does |
|---|---|---|
SetGodMode(on) | bool | Turns god mode on or off. |
SetGodMode(owner, on) | bool | The same, as one mod’s claim. |
SetNeedsFrozen(on) | bool | Turns frozen needs on or off. |
SetNeedsFrozen(owner, on) | bool | The same, as one mod’s claim. |
Things to know
- While god mode is on, the player does not die. Health still drops to 0 and
IsAlivestaystrue, but the death never happens, soSurvival.PlayerDieddoes not fire.SetGodModereturnsfalsewhen there is no player and while a save is loading or being written. (The game does not callDeath.PlayerDeathwhilePlayerStats.Godmodeis set.) - While needs are frozen, the player’s stats do not change. Food and drink do not change them, and the sauna does not tick them. The game’s
disable_progressconsole command toggles the same flag. It stops all stats. To slow down one stat instead, useSurvival.Decay. (It isPlayerStats.StatsProgressDisabled.) - The versions with
ownerlet several mods use a flag without clashing.owneris your mod’s id (see Owner). Each flag keeps a list of mods that want it on.trueadds your mod and turns the flag on.falseremoves your mod, and when the last mod is gone, the flag returns to the player’s own value. - That value is the one from before the first claim, or the latest console change made during the claim. If the console turned it off during a claim, it stays off. The flag is on while any mod holds it.
ownermust be a valid mod id. Releasing a claim that holds nothing returnsfalse. SetGodMode(on)andSetNeedsFrozen(on)without an owner use one shared claim of their own, which is never saved either.truemakes the claim andfalsereleases it. If no mod holds the flag,falsewritesfalsedirectly, so it can still turn off a god mode that the console set. If another mod holds the flag and the shared claim is not held,falsechanges nothing and returnsfalse.- Claims are never written to the save. While the game writes a save, the flag shows the value from before the first claim, and the claim is put back when the save ends. A new scene load drops every claim. A claim made between the scene load and the
Events.Loadedevent is applied again after the game reloads the flag. Make your claim again from your ownEvents.Loadedhandler.
Limits
- Both flags are saved with the player’s save and come back on load. If the flag is on when the game saves, the player starts the next load with it on, unless you used a claim (see above). The game’s console commands toggle the same flags. (
PlayerStats.GodmodeandStatsProgressDisabledare public fields of the savedPlayerStats. A save’sGlobals.tnmtholds"Godmode":false.)