diff --git a/PLAN.md b/PLAN.md index 9a38685d..922a2ca4 100644 --- a/PLAN.md +++ b/PLAN.md @@ -6,6 +6,74 @@ When the GDD changes, update README.md first, then revisit this plan. When this --- +## 0. Vertical Slice (First Playable Demo) — milestone plan + +> Added 2026-05-30. This is the **active near-term target** and supersedes the linear Phase 1→10 ordering below as the working priority. The phased roadmap (§3) is still the long-range map; this section re-prioritizes it toward one goal: a playable build that proves the core loop is fun before we invest in breadth. + +### 0.1 Status re-audit (the §1 snapshot below is stale) + +A pass over the actual tree on 2026-05-30 shows the code is **well ahead** of §1. Corrections (verified by reading source, not inferred): + +- **Phase 1 — done.** `EClothingSlotType` is the locked 18-slot list (`Clothing/ClothingSlotType.h`). Item identity is a clean `UItemDefinition`/`UItemInstance` split with `CreateInstance`, `CreateFromRecord`, `ToSaveRecord` and stable GUIDs (`Items/`). `UClothingItemDefinition` dropped `IsUnderwear`/`IsRestrictive` and now carries a `Restrictions` list (`FClothingRestriction` + `ERestrictionType`), `CanExpose`, `ContainerSlots`, `CoveredBodyParts`, `HiddenBodyParts`. Toy items exist (`Items/SexToyItem` + `SexToyInstance`). `STARTING_MONEY` is applied at new-save creation; `Money` lives on the save. +- **Save — rearchitected, the "empty save" bug is gone.** `UGlobalSaveGameData` is now the durable state container with granular `Add/Update/Remove` for `WardrobeItems`/`EquippedItems`/`WorldItems` (all `FItemSaveRecord`). `USaveSubsystem::GetCurrentSave` creates + seeds a new save from `StartingSaveData`. `GameMode::BeginPlay` rehydrates world `AItemPickup`s from records with transforms. Round-trip architecture is in place. +- **Phase 2 — done.** `Interactables/ItemPickup` is the world item actor; drop/pickup + interaction (`Interaction/InteractionComponent`) exist. +- **Phase 3 — done.** `SessionManagerSubsystem` + `SessionLossResolver` as previously noted. +- **New since snapshot:** `Censorship/CensorshipComponent`, `Clothing/ClothingVisualsComponent` (runtime per-slot mesh spawning) + `ClothingSlotsData`, GASP-style movement enums (`Global/Gait|Stance|AirMode|MovementState`), and a full **UI layer** (`UI/HUDWidget`, `GameLayoutWidget`, `Inventory/*` panels, **`RadialMenu/*` = the §14.1 quick-action menu**). +- **Minor spec drift to fix when convenient:** `ERestrictionType` spells `BlockPhoneUse` as `BlockPhoneUsage` and splits the GDD's single `BlockExposeAction` into `BlockBoobsExpose`/`BlockVaginaExpose`/`BlockAnalExpose`. `FClothingRestriction` fields lack `EditDefaultsOnly` so they aren't author-editable in the asset. Not blocking the slice. + +§1 should be rewritten in a later pass; until then, trust §0.1 over §1 where they disagree. + +### 0.2 What the slice must prove + +One question: **is the risk-vs-reward exhibition loop (Pillar 1) fun, moment to moment?** Everything else is breadth we can add once that's validated. The slice is the smallest build that lets a playtester feel the core tension end-to-end: + +> From a cold save: wake in the apartment → dress at the wardrobe → accept a commission from the forum → step outside (**session starts**) → walk a populated street where NPCs observe you and **coverage-weighted embarrassment, lust, and pulse climb** → complete the commission's public-exposure objective → **money / XP / followers credit instantly** → either walk home safely (embarrassment decays, day ends, **autosave**) or fail the session (embarrassment-max / energy-zero / police) and get resolved home per §4.4. Sleep advances the day; the run survives save → quit → reload. + +If that loop reads as tense and rewarding on a greybox street, the design is proven. If it doesn't, no amount of casino/phone/path breadth will save it — so we find out now. + +### 0.3 Cut list (explicitly OUT of the slice) + +Deferred to post-slice phases. Do **not** build these for the demo: + +- Full phone & forum stack — battery, gallery, livestream, Feetex, maps, bank app, health tracker, phone models, Electronics Shop (§9, §9.8, §9.9, Phase 8). Replace with a **minimal commission-board widget** + the existing attribute HUD. +- 90-day calendar, weekly rent, eviction, endless mode, weekly missions, weekly follower auto-deposit (§2.4, §15.2, Phase 5). Slice uses a bare day counter only. +- Casino, gym, beauty salon, café, convenience store, adult shop (§10.4, Phase 10). Wardrobe buy-flow already covers "acquire clothing." +- GAS migration (§17.2, Phase 4) — keep the bespoke `StatsManager`. +- Procedural commission generation at scale, path-requirement filtering, `failurePenalty` tiers (§13.4, Phase 7) — slice hand-authors ~6–10 templates. +- Recognition→news pipeline, wanted posters, theft, rip & tear, restraint unlock minigame, food/cooking, bags, underwear selling, XP-spend/path-level UI, multiple phone tiers. +- Toys beyond the data model already present. + +### 0.4 Core code workstreams (priority order) + +Each `VS-n` is a vertical task with a concrete exit check. VS-1 is the gate — it unblocks the entire risk side and should land first. + +- **VS-1 — Coverage → embarrassment (THE dial).** Implement `ClothingManager::GetEffectiveCoverage(EBodyPart)` per §6.3.2 (`max()` of `CoveredBodyParts[b].Coverage` across equipped garments + active expose state; absent part = 0). Feed a per-part exposure weight into `StatsManager::SetObserved` and delete the `0.0f` stub (`StatsManager.h:43`, `StatsManager.cpp`). Day/night and recognition multipliers may be stubbed to `1.0` for now. **Exit:** standing nude in front of an NPC raises embarrassment visibly faster than standing fully clothed; per-garment coverage changes the rate monotonically. +- **VS-2 — Lust + Pulse (minimal).** Add `Lust`/`MaxLust` and `Pulse`/baseline to `StatsManager`. Passive lust gain; pulse rises on run / exposure events / observed-while-exposed and decays at rest; pulse multiplies embarrassment **and** lust gain (§7.5). Masturbate quick-action resets lust. **Gating (§23 #25): home masturbation is always available; in-session masturbation is Slut-path-gated.** For the slice the in-session entry can ship open if path investment isn't wired yet, but keep the home-vs-session split in mind so it's a config flip later, not a rewrite. **Exit:** the three attributes visibly interact in a playtest — running spikes pulse, which accelerates embarrassment gain; masturbating drops lust. +- **VS-3 — Expose action.** Radial-menu entry per equipped garment exposing the parts in its `CanExpose`; temporarily counts those parts as uncovered for VS-1 math; blocked when another garment covers the same part (§6.3.6). Reuses the existing `RadialMenu` + `ClothingManager`. **Exit:** flashing a coat in front of an NPC produces an embarrassment spike that ends when the expose ends. +- **VS-4 — Commission accept + instant reward.** Add the Accept lifecycle (commit on accept, no penalty when un-accepted) and **instant reward crediting on `OnMissionCompleted`** — money to the save, XP to the shared pool, followers stub (§13.1/§13.2/§23 #23). `MissionsManager` currently completes a mission but credits nothing (`MissionsManager.cpp:27-32`) — wire crediting here. Ensure the typed goals the slice needs exist (`BeFullyNaked`, `BeFullyNakedNearNPCs`, `ExposeBodyPart` — partially covered by `FlashGoal`/`ExposeBodyPartRestriction`). Surface it through a **minimal forum/board widget** (accept + active-objective tracker) reusing the existing UI layer. **Exit:** accept a commission, satisfy it in the world, see money/XP/followers tick up at the moment of completion with no return-home step. +- **VS-5 — NPC types + the session-loss threat.** Differentiate at least **Walker / Stalker / Blogger** by observation weight + behavior (Stalker = sustained stare, high embarrassment; Blogger = photo → recognition stub), plus a **Snitch → Police** beat that drives a real escape: Snitch report sets a chase, Police capture routes through the existing `SessionLossResolver` (`PoliceCapture`, `bPoliceChaseActive`). This is what makes the street a risk space (Pillar 1). **Exit:** the three civilian types feel distinct; a Snitch can trigger a police chase that ends in a §4.4 capture resolution. +- **VS-6 — Day loop.** A lightweight `TimeOfDaySubsystem` (or formalize the BP-driven `GameMode::OnHourChanged`): day phase 08:00–20:00, NPC density gated by phase (fix the `09–21` window in `NPCSpawner.cpp:40` and the `Hour==4` day-roll in `GameMode.cpp:54`). Sleep at the apartment bed advances the day, restores energy, and autosaves. Rent stays stubbed off. **Exit:** play a full day, sleep, wake on the next day with state intact. +- **VS-7 — Save round-trip across the loop (gate).** Validate equip/unequip, world drop, wardrobe, money, day index, and attribute snapshot survive save → quit → reload, exercising the loop end-to-end (this is the existing Phase 1 exit criterion, re-run against the live loop). **Exit:** §6.6 inventory table holds after each session-loss cause, and a mid-run reload reproduces the player's exact state. + +### 0.5 Art & content track (parallel — the long pole) + +Runs alongside the code track; the district + clothing set gate the first real playtest, so start them immediately. For Oleh / artist: + +- **One functional district.** Apartment interior (wardrobe, bed; charger spot optional) + a contiguous block of streets/alley with built nav mesh, NPC spawn points, and 2–3 commission landmarks. Greybox is acceptable for the slice, but it needs working collision, lighting, and a clear "apartment door = session boundary" threshold for the `ALocationTrigger`. +- **Clothing set spanning the coverage curve.** ~8–12 items across slots, authored from fully-covering → revealing → underwear so the VS-1 dial is actually testable, plus 1–2 expose-capable garments (coat / pleated skirt) for VS-3. Skeletal meshes + materials wired through `ClothingVisualsComponent`. Author `CoveredBodyParts` values deliberately (the "just underwear" discount lives in the numbers, §6.3.2 / §23 #20). +- **Player body states.** Base body + the existing censorship meshes + a clean nude state that reads correctly with the coverage system. +- **Exhibition animation set.** Montages for expose, masturbate, photo-react idle, and embarrassment reactions; NPC reaction anims (Walker glance, Stalker stare, Blogger photo, Snitch point/call). A shared retargeted GASP set is fine for the slice — these don't need to be bespoke yet. +- **3–5 NPC visual variants** so a crowd doesn't look cloned. +- **Minimal UI/audio.** Commission-board + objective-tracker widget art (reuse existing `UI/` + `Audio/UI` tone set), an observation/exposure stinger, and a camera-shutter SFX for Blogger photos. + +### 0.6 Sequencing, risks, and definition of done + +- **Critical path:** VS-1 → (VS-2, VS-3, VS-5 in parallel) → VS-4 board → VS-6 loop → VS-7 gate. VS-6 and the art track can run from day one independently. +- **Top risks:** (1) the coverage→embarrassment dial doesn't *feel* like risk even when wired — mitigate with the debug overlay (Phase 4 note) showing live modifier sources from VS-1 onward; (2) art content is the schedule driver, not code — lock the district + clothing scope early and greybox aggressively; (3) NPC density vs. perf on a populated street (§19) — cap spawns low for the slice, defer instanced-extras LOD. +- **Definition of done:** a first-time playtester completes the §0.2 walkthrough end-to-end in one sitting on the greybox district, the risk dial legibly tracks coverage/exposure, both a safe return and at least one loss cause resolve correctly, and the run persists across a save/quit/reload. When that's true, return to §3 for breadth (phone/forum, calendar/rent, NPC/recognition depth, paths, then the Phase 10 locations). + +--- + ## 1. Implementation status snapshot State of the C++ module as of the latest pass. File references use `Source/NakedDesire/...` paths. @@ -139,7 +207,7 @@ State of the C++ module as of the latest pass. File references use `Source/Naked - **Per-item `restrictions` list** replaces `IsRestrictive` boolean (§6.3.7). Granular vocabulary: `BlockRun`, `BlockCrouch`, `BlockPhoneUse`, `BlockItemPickup`, `BlockMasturbate`, `BlockExposeAction`, parameterized `BlockSlotChange(slot)`. Restrictions union across equipped items. - **Coverage math** is `max()` across garments covering a body part — not sum. No underwear halving; the `IsUnderwear` flag is removed entirely (§6.3.2). - **Hunger / max-energy decay (§7.3):** two-layer max energy — base (gym) and effective (decays via hunger, restored by eating). Eating any food triggers the restoration as a universal built-in effect. Sleep does not clear hunger. - - **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). (Note: the README has a current contradiction about home-masturbation for non-Slut players — see Working notes.) + - **Masturbation gating is home-vs-public** (§23 #25, resolved): home masturbation is always available to every player; *in-session* (public) masturbation is Slut-path-gated. Generator filters `PerformAction(masturbate)` (a public objective) for non-Slut players; the §14.1 quick-action shows the entry unconditionally at home and hides the in-session entry until the player has Slut investment (§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). **Rewards land instantly on completion** — money / XP / followers credit at the moment the commission completes; no return-to-home "collect rewards" step. Replace the manual `UMissionsManager::CollectRewards` flow with immediate crediting on `OnMissionCompleted`. @@ -221,7 +289,7 @@ Phase estimates are rough and assume one engineer. Adjust as we go. - 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). - **Hunger / max-energy decay (§7.3):** add a second layer to max energy. `baseMaxEnergy` (gym progression) stays; introduce `effectiveMaxEnergy` (decays at `maxEnergyDecayRate` per in-game hour toward a floor). Eating any food sets `effectiveMaxEnergy` back to `baseMaxEnergy` as a universal hook in the eat-item flow. Sleep does **not** reset hunger. Health Tracker (§9.7) surfaces effective max alongside current energy. - Implement `GetEffectiveCoverage(EBodyPart)` on `ClothingManager` per §6.3.2 — **`max()` across garments covering the part** (no sum, no underwear halving). Replace the `0.0f` stub in `StatsManager::TickComponent`. -- Lust → masturbate action (Slut-path gated, §7.2). Block the action in BP / quick-action when the player has no Slut investment. +- Lust → masturbate action (§23 #25): home masturbation always available; in-session (public) masturbation Slut-path-gated. Block only the in-session quick-action entry when the player has no Slut investment; the home entry is always live (§7.2 / §14.1). - **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` + `Eyes` slots** (§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. @@ -309,7 +377,7 @@ Phase estimates are rough and assume one engineer. Adjust as we go. - 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. +- Masturbation gating (§5.1, §7.2, §23 #25) — hide only the *in-session* quick-action entry until the player has at least one Slut-path upgrade; the home (apartment) entry is always available. **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. @@ -353,6 +421,6 @@ Use this section for in-flight decisions, blockers, and open questions that emer - **Hunger hookpoint also belongs in Phase 4.** Add `effectiveMaxEnergy` + decay tick when adding Lust / Pulse / etc., so Phase 10's food items only need to call an existing reset method. - **README contradiction — follower income cadence.** §7.9 line 433 says "Followers generate money each day"; §9.4 and §13.3 say weekly auto-deposit at week boundary. Don't pick one in code until the GDD is reconciled. Phase 5 implementation depends on resolution. - **README contradiction — hiding spots vs sleep loss.** §6.3.4's new "Hiding spots" bullet says items have a *chance* of theft after sleep, but §4.4 says sleep = guaranteed loss of anything outside. Phase 10 theft work must wait until the GDD resolves whether hiding spots are an explicit exception to the sleep rule or only affect in-session theft chance. -- **README contradiction — masturbation gating.** §7.2 says non-Slut players "must accept the max-lust handicaps... until they go home and masturbate in home before sleep" — but §5.1 has masturbation as a Slut-path unlock. Phase 4 masturbate-action work needs the spec reconciled: either home masturbation is universally available (with public masturbation gated by path) or non-Slut players cannot masturbate at all. +- **~~README contradiction — masturbation gating.~~ RESOLVED (2026-05-30, §23 #25).** Home masturbation is always available to every player; *in-session* (public) masturbation is the Slut-path unlock. README §5.1 / §7.2 / §6.7 / §13.4 / §14.1 and §20 #25 are updated. Phase 4 / VS-2 implementation: gate only the in-session quick-action entry on Slut investment. - **Stale §5.3 Slave path text** in the README still says "(cuffs require NPC help to remove)" — contradicts the Key + minigame removal flow. Phase 6 / Phase 10 work should not implement an NPC removal path; if encountered, treat it as stale documentation. - _empty beyond this point_ diff --git a/README.md b/README.md index 73d30fa4..b56e3213 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ On loss: The player chooses how they level up but is not locked into one path. **XP is a single shared pool** — every commission, mission, and stream feeds the same number. The player decides which path's attribute pool to spend it on. Given enough XP, every attribute on every path can be upgraded; there is no requirement to earn "Slut XP" before buying a Slut-path upgrade. ### 5.1 Slut -- **Unlocks:** revealing clothing (mini skirts, high heels, lingerie variants), masturbation action, masturbation-related missions. +- **Unlocks:** revealing clothing (mini skirts, high heels, lingerie variants), **public masturbation** (masturbating during a session, outside the apartment), masturbation-related missions. *Home masturbation is always available to every player regardless of path — see §7.2.* - **Attribute access:** lust-related attributes (max lust, lust gain rate modifiers, masturbation energy efficiency). - **Playstyle:** pushes lust as a resource. Risks blackout effects (§7.2). @@ -321,7 +321,7 @@ Food items live in the `UItemInstance` system (§6.1). They come from two source **Instant effects** (one-shot on consumption, no timer, per-food authored): - **Energy restore** — adds a fixed amount of current energy (§7.3), clamped to the (just-restored) effective max. -- **Lust decrease** — subtracts a fixed amount of lust. Particularly relevant for non-Slut players who cannot masturbate to reset lust (§7.2). +- **Lust decrease** — subtracts a fixed amount of lust. Particularly relevant for non-Slut players who cannot masturbate to reset lust *during a session* (§7.2). **Timed buffs** (run for a per-item duration): - **Stamina regen +** — raises `staminaRecoveryRate` above baseline (§7.4). The original ramen example. @@ -368,7 +368,7 @@ All attributes update in real time. Indoor and outdoor behavior is identical — - Blurred peripheral vision. - Player cannot tell whether NPCs are calling police or taking photos. - No indicator of which NPCs noticed them. -- Reset by **masturbating** (consumes more energy than usual, modified by `energyDrainMasturbateModifier`). Masturbation is a Slut-path unlock (§5.1) — players who haven't taken that path cannot reset lust within a session and must accept the max-lust handicaps above until they go home and masturbate in home before sleep. +- Reset by **masturbating** (consumes more energy than usual, modified by `energyDrainMasturbateModifier`). **Home masturbation — performed in the apartment — is always available to every player, regardless of path.** Masturbating *during a session* (outside the apartment) is a Slut-path unlock (§5.1); players who haven't taken that path cannot reset lust mid-session and must accept the max-lust handicaps above until they return home, where masturbation is always available. ### 7.3 Energy - Drained by all activity. Base rate plus modifiers: @@ -736,7 +736,7 @@ Typed objective steps (initial set): - `BeFullyNakedNearNPCs(count, durationSeconds)` - `WalkNakedDistance(meters)` - `MoveDistanceFromClothing(meters)` -- `PerformAction(actionId)` (e.g., masturbate) — actions with path gating are only used in templates whose `pathRequirement` matches; generator filter enforces this. +- `PerformAction(actionId)` (e.g., masturbate) — actions with path gating are only used in templates whose `pathRequirement` matches; generator filter enforces this. (Commission masturbation objectives are public / in-session, so they require the Slut path; the always-available home masturbation is never a commission objective.) - `BeObservedByNPCType(type, durationOrCount)` - `TakePhotoAtLocation(locationTag)` - `DeliverItemTo(npcOrLocation)` — the player must **source the item from their own inventory**. The commission does not auto-issue items on accept. Worn-underwear sales (§15.1) are the canonical use case. "Deliver this pre-issued package to X" is intentionally not supported by this primitive — if that flavor is needed later, add a separate `DeliverIssuedItemTo` step rather than overloading this one. @@ -771,7 +771,7 @@ Radial or hotbar accessible mid-session. Actions: - Expose body part (per garment with `canExpose`). - Open phone. - Drop bag / pick up bag. -- Masturbate (Slut-path unlock, §5.1 — entry hidden until unlocked). +- Masturbate. Always available at the apartment (home). During a session (outside the apartment) it is a Slut-path unlock (§5.1) — the in-session entry is hidden until unlocked. - Crouch / stand. - Open emote wheel (§14.5). @@ -974,6 +974,7 @@ Decisions previously open, now fixed: 22. **Restraint-removal unlock minigame.** DBD-style skill-check minigame (rotating pointer + target zone). Successful hits **speed up** the removal. Missed checks have **no penalty** — they just don't grant the speed bonus. The restraint always comes off when the baseline timer expires. No noise alerts, no key loss, no fail state. See §10.4.1. 23. **Commission rewards land on completion, not on return home.** Money wires to the bank instantly, XP credits to the shared pool, followers update on the profile. No "collect rewards" step at the apartment. See §13.1 / §13.2 / §4.3 / §3.1. 24. **Hunger via max-energy decay.** Effective max energy decays over time (a hunger rate); eating any food restores effective max to base max as a built-in universal effect (no per-food authoring). Sleep restores current energy but does NOT reset hunger — only eating does. Floors at a TBD fraction of base max so the player can't be starved into a forced game-over. See §7.3 / §6.7. +25. **Masturbation gating — home vs. public.** Home masturbation (in the apartment) is **always available to every player, regardless of path**. Masturbating *during a session* (outside the apartment) is a **Slut-path unlock** (§5.1). The §14.1 quick-action shows the masturbate entry unconditionally at home; in-session it is hidden until the player has Slut-path investment. Non-Slut players therefore cannot reset lust mid-session and rely on lust-decrease food (§6.7) or returning home. Commission `PerformAction(masturbate)` objectives are public and thus Slut-gated by the generator (§13.4). Resolves the prior §5.1 ↔ §7.2 contradiction. See §7.2 / §5.1 / §14.1. ## 21. Open Design Questions