Jobs and Quests
The Escapists 2 - Jobs and Quests system documentation
Overview
The Jobs, Quests & Objectives system in The Escapists 2 is a three-tier architecture. Jobs are prison work assignments (cooking, plumbing, mail sorting, etc.) with quotas, employee tracking, and serialization. Quests (Favours) are inmate-given multi-step tasks with rewards, using an expiration/timer system. Objectives form the atomic unit of both quests and tutorials, implemented via a tree-based directed graph with 45+ concrete types.
Jobs System
Class Hierarchy
BaseJob (abstract)
├── BaseCustomerJob (abstract) — jobs serving NPC customers
│ └── CustomerJob<CustomerClass> (abstract) — generic customer lifecycle
│ └── ServiceCustomerViaProxyJob — queue/beckon/service workflow
│ └── ServiceItemJob — dispense → craft → deliver to customer
│ ├── BeckonAndServiceCustomerJob — beckon + minigame per interaction
│ ├── ServiceItemAtRandomServicePointJob — floating service point
│ └── FacePaintingJob — applies face customisation on service
├── HandymanJob — repair/fix‑it jobs with random interaction selection
│ ├── PlumberJob — flushes toilets in cells, fixes flooding
│ ├── ElectricianJob — reading‑masher minigame on fuse boxes
│ ├── MinstrelJob — lute minigame with NPC reactions
│ ├── DecayingItemHandymanJob — items degrade each use
│ │ ├── PaintingJob — painting minigame
│ │ └── TreeDecorationJob — decoration minigame
│ └── (PaintJob, TreeDecorationJob — via DecayingItemHandymanJob)
├── ProcessItemJob — dispense → process → collect workflow
│ ├── CookingJob — timed cooking with overcooked/undercooked bounds
│ └── ExtendedProcessItemJob — dual processor (A/B) support
│ └── (HorseshoeMaking — uses ExtendedProcessItemJob)
├── MultistageItemConversionJob — multi‑stage converter chain
│ └── GrowPlantJob — plant patches growing lifecycle
├── CarriedInputJob — carry‑object dispense → deliver to consumer
│ ├── MailSortJob — sorting machines + tag‑matched collectors
│ └── FilteredCarryableIntoConsumerJob — tag‑filtered consumers
├── StoneMasonJob — stone → carving → statue workflow
├── DogFoodJob — bowl → receptacle → feed dog workflow
├── RelightTorchesJob — fuel + lighter → light torches
└── StayInRoomJob — employee stays in job room, earns quota over timeBaseJob (BaseJob.cs)
Abstract foundation for all jobs. Key fields and methods:
public JobType m_Type; // Which job this is (Cooking, Plumber, …)
public RoomBlob m_Room; // Assigned job room
public JobInfo m_Info; // Display metadata (name, description)
public Character m_Employee; // Assigned inmate/staff
public int m_QuotaTarget; // Number of completions needed per shift
public int m_QuotaAchieved; // Current completions
public float m_fTimeToComplete; // Seconds per completion
public int m_MoneyReward; // Payout per completion
public List<JobTutorialStep> m_TutorialSteps; // Paginated tutorial steps
public List<ItemData> m_OneTimeJobRelatedItems; // Items to init at level loadCore methods:
Init(RoomBlob)— one‑time room setup; readsRoomBlob_JobRoomfor dispensers, processors, collectorsOnJobTimeStarted(bool isSaveRestore)— called when daily job period begins; resets state, fills dispensersOnJobTimeEnded()— called when job period ends; dismisses customers, empties collectors, stops interactionsIncrementQuotaAchieved()— thread‑safe increment; firesOnJobCompletewhen target reachedSetRoutineInformationForCharacter(Character)— updates player UI arrow to next task targetDoesEmployeeHaveToReportToJobRoom()— false if employee already has needed itemsSerialize()/Deserialize(ulong[])— bit‑packed save data, versioned
Serialization format: Base uses 1 ulong (64 bits) for core state. Subclasses append their own data. Bit‑packed via BitField helper.
JobsManager (JobsManager.cs)
Central singleton managing all job instances.
- Contains a
PrisonJobInfo[]array configured viaLevelSetup_Jobsin the level prefab JobType[]enum of 31 entries (including DLC: Woodwork, Laundry, Library, Gardening, Horseshoe, DogFood, TreeDecoration, FacePainting, StoneMason, Minstrel, etc.)JobCategoryenum:Repair,ProcessItem,CarriedInputJob,Customer,Invalid- Allocates reserved
T17NetViewIDs for jobs viaTakeAReservedIdForJobs() - Handles lockdown → abort active jobs, clear quotas
- Routes
OnJobAssigned/OnJobUnassignedevents
JobCategory Enum (JobCategory.cs)
| Value | Description |
|---|---|
Invalid | Unassigned |
Repair | Handyman‑style (Plumber, Electrician, Minstrel, Painting, TreeDecoration) |
ProcessItem | Process‑style (Cooking, Laundry, Library, Gardening, etc.) |
CarriedInputJob | Carry‑object style (MailSort, FilteredCarryableIntoConsumer) |
Customer | Customer‑serving style (Kitchen, FacePainting, etc.) |
Job Room Configuration (RoomBlob_JobRoom.cs)
Data component on job room RoomBlob. Fields:
m_JobType— links to the job prefab typem_Door— key‑coded door (m_DoorKeySubCodeauto‑incremented)m_Dispensers,m_Processors,m_Collectors—List<InteractiveObject>for job stationsm_CustomerWaitObject,m_CustomerWaitPosition— customer queue pointm_CustomerPatronType—GroupA/B/C/Dm_CustomerServicePointLinks— links between service stations and waiting pointsm_CustomerIdleActiveRooms— where customers wander during job timem_CustomerNotActiveRoutinePosition— where customers go outside job timem_BespokeJobObjects— extra per‑level objects (statue consumers, etc.)m_JobTaunters—FakeCharacters that taunt the employeem_TutorialBoard—JobTutorialBoardInteractionm_JobBehaviour—BehaviourTreefor AI employee routing
Level Setup (LevelSetup_Jobs.cs)
At level load, creates PrisonJobInfo[] from configured JobInfo[] entries. Each entry specifies:
m_LimitationGroup—BuildingBlockManagergroupm_JobPrefabRef—BaseJobprefabm_EmployNPCOnStart— auto‑assign an NPC employeem_DaysKeptVacant— days before auto‑filling
Customer Job System
BaseCustomerJob (BaseCustomerJob.cs)
Abstract customer‑serving job. Manages customer lifecycle via JobCustomerRequester.
m_CustomerRequester— singleton pool ofAICharacter_JobCustomerm_CustomerType— patron group filterm_bCustomerWantsRandomCustomisation— random appearance per customerm_bCustomerWaitsAtExitPoint— customer waits at room exitm_bInfiniteCustomers— keep spawning replacementsm_IdleActiveRoutines— routine subtypes where customers roamm_RoomsWhenIdleActivem_CustomerWaitingForServiceLines— speech when waiting (localized key)
Flow: Init() → register with RoutineManager.OnRoutineChanged → on job time, customers roam idle rooms or wait at exit point → RequestNewCustomerCharacter() pulls from pool → DismissCustomerRPC() returns to pool
CustomerJob<CustomerClass> (CustomerJob.cs)
Generic customer lifecycle with type‑safe CustomerClass (e.g. CustomerViaProxy).
BehaviourTree m_CustomerBehaviour— AI behaviour tree for customer actionsList<CustomerClass> m_Customers— active customers- Serialization: 5‑bit header for count, then per‑customer serialized data
- Auto‑dismisses all customers on
OnJobTimeEnded()
CustomerViaProxy
Saveable data class wrapping an AICharacter_JobCustomer with service‑ready flag and serialization support.
ServiceCustomer (ServiceCustomer.cs)
MonoBehaviour on service points. Links to ServiceCustomerViaProxyJob via LinkToJob(). Methods:
ServiceActionPerformed(Character server)— generic service eventServiceActionPerformed(ItemData item, Character server)— item‑based serviceDoesLinkedJobHavePendingCustomer()— check queue
ServiceCustomerViaProxyJob (ServiceCustomerViaProxyJob.cs)
Full customer queue system.
m_ServicePoints—List<CustomerServicePointLinker.CustomerServicePoint>from room configm_CustomerServicePointMap— mapsAICharacter_JobCustomer → CustomerServicePointm_CustomersWaitingForService— FIFO queue ofCustomerViaProxyready for serviceCustomerWaitingForServiceChangedEvent— event when queue changes- Proximity speech:
m_RequestServiceProximitySpeech, distance, cooldown
Flow: CreateNewCustomer() → customer arrives → ReadyToBeServed() → CustomerReadyForServicing() adds to queue → GetWaitingCustomer() → ServiceWaitingCustomerRPC() → OnCustomerServiced() → IncrementQuotaAchieved() + DismissCustomerRPC()
ServiceItemJob (ServiceItemJob.cs)
Structured item‑based customer service.
ItemOptionPODO— recipe:List<ItemData> m_Ingredients→ItemData m_FinishedProduct+ NPC response speechm_ServiceItemObjects—ServiceItemInteractiveObjects on collectorsm_ServiceMaps— mapsServiceCustomer → ServiceItemInteractiveObject- Dispensers:
TransferItemsInteractions filled with ingredients - Auto‑refills when dispenser empties
- Guides player via
SetRoutineInformationForCharacter()— arrows to nearest service point or dispenser
BeckonAndServiceCustomerJob (BeckonAndServiceCustomerJob.cs)
Extends ServiceItemJob with beckon + minigame per interaction.
m_BeckonInteractionMaps— mapsBeckonCustomer → BeckonAndMinigameServeCustomerInteractionCallForNextCustomerRPC()— beckons next customer from poolCancelRequestForCustomerRPC()— dismisses without service- Tracks which interactions have been serviced from for finite‑customer mode
ServiceItemAtRandomServicePointJob (ServiceItemAtRandomServicePointJob.cs)
Floating service point that attaches to the customer.
- On ready: attaches
ServiceItemInteractiveObjectas child of customer - On dismiss: detaches and hides
- Random service point selection per customer
AICharacter_JobCustomer (AICharacter_JobCustomer.cs)
AI character subclass for job customers.
PatronTypes:Unassigned,GroupA,GroupB,GroupC,GroupD- Blackboard keys:
m_JobCustomerBehaviour,m_EnactingJob,m_IsBeingUsed,m_ExitPoint,m_HasProximitySpeech, etc. SetupForJob(BaseCustomerJob, BehaviourTree)— configures blackboardSetIsBeingUsed(bool, bool)— marks customer as takenReadyToBeServed()→SoftSetReadyToBeServed()→ notifiesServiceCustomerViaProxyJobControlledUpdate()— proximity speech to employee while waiting
JobCustomerRequester (JobCustomerRequester.cs)
Singleton managing the customer NPC pool.
m_AvailableCustomers/m_TakenCustomers— separate pools for free/in‑use customersRegisterCustomerWithSystem()— called byAICharacter_JobCustomer.StartInit()TakeAvailableCustomerRPC(PatronTypes, bool)— pops from availableMarkCustomerAsFreeRPC()/MarkCustomerAsTakenRPC()— network RPCs for pool state- Random customisation via
m_CustomerAstehticSetups— seed‑based deterministic appearance - Save/load via
NetSaveDatawith BinaryFormatter
SetJobCustomerCustomisation (SetJobCustomerCustomisation.cs)
NodeCanvas ActionTask that applies seeded random appearance from JobCustomerRequester.
AICharacter_JobOfficer (AICharacter_JobOfficer.cs)
Officer NPC at job office desk.
CanSpeekToCharacter(int)— checks character on time + not already spoken to + no jobGiveReward(int)— paysJobConfig.m_MoneyRewardviam_CharacterStats.IncreaseMoney()GetSpeechLines()— picks random speech fromJobConfig.m_SpeechLines- Tracks spoken‑to characters per routine cycle
JobConfig (JobConfig.cs)
ScriptableObject config:
m_CharacterLateTime(0–60s) — how late before flaggedm_MissedJobOfficerHeatIncrease(0–100%) — heat penaltym_MoneyReward— base pay per job completionm_SpeechLines— officer dialogue pools
ServiceCustomerViaProxyJob Customer Impatience
Configurable per job:
m_RequestServiceProximitySpeech— speech played when employee is nearbym_RequestServiceSpeechDistance— trigger radius (default 3.5)m_RequestServiceSpeechCooldown— seconds between speech (default 10)m_CustomerServicedSound— Wwise event on service
Job‑Specific Implementations
HandymanJob (HandymanJob.cs)
Repair‑style jobs with random interaction selection.
m_MinigameRequirements— items needed to perform repairm_MinigameRequiredEquippedItem— must be equippedm_CraftableItemRequirements— items player can craft for repairm_DispensedStartingItems— items in room dispensersm_NumItemsPerDispenser,m_bDispensersUsableOutsideJobTimem_NumRepsForMinigameComplete,m_TimeForAutoCompletion
Flow: Init() → SearchForAllPossibleInteractions() (finds matching HandymanInteractions by m_JobType) → OnJobTimeStarted() → Master_PickInteractionsAndNotifyRPC() (randomly picks up to m_QuotaTarget interactions) → player fixes → OnInteractionFixed → IncrementQuotaAchieved() → all fixed → job complete
Serialization: Versioned (v0/v1). Saves active and fixed interaction NetView IDs in bit‑packed format (12 bits per ID, up to 4 per ulong).
PlumberJob (PlumberJob.cs)
Extends HandymanJob. Searches all InmateCell rooms for ToiletInteractions, adds PlumberInteraction component.
SetInteractionForJobTimeActive()— floods toilet when interaction becomes activeCopyPossibleInteractionsForNewJobTime()— excludes locked interactions
PlumberInteraction (PlumberInteraction.cs)
HandymanInteraction subclass. Uses GymMasher_Threadmill_ExerciseBike masher.
- Visible only when toilet is flooded
OnFixed()→UnClogToilet(), plays Wwise events
ElectricianJob (ElectricianJob.cs)
Extends HandymanJob. Minimal — sets m_MasherSettings on ElectricianInteraction.
ElectricianInteraction (ElectricianInteraction.cs)
Uses ReadingMasher. Tracks masher gain/sweetspot states for Wwise audio feedback.
MinstrelJob (MinstrelJob.cs)
Extends HandymanJob. Sets m_MasherSettings on LuteInteraction.
LuteInteraction (LuteInteraction.cs)
HandymanInteraction using SolitaryPotatoMasher.
- Triggers NPC reactions via
RPC_TriggerNearbyNPCReaction()everym_fReactionCooldownTime(default 3s) - Finds nearby inmates/guards, plays
m_NPCReactionTextspeech, pauses movement - Wwise loop events for lute music
- Hidden from proximity detector in versus mode
PaintingJob (PaintingJob.cs) / TreeDecorationJob (TreeDecorationJob.cs)
Extend DecayingItemHandymanJob. Sets masher settings on their respective interactions.
DecayingItemHandymanJob (DecayingItemHandymanJob.cs)
Extends HandymanJob — each repair degrades the required items.
m_RequiredItemsUsedReplacement— item given when tool breaksm_ItemHealthDecayPerUse— health decrement per fixAll_OnInteractionFixed()— decreases item health; replaces broken items
ProcessItemJob (ProcessItemJob.cs)
Dispense → process → collect pipeline.
m_DispensedItems— items in dispensersm_NumItemsPerDispenser,m_DispenserUsableOutsideJobTime,m_InfintelyDispenseDuringJobTimem_ProcessorInputItems,m_ProcessorOutputItems— conversion recipem_ProcessingTime,m_ProcessorUsableOutsideJobTimem_CollectedItems— items that count toward quota when depositedm_PreCraftItems— items that must be crafted before processingSetProcessorInputItem()— assign I/O toItemProcessorBase
Events: OnDepositFinishedItemEvent increments quota + clears collector. Dispenser_OnItemRemoved auto‑refills if m_InfintelyDispenseDuringJobTime.
CookingJob (CookingJob.cs)
Extends ProcessItemJob. Configures CookingItemProcessors with:
m_OvercookedItemDatam_CookedLowerBound,m_CookedUpperBound(seconds)- Processors set interruptable + UI visible when player is assigned
- Hooks
OnJobAssignedto toggle cooking UI visibility
ExtendedProcessItemJob (ExtendedProcessItemJob.cs)
Dual‑processor variant. Secondary processor uses m_Processor_BInputItems / m_Processor_BOutputItems.
MultistageItemConversionJob (MultistageItemConversionJob.cs)
Converter‑chain workflow using MultistageItemConverter.
m_InputOutputs—List<MultistageItemConverter.ItemConverterConversions>m_CanConvertersBeUsedOutsideJobTime,m_MaxConverterInputsFillDispensers()→GetDispenserContentsForFilling()→ spawns items
GrowPlantJob (GrowPlantJob.cs)
Extends MultistageItemConversionJob. Manages PlantPatch lifecycle.
m_Trowel,m_Seeds,m_PottedPlant— item definitionsm_NumSeedsPerTrowel— seed multiplier- Listens to
SeedGrowingEventandGrownPlantTakenEvent→MasterPlantQuotaIncrease() SetRoutineInformationForCharacter()— prioritises fully grown plants, then patches to dig/seed
CarriedInputJob (CarriedInputJob.cs)
Carry‑object workflow. Dispenses HazardousCarryableObjectInteraction prefabs.
m_ObjectPrefabToDispense— prefab with required itemsm_bCanDispensersBeUsedOutsideJobTime,m_NumberEquipmentItemsSpawnedSetupDispensers()— scans forCarriedObjectDispenserandTransferItemsInteractionFillDispensers()— cycles through required items
MailSortJob (MailSortJob.cs)
Extends CarriedInputJob. Sorting machine + tag‑matched collector workflow.
PostBoxTagMap— mapsuint m_Tag→ItemData m_ItemDatam_SortingMachineMaps— tag/item mappings for each machinem_SortingMachineNumDispensedItems— items per batchCarryableConsumer_AcceptedInputEvent— recycles objects back to spawn poolOnDepositFinishedItemEvent— increments quota on correct collector deposit
FilteredCarryableIntoConsumerJob (FilteredCarryableIntoConsumerJob.cs)
Extends CarriedInputJob. Generic tag‑filtered consumer workflow.
- Scans
m_BespokeJobObjectsforCarryableObjectConsumers CarryableConsumer_AcceptedInputEvent— increments quota if tag matchesm_ProcessingTags
StoneMasonJob (StoneMasonJob.cs)
Standalone job: stone dispenser → carving desk → statue consumer.
m_StoneDispensers— carryable stone objectsm_StonemasonDesks— carving stations with state machine (NoStone,WaitingForStone,Carving,WaitingForPickup)m_StatueConsumers— accept carved statues → increment quota- On
LightsOutroutine → resets all desks toNoStone - Serialization: saves desk NetView IDs + state (12 + 4 bits per entry)
DogFoodJob (DogFoodJob.cs)
Standalone job: receptacle dispenser → dog bowl → dog approval.
m_FoodReceptacleItem,m_DogFoodItem— item typesm_NumSpareItemsProduced— extra items beyond bowl countm_DogBowls—DogBowlcollectorsOnDogBowlFedEvent— increments quota; when quota reaches target, increases all dog NPCs' opinion of employee bym_DogApprovalOnCompletion(default 10)- On
LightsOut→ resets all bowls toNoBowl - Serialization: bowl NetView ID + stage (12 + 4 bits)
RelightTorchesJob (RelightTorchesJob.cs)
Standalone job: fuel + lighter dispensers → light wall torches.
m_FuelItem,m_LighterItem— item typesm_NumLighterItemsProduced,m_NumFuelItemsProduced— quantity per fillm_WallTorches—WallTorchcollectors withTorchState(Unfueled/Lit/FueledExtinguished)OnWallTorchLitEvent→IncrementQuotaAchieved()+ delayed routine info recalculation- On
LightsOut→ resets all torches toUnfueledTorch SetRoutineInformationForCharacter()— arrows to nearest unlit torch (or dispenser if missing items)
StayInRoomJob (StayInRoomJob.cs)
Simplest job — employee earns quota by staying in the job room.
IControlledUpdate— every 1s in room → +1 quotam_TaunterInRoomSpeech,m_TaunterInterval— periodic taunting fromFakeCharacters
Job Board & UI
JobBoard (JobBoard.cs)
MonoBehaviour with m_AllJobKeys[]. SwapJob() — removes the wrong job key from player's hidden inventory when switching jobs.
JobBoardInteraction (JobBoardInteraction.cs)
InteractiveObject on job board. OnStartInteraction() → InGameMenuFlow.Instance.OpenJobsBoard(). Disabled in Versus mode.
JobBoardMenu (JobBoardMenu.cs)
UI for job listing, selection, and confirmation. Shows stat requirements and job details.
JobMarker (JobMarker.cs)
Map/overworld marker for job room locations.
JobProgressHUD (JobProgressHUD.cs)
In‑game HUD element showing current job quota progress.
JobRoom_ContentsMarker (JobRoom_ContentsMarker.cs)
Editor marker classifying room objects as Dispencer, Collectors, Processors, Behaviour, or Objects. Used by RoomBlob_JobRoom.AutoSetup().
JobOfficerScreen (JobOfficerScreen.cs)
UI screen for job officer interaction — assigning jobs, viewing stats.
ServiceItemInteractiveObject
TransferItemsInteraction subclass for service points. Fields:
m_MinigameSettingsContainerm_NoEquippedItemSpeech,m_PlayerSpeechWhenServingLinkToJob(ServiceItemJob)— bidirectional linking
ServiceItemMinigameInteractiveObject
Adds minigame integration to service interactions (e.g. FacePaintingInteraction).
Tutorial Jobs
JobTutorialBoardInteraction (JobTutorialBoardInteraction.cs)
InteractiveObject on tutorial boards in job rooms. Opens JobTutorialMenu via InGameMenuFlow.Instance.OpenJobTutorialBoard().
JobTutorialMenu (JobTutorialMenu.cs)
Paginated tutorial display. Shows steps from BaseJob.m_TutorialSteps. Each page shows m_StepElements.Length steps with Next/Prev navigation and page counter.
JobTutorialStep (JobTutorialStep.cs)
Data class: string m_BodyText + Sprite m_Image.
UIJobTutorialStep (UIJobTutorialStep.cs)
UI element: T17Text m_BodyLabel + T17Image m_DisplayImage. Renders a single step.
Quest System (Favours)
QuestManager (QuestManager.cs)
Singleton managing the entire quest lifecycle.
QuestGiver Pool: Fixed array of 24 QuestGiver slots. Inmates register via RegisterQuestableInmate(). Guards via RegisterQuestableGuard().
Quest Types:
QuestType— category withm_AvailablePercentage,m_QuestRefreshTimeInHours,m_QuestListQuestMapping— specific character→quest bindings (m_QuestGiver,m_Quest,m_AutoCreate)- Robinson-specific quests (
m_RobinsonDefaultQuest,m_RobinsonQuests,m_RobinsonMapQuestIcon)
Flow:
Initialise()→ appliesQuestConfigoverrides, registersGamer.OnDeleteImminent+OnBecameMasterClientBegin()→ creates callback timer form_TimeInHoursBeforeInmatesHaveQuests, caches all quest objective treesStartHandingOutQuests()→m_bStartGivingQuests = true, auto‑creates specific quests, creates Robinson questsUpdate()— every 3s, finds available inmates, assigns random quest type by weighted percentage viaRPC_CreateQuestGiver()- Expired quest givers removed every tick
QuestGiver lifecycle:
SetQuest(QuestList, typeIndex, randomIndex)→ sets available questPrepareMenu(FavourMenu, Player)— deserializes objective tree, sets UI text/rewardsOnQuestAccepted()— firesOnObjectiveTreeCompleted/Canceled/Failedevents, starts tutorial, adds trees toObjectiveManager, increases active quest countOnQuestDeclined()— removes quest giver; special handling for typeIndex-2(specific) → re‑createsOnObjectiveTreeCompleted()— plays pass sound, firesQuestCompletedEvent, increments stat, advances to next quest in chain viaGotoNextQuest()OnObjectiveTreeFailed()— plays fail sound, firesQuestFailedEvent, decrements active quests; specific quests get re‑createdOnQuestExpired()— setsm_bIsExpiredflag (removed next update tick)ShowQuestAvailable(bool)— togglesCharacterIconHandler.IconType.Questand pin image
Quest Items: Tracked via m_QuestItems (Dictionary<int, int> — item view ID → owner player view ID). Grouped by PlayerQuestItemGroups. AddQuestItem(), RemoveQuestItem(), DoesPlayerOwnQuestItem(), GetItemIDsForGroup().
Serialization: Serialize() saves all 24 quest giver slots as bitfields + quest items string. DeserializeBinary() via BinaryFormatter. CreateSnapshot() for prison snapshots.
QuestConfig (QuestConfig.cs)
ScriptableObject with:
m_OverrideQuests— replaces default quest poolm_MaxPercentageQuestGivers(1–100%) — % of inmates with questsm_TimeInHoursBeforeInmatesHaveQuests— delay before quests startm_bAllowSpecificQuests— toggle for specific character quests
QuestCompletedHUD / QuestIntroObjective
UI elements showing quest completion/failure notifications and introductory objective display.
Objectives System
ObjectiveManager (ObjectiveManager.cs)
Singleton managing active objective trees per player.
AddActiveTrees(Player, List<ObjectiveTree>)— registers trees for trackingGetActiveTrees(Player, out List<ObjectiveTree>)— retrieves per‑player treesLoadObjectiveTreeData(TextAsset, ref List<ObjectiveTree>)— deserializes JSON‑format objective data- State machine:
Idle→Saving→Evaluating - Ruckus observation for objectives that trigger on combat/alarms
ObjectiveTree (ObjectiveTree.cs)
Directed graph of ObjectiveGoal nodes.
m_MainBranch— rootObjectiveGoalActiveTreeID— unique identifier for save/network syncBuildOrderList()— flattens tree to linear execution orderInitialize()— starts all root objectivesm_bShowTrackingArrows,m_MultiPartText— for quest UI- Events:
OnObjectiveTreeCompleted,OnObjectiveTreeFailed,OnObjectiveTreeCanceled EndTreeEarly(bool isTreeFailed)— aborts all active objectives
ObjectiveGoal (ObjectiveGoal.cs)
Wrapper linking a BaseObjective to tree position.
m_Objective— the concreteBaseObjectiveinstancem_Dependency— parent goal that must complete firstm_BranchOpenCondition— condition goals for branch activationSetBaseInfo(Player, Character)— assigns player/quest giver contextPickAllRandomTargets()— randomizes any[ObjectiveRandom]‑tagged fields
BaseObjective (BaseObjective.cs)
Abstract base for all 45+ objective types.
ObjectiveStatusenum:InActive,InComplete,Done,Failed,Canceled,Invalid,Resetm_Status,m_Information,m_LocalizedObjectiveName,m_LocalizedDescription- Events:
OnStatusChanged,OnProgressUpdate Init(),UpdateStatus(),OnComplete(),OnFail()- JSON serialization via
ReadFromToken(JsonToken)/WriteToToken() GetProgress()→ returns(float current, float max, string tooltip)m_bUsePerObjectiveTitles,m_bShouldShowQuestArrow
ObjectiveStatus Enum
| Value | Description |
|---|---|
InActive | Not yet started |
InComplete | Active and in progress |
Done | Successfully completed |
Failed | Failed (quest fail) |
Canceled | Aborted |
Invalid | Error state |
Reset | Reset for retry |
ObjectiveSceneElement (ObjectiveSceneElement.cs)
MonoBehaviour for scene‑bound objective references (target items, locations, NPCs). Used by objectives that need inspector assignments.
ObjectiveTrackerHUD (ObjectiveTrackerHUD.cs)
HUD panel listing tracked objectives. Shows progress bars and text per active objective.
ObjectiveSubGoalHUD (ObjectiveSubGoalHUD.cs)
Individual sub‑goal UI element within the tracker.
TriggerObjectiveObserver (TriggerObjectiveObserver.cs)
Trigger collider component used by TriggerObjective. Detects player enter/stay/exit with configurable player count and stay time thresholds.
Objective Types (Enum)
45+ types defined in the ObjectiveType enum. Key categories:
| Objective | File | Description |
|---|---|---|
| ItemObjective | ItemObjective.cs | Acquire item from specific location/drop; delivery target; item spawning |
| CraftObjective | CraftObjective.cs | Multi‑state: Collect → Craft → Deliver; recipe management; contraband |
| InteractObjective | InteractObjective.cs | Interact with specific interactive object |
| DialogObjective | DialogObjective.cs | Speak to specific character; dialog lines |
| TriggerObjective | TriggerObjective.cs | Enter/stay in trigger zone for duration |
| SpeechObjective | SpeechObjective.cs | Player speech at specific time/place |
| CombatObjective | CombatObjective.cs | KnockOut/Punch/TieUp/CauseRuckus with timing |
| DestroyItemObjective | DestroyItemObjective.cs | Destroy specific item |
| DamageTileObjective | DamageTileObjective.cs | Damage wall/floor tiles with row/col/floor targeting |
| FloodToiletObjective | FloodToiletObjective.cs | Flood specific toilet |
| InventoryObjective | InventoryObjective.cs | Check inventory contents |
| OutfitObjective | OutfitObjective.cs | Equip specific outfit |
| PassiveDialogObjective | PassiveDialogObjective.cs | Overhear NPC conversation |
| JobDisruptionObjective | JobDisruptionObjective.cs | Disrupt a job (ruckus) |
| SetObjectiveArrowObjective | SetObjectiveArrowObjective.cs | Update quest arrow target |
| SpawnVendorObjective | SpawnVendorObjective.cs | Spawn/activate vendor |
| UseItemObjective | UseItemObjective.cs | Use item on specific target |
| WaitUntilTimeObjective | WaitUntilTimeObjective.cs | Wait until specific in‑game time |
| SwapBehaviourObjective | SwapBehaviourObjective.cs | Swap AI behaviour tree |
| PlayEscapeCutsceneObjective | PlayEscapeCutsceneObjective.cs | Trigger escape cutscene |
| EnableMultistageInteractionObjective | EnableMultistageInteractionObjective.cs | Enable multi‑stage interaction |
| EnableInGameMenuObjective | EnableInGameMenuObjective.cs | Force open in‑game menu |
| EnableInputObjective | EnableInputObjective.cs | Enable/disable player input |
| EnableInteractionObjective | EnableInteractionObjective.cs | Enable/disable specific interaction |
| SetRoutineObjective | SetRoutineObjective.cs | Change NPC routine |
| SetUsableItemObjective | SetUsableItemObjective.cs | Mark item as usable |
| MoveDeskObjective | MoveDeskObjective.cs | Move office desk |
| TutorialCompleteObjective | TutorialCompleteObjective.cs | Mark tutorial step complete |
AI Behaviour Conditions (Check*.cs)
NodeCanvas ConditionTasks used by job AI behaviour trees:
| Class | Category | Purpose |
|---|---|---|
CheckHaveItem | Items | Check if AI has required items (all/any, equipped) |
CheckCarryingObject | Jobs | Check if carrying object with expected tag |
CheckCarryObjectOnFloor | Jobs | Find carryable object on job room floor |
CheckJobColouredCarriable | Jobs | Check consumer for matching tag |
CheckDogBowlState | Jobs | Check DogBowl stage (NoBowl/HasBowl/HasFood/Ready) |
CheckWallTorchState | Jobs | Check WallTorch.TorchState |
CheckStonemasonDeskState | Jobs | Check StonemasonDesk state |
CheckItemProcessor | Jobs | Check if processor is idle/has finished item |
CheckObjectConsumer | Jobs | Check consumer idle/has item |
CheckMultiStageTransferStage | Jobs | Check multistage converter stage |
CheckItemTransferable | Items | Check if item can be transferred to interaction |
CheckInteractableReserved | Events | Check if interaction is reserved |
CheckIfHandymanActive | Action | Check if HandymanInteraction needs fixing |
CheckIfAllHandymansInactive | Action | Check no handyman interactions need fixing |
CheckHasTray | Events | Check if character has tray |
CheckHasOutfit | Events | Check if has default outfit |
CheckHasDefaultWeapon | Events | Check guard has default weapon |
CheckIsKnockedOut | Events | Check character KO state |
CheckIsBound | Events | Check character bound state |
CheckFlee | Events | Combat flee check (energy/health thresholds) |
CheckCurrentRoutine | Events | Check current base routine type |
CheckHavePatrol | Events | Check if patrol exists for current routine |
CheckAIEvent | Events | Check if matching AI event received |
CheckAlertness | Events | Check prison alertness level |
CheckCombatEnded | Events | Check if combat has ended |
CheckCrowdShowTime | Events | Check if crowd show time (CrowdNPC) |
CheckVisitorState | Events | Check visitor state via VisitorManager |
CheckCharacterRecievedVisitorGift | Events | Check if character received gift this free‑time |
CheckRollCallSpeech | Events | Check roll call speech state |
DoesServiceJobHaveWaitingCustomer | Jobs | Check ServiceCustomerViaProxyJob queue |
CheckIfHandymanActive/CheckIfAllHandymansInactive | Action | Handyman interaction active state |
AI Behaviour Initialisers (JobInit*.cs)
NodeCanvas ActionTasks that populate blackboard variables for AI job behaviours:
| Class | Job Type(s) |
|---|---|
HandyManJobInit | HandymanJob (dispensers, processors, required items/equipment) |
ItemProcessingJobInit | ProcessItemJob (dispensers, processors, collectors, pre‑craft, accepted items) |
ServiceItemJobInit | ServiceItemJob (dispensers, collectors, post‑dispenser craft items, collector accepted) |
CarryItemJobBehaviourInit | CarriedInputJob (carried object dispenser, required items, processors, collectors) |
StonemasonJobBehaviourInit | StoneMasonJob (dispensers, processors, desk, carving/pickup interactions) |
HorseshoeMakingJobInit | ExtendedProcessItemJob (dual processor A/B, collector accepted items) |
FarmingJobInit | GrowPlantJob (dispensers, processors, trowel/seeds/potted plant IDs) |
CanineJobInit | DogFoodJob (bowl dispensers, food dispensers, collectors, dog bowl/food IDs) |
RelightTorchesJobInit | RelightTorchesJob (dispensers, wall torches, lighter/fuel IDs) |
Job Interaction Types
| Interaction | Job | Minigame Type |
|---|---|---|
PlumberInteraction | Plumber | ThreadMill masher (unclog toilet) |
ElectricianInteraction | Electrician | Reading masher (fix fuse box) |
PaintingInteraction | Painter | SolitaryPotato masher (paint) |
TreeDecorationInteraction | TreeDecorator | SolitaryPotato masher (decoration) |
LuteInteraction | Minstrel | SolitaryPotato masher (NPC reactions) |
HorseshoeAnvilInteraction | Horseshoe | Reading masher (smelt horseshoe) |
FacePaintingInteraction | FacePainter | Reading masher (paint face) |
StonemasonCarvingInteraction | StoneMason | Minigame + auto‑pickup |
Save/Load Architecture
All jobs implement ISaveable with bit‑packed ulong[] serialization. The format:
- BaseJob: 1
ulong— status, employee ID, quota achieved, routine state - CustomerJob: +1
ulongheader (5‑bit customer count) + per‑customerulong[]data - ServiceCustomerViaProxyJob: + waiting customer IDs (12 bits each, up to 4 per
ulong) - HandymanJob: + active/fixed interaction IDs (12 bits each, up to 4 per
ulong), versioned (v0/v1) - StoneMasonJob: + desk state entries (12 bits ID + 4 bits state, up to 3 per
ulong) - DogFoodJob: + bowl stage entries (12 bits ID + 4 bits stage, up to 3 per
ulong) - RelightTorchesJob: + torch state entries (12 bits ID + 4 bits state, up to 3 per
ulong) - ProcessItemJob: + processor state via
ItemProcessorBase.Serialise()
Quests serialized via BinaryFormatter + JSON snapshots. QuestGiver serialized as 64‑bit bitfield (12 char ID, 12 player ID, 5 pool index, 7 timer, 3 type, 5 list index, 7 tree ID, 6 quest index, 4 tree high bits).
Key Patterns
- RPC‑first networking: All state mutations go through
[PunRPC]methods onT17NetView - Master‑client authority: Most job logic gated by
T17NetManager.IsMasterClient - Bit‑packed serialization:
BitFieldhelper packs small values (5–12 bits) intoulongs for efficient save files - Component‑based room config:
RoomBlob_JobRoomstores lists ofInteractiveObjectreferences for dispensers/processors/collectors, populated byJobRoom_ContentsMarkerin the editor - Behaviour tree AI: Each job type has a
BehaviourTreethat populates its blackboard viaJobInit*tasks, then usesCheck*conditions to decide AI actions - Quota system: Jobs track
m_QuotaTarget/m_QuotaAchieved. Completion triggersOnJobCompleteevents. Failure (missed job time) triggers officer heat increase - Pooled customers:
JobCustomerRequestermaintains available/taken pools. Customers are reused across job days