Block 1 — Foundation (2 days)
Goal: Walkable blockout hideout and city map with interactable station volumes, the core data model compiled and instantiable, and all subsystem stubs in place. No gameplay — just the shell everything plugs into.
Depends on: Nothing — this is the foundation.
Deliverables
Home Base Blockout (L_Hideout)
UE5 Modeling Tools geometry (not BSP) defining the tunnel layout: main corridor, alcoves for stations, dead ends for boundaries. Sized for 7 station spots plus walking paths. Use Cube Grid tool → PolyEdit to extrude alcoves. Flat unlit materials with distinct colors per zone. Scale for raccoon height: tunnels ~60–80 cm tall, 80–100 cm wide.
City Map Sublevel (L_City)
Separate sublevel added to L_Hideout persistent level via Levels panel. Streaming method set to “Always Loaded” — L_City stays resident at all times because raccoon AI pawns navigate it during active raids and NavMesh must persist regardless of whether the player is viewing the city map. At blockout scale the memory cost is negligible; revisit if L_City grows to production art with significant asset weight. Contains: flat ground plane (road grid mesh), 2 box-primitive buildings (ATNTBuilding actors) for Average Home and The Dump, ANavMeshBoundsVolume covering road network, ATNTHideoutExit marker at map edge, ATNTCityCamera overhead camera actor with pan/zoom support.
First-Person Movement
ATNTPlayerPawn extending ACharacter with UCharacterMovementComponent in walking-only mode. Disable jumping and crouching. UCapsuleComponent at 30 cm half-height, UCameraComponent at raccoon eye height. CMC handles gravity and floor pinning — avoids floating on uneven geometry. No paw hands or character model yet — camera only.
Player Controller
ATNTPlayerController with two Enhanced Input mapping contexts:
IMC_Hideout:
| Input Action | Type | Binding |
|---|---|---|
IA_Move | Vector2D | WASD |
IA_Look | Vector2D | Mouse XY |
IA_Interact | Bool (pressed) | E |
IMC_CityMap:
| Input Action | Type | Binding |
|---|---|---|
IA_Pan | Vector2D | WASD / mouse drag (middle button) |
IA_Zoom | Float (axis) | Scroll wheel |
IA_Click | Bool (pressed) | Left mouse |
IA_Escape | Bool (pressed) | Escape |
Interaction system: Overlap-based (not line trace). ATNTStationBase has UBoxComponent set to overlap. When player pawn overlaps a station volume → controller caches reference + shows interact prompt on HUD. On IA_Interact → Station->OnPlayerInteract(). On end overlap → clear prompt. Only one station overlap active at a time (nearest or most recent). For MVP blockout: print to screen confirming which station was activated.
Game Mode
ATNTGameMode extending AGameModeBase. Sets default pawn class and player controller class. No gameplay init yet (that’s Block 2+).
Station Volumes
7 instances of ATNTStationBase placed at intended locations. Each is the same class, configured per-instance:
ATNTStationBase : AActor
UBoxComponent* InteractionVolume // Overlap volume — generates overlap events with player pawn
UStaticMeshComponent* PlaceholderMesh // Differently colored cube per station
UWidgetComponent* LabelWidget // Floating text: "Raid Board", "Pantry", etc.
UStationDataAsset* StationData // Assigned in editor — drives behavior
EStationType StationType // Cached from DataAsset on BeginPlay
void OnPlayerInteract()
// Branch logic:
// if StationType == RaidBoard → UCityMapSubsystem::SetOverheadCamera(true)
// (SetViewTargetWithBlend to ATNTCityCamera + switch input to IMC_CityMap)
// else → spawn StationData->UIWidgetClass, add to viewport,
// set input mode Game+UI, show cursor
int32 GetEffectiveStat(EStatType) // Delegates to UStationSubsystem
No subclasses. UStationDataAsset specifies station type, relevant stats, base storage cap, upgrade cost curve, and which UMG widget class to spawn on interact. Raid Board leaves UIWidgetClass null — uses city map flow instead.
City Map Actors (stubs)
| Class | Base | Purpose |
|---|---|---|
ATNTBuilding | AActor | UStaticMeshComponent (box) + UBoxComponent (hover detect). References UBuildingDataAsset. Highlight material on hover. Click to select target. |
ATNTRaccoonAIPawn | APawn | Stub class only — spawning/AI wired in Block 4. |
ATNTCityCamera | AActor with UCameraComponent | Top-down overhead. Not possessed — PlayerController uses SetViewTargetWithBlend to switch view to this actor. Controller moves camera transform directly via IMC_CityMap input (pan = translate XY, zoom = adjust arm length or Z height). |
ATNTHideoutExit | AActor | Spawn point marker for raccoon AI pawns at map edge. |
Core Data Model (C++)
All enums, structs, and subsystem stubs compiled and instantiable:
Enums:
| Enum | Values |
|---|---|
ERaccoonType | Scout, Hauler, Distractor (post-MVP: Sorter, Scrapper, Fence, Lookout, Climber) |
ERaccoonStatus | Idle, Raiding, Assigned, Injured, Hungry, Deserted, Training |
EStatType | Speed, Stealth, Strength, Cunning, Luck |
EStationType | RaidBoard, TrainingCorner, LootSortingStation, OnlineSales, Pantry, GearBench, UpgradeDesk |
EResourceType | Trash, Currency, Scrap |
EEncounterConsequence | None, Injury, Capture, Abort, LootLoss, BonusLoot, TimeReduction |
Structs:
| Struct | Key Fields | Notes |
|---|---|---|
FStatBlock | Speed, Stealth, Strength, Cunning, Luck (int32, 1–100) | GetStat(EStatType), ModifyStat(EStatType, Delta), operator+ for crew summing. All BlueprintCallable. |
FRaccoonData | Id (FGuid), Name, Type, BaseStats, TrainingBonus (FStatBlock, default 0s), EquippedGearRowName (FName), AssignedStation, bHasAssignment, Status, InjuryRaidsRemaining, ConsecutiveHungryTicks | Runtime raccoon instance. BaseStats immutable after creation. TrainingBonus accumulates from training sessions. See Raccoon Stats. |
FResourceLedger | Trash, Currency, Scrap (int32) | Global counters owned by UResourceSubsystem. |
FValuableItem | ItemId, Tier (1–3), BaseSellPrice, HiddenCeiling (post-MVP) | Individual valuable in loot payload. |
FLootPayload | Trash, Currency, Scrap amounts + TArray<int32> FoodItems + TArray<FValuableItem> Valuables + bRecruitAvailable + RecruitType | Transient. Generated at raid dispatch, consumed at loot sorting. |
FActiveRaid | RaidId, Target (soft ref), CrewRaccoonIds, TotalDuration, ElapsedTime, EncounterTriggerTimes, NextEncounterIndex, PendingLoot, SpawnedPawns (weak ptrs) | Active raid state. Tracks AI pawns on city map. |
FStationRuntimeState | AssignedRaccoonId, CurrentStorage, CapTier | Mutable per-station state. |
FCostData | Trash, Currency, Scrap (int32) | Multi-resource cost for upgrades/crafting. |
FMilestoneProgress | CurrentCount (int32), bCompleted (bool) | Per-milestone runtime state. Referenced by UProgressionSubsystem’s TMap. Stub here, populated Block 9. |
FEncounterResult | bPassed, Consequence (EEncounterConsequence), AffectedRaccoonId, EncounterName | Outcome of encounter resolution. Stub here, used by URaidSubsystem in Block 4. |
DataAsset classes (C++ headers, no content authored yet):
| DataAsset Class | Key Properties |
|---|---|
URaccoonTypeDataAsset | Type enum, starting stat ranges (min/max per stat), primary/secondary stat tags, unlock condition |
UStationDataAsset | Station type enum, relevant stat types, base storage cap, TArray<FCostData> upgrade cost tiers, TSubclassOf<UTNTStationUIBase> UIWidgetClass |
URaidTargetDataAsset | Name, loot bias weights (per resource type), difficulty, TArray<TSoftObjectPtr<UEncounterDataAsset>> encounter pool, unlock condition |
UEncounterDataAsset | Type enum, stat check type, threshold, pass consequence, fail consequence |
UBuildingDataAsset | Display name, linked URaidTargetDataAsset, visual type enum, hover tooltip data |
Subsystem stubs (C++ — UGameInstanceSubsystem subclasses, empty implementations):
| Subsystem | Internal State | Type | Purpose |
|---|---|---|---|
URaccoonSubsystem | Raccoons | TArray<FRaccoonData> | Live roster of all raccoon instances |
NamePool | TArray<FString> | Curated name list for GenerateName. Avoids duplicates against current roster | |
UResourceSubsystem | Ledger | FResourceLedger | Global resource counters (Trash, Currency, Scrap) |
UStationSubsystem | StationStates | TMap<EStationType, FStationRuntimeState> | Per-station mutable runtime state |
PendingPayloads | TMap<EStationType, TArray<FLootPayload>> | Loot queued for station processing (populated Block 5) | |
URaidSubsystem | ActiveRaids | TArray<FActiveRaid> | All in-progress raids |
UProgressionSubsystem | MilestoneProgress | TMap<FName, FMilestoneProgress> | Per-milestone runtime state |
UUpkeepSubsystem | (no owned collections) | — | Reads/writes FRaccoonData::ConsecutiveHungryTicks via URaccoonSubsystem. Timer callback driven by Game Clock |
UCityMapSubsystem | BuildingUnlockStates | TMap<FName, bool> | Tracks which buildings are unlocked |
UGameClockSubsystem | GameClockTime | float | Current time in game-minutes (0–1440). See Game Clock |
Content Browser Layout (initial)
Content/TrashNTreasure/
Data/
RaccoonTypes/ (empty — populated Block 2)
Stations/ (empty — populated Block 3+)
RaidTargets/ (empty — populated Block 3)
Encounters/ (empty — populated Block 3)
Buildings/ (empty — populated Block 3)
Tables/ (empty — populated Block 8–9)
Blueprints/
Stations/ BP_StationBase
Player/ BP_PlayerPawn, BP_PlayerController, BP_GameMode
CityMap/ BP_Building, BP_RaccoonAIPawn, BP_CityCamera, BP_HideoutExit
UI/ (empty — populated Block 2+)
Maps/
L_Hideout.umap
L_City.umap
Materials/ M_BlockoutBase (parameterized color instance)
Done When
- Player walks around blockout hideout in first person at raccoon height
- 7 labeled station volumes placed and interactable (print to screen on interact)
- Raid Board interact switches to city sublevel overhead camera with pan/zoom
- City sublevel has 2 box buildings with hover highlight, NavMesh on roads, hideout exit marker
- Escape from city view returns to hideout camera
- All enums, structs compile — can instantiate an
FRaccoonData, read its stats, check a resource counter in a C++ test - All 7 subsystem stubs instantiate via
GetGameInstance()->GetSubsystem<T>() - All DataAsset C++ headers compile (no content assets yet)