Block 2 — Raccoon Roster (1 day)

Goal: Raccoons exist as persistent, named entities the player can inspect. Starter crew spawns on game start. Full UTNTRaccoonSubsystem operational.

Depends on: Block 1 data model (FTNTRaccoonData, FTNTStatBlock, subsystem stubs).

Naming convention: All gameplay types carry the TNT prefix (UTNT…, FTNT…, ETNT…). Earlier drafts of this page used un-prefixed names; the implementation standardised on the prefix during Block 1.


Deliverables

UTNTRaccoonSubsystem — Full Implementation (C++)

Class: UTNTRaccoonSubsystem : UGameInstanceSubsystem. Header: Source/TrashNTreasure/Public/Subsystems/TNTRaccoonSubsystem.h · Impl: Source/TrashNTreasure/Private/Subsystems/TNTRaccoonSubsystem.cpp.

All functions UFUNCTION(BlueprintCallable, Category = "TNT|Raccoon"):

FunctionSignaturePurpose
AddRaccoonFGuid (ETNTRaccoonType, const FString& Name = TEXT(""))Roll FTNTRaccoonData from the resolved UTNTRaccoonTypeDataAsset (random within stat ranges). Generate name if empty. Append to TArray<FTNTRaccoonData>. Broadcast OnRosterChanged and OnRaccoonAdded.
RemoveRaccoonvoid (FGuid)Remove from array. Unassign from station if assigned. Broadcast OnRosterChanged. Used for desertion and capture.
GetRaccoonFTNTRaccoonData (FGuid) constReturn copy for Blueprint. Sentinel: empty Name == not found. Internal helpers Find / FindMutable return pointers.
GetAllRaccoonsTArray<FTNTRaccoonData> () constFull roster for UI.
GetEffectiveStatsFTNTStatBlock (FGuid) constBase + Training + Gear. Sums FTNTRaccoonData::BaseStats + TrainingBonus + resolved row from GearTable (FTNTGearRow::StatBonus). Clamped to 100 per stat via ClampBlock100.
GetInheritedStatsFTNTStatBlock (FGuid) constBase + Training (no gear). Used by breeding to determine parent contribution.
GetCrewStatSumFTNTStatBlock (const TArray<FGuid>& Crew) constSum GetEffectiveStats across crew. Used by encounter resolution (Block 4).
SetStatusvoid (FGuid, ETNTRaccoonStatus)Validate transition via IsLegalTransition, update, broadcast OnRosterChanged.
GetRaccoonsByStatusTArray<FGuid> (ETNTRaccoonStatus) constFilter roster by status.
EquipGearbool (FGuid, FName GearRow)Set EquippedGearRowName. Returns false if raccoon not found or already equipped.
UnequipGearFName (FGuid)Clear gear slot, return row name for inventory.
GenerateNameFString ()Pick from NamePool (seeded via SeedNamePool). Avoid duplicates within current roster.

Internal state (extends Block 1 stubs — Raccoons and NamePool declared there):

MemberTypePurpose
OnRosterChangedFOnRosterChanged (DYNAMIC_MULTICAST_DELEGATE)BlueprintAssignable. Broadcast on any roster mutation. UI binds to this.
OnRaccoonAddedFOnRaccoonAdded (DYNAMIC_MULTICAST_DELEGATE_OneParam)BlueprintAssignable. Param: FGuid RaccoonId. Fired from AddRaccoon only. Used by UTNTProgressionSubsystem to track recruitment milestones.
GearTableTObjectPtr<UDataTable> (EditDefaultsOnly)Gear modifier table. Rows are FTNTGearRow { FName DisplayName; FTNTStatBlock StatBonus; } (Source/TrashNTreasure/Public/Data/TNTGearRow.h). GetEffectiveStats resolves EquippedGearRowName against this table.

Type asset resolution — UTNTRaccoonSettings (Developer Settings)

Type → asset mapping is held in a UDeveloperSettings rather than scanned from the AssetRegistry.

  • Class: UTNTRaccoonSettings : UDeveloperSettings (Source/TrashNTreasure/Public/Settings/TNTRaccoonSettings.h).
  • Property: TMap<ETNTRaccoonType, TSoftClassPtr<UTNTRaccoonTypeDataAsset>> TypeAssets (Config, EditAnywhere).
  • Edited in Project Settings → Game → Trash N Treasure - Raccoons, persisted to Config/DefaultGame.ini.
  • UTNTRaccoonSubsystem::ResolveTypeAsset(ETNTRaccoonType) lazy-loads only the requested type’s CDO on demand.

