36 KiB
Development Plan
Working document for Naked Desire implementation. Tracks current state vs. the GDD (README.md) and the phased roadmap. Update this file as state changes — code is the source of truth, this file is the navigation chart.
When the GDD changes, update README.md first, then revisit this plan. When this plan changes, keep phase exit criteria concrete so we know when to move on.
1. Implementation status snapshot
State of the C++ module as of the latest pass. File references use Source/NakedDesire/... paths.
1.1 Implemented
- Item identity scaffold (GDD §6.1) —
Items/ItemInstance.hdefinesUItemInstanceas an abstractUObjectwith a stableFGuid InstanceID, auto-assigned inPostInitPropertiesand refreshed inPostDuplicate.Clothing/ClothingItemInstance.hinherits from it and holds per-instanceCondition, a pointer to the immutableUClothingItemdefinition, and aStoredItemsarray for container slots. - Definition / instance split (GDD §6.1, §17.4) —
Clothing/ClothingItem.his the immutableUPrimaryDataAssetdefinition with GDD-aligned fields:Coverage,IsUnderwear,CanExpose,IsRestrictive,ContainerSlots(typed S/M/L viaEGarmentContainerSlotType+FGarmentContainerSlot),ProgressionPath, plus rendering data (SkeletalMesh,Materials,StaticMesh). - Progression path enum (GDD §5) —
Progression/ProgressionPath.hdefinesEProgressionPath { None, Slut, Exhibitionist, Slave }. Used onUClothingItem::ProgressionPath. - Body-part enum (GDD §6.3) —
Clothing/BodyPart.hdefinesEBodyPart { None, Boobs, Ass, Genitals }. Used onUClothingItem::CanExpose. - Save scaffolding (GDD §16) —
SaveGame/SaveSubsystem.h/.cpp(UGameInstanceSubsystem),SaveGame/ItemSaveRecord.h(generic{ InstanceId, Definition, Condition, ParentId }).Global/Constants.hnow usesDefaultSaveSlotNameinstead of a singleSLOT_NAMEmacro. - Observation-driven embarrassment (GDD §7.1) —
NPC/NPCAIController.cpp:56-69listens toOnTargetPerceptionUpdatedand forwards bSensed transitions toStats/StatsManager::SetObserved.Stats/StatsManager::TickComponent(StatsManager.cpp:23-38) now gates gain vs. decay onObserverCountinstead of unconditional decay. Foundation for Phase 4. - Modular character w/ per-slot meshes —
Player/NakedDesireCharacter.cpp:40-67creates 14 skeletal mesh components, one per currentEClothingSlotTypevalue. Aligns with GDD §17.6 in spirit; the specific slot list needs reshaping per §1.4 (locked 18-slot list now lives in GDD §6.5). - Equip / unequip / drop event —
Clothing/ClothingManager.cpp:88-163(slot-based, broadcastsOnClothingEquip / Unequip / DroppedwithUClothingItemInstance*). - Censorship toggle — compliance feature on
NakedDesireCharacter(BoobL/R,Front/BackBottomstatic meshes), driven byUNakedDesireUserSettings. - AI sight + behavior tree —
NPC/NPCAIController.cppruns a BT withPlayer/TargetLocation/SpawnLocationblackboard keys.NPC/NPCSpawner.cppproximity-gated spawn with day / night caps. - Mission framework —
Mission→MissionGoal→GoalRestrictioncomposition (MissionBuilder/). Two goals (FlashGoal,MinTimeGoal), three restrictions (EquipClothing,ExposeBodyPart,Location). Iterate-and-mutate bug inMissionsManager::RefreshDailyMissionsresolved (MissionsManager.cpp:53-68). - Daily-mission OOB guarded —
NakedDesireGameMode::RefreshDailyMissionsnow clampsDaysPassedto the authored array bounds (NakedDesireGameMode.cpp:70-71). Still a hand-authored list (see §1.3). - Location triggers —
Locations/LocationTrigger,Locations/LocationDatavia gameplay tags (GDD §10.4 area foundation). - Movement —
EnhancedInput, walk / run / crouch (NakedDesireCharacter.cpp:115-127), stamina-gated run (Ticklines 91-113). - Wardrobe interactable —
Interactables/Wardrobe.hholdsTArray<TObjectPtr<UClothingItemInstance>> ClothingItems;NakedDesireGameMode::BuyItemcharges money and pushes into the wardrobe.
1.2 Partially implemented (deviates from GDD)
- Save subsystem (GDD §16) — scaffolded but not actually wired through gameplay.
USaveSubsystem::SaveGame(SaveSubsystem.cpp:10-13) delegates toUGlobalSaveGameData::SaveGame, which creates a fresh emptyUGlobalSaveGameData(GlobalSaveGameData.cpp:45-53) and writes it — i.e., it does not capture the live player / wardrobe / world state at all.USaveSubsystem::LoadGamecalls the static loader but discards the result without applying it (SaveSubsystem.cpp:5-8).ClothingManager::HydrateClothing(ClothingManager.cpp:66-73) is an empty stub with the previous logic commented out. Exit criterion of Phase 1 (round-trip an item with modified condition) is not met yet. - Item identity → world (§6.1) —
UItemInstanceGUIDs exist, but no item has been promoted to a worldAActor.ClothingManager::DropClothing(ClothingManager.cpp:156-163) still only broadcastsOnClothingDropped— no spawn, no parent reassignment in any registry. - Attributes (§7) —
StatsManagercovers Embarrassment, Energy, Stamina with observation-driven gain now correctly tied to NPC perception. Missing: Lust, Pulse (§7.5), Recognition, Reputation, Followers, Wanted. Coverage weighting in the gain formula is stubbed at0.0fwith a TODO marker (StatsManager.cpp:30-32). Food-buff hookpoints (per-rate multipliers for stamina regen, embarrassment-gain resistance, lust-gain resistance — see GDD §6.7) are not in place; future Phase 10 work depends on the attribute simulation accepting external multipliers cleanly. - Coverage (§6.3.2) —
UClothingItem::CoverageandIsUnderwearexist on the definition, butClothingManager::IsBodyTypeExposed(ClothingManager.cpp:14-25) is still binary. NoGetEffectiveCoverage(EBodyPart)function, no underwear-halving, no sum-of-garments math. - Body-part enums — duplicated — both
Player/PrivateBodyPartType.h(EPrivateBodyPartType { FrontBottom, BackBottom, FrontTop }) andClothing/BodyPart.h(EBodyPart { Boobs, Ass, Genitals }) exist.UClothingItem::CoveredBodyPartsuses the old enum;UClothingItem::CanExposeuses the new one. Half-migrated. - Mission system — composable goals work but lacks the typed objective steps from §13.4 (
BeFullyNaked,BeFullyNakedNearNPCs,WalkNakedDistance,MoveDistanceFromClothing,BeObservedByNPCType,TakePhotoAtLocation,DeliverItemTo). Missions still hand-authored inMissionsConfig::DailyMissionskeyed by day index — no procedural generation, no Accept lifecycle (§13.1 / §13.2), no path-filtering on the generator (§13.4). - Day / night —
NPCSpawner.cpp:38-41readsGetCurrentTime().Hoursand gates spawn cap, but does not affect embarrassment gain, NPC type weighting, or police spawning (see §1.3).
1.3 Missing
- Session system (GDD §4) — no
USessionManager, no session start / end events, noUSessionLossResolver. Game-over on embarrassment is a singleEndGameEmbarrassedBP event inNakedDesireGameMode; none of §4.4's behavior (energy-zero cutscene to home, bag-placed-in-world loss, sleep-deterministic clothing loss, embarrassment-max → apartment with no extras) is implemented. - Three progression paths runtime (§5) — enum exists; no XP pool, no per-path level derived from investment, no path-gated unlocks at runtime, no level-up flow. XP is a single shared pool, not per-path (GDD §5, §7.10).
- Phone (§9) — entire system absent: camera, gallery, livestream, bank, Feetex, maps, health tracker. Includes the new sub-systems:
- Battery (§9.8) — passive base + per-app multiplier drain; apartment charger; portable powerbank consumable (Convenience Store); hard shutdown at 0%; mid-livestream cutoff with earnings-to-date deposited; sleep always charges to 100%.
- Livestream tip requests (§9.1.1) — viewer-driven action requests with phone popup (Accept / Decline + countdown); fail = viewer count drops, no rep hit.
- Livestream follower trickle (§9.1.1) —
streamQualityScoreticks throughFollowerGainCalculatorper tick. - Bank app income breakdown (§9.4) — line items by source incl. the weekly follower auto-deposit at week boundary.
PhoneSubsystem(§17.1) — tickable subsystem owning phone state (battery %, active app, livestream session lifecycle, charger interaction). Does not yet exist.- Forum (§13) — no
UCommissionTemplate, no procedural generation, no weekly missions distinct from daily, no profile (incl. weekly follower-income summary), no posting photos. Forum scope is locked minimal (board + own profile only, no threads / no other-users feed) — that's a non-build, but worth recording. - Photo & livestream — absent.
- NPC types (§10.2) — only one generic
ANPCclass. No Walker / Stalker / Blogger / Snitch / Harasser, no Police, no Wanted-poster mechanic. - Calendar, rent, sleep (§2.4, §15.2) —
DaysPassedincrements inNakedDesireGameMode::OnHourChanged(4), but no week, no rent, no eviction, no sleep action, no apartment bed interaction. - Item-world AActor (§6.1) — no
AItemActor/AClothingPickupbase. - Bag inventory (§6.4) — absent.
- Theft (§6.3.4) — new chance-based model (per-tick
P_theftafter grace period) not implemented. No theft timer / probability code at all. - Rip & tear (§6.3.5) — absent.
UClothingItemInstance::Conditionis read-only in code; no decrement source. - Expose action (§6.3.6) —
CanExposedata exists on the definition; runtime action absent. - Restrictive clothing (§6.3.7 / §10.4.1) —
IsRestrictivefield exists; no enforcement of hand-action locks, no Key-based unlock flow. - Bodysuit exclusion rule (§6.5) — when implementing the new slot enum,
ClothingManagermust auto-unequipTop/Bottom/UnderwearTop/UnderwearBottomon bodysuit equip, and vice versa. - Toy slots (§6.5) —
Nipples,Anal,Vaginaare now toy slots (not body-clothing slots, not body-parts conflict). Independent; all three can be active. Items in these slots are sex toys from the Adult Shop (§10.4), follow standard item-identity rules, do not contribute to coverage, and may modify lust / embarrassment / pulse plus add audible vibration NPCs may detect. - Adult shop, gym, beauty salon, café, convenience store — none.
- Food / consumables (§6.7) — absent. Vocabulary now locked: 2 instant effects (energy restore, lust decrease), 4 timed buffs (stamina regen +, max stamina +, embarrassment-gain resistance, lust-gain resistance). Stacking: different types parallel; same type additive up to per-type cap. Cooking minigames (slice / stir / cook) modulate buff strength; never poison.
- Recognition, wanted state, news (§7.6–§7.7, §11.1) — absent. Face-cover bypass via
FaceandEyesslots is part of this work. - Underwear selling (§15.1) — absent. Backed by the
DeliverItemTotyped objective (player-owned source only, §13.4). - Endless mode flag (§3.3) — absent.
- Pulse attribute (§7.5) — absent (new in the updated GDD).
- GAS adoption (§17.2) —
StatsManageris still a bespokeUActorComponent; noUAttributeSet, noGameplayEffect-driven modifiers.
1.4 Conflicts to resolve
-
SaveGameUPROPERTY typo —GlobalSaveGameData.h:35declaresUPROPERTY(SaceGame)instead ofSaveGameonDaysPassed. The field will not serialize. -
USaveSubsystem::SaveGamewrites an empty save — does not pull state from the live world before writing (SaveSubsystem.cpp:10-13,GlobalSaveGameData.cpp:45-53). Any "save" call at present destroys progress. Highest-priority correctness bug. -
USaveSubsystem::LoadGameignores the loaded object — static returns a populatedUGlobalSaveGameData; subsystem stores / applies nothing. -
EClothingSlotType— concrete reshape to the locked 18-slot list (GDD §6.5)Current enum (
Clothing/ClothingSlotType.h, 14 values):Nipples, Anal, Vagina, Head, Neck, Face, Eyes, Body, Top, Bottom, Bra, Panties, Socks, Shoes.Target (18 slots, 4 groups): see GDD §6.5. Migration table:
Current Target Action TopTopKeep BottomBottomKeep BraUnderwearTopRename PantiesUnderwearBottomRename BodyBodysuitRename + enforce exclusion with Top/Bottom/UnderwearTop/UnderwearBottomSocksSocksKeep ShoesFootwearRename — OuterwearAdd HeadHeadKeep FaceFaceKeep (now a face-cover slot per §7.6) EyesEyesKeep (now a face-cover slot per §7.6) NeckNeckKeep — WristRestraintAdd — AnkleRestraintAdd — NeckRestraintAdd (distinct from cosmetic Neck; auto-exclusion is not enforced — content authoring handles visual collision)NipplesNipplesKeep — now a toy slot, not a body-clothing slot AnalAnalKeep — now a toy slot VaginaVaginaKeep — now a toy slot Net: 14 → 18 (4 renames, 4 additions, 3 semantic repurposes).
NakedDesireCharacter::SetupClothingSlots(NakedDesireCharacter.cpp:357-433) needs four new mesh components added and four existing components renamed in lockstep with BP references inContent/Blueprints/Player.Bodysuit exclusion is a runtime rule on
ClothingManager::PutOnClothing— equipping a bodysuit must un-equip the four body slots; equipping any of those four must un-equip a present bodysuit.Toy slots are independent and stackable; their items are sex toys (not clothing) but use the same
UItemInstancemodel. TheUClothingItemdata class is named for clothing — aUSexToyItem(or similar)UItemInstancesubclass may be cleaner than reusingUClothingItemfor toys, since the toy effects (lust modifier, embarrassment modifier, pulse modifier, NPC-audible vibration) don't map onto clothing's coverage /CanExpose/IsRestrictivemodel. -
Two competing body-part enums —
EPrivateBodyPartTypevs.EBodyPart.ClothingItem::CoveredBodyPartsuses one,ClothingItem::CanExposeuses the other. The censorship / observation code paths inNakedDesireCharacterandClothingManagerare still onEPrivateBodyPartType. Pick one (recommendEBodyPart) and migrate. -
UClothingListforward-declared inGlobalSaveGameData.h:11;Wardrobeand save records no longer use it. Dead reference; remove. -
Moneyrepresentation —ANakedDesireCharacter::Moneyisint(NakedDesireCharacter.h:132);UGlobalSaveGameData::Moneyisfloat(GlobalSaveGameData.h:27). Pick one authoritative location and one type. -
STARTING_MONEYmacro defined inConstants.h:8but unreferenced. Either wire it into save / character init or remove. -
ClothingItemInstancehas no public constructor / factory —ClothingItempointer isprotectedwith noInit(UClothingItem*). Wardrobe / BuyItem flows rely onEditAnywhere Instanceddesign-time population, which won't support runtime purchase or save-driven hydration. -
StatsManager::TickComponentenergy drain — drains energy at a flat0.9fper tick (StatsManager.cpp:26) regardless of activity. GDD §7.3 specifies per-activity modifiers. -
NPCSpawnerday window — usesHours >= 9 && < 21for "day" (NPCSpawner.cpp:40); GDD §10.1 says08:00–20:00. Off by one hour on each end. -
GDD shifts not yet reflected in code:
- Loss resolver must not strip equipped clothing (§4.4).
- Energy = 0 must trigger a "cutscene → apartment → sleep" flow, not a teleport (§4.4).
- Embarrassment = max must fade to apartment with no extra cost (no time skip, no money penalty, no rep hit) — GDD §4.4.
- Theft is a chance-based model with grace periods and flat per-tick
P_theft, not a ramping curve (§6.3.4). - Sleep is the deterministic side of clothing loss — guaranteed loss of every clothing item left outside the apartment (§4.4).
- No Helper NPC; restraint removal is Key + timed unlock only (§10.4.1).
- Masturbation is Slut-path gated — generator must filter
PerformAction(masturbate)for non-Slut players; quick-action entry must hide until unlocked (§5.1 / §7.2 / §14.1). - Police spawn day and night while
wanted(§7.7 / §10.3). - XP is a single shared pool, not per-path — Phase 9 implementation must use a shared XP counter; a path's level is derived from how many upgrades the player has bought from that path's attribute pool (§5, §7.10).
- Commission lifecycle: explicit Accept required for daily and weekly; un-accepted commissions carry no penalty; weekly rewards now include followers (§13.1 / §13.2).
- Commission generator must respect
pathRequirement(incl.None= path-neutral) and filter templates whose steps reference path-locked actions (§13.4).failurePenaltyfield is canonical; generator supplies tier-scaled default when empty. DeliverItemTomust source from player inventory only; commission does not auto-issue items. Worn-underwear sales (§15.1) are the canonical use case (§13.4).- Livestream → follower trickle via
FollowerGainCalculatorper tick; signed by reputation. Tip requests give an additional bonus on completion (§9.1.1 / §13.5). - Locations locked for launch: Beach + Train Station are in; School exterior and Hot springs were cut. Vertical slice is the basic shop set only (§10.4, §18.1).
- Food vocabulary locked: 2 instant effects + 4 timed buffs; same-type stacks additively up to a cap; never poison (§6.7).
2. Architectural premise
The item-identity rule (§6.1) and the save contract (§16.3) are still load-bearing. With the definition / instance split in place, the next bottleneck is wiring serialization through gameplay: condition mutation, world drops, container parent links, hydration on load. Until that round-trip works, content on top of the current system has no durable home.
The session-system + loss resolver (Phase 3) is the second pin. Several GDD shifts (equipped-never-dropped, energy-zero cutscene, embarrassment-max no-extras, sleep-deterministic clothing loss) move complexity from §4.4 prose into a single deterministic resolver. Build it once, well.
GAS adoption (§17.2) remains deferred until Phase 4. Adding new attributes to the bespoke StatsManager in the meantime is fine — keep them additive and easy to migrate. Food buffs (§6.7) are external multipliers on attribute rates, so design the per-rate interface with that in mind even before GAS lands.
3. Phased roadmap
Phase estimates are rough and assume one engineer. Adjust as we go.
Phase 1 — Finish item identity + save round-trip; reshape slot enum (1–2 weeks)
- Fix the
SaceGameUPROPERTY typo onDaysPassed(GlobalSaveGameData.h:35). - Add
UClothingItemInstance::Init(UClothingItem* Definition)(or static factory) so instances can be constructed at runtime. - Make
USaveSubsystem::SaveGameactually capture live state intoUGlobalSaveGameData: player money, equipped items, wardrobe items, calendar, observation-attribute snapshot. PopulateFItemSaveRecordfrom current instances. - Make
USaveSubsystem::LoadGameactually apply the loaded data: rebuild instances from records, push into wardrobe +ClothingManagerslots. Replace the commented-outClothingManager::HydrateClothingwith real hydration. - Unify
EPrivateBodyPartTypeandEBodyPartonEBodyPart. MigrateClothingItem::CoveredBodyParts,ClothingManager::IsBodyTypeExposed, censorship paths inNakedDesireCharacter, BT / observation paths. - Reshape
EClothingSlotTypeto the locked 18-slot list (§1.4 table). AddOuterwear,WristRestraint,AnkleRestraint,NeckRestraint. RenameBra → UnderwearTop,Panties → UnderwearBottom,Body → Bodysuit,Shoes → Footwear. Add four newUSkeletalMeshComponents inNakedDesireCharacterfor the new slots. Update BP references in lockstep. - Implement Bodysuit exclusion in
ClothingManager::PutOnClothing(auto-unequipTop/Bottom/UnderwearTop/UnderwearBottom; vice versa). - Define toy items: either a new
USexToyItem : UItemInstance(recommended) or extendUClothingItemwith a toy variant. Toy items targetNipples/Anal/Vaginaslots, carry lust / embarrassment / pulse modifier fields, and an optional NPC-audible-vibration flag. Do not contribute to coverage. - Money: pick one authoritative location (
UGlobalSaveGameData), makeANakedDesireCharacter::Moneya read-through. ApplySTARTING_MONEYat new-save creation. Reconcile int vs. float. - Remove dead
UClothingListforward declarations.
Exit criteria:
- Item dropped at runtime, condition modified, save → quit → load reproduces the same
FGuid, condition value, and slot / wardrobe membership. EBodyPartis the only body-part enum in use.EClothingSlotTypematches the §6.5 18-slot list. Bodysuit exclusion is enforced at runtime. Toy slots work with at least one placeholder toy item.- A new game starts with
STARTING_MONEYand rent / purchase flows debit the canonical money field.
Phase 2 — World item actors + drop / pickup (1 week)
AItemActorbase wrapping aUItemInstance*(inItems/). Spawn transform, owning instance pointer, SaveGame-tagged.AClothingPickup : AItemActorwith a visual representation (UClothingItem::StaticMeshwhen set, fallback to skeletal mesh impostor).- Hook
ClothingManager::DropClothingto spawnAClothingPickupat the player location with the actual instance reference — not a template copy. Reparent the instance from "equipped slot" to "world". - Pickup interaction via existing
UInteractionManager+IInteractionTarget. Pickup re-parents the instance into wardrobe or directly into the matching slot. USaveSubsystemextension: serializeAClothingPickups asFItemSaveRecords with world transform.
Exit criteria: unequip → world pickup actor appears → save / reload → pickup still there at the same transform with the same instance ID → pick up restores the same instance to the slot.
Phase 3 — Session system + loss resolver (1 week)
USessionManager(subsystem onUNakedDesireGameInstanceor aUWorldSubsystem). ApartmentALocationTriggerflag drives session start / end. EmitsOnSessionStart/OnSessionEndwith cause.USessionLossResolver— single class, one methodResolveLoss(ESessionLossCause Cause). Implements GDD §4.4:- Equipped clothing stays equipped (do not strip).
- Bag placed in world: mark its world record for deletion.
- Loose clothing on ground: leave as-is at this stage; sleep step finalizes any guaranteed loss.
- Energy = 0: trigger a cutscene → apartment → sleep cycle → guaranteed loss of every world clothing outside the apartment.
- Embarrassment = max: fade to apartment. No extra cost (no time skip, no money, no rep).
- Police capture: fade to apartment, deduct money penalty, queue skipped days for the unpaid remainder, clear
wanted.
- Wire
StatsManager::IncreaseEmbarrassmentmax-hit and energy-zero intoUSessionLossResolver. ReplaceEndGameEmbarrassedBP-event with the C++ path. - Add a debug overlay showing the current loss state and what would be lost if a given cause fired.
Exit criteria: all four code paths (safe end, embarrassment max, energy zero, police capture) produce the §4.4 outcomes deterministically. Inventory state after each loss matches the §6.6 summary table 1:1.
Phase 4 — Attributes refactor (1–2 weeks)
- Decision: GAS vs. extended
StatsManager. Recommend GAS — the embarrassment formula has Pulse, Recognition, Coverage, Day/Night, per-NPC-type weights, and food-buff multipliers (§7.1, §6.7), which is exactly whatUGameplayEffectis shaped for. - Add Lust (§7.2), Pulse (§7.5), Recognition (§7.6), Wanted (§7.7), Reputation (§7.8), Followers (§7.9). Money remains in the save schema directly (non-attribute side effects).
- Implement
GetEffectiveCoverage(EBodyPart)onClothingManagerper §6.3.2 (sum of garments covering the part, underwear halved, clamped to 1.0). Replace the0.0fstub inStatsManager::TickComponent. - Lust → masturbate action (Slut-path gated, §7.2). Block the action in BP / quick-action when the player has no Slut investment.
- Pulse simulation: rises with running, masturbation, exposure events; decays toward baseline at rest. Modifies embarrassment and lust gain rates (§7.5).
- Recognition rise from Blogger photo events; face-cover bypass via
Face+Eyesslots (§7.6); reduction via news-site reporting (§11.1). - Define the per-rate multiplier interface that food buffs (§6.7) and toy effects (§6.5) will hook into. Don't ship the buffs here; just leave the seams.
- Debug overlay extension: live values + active modifier sources for every attribute.
Exit criteria:
- Observed-while-exposed embarrassment gain reads coverage and modifiers from the attribute system (no more
0.0fstub). - Lust + Pulse simulate correctly and visibly influence embarrassment in a playtest scenario.
- Recognition increases after a (mocked) photo event and decreases after a news-report action. Face-cover slot occupancy reduces recognition gain.
Phase 5 — Time + calendar + rent + sleep (3–4 days)
UTimeOfDaySubsystemreplacing the BP-implementable time onNakedDesireGameMode. 90-day calendar, week boundary, day phase08:00–20:00(fix the09–21mismatch inNPCSpawner.cpp:40).- Sleep action on apartment bed: triggers the same path as energy-zero (§4.4) for the "items left outside" cleanup, restores energy, autosaves, advances calendar.
- Weekly rent transaction at week boundary; eviction if money insufficient (game over (run), §3.3).
- Weekly follower-income auto-deposit to the bank at week boundary (§7.9, §9.4).
- Endless-mode flag on
UGlobalSaveGameData; rent-eviction branch checks it.
Exit criteria: play through 7 in-game days, get charged rent at the week boundary, eviction triggers on insufficient funds, endless-mode disables eviction, weekly follower income lands in the bank.
Phase 6 — NPC types + recognition pipeline (1–2 weeks)
ENPCTypeenum, type-specific BT branches or per-type controller subclasses: Walker / Stalker / Blogger / Snitch / Harasser. No Helper.- Police as a separate AI controller / spawn pipeline. Patrols spawn day and night while
wanted(§7.7 / §10.3). Detection logic (face hidden? + coverage threshold) → chase → break-LOS timer. - Wanted-poster mechanic: spawn posters in the city; tearing all down clears
wanted(§10.3). - Recognition flow: Blogger sight + photo event → article → news-site article state → "report" reduces recognition.
- Wire Snitch's "report to police" → immediate police spawn this session + sets
wanted(§7.7).
Exit criteria: every listed NPC type observably distinct; recognition rises after a Blogger event and can be reduced via news report; Snitch report triggers police spawn and the wanted tag that persists across sessions until posters torn down or capture.
Phase 7 — Commission template system + accept lifecycle (1–2 weeks)
- Replace
MissionsConfig's hand-authored daily list withUCommissionTemplate+ procedural generation per §13.4. - Add typed objective steps as new
UMissionGoalsubclasses:BeFullyNaked(duration)BeFullyNakedNearNPCs(count, duration)WalkNakedDistance(meters)MoveDistanceFromClothing(meters)BeObservedByNPCType(type, durationOrCount)TakePhotoAtLocation(locationTag)(gated by Phase 8 phone work)DeliverItemTo(npcOrLocation)— player-owned inventory only (§13.4); the commission does not auto-issue items.PerformAction(actionId)— generator filters path-locked actions (e.g.,masturbateis Slut-only).
- Accept lifecycle (§13.1 / §13.2):
- Both daily and weekly require explicit Accept on the forum.
- Un-accepted commissions carry no penalty; accepted-but-failed apply the template's
failurePenalty. - Weekly rewards include followers; weekly
failurePenaltyis heavier than daily.
- Generator rules: respect
pathRequirement(incl.None); filter path-locked-action templates by player path investment; substitute a tier-scaled default penalty whenfailurePenaltyis empty.
Exit criteria: daily commissions regenerate from templates each in-game day; weekly arc is distinct; explicit Accept committed flow works end-to-end; failed accepts deduct the template penalty; un-accepted commissions never penalize the player.
Phase 8 — Phone + forum UI + battery + livestream (3–4 weeks)
- Phone as an
AItemActor(Phase 2 base) with hand / pocket / bag location semantics (§9). PhoneSubsystem(§17.1): tickable; owns battery %, active app, livestream session lifecycle, charger interaction.- Battery (§9.8):
- Passive base drain + per-app multiplier (Forum/Bank/Maps/Health Tracker/Gallery ~1×, back-camera ~3×, livestream ~5×). Livestream stacks on top of foreground app.
- Apartment charger interactable: place phone on it, recharges at a fixed rate.
- Portable powerbank: consumable
UItemInstancepurchasable at Convenience Store (§10.4). Single-use, restores fixed % when consumed. S-size container slot. - Hard shutdown at 0%: all apps lock; livestream ends and deposits earnings-to-date; future tips forfeit. Phone wakes from a consumed powerbank.
- Sleep auto-charges to 100% (voluntary or energy-zero cutscene).
- Battery % is part of the phone's
UItemInstancestate; persists across saves.
- Apps: Camera + Gallery, Livestream, Bank, Feetex, Maps, Health Tracker, Forum.
- Bank app income breakdown (§9.4): line items by source — commissions, livestream donations, in-stream tip-request completions, underwear sales, weekly follower auto-deposit.
- Livestream (§9.1.1):
UStreamSessiontickable UObject — works while phone is held OR placed.- Per-tick
streamQualityScore→FollowerGainCalculatorfor the follower trickle (signed by reputation; shrinks at negative rep). - End-of-stream deposits both money and accumulated follower delta.
- Tip requests: phone popup with Accept / Decline + countdown. Accept = spawn live objective tracker (reuse Phase 7 primitives). Complete = tip lands + small follower bonus. Fail = viewer count drops (less passive income for the remainder); no rep hit. Decline / timeout = no effect.
- Photo system: render-to-texture (§17.6 / §21 Q5 — recommended).
- Wire
TakePhotoAtLocationcommission step to actual photo events.
Exit criteria: end-to-end photo loop (capture → gallery → post → follower count updates). Livestream can be started, run while the phone is placed, generate trickle followers + donations, accept and complete a tip request for a bonus, end with payout. Battery drain visibly different per app; charger and powerbank both restore charge; 0% hard-shutdown behaves correctly.
Phase 9 — Path progression + content authoring (2 weeks)
- Single shared XP pool — not per-path. Add
XPto the save schema. Player invests XP via the forum profile (§13.3) into any path's attribute pool. - A path's level is derived from how many upgrades the player has purchased from that path's pool (§5.4 / §7.10) — there is no per-path XP counter.
- Level-gating on clothing (§5.1–5.3) and on path-tagged commission templates (§7).
- Author the vertical-slice content set from GDD §18.1 (15–20 clothing items, 3 bag variants, 8 food items, 20 commission templates, 1 functional district).
- Masturbation gating (§5.1, §7.2) — hide the quick-action entry until the player has at least one Slut-path upgrade.
Exit criteria: all three paths have at least 5 unlockable items and 3 path-specific commission templates. Slut-path-locked actions correctly hidden until the player invests. XP spent into one path raises that path's level without consuming XP that could go to another path.
Phase 10 — Remaining systems & polish
- Bag inventory (§6.4) — uses Phase 2's
AItemActorfor world placement. - Food (§6.7):
- Implement the locked vocabulary: 2 instant effects (energy restore, lust decrease) + 4 timed buffs (stamina regen +, max stamina +, embarrassment-gain resistance, lust-gain resistance).
- Stacking: different types parallel; same type additive to a per-type cap.
- Three cooking minigames (slice / stir / cook); scoring modulates buff strength; never poison.
- Gym / beauty salon / adult shop / café / convenience store (§10.4). Convenience Store stocks powerbanks (Phase 8 dep). Adult Shop stocks toy items for the three toy slots (Phase 1 dep).
- Rip & tear (§6.3.5).
- Theft model (§6.3.4) — implement
T_grace/T_grace_baggrace timers and per-tickP_theftchance roll. No ramp. - Expose action (§6.3.6) — read
CanExposeper garment, blocked by overlapping coverage. - Restrictive-clothing flow (§6.3.7 / §10.4.1) — Key + timed unlock action. Lock hand-dependent actions while restrained.
- Underwear selling (§15.1) — Feetex drop-box or location drop-off variant. Backed by
DeliverItemTo(npcOrLocation)from Phase 7. - Wanted-poster takedown (§10.3) — interaction + spawn placement pass.
- Beach + Train Station locations (§10.4) for full-launch scope.
- Final tuning of all §21 numbers (theft, food caps, battery, tip-request distribution, embarrassment / lust / energy / pulse rates, face-cover magnitudes, etc.).
4. Working notes
Use this section for in-flight decisions, blockers, and open questions that emerge during a phase. Move resolved items into the README's §20 "Resolved Design Decisions" or into git history.
- Phase 1 critical path: the save-write-without-state bug is the most damaging current issue — any "save" call destroys progress. Fix the SaveSubsystem before anything else builds on save behaviour.
- Body-part enum migration: the existing censorship code in
NakedDesireCharacter::OnClothingEquip/OnClothingUnequipreadsEPrivateBodyPartType. Migration toEBodyPartmust update that path or the censorship visibility will silently desync. - Slot-vocabulary reshape will break BP references — coordinate before renaming/adding values in
EClothingSlotType. The character constructor creates skeletal-mesh components keyed to those names; expect BPs inContent/Blueprints/Playerto need a touch. - Toy items vs. clothing items: the
UClothingItemschema (coverage,CanExpose,IsRestrictive) doesn't fit sex toys cleanly. Strongly recommend a separateUSexToyItem : UItemInstance(withLustModifier,EmbarrassmentModifier,PulseModifier,VibrationAudiblefields) rather than overloadingUClothingItem. Decide before Phase 1 toy work begins. - XP is a single shared pool (GDD §5, §7.10). Do not introduce per-path XP counters in Phase 9 or earlier — a path's level is derived from how much the player has invested into that path's attribute pool.
- Food buff hookpoints belong in Phase 4 (attribute multiplier interface), even though the food items themselves ship in Phase 10. Leave the seams; don't retrofit later.
- empty beyond this point