Files
Naked-Desire/PLAN.md
T
2026-05-17 22:44:49 +03:00

12 KiB
Raw Blame History

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

  • Modular character w/ per-slot meshesPlayer/NakedDesireCharacter.cpp:40-67 creates 14 skeletal mesh components, one per clothing slot. Aligns with GDD §17.6.
  • Equip / unequip / drop eventClothing/ClothingManager.cpp:88-172 (slot-based, broadcasts OnClothingEquip / Unequip / Dropped).
  • Basic perceptionPlayer/NakedDesireCharacter.cpp:167-203 implements IAISightTargetInterface::CanBeSeenFrom against boobs_root and pelvis bones with line-of-sight checks. Foundation for GDD §7.1.
  • AI sight + behavior treeNPC/NPCAIController.cpp runs a BT with Player / TargetLocation blackboard. NPC/NPCSpawner.cpp does proximity-gated spawning with day / night caps.
  • Mission frameworkMissionMissionGoalGoalRestriction composition (MissionBuilder/). Two goals (FlashGoal, MinTimeGoal), three restrictions (EquipClothing, ExposeBodyPart, Location).
  • Location triggersLocations/LocationTrigger, Locations/LocationData via gameplay tags (GDD §10.4 area foundation).
  • Censorship toggle — compliance feature on NakedDesireCharacter (BoobL/R, Front/BackBottom static meshes), driven by user settings.
  • MovementEnhancedInput, walk / run / crouch (NakedDesireCharacter.cpp:115-127), stamina-gated run (Tick lines 91-113).
  • Wardrobe interactableInteractables/Wardrobe.h holds ClothingItems[]; NakedDesireGameMode::BuyItem charges money and pushes into wardrobe.

1.2 Partially implemented (deviates from GDD)

  • Item identity (§6.1)Clothing/ClothingItemData.h:14-27 exists as an "instance" UObject but has no unique ID and no per-instance state (no condition, color, coverage float, isUnderwear, canExpose, isRestrictive, containerSlots). SaveGame/ClothingItemSaveData.h only stores a TSoftObjectPtr<UClothingItem> — it saves the template, not the instance. Directly violates the "every item is a unique physical instance" rule.
  • Save system (§16)SaveGame/GlobalSaveGameData.h only persists HaveSeenTutorial, Money, and two clothing lists. No world items, NPCs, time, mission state, recognition / reputation / followers, or wanted flag. Save fires only on explicit Blueprint call; load only happens in ANakedDesireCharacter::BeginPlay.
  • Attributes (§7)Stats/StatsManager.h:17-31 has only Embarrassment, Energy, Stamina. Missing Lust, Recognition, Reputation, Followers, Wanted. No GAS. TickComponent (StatsManager.cpp:23-28) unconditionally drains energy and decays embarrassment — observation-driven gain is not wired in C++.
  • Coverage (§6.3.1)ClothingManager::IsBodyTypeExposed (ClothingManager.cpp:14-25) is binary. No coverage float, no underwear halving, no max-of-covering-garments math.
  • Body parts (§6.3) — only FrontTop / FrontBottom / BackBottom exist (Player/PrivateBodyPartType.h:14-20). GDD references boobs, ass, genitals as distinct parts.
  • Mission system — composable goals work but lacks the typed objective steps from §13.4 (BeFullyNakedNearNPCs, WalkNakedDistance, MoveDistanceFromClothing, BeObservedByNPCType, TakePhotoAtLocation, DeliverItemTo). Missions are hand-authored in MissionsConfig.
  • Day / night — affects spawn caps (NPCSpawner.cpp:40-41) but not embarrassment rate, NPC type weights, or police spawning.