Why: earlier registry scan during subsystem init caused 15–20 s cold-PIE stalls. Soft-class map sidesteps it and keeps designer-facing wiring in Project Settings (commit 7ab039a).

Raccoon Type DataAssets

Author UTNTRaccoonTypeDataAsset content assets:

AssetPrimary StatSecondaryStarting Ranges
DA_ScoutStealth (15–25)Cunning (12–20)Speed 8–15, Strength 5–10, Luck 5–15
DA_HaulerStrength (15–25)Speed 5–10, Stealth 5–10, Cunning 5–10, Luck 5–15

Values are tunable placeholders. Each DataAsset lives in Content/TrashNTreasure/Data/RaccoonTypes/ and is registered in UTNTRaccoonSettings::TypeAssets (see above).

Stat Display UI — Player’s Clipboard

Diegetic: the roster is rendered as a clipboard the player holds. No abstract HUD overlay — the fantasy is “raccoon-boss reading the crew sheet”. Blueprint-only UMG, no C++ widget class.

  • Content/TrashNTreasure/UI/WBP_Roster.uasset — clipboard surface, scrollable list, binds to UTNTRaccoonSubsystem::OnRosterChanged to auto-refresh.
  • Content/TrashNTreasure/UI/WBP_Roster_Card.uasset — per-row entry showing Name, Type, all 5 stats (base / training / gear layers + total), gear slot, current assignment, status.

Toggle is bound to IA_Clipboard (Content/TrashNTreasure/Input/IA_Clipboard.uasset) on BP_PlayerController — pulling the clipboard out / putting it away is the in-fiction equivalent of opening the roster.

Starter Raccoon

ATNTGameMode::BeginPlay (Source/TrashNTreasure/Private/GameModes/TNTGameMode.cpp:34–38) calls UTNTRaccoonSubsystem::AddRaccoon(ETNTRaccoonType::Scout) if the roster is empty, producing a single auto-named Scout.

Player starts with a single Scout. First Hauler is a guaranteed reward from scouting the first house — tutorial-as-gameplay-progression rather than a freebie spawn.

Save/Load

UTNTSaveGame : USaveGame (Source/TrashNTreasure/Public/Save/TNTSaveGame.h):

UTNTSaveGame
  TArray<FTNTRaccoonData> Raccoons
  FTNTResourceLedger Ledger
  TMap<ETNTStationType, FTNTStationRuntimeState> Stations
  TArray<FTNTActiveRaid> ActiveRaids
  TMap<FName, FTNTMilestoneProgress> Milestones
  float GameClockTime                    // 0–1440 game-minutes, see Game Clock system

FTNTActiveRaid will include phase state, travel/loot progress, backup crew, and encounter pending state — expanded in Block 4. On load, UTNTRaidSubsystem::LoadFromSave will reconstruct raid state: respawn AI pawns for active raids and teleport them to interpolated positions based on saved TravelElapsed / LootProgress.

Each subsystem implements SerializeToSave(UTNTSaveGame*) and LoadFromSave(const UTNTSaveGame*). Orchestrated by a save manager (currently on GameMode). Uses UGameplayStatics::SaveGameToSlot / LoadGameFromSlot. This block only serialises raccoons — other subsystems add their data in later blocks.

Dev save/load round-trip is exercised through input bindings on BP_PlayerController (commit badf844) so the loop can be smoke-tested without UI.


Done When

  • Game starts with 1 named Scout visible in the roster UI (clipboard via IA_Clipboard)
  • Player can see the raccoon’s name, type, and all 5 stats
  • GetEffectiveStats returns correct values (base + training for now — gear tested in Block 8)
  • GetInheritedStats returns base + training (no gear component)
  • GetRaccoonsByStatus(Idle) returns the starter
  • Raccoons persist through save/load cycle (smoke-tested via BP_PlayerController bindings)
  • OnRosterChanged delegate fires and roster UI refreshes
  • Roster toggle bound to IA_Clipboard on BP_PlayerController

References

Units · Scout · Hauler · Raccoon Stats

0 items under this folder.