From fd040d6a015fb0cc85aa779a99eb98bdfdbbf32a Mon Sep 17 00:00:00 2001 From: koritsa Date: Sun, 31 May 2026 22:37:48 +0300 Subject: [PATCH] Updated documentation --- PLAN.md | 7 ++++--- README.md | 20 ++++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/PLAN.md b/PLAN.md index 90c3e286..24838ebb 100644 --- a/PLAN.md +++ b/PLAN.md @@ -96,7 +96,7 @@ State of the C++ module as of the latest pass. File references use `Source/Naked - **Session manager (GDD §4.1–§4.4)** — `Global/SessionManagerSubsystem.h/.cpp` (`UWorldSubsystem`). Tracks `bSessionActive`, emits `OnSessionStart` / `OnSessionEnd(ESessionLossCause)`; `ESessionLossCause = { SafeReturn, EmbarrassmentMax, EnergyZero, PoliceCapture }`. Apartment `ALocationTrigger` starts a session on exit and safely ends it on re-entry. Subscribes (next-tick after world begin play) to `UStatsManager::EmbarrassmentUpdate` (max-hit → `EmbarrassmentMax`) and `EnergyUpdate` (≤0 → `EnergyZero`). Exposes `bPoliceChaseActive` (+ setter / getter) for the §4.4 loss-precedence rule the resolver owns. Replaces the old `EndGameEmbarrassed` GameMode BP call, which `UStatsManager::IncreaseEmbarrassment` no longer invokes. The `EndGameEmbarrassed` BlueprintImplementableEvent declaration still exists on `ANakedDesireGameMode` but is now dead from C++ and should be removed once BP no longer references it. - **Session loss resolver (GDD §4.4)** — `Global/SessionLossResolver.h/.cpp` (`UWorldSubsystem`). Single entry point `ResolveLoss(ESessionLossCause)`, bound to `USessionManagerSubsystem::OnSessionEnd`. Applies the police-chase precedence override (any cause → `PoliceCapture` while `bPoliceChaseActive`), then per cause: `EmbarrassmentMax` no-cost; `EnergyZero` destroys every world `AItemPickup` + clears its save record (guaranteed sleep loss); `PoliceCapture` deducts `PoliceCaptureMoneyPenalty` if affordable else flags a holding-cell outcome; `SafeReturn` no loss. Never strips equipped clothing. Autosaves, then broadcasts `OnSessionLossResolved(FinalCause, bWentToHoldingCell)` for the BP presentation / time-skip layer. See §1.3 for the pieces still delegated to BP / later phases. - **Movement** — `EnhancedInput`, walk / run / crouch (`NakedDesireCharacter.cpp:115-127`), stamina-gated run (`Tick` lines 91-113). -- **Wardrobe storage + management** — `Inventory/InventorySubsystem` (`UGameInstanceSubsystem`) is the single runtime owner of the off-body store. It holds live `UItemInstance`s mirrored from `UGlobalSaveGameData::WardrobeItems` and exposes the atomic moves `AddToWardrobe` / `RemoveFromWardrobe` / `EquipFromWardrobe` / `UnequipToWardrobe`, each mutating the wardrobe + equipped save buckets together and broadcasting `OnWardrobeChanged`. `AClothingManager` stays the body-state authority (owns the `EquippedItems` bucket via the new `EquipSlot` + existing `RemoveClothing`); the bodysuit exclusion rule is now the shared static `UClothingManager::GetBodysuitExcludedSlots` and routes displaced garments back to the wardrobe instead of dropping them to the world. `AWardrobe` is reduced to an interaction shell that forwards to the subsystem (its stale `ClothingItems` array is gone). UI: `WardrobeScreenWidget` inits the inventory list and hosts the `EquipmentSlotMenuWidget` popup (same plumbing as `InventoryScreenWidget`); `WardrobeInventoryWidget` renders the live list and re-renders on `OnWardrobeChanged`; clicking a wardrobe item calls `EquipFromWardrobe`. The slot menu has a single Remove button whose `Init(slot, bAtWardrobe)` flag decides the action — store via `UnequipToWardrobe` when opened at the wardrobe, drop to the world otherwise. **Follow-ups:** `BuyItem` buy-flow not reattached (no caller yet); world pickup (`ItemPickup`→`TakeClothing`) still doesn't clear the `WorldItems` record; non-clothing wardrobe items (phones/toys) are stored but not yet rendered. +- **Wardrobe storage + management** — `Inventory/InventorySubsystem` (`UGameInstanceSubsystem`) is the single runtime owner of the off-body store. It holds live `UItemInstance`s mirrored from `UGlobalSaveGameData::WardrobeItems` and exposes the atomic moves `AddToWardrobe` / `RemoveFromWardrobe` / `EquipFromWardrobe` / `UnequipToWardrobe`, each mutating the wardrobe + equipped save buckets together and broadcasting `OnWardrobeChanged`. `AClothingManager` stays the body-state authority (owns the `EquippedItems` bucket via the new `EquipSlot` + existing `RemoveClothing`); the bodysuit exclusion rule is now the shared static `UClothingManager::GetBodysuitExcludedSlots` and routes displaced garments back to the wardrobe instead of dropping them to the world. `AWardrobe` is reduced to an interaction shell that forwards to the subsystem (its stale `ClothingItems` array is gone). UI: `WardrobeScreenWidget` inits the inventory list and hosts the `EquipmentSlotMenuWidget` popup (same plumbing as `InventoryScreenWidget`); `WardrobeInventoryWidget` renders the live list and re-renders on `OnWardrobeChanged`; clicking a wardrobe item calls `EquipFromWardrobe`. The slot menu has a single Remove button whose `Init(slot, bAtWardrobe)` flag decides the action — store via `UnequipToWardrobe` when opened at the wardrobe, drop to the world otherwise. **Home-storage model (GDD §6.5 / §10.4 / §28):** the wardrobe is the general home stockpile for **all non-food** items (clothing, sex toys, phones, keys, spare bags) — `WardrobeItems` is already a generic `UItemInstance` list, so this matches with no change. Food is **not** stored in the wardrobe; it lives in the **fridge** (separate fixture, pending — see §1.3). **Follow-ups:** `BuyItem` buy-flow not reattached (no caller yet); world pickup (`ItemPickup`→`TakeClothing`) still doesn't clear the `WorldItems` record; non-clothing wardrobe items (phones/toys) are stored but not yet rendered in the wardrobe UI. ### 1.2 Partially implemented (deviates from GDD) @@ -125,7 +125,7 @@ State of the C++ module as of the latest pass. File references use `Source/Naked - **Item-world AActor (§6.1)** — no `AItemActor` / `AClothingPickup` base. - **Bag inventory (§6.4)** — absent. Per the locked model (GDD §6.4 / §27): bags are the **only** container, capacity is a flat per-bag **item count** (no S/M/L size classes), and any item type can be stored. The container concept is removed from clothing — the per-garment `UClothingItemInstance::StoredItems` array has been deleted; the item list will live on a future bag `UItemInstance` subclass. - **Dedicated carry slots (§6.5 / §27)** — `Phone`, `Bag`, `Key` are single-item slots on the player, separate from the 18 clothing/accessory/restraint/toy slots and from the old (removed) hand slot. Deliberately **not** in `EClothingSlotType` (it's clothing-named); each carry slot is modeled independently. - - **Phone slot + phone item — done (data + slot).** `Phone/PhoneItemDefinition` (`UItemDefinition`) + `Phone/PhoneItemInstance` (`UItemInstance`, per-instance `BatteryPercent` in `FPhoneInstanceState`). The slot lives on `UInventorySubsystem`: `EquippedPhone`, `GetEquippedPhone()`, `OnPhoneChanged`, hot-swap on equip (§9.9). `EquipFromWardrobe`/`UnequipToWardrobe` route phones to `EquipPhone`/`UnequipPhone`; the equipped phone persists via the shared `EquippedItems` save bucket and re-hydrates in `EnsureHydrated` (clothing in that bucket is still hydrated by `ClothingManager`). **Follow-ups:** no phone-slot UI widget yet and the wardrobe list (`WardrobeInventoryWidget`) renders clothing only, so a phone is equippable from code / `StartingItems` but not yet via the wardrobe screen; battery drain/charge is Phase 8/9. + - **Phone slot + phone item — done (data + slot).** `Phone/PhoneItemDefinition` (`UItemDefinition`) + `Phone/PhoneItemInstance` (`UItemInstance`, per-instance `CurrentBattery` in `FPhoneInstanceState`; `MaxBattery` on the definition). The slot lives on `UInventorySubsystem`: `EquippedPhone`, `GetEquippedPhone()`, `OnPhoneChanged`, hot-swap on equip (§9.9). `EquipFromWardrobe`/`UnequipToWardrobe` route phones to `EquipPhone`/`UnequipPhone`; the equipped phone persists via the shared `EquippedItems` save bucket and re-hydrates in `EnsureHydrated` (clothing in that bucket is still hydrated by `ClothingManager`). **Follow-ups:** no phone-slot UI widget yet and the wardrobe list (`WardrobeInventoryWidget`) renders clothing only, so a phone is seedable via `StartingSaveData.Phone` / code but not yet equippable via the wardrobe screen; battery drain/charge is Phase 8/9. - **Bag + key slots — pending** (deferred with the bag system, see above). - **Theft (§6.3.4)** — new chance-based model (per-tick `P_theft` after grace period) not implemented. No theft timer / probability code at all. - **Rip & tear (§6.3.5)** — absent. `UClothingItemInstance::Condition` is read-only in code; no decrement source. @@ -134,7 +134,8 @@ State of the C++ module as of the latest pass. File references use `Source/Naked - **Bodysuit exclusion rule (§6.5)** — when implementing the new slot enum, `ClothingManager` must auto-unequip `Top`/`Bottom`/`UnderwearTop`/`UnderwearBottom` on bodysuit equip, and vice versa. - **Toy slots (§6.5)** — `Nipples`, `Anal`, `Vagina` are 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. +- **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. No `UFoodItemDefinition` / `UFoodItemInstance` types yet. +- **Fridge — food home storage (§6.5 / §10.4 / §28)** — absent. Per the home-storage model, food is stored **only** in the apartment fridge (never the wardrobe). Needs: an `AFridge` interactable actor (mirror `AWardrobe`), a `FridgeItems` save bucket + `Add/Remove/Get` on `UGlobalSaveGameData`, fridge storage + `OnFridgeChanged` on `UInventorySubsystem`, the minimal food item types above, and a fridge screen widget. Tracks with the Phase 10 food system. - **Recognition, wanted state, news (§7.6–§7.7, §11.1)** — absent. Face-cover bypass via `Face` and `Eyes` slots is part of this work. - **Underwear selling (§15.1)** — absent. Backed by the `DeliverItemTo` typed objective (player-owned source only, §13.4). - **Endless mode flag (§3.3)** — absent. diff --git a/README.md b/README.md index 7328318f..52b92aa2 100644 --- a/README.md +++ b/README.md @@ -246,7 +246,7 @@ Authored examples: ### 6.5 Inventory & Equipment -The player has 18 equipment slots in four groups, plus three dedicated carry slots — **phone**, **bag**, and **key**. There is no hand slot and no per-garment container slots; general item storage is the equipped bag's inventory only (§6.4). +The player has 18 equipment slots in four groups, plus three dedicated carry slots — **phone**, **bag**, and **key**. There is no hand slot and no per-garment container slots; in-session carry storage is the equipped bag's inventory (§6.4), while owned items rest in apartment home storage (wardrobe / fridge) between sessions — see **Home storage** below. #### Equipment slots @@ -296,16 +296,23 @@ Sex toys are bought from the Adult Shop (§10.4) and follow the standard item-id #### Dedicated carry slots - **Phone slot** — 1. Holds the active phone (§9, §9.9). The phone is usable directly from this slot; an empty slot means no phone is available. `BlockPhoneUse` (§6.3.7) still disables it while a restraint is on. -- **Bag slot** — 1. Holds one bag (§6.4). The bag's inventory is the only general item storage. +- **Bag slot** — 1. Holds one bag (§6.4). The bag's inventory is the only general carry storage during a session. - **Key slot** — 1. Holds the key used for the restraint unlock action (§10.4.1). Each of these slots accepts only its own item type — a phone in the phone slot, a bag in the bag slot, a key in the key slot. Everything else the player carries lives in the equipped bag. Actions that previously implied a free hand (item pickup, masturbate, expose action) are gated only by the relevant `Block*` restriction (§6.3.7); wrist cuffs are the canonical case. -#### Item storage -- The only item storage is the equipped bag's inventory (§6.4). Clothing exposes no container slots. +#### Carry storage (in-session) +- The only thing the player carries items in is the equipped bag's inventory (§6.4). Clothing exposes no container slots. - Capacity is the equipped bag's authored item-count limit. With no bag equipped, the player carries only what is worn plus what occupies the phone, bag, and key slots. - There are no item size classes — one bag slot holds one item of any type. +#### Home storage (apartment) +Owned items rest in the apartment between sessions, in two fixtures (§10.4): +- **Wardrobe** — stores every **non-food** item: clothing, sex toys, phones, keys, and spare bags. It is the general home stockpile and the loadout point — equip clothing, swap the active phone (§9.9), grab a key or bag before leaving. +- **Fridge** — stores **food / consumables only** (§6.7). Food cannot be kept in the wardrobe. + +Home storage is separate from carry storage: the wardrobe and fridge are the apartment stockpiles where owned items live, whereas the equipped bag is the limited inventory carried into a session. Items move between home storage and the player at the fixture. + ### 6.6 Item loss summary table | Situation | Outcome | |-------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------| @@ -579,7 +586,7 @@ Sleeping at home fast-forwards 8 hours. - **Wanted poster mechanic:** wanted posters spawn in the city. Tearing them all down clears the `wanted` tag and stops police spawning until a new Snitch report retriggers it. ### 10.4 Locations -- **Apartment** — safe zone. Wardrobe, bed, PC, kitchen. +- **Apartment** — safe zone. **Wardrobe** (home storage for all non-food items — clothing, sex toys, phones, keys, spare bags; §6.5), **Fridge** (home storage for food / consumables only; §6.5 / §6.7), bed, PC, kitchen. - **Convenience store** — cooking ingredients; portable phone powerbanks (§9.8). - **Café** — pre-made food. - **Clothing shops** — various types, each with a different inventory mix. @@ -980,7 +987,8 @@ Decisions previously open, now fixed: 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. **Follower income cadence — daily, not weekly.** Passive follower income accrues and auto-deposits to the bank **every in-game day** at the 04:00 day-roll, not in a weekly lump. Resolves the prior §7.9 ↔ §9.4 / §13.3 contradiction in favor of §7.9's daily model. Rent remains a separate **weekly** charge (§15.2); the two cadences are intentionally offset. See §7.9 / §9.4 / §13.3 / §15.1. 26. **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. -27. **Bags are the only containers; clothing has no pockets.** Per-garment container slots and item size classes (S / M / L) are removed. Only an equipped bag stores items, capacity is a flat per-bag **item count** (no size constraints), and any item type can go in any bag slot. The player also gains three dedicated single-item carry slots — **phone**, **bag**, and **key** — replacing the old generic hand slot; the phone is usable directly from the phone slot. See §6.3.1 / §6.4 / §6.5. +27. **Bags are the only carry container; clothing has no pockets.** Per-garment container slots and item size classes (S / M / L) are removed. The only thing the player *carries* items in is an equipped bag — capacity is a flat per-bag **item count** (no size constraints), and any item type can go in any bag slot. The player also gains three dedicated single-item carry slots — **phone**, **bag**, and **key** — replacing the old generic hand slot; the phone is usable directly from the phone slot. See §6.3.1 / §6.4 / §6.5. +28. **Home storage is two fixtures: wardrobe + fridge.** Owned items rest in the apartment between sessions. The **wardrobe** holds every non-food item (clothing, sex toys, phones, keys, spare bags) and is the loadout point; the **fridge** holds food / consumables only, and food cannot be kept in the wardrobe. Home storage (the apartment stockpile) is distinct from carry storage (the count-limited equipped bag, §27). See §6.5 / §10.4. ## 21. Open Design Questions