CRoommaker
Overview
UCRoommaker is the core room generation engine. It implements ICCell, ICRoomBoundable and ICCoordBoundable. It generates clusters of rooms, connects them with MST-based corridors, assigns spatial cells for fast lookup, creates box collisions for overlap detection, and computes a longest-path ordering for progression.
Instantiation
| Name |
Description |
| instantiate |
Static factory. Creates a singleton UCRoommaker bound to a scene component, with a random stream and cluster configuration |
// Called by ACRoomSpawner::init()
UCRoommaker::instantiate(GetRootComponent(), roommaker, stream, *data);
Generation
| Name |
Description |
| buildASync |
Entry point for async generation. Delegates to drawRoom then finalize_sync via queue |
| drawRoom |
Generates all rooms and clusters: random placement, relaxation, Delaunay, MST, edge breaking, cell assignment |
| createRoom |
Creates rooms for a single FCRoomCountStruct within a cluster |
| finalize_sync |
Dequeues generation results and creates metadata (UCRoomMetadata, UCClusterMetadata) |
| finishWorldObject |
Spawns box collisions per room after both room and world spawners are ready |
// buildASync is called on tick by ACRoomSpawner.
// It runs drawRoom asynchronously, then finalize_sync on the game thread.
roommaker->buildASync(singleDoRun);
// drawRoom pipeline:
// 1. For each FCRoomMakerCountStruct, create rooms with random positions
// 2. Relax rooms using the configured CAlgoRelaxType until stable
// 3. Relax clusters in a second pass
// 4. Delaunay triangulation for room connectivity
// 5. MST for corridor paths (straight or flex)
// 6. Break edges with noise for organic corridors
// 7. Assign rooms, clusters and edges to spatial cells
// finalize_sync creates UCRoomMetadata per room (doors, tags)
// and UCClusterMetadata per cluster (fog of war, specific noise).
// After all clusters are finalized, longestOrderedPath computes
// room ordering along the MST for progression.
// finishWorldObject spawns UCRoomBoxCollision per room
// for overlap detection (quest/skill triggers).
Retrieval
| Name |
Description |
| retrieveClusterById |
Returns a cluster FCRectangle by cluster ID |
| retrieveRoomById |
Returns a room FCRectangle by cluster ID and room ID |
| retrieveRoomDetailById |
Returns FCRoomDetailData for a cluster |
| retrieveClusterByTag |
Returns all clusters matching a FName tag |
| retrieveRoomByTag |
Returns all rooms matching a FName tag |
| retrieveEdgeById |
Returns a corridor FCEdge by cluster ID and edge ID |
| retrieveClusterByRoom |
Returns the parent cluster of a room via its metadata |
| retrieveClusterMetadata |
Casts a cluster’s metadata to UCClusterMetadata |
| retrieveRoomMetadata |
Casts a room’s metadata to UCRoomMetadata |
| retrieveSpecificNoiseData |
Returns per-cluster specific noise and shift noise |
// Retrieve a room by IDs:
FCRectangle* room = roommaker->retrieveRoomById(clusterId, roomId);
// Retrieve all rooms with a specific tag:
TArray<FCRectangle*> treasureRooms = roommaker->retrieveRoomByTag(FName("treasure"));
// Get room metadata (doors, tag, consumption state):
UCRoomMetadata* meta = roommaker->retrieveRoomMetadata(room);
// Get cluster-specific noise for terrain modulation:
auto [noise, shiftNoise] = roommaker->retrieveSpecificNoiseData(cluster);
Iterators
| Name |
Description |
| iterateOnCluster |
Iterates over all clusters. Callback returns true to break |
| iterateOnClusterRoom |
Iterates over all rooms in all clusters. Callback returns true to break |
// Iterate all clusters:
roommaker->iterateOnCluster([](FCRectangle* cluster) {
// process cluster
return false; // true to break
});
// Iterate all rooms across all clusters:
roommaker->iterateOnClusterRoom([](FCRectangle* cluster, FCRectangle* room) {
// process room within its cluster
return false; // true to break
});
Geometry Finders
| Name |
Description |
| closestCluster |
Finds the closest cluster containing a 2D point (cell-limited) |
| closestRoom |
Finds the closest room containing a 2D point with optional tolerance (cell-limited) |
| closestEdgeWithin |
Returns all corridor edges within a distance from a 2D point (cell-limited) |
| closestEdge |
Finds the single closest corridor edge to a 2D point (cell-limited) |
| nearEdge |
Finds the nearest edge within its influence width (cell-limited) |
| fogOfWarPart |
Returns the fog of war rectangle for a cluster |
// Find closest room at a world position:
FCRectangle* rect;
if (roommaker->closestRoom(FVector2D(x, y), rect)) {
// rect is the room containing or nearest to (x, y)
}
// Find corridor edges within 500 units:
TArray<FCEdge> edges = roommaker->closestEdgeWithin(FVector2D(x, y), 500.0f);
// Check if a point is near a corridor (within edge width):
FCEdge edge;
if (roommaker->nearEdge(FVector2D(x, y), edge)) {
// point is within the corridor influence zone
}
Overlap & Interaction
| Name |
Description |
| OnBeginOverlap |
Triggered when an actor enters a room box collision |
| OnEndOverlap |
Triggered when an actor leaves a room box collision |
| isRoomEligibleForTagProba |
Checks room content eligibility based on character tags and probability ranges |
| longestOrderedPath |
Computes the longest path through the MST for room progression ordering |
// Room overlap triggers quest actions and skill consumption:
// On begin overlap: checks quest system first, then skill system.
// If interactWithPlayerOnly is true, only the player pawn triggers.
// If canOnlyBeConsumedOnce is true, the room is marked consumed after first interaction.
// Room eligibility for content:
int contentCount;
if (roommaker->isRoomEligibleForTagProba(contentCount, room, charMainTag, charTagArray, true)) {
// room is eligible, contentCount indicates how many tags matched
}