1.3 Missing

  • Session system (§4) — no USessionManager, no session start / end events, no SessionLossResolver. Game-over on embarrassment is a single EndGameEmbarrassed Blueprint event in NakedDesireGameMode; none of §4.4's item-drop logic is implemented.
  • Three progression paths (§5) — no path enum on UClothingItem, no Path XP, no path levels, no path-gated content.
  • Phone (§9) — entire system absent: camera, gallery, livestream, bank, Feetex, maps, health tracker.
  • Forum (§13) — no UCommissionTemplate, no procedural generation, no weekly missions distinct from daily, no profile / followers, no posting photos.
  • Photo & livestream — absent.
  • NPC types (§10.2) — only one generic ANPC class. No Walker / Stalker / Paparazzi / Snitch / Harasser / Helper, no Police, no Wanted-poster mechanic.
  • Calendar, rent, sleep (§2.4, §15.2)DaysPassed increments in NakedDesireGameMode::OnHourChanged(4), but no week, no rent, no eviction, no sleep action.
  • Item-world AActor (§6.1) — clothing drops broadcast a delegate but no AItemActor exists.
  • Bag inventory (§6.4) — absent.
  • Rip & tear, theft (§6.3.3-4) — absent.
  • Expose action (§6.3.5) — absent.
  • Restrictive clothing (§6.3.6) — absent.
  • Adult shop, gym, beauty salon, cafe, convenience store — none.
  • Food / consumables (§6.6) — absent.
  • Recognition, wanted state, news (§7.57.6, §11.1) — absent.
  • Underwear selling (§15.1) — absent.
  • Endless mode flag (§3.3) — absent.

1.4 Conflicts to resolve

  • EClothingSlotType (Clothing/ClothingSlotType.h) treats Nipples / Anal / Vagina as equipment slots; GDD treats those as body parts. Slot list also lacks Outerwear, Accessory, Restraint. Slot vocabulary needs a cleanup pass.
  • Money lives on ANakedDesireCharacter (NakedDesireCharacter.h:139) as int Money = 300000, and also as a field on UGlobalSaveGameData. Duplicate state. Default 300k vs. ~20k weekly rent (§15.3) — test value.
  • MissionsManager::RefreshDailyMissions (MissionBuilder/MissionsManager.cpp:53-68) has a remove-while-iterating bug; OnComplete.RemoveAll(this) is called on the mission, not on the manager handle.
  • NakedDesireGameMode::RefreshDailyMissions indexes MissionsConfig->DailyMissions[DaysPassed] — crashes past the authored array and contradicts §13.4 procedural generation.
  • StatsManager::TickComponent unconditionally decays embarrassment (StatsManager.cpp:27). §7.1 says decay should happen only when not observed; today no observation-driven gain offsets it.
  • Save constant SLOT_NAME "Slot2" (Global/Constants.h:5) — magic single-slot save, no multi-save support.
  • UClothingItemData is EditInlineNew and stored inline in UClothingList::ClothingItems. Instances live inside the list asset, not as standalone objects with stable identity. Direct conflict with §6.1.

2. Architectural premise

The item-identity rule (§6.1) and the save contract (§16.3) are load-bearing. Clothing condition, world drops, session loss, theft, the bag, and the forum's "post a photo of this specific worn item" all depend on stable per-instance state.

Until Phase 1 lands, content authored on top of the current system needs migration. Do not build the higher phases first.


3. Phased roadmap

Phase estimates are rough and assume one engineer. Adjust as we go.

Phase 1 — Item identity + save foundation (12 weeks)

  • Split UClothingItem (immutable definition, UPrimaryDataAsset) from a new UItemInstance UObject with FGuid InstanceId and mutable state (Condition, Color, container parent, world transform). Make UClothingItemInstance : UItemInstance.
  • Add to the definition: Coverage float, IsUnderwear, CanExpose list, IsRestrictive, ContainerSlots, ProgressionPath enum.
  • Enumerate slots cleanly — split slot vs. body-part vocabulary (resolves §1.4 conflict).
  • Replace FClothingItemSaveData with a generic FItemSaveRecord { Guid, DefinitionPath, InstanceState, Location, ParentRef }.
  • Introduce USaveSubsystem (GameInstance subsystem) that orchestrates serialization across player, world items, time, missions, attributes, recognition.
  • Convert single-slot SLOT_NAME to a slot-name argument.

Exit criteria: an item dropped in the world, with its condition modified, survives save / load with the same GUID and condition value.

Phase 2 — World item actors + drop / pickup (1 week)

  • AItemActor base wrapping a UItemInstance*. AClothingPickup : AItemActor.
  • Hook ClothingManager::DropClothing to spawn AClothingPickup at the player location with the actual instance reference (no template copy).
  • Pickup interaction via existing InteractionManager.

Exit criteria: unequip → world actor appears → re-pick-up restores the same instance to the slot.

Phase 3 — Session system + loss resolver (1 week)

  • USessionManager (GameMode component). Apartment LocationTrigger flag drives session start / end.
  • USessionLossResolver — single class, per §4 implementation note. Takes the loss cause and runs §4.4 deterministically over the new world-item registry.
  • Wire StatsManager::IncreaseEmbarrassment max-hit and energy-zero into the resolver.

Exit criteria: lose to embarrassment → equipped clothing spawns as world actors at the loss location, persists through save.

Phase 4 — Attributes refactor (1 week)

  • Decide GAS vs. extended StatsManager (recommend GAS per §17.2; embarrassment formula has many modifiers that GAS effects model cleanly).
  • Add Lust, Recognition, Reputation, Followers, Wanted.
  • Move observation-driven embarrassment gain out of BP into the C++ pipeline (use the existing CanBeSeenFrom result + per-NPC type weights).
  • Add Lust + masturbate action + blackout vision effect.
  • Add Recognition with face-cover bypass + Wanted bool.

Exit criteria: observed-while-exposed gains embarrassment from C++; unobserved decays; both rates are inspectable in a debug overlay.

Phase 5 — Time + calendar + rent + sleep (34 days)

  • UTimeOfDaySubsystem replacing the BP-implementable time on NakedDesireGameMode. 90-day calendar, week boundary, rent transaction.
  • Sleep action on apartment bed: time-skip + energy restore + autosave.
  • Endless-mode flag on the save.

Exit criteria: play through 7 in-game days, get charged rent at week boundary, eviction triggers on insufficient funds.

Phase 6 — NPC types + recognition pipeline (12 weeks)

  • ENPCType enum, type-specific BT branches or per-type controller subclasses.
  • Walker / Stalker / Paparazzi / Snitch / Harasser / Helper / Police.
  • Recognition flow: Paparazzi photo → article → news site → "report" reduces recognition.

Exit criteria: each NPC type observably distinct behavior; recognition rises after paparazzi exposure and can be reduced via news report.

Phase 7 — Commission template system (12 weeks)

  • Replace MissionsConfig's hand-authored daily list with UCommissionTemplate + procedural generation per §13.4.
  • Add typed objective steps as new UMissionGoal subclasses (BeFullyNakedNearNPCs, WalkNakedDistance, MoveDistanceFromClothing, BeObservedByNPCType, TakePhotoAtLocation).
  • Weekly vs. daily generation pass.

Exit criteria: daily commissions regenerate from templates each in-game day; weekly arc is distinct; failed commissions deduct reputation.

Phase 8 — Phone + forum UI (23 weeks)

  • Phone as a holdable / pocketable AItemActor.
  • Apps: Camera + Gallery, Livestream (StreamSession tick object), Bank, Feetex, Maps, Health Tracker, Forum.
  • Photo system: pick render-to-texture (§17.6) — recommended for in-fiction photo posts.

Exit criteria: end-to-end photo loop — equip phone, capture photo, view in gallery, post to forum, follower count updates.

Phase 9 — Path progression + content authoring (2 weeks)

  • Path XP per path, level gating on clothing / missions / attribute upgrades.
  • Author the vertical-slice content set from §18.1.

Exit criteria: all three paths have at least 5 unlockable items and 3 path-specific commission templates.

Phase 10 — Remaining systems & polish

  • Bag inventory (§6.4).
  • Food / cooking (§6.6).
  • Gym / beauty salon / adult shop (§10.4).
  • Rip and tear (§6.3.4).
  • Theft timer (§6.3.3).
  • Expose action (§6.3.5).
  • Restrictive-clothing flow (§6.3.6, §10.4.1).
  • Underwear selling (§15.1).
  • Wanted-poster takedown (§10.3).

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.

  • empty