Skip to content

AcresNpc.h#

Acres/Source/Acres/AcresNpc.h Generated

Farm life: pickups and tractors that drive the farm roads, workers who walk and scout crops, and highway traffic on US 52 along the south edge of the farm.

Turned on per session in the NPC tab (launch flags -NpcVehicles and -NpcWorkers; -NpcTraffic=<n> sets the number of highway cars, 16 by default with -NpcVehicles). One AAcresNpcDirector is spawned by the player's tractor; it builds a road graph from the survey, sets up the Beck lot parking spots and spawns the vehicles and workers.

NPC vehicles are kinematic: they are moved directly each frame along planned paths (a simple bicycle model limits how fast the heading can change) and never run the tractor physics. They only affect the player through their collision boxes. Workers are skeletal meshes playing walk / idle / inspect animations; if the player's tractor hits one faster than walking pace, the worker switches to a physics ragdoll, a blood decal spreads under the body, a banner shows on the HUD and the incident is written to npc-events.csv in the session folder.

Unreal notes: an AActor is an object placed in the world. UCLASS() and GENERATED_BODY() are markers for Unreal's code generator (the AcresNpc.generated.h include is its output). Tick(Dt) runs once per rendered frame on the game thread with Dt in seconds. UPROPERTY() on an object pointer keeps it alive for Unreal's garbage collector; TWeakObjectPtr is a non-owning pointer that becomes null when the object is destroyed.

FAcresNpcWheelRig#

struct FAcresNpcWheelRig

Spinning and steering wheels for a kinematic NPC vehicle.

Each wheel is a pivot (USceneComponent, a transform-only component) at the wheel centre with the wheel mesh attached to it. Every frame the pivot is rolled about its axle by distance / radius and the front pivots are yawed by a bicycle-model steering angle, atan(wheelbase * yaw rate / speed). The pivots are owned (and kept alive) by the actor they are attached to, so plain pointers are fine here.

FAcresNpcWheelRig::Update#

Rolls the wheels for one frame.

Argument Description
Dt Frame time, s.
SpeedMps Forward speed, m/s (negative when reversing).
YawRateDegS Body yaw rate, degrees/s (positive = turning right, since Unreal yaw grows clockwise seen from above).
void Update(double Dt, double SpeedMps, double YawRateDegS);

FAcresCarModel#

struct FAcresCarModel

One traffic car model, from Content/Simulation/npc_cars.json (written by Tools/ACRE/Tools/import_npc_cars.py).

Parts are drawn with PartXf relative to a ground-level origin under the body centre. Wheel positions are in the same frame (m, x forward, y right, z up); the wheel mesh is a left wheel and is mirrored for the right side.

Name Type Unit Default Description
PaintSlots TArray&lt;int> Material indices of Parts[0] that are car paint (repainted per car for variety).

FAcresHighway#

struct FAcresHighway

The US 52 centreline as a smooth curve for highway traffic.

The survey polyline (site.json road "US52", west to east) is turned into a Catmull-Rom spline (a smooth curve passing through every control point) and resampled every Spacing metres, so a car's position is a single number: its distance S along the road.

FAcresHighway::Build#

Builds the curve from a polyline (world metres). Leaves Length at 0 for fewer than two points.

void Build(const TArray<FVector2D>& Poly);

FAcresHighway::Sample#

Centreline point and unit tangent at distance S (clamped to the road).

void Sample(double S, FVector2D& OutPoint, FVector2D& OutTangent) const;

FAcresHighway::Project#

Distance along the road of the closest centreline point to Q; OutLateral is the signed offset from the centreline, m (positive = south of the road for eastbound tangent, i.e. to the right of eastbound traffic).

double Project(const FVector2D& Q, double& OutLateral) const;

FAcresRoadGraph#

struct FAcresRoadGraph

Drivable farm-road network for NPC routing.

Built from the "roads" polylines in Content/Simulation/ACRE/site.json. The public highway (US 52, 20 m wide or more) is left out. Polylines are resampled every ~8 m and points closer than 4.5 m are merged into one node, so crossings and T-junctions connect without hand-authored topology.

Name Type Unit Default Description
Nodes TArray&lt;FVector2D> Nodes: node positions in world metres (X east, Y south). Links: neighbours of each node (undirected). NodeWidth: widest road through each node, m.

FAcresRoadGraph::Build#

Rebuilds the graph from a parsed site.json object. Clears the graph if Site is null.

void Build(const TSharedPtr<class FJsonObject>& Site);

FAcresRoadGraph::Nearest#

Index of the node closest to a point (brute force), or -1 for an empty graph.

int Nearest(const FVector2D& P) const;

FAcresRoadGraph::Route#

Shortest road path between two nodes (Dijkstra on straight-line edge lengths).

Argument Description
From Start node index.
To End node index.

Returns: Node positions from start to end, or an empty array when there is no connection.

TArray<FVector2D> Route(int From, int To) const;

AAcresNpcDirector#

class AAcresNpcDirector : public AActor

Owner of all farm-life NPCs and the shared data they use (roads, parking, fields, incidents).

Spawned and set up by the player's tractor (AAcresVehiclePawn::BeginPlay) when a session asks for NPCs.

Example

if (AAcresNpcDirector* Npc = World->SpawnActor<AAcresNpcDirector>())
    Npc->Setup(/*bVehicles=*/true, /*bWorkers=*/true, SessionFolder);
Name Type Unit Default Description
Roads FAcresRoadGraph Farm road network used for routing.
SpotYaw TArray&lt;float> Heading of each spot, degrees (UE yaw). Same order as ParkingSpots.
SpotTaken TArray&lt;bool> Which spots are occupied.
LotEntry FVector2D Where vehicles enter and leave the lot, world metres.
EmptyFields TArray&lt;TArray&lt;FVector2D>> Outlines of the fields that NPC tractors may till, world metres.
ServicePoints TArray&lt;FVector2D> Destinations for pickup errands (bin yard, barn aprons), world metres.
LastAlert FString LastAlert: text of the latest incident banner. AlertUntil: game time (s) until which the HUD shows it.
Npcs TArray&lt;TObjectPtr&lt;AActor>> Every NPC actor spawned by Setup (kept alive by UPROPERTY). Includes the highway traffic cars, so farm vehicles and workers yield to them too.
Traffic TArray&lt;TObjectPtr&lt;AAcresNpcCar>> Highway traffic on US 52 (see SetupTraffic). Moved by this director's Tick, not their own.
Highway FAcresHighway US 52 centreline used by the traffic.
LaneOffsetM double m Inner and outer lane centres from the US 52 centreline, m: site.json "lane_offsets_m" of the US52 road (Tools/ACRE/Map/us52.py), else these older values (a 10 m median).

AAcresNpcDirector::EndPlay#

Writes npc-events.csv when the session ends.

virtual void EndPlay(const EEndPlayReason::Type Reason) override;

AAcresNpcDirector::Setup#

Builds the world data and spawns the NPCs.

Loads site.json, builds the road graph, lays out 28 parking spots at the Beck lot (paved with a decal; the ground-cover grass under it is removed), finds the empty fields and the service points (bin yard and barns), then spawns two repainted tractors and two pickups and/or four workers (two road walkers, two crop scouts).

Argument Description
bVehicles Spawn tractors and pickups.
bWorkers Spawn workers.
OutputDir Session folder for npc-events.csv; empty to skip the file.
void Setup(bool bVehicles, bool bWorkers, const FString& OutputDir);

AAcresNpcDirector::GroundZ#

Ground height at a point, metres: survey DTM plus any terrain edits from the Fields tab.

double GroundZ(const FVector2D& P) const;

AAcresNpcDirector::RouteBetween#

Road route between two arbitrary points (via their nearest road nodes). Endpoints are not included.

TArray<FVector2D> RouteBetween(const FVector2D& A, const FVector2D& B) const;

AAcresNpcDirector::Blocked#

True when something is in the way ahead: another NPC or the player's tractor inside a box LookM ahead and HalfWidthM to each side. Used for yielding.

Argument Description
Self The asking actor (ignored in the check).
Pos Its position, cm (Unreal units).
Forward Its heading as a unit vector.
LookM How far ahead to look, m.
HalfWidthM Half the width of the corridor, m.
bool Blocked(const AActor* Self, const FVector& Pos, const FVector& Forward, double LookM, double HalfWidthM) const;

AAcresNpcDirector::Overlaps#

True if a box overlaps the footprint of the player's tractor, another NPC vehicle, a highway car or a standing worker (the CARLA Traffic Manager "collision stage": a vehicle's box, stretched along its motion, is tested against everyone else's before it moves). Oriented boxes, separating-axis test.

Argument Description
Self The asking actor (ignored).
Centre Box centre, world metres.
Forward Unit heading of the box's long axis. HalfLengthM, HalfWidthM: Half the box length and width, m.
bVehiclesOnly Test only vehicles and the player's tractor, not workers (for workers' own steps).
bool Overlaps(const AActor* Self, const FVector2D& Centre, const FVector2D& Forward, double HalfLengthM, double HalfWidthM, bool bVehiclesOnly = false, const AActor** Hit = nullptr) const;

AAcresNpcDirector::RequestLot#

First-come-first-served reservation of the parking lot's aisle and entrance: one vehicle at a time parks, pulls out or drives through, so vehicles never meet nose to nose in the lot. Joins the queue if needed.

Returns: True when Who holds the lot.

bool RequestLot(const AActor* Who);

AAcresNpcDirector::ReleaseLot#

Gives the lot back (and leaves the queue).

void ReleaseLot(const AActor* Who);

AAcresNpcDirector::Incident#

Records a safety incident: appends a row to npc-events.csv, shows a HUD banner for a few seconds and logs a warning.

Argument Description
What Event name ("worker_struck").
Where World position, cm.
SpeedMps Tractor speed at the moment, m/s.
void Incident(const FString& What, const FVector& Where, double SpeedMps);

AAcresNpcDirector::ParkingSpots#

Parking spot centres at the Beck lot, world metres (two rows of 14 facing away from the aisle).

const TArray<FVector2D>& ParkingSpots() const ;

AAcresNpcDirector::SetupTraffic#

Spawns Count cars on US 52: both directions, two lanes each, looping forever (a car leaving the survey tile at one end reappears at the other). Models come from Content/Simulation/npc_cars.json; without it the Hilux pickup is used. Deterministic (fixed random seed). Called by Setup with -NpcTraffic=<n> (default 16 when -NpcVehicles is on).

Argument Description
Site Parsed site.json (for the US52 polyline).
Count Number of cars; 0 does nothing.
void SetupTraffic(const TSharedPtr<class FJsonObject>& Site, int Count);

AAcresNpcCar#

class AAcresNpcCar : public AActor

A highway traffic car: body mesh, spinning / steering wheels and a box collider.

Kinematic like AAcresNpcVehicle: the director decides the speed (Intelligent Driver Model car-following, braking for the car or tractor ahead in the lane) and calls Place() every frame; the actor has no Tick of its own, which keeps dozens of cars cheap. The box blocks the player's tractor (Chaos physics pushes the tractor out of it) and is tagged ACREObstacle / ACREVehicle.

AAcresNpcCar::Init#

Builds the visuals and the collider from a model.

Argument Description
InDirector The director (ground height).
Model Car model (meshes and dimensions).
Paint Colour for the model's paint slots (BaseColorFactor).
void Init(AAcresNpcDirector* InDirector, const FAcresCarModel& Model, const FLinearColor& Paint);

AAcresNpcCar::Place#

Moves the car to a road position, sets its pose on the ground from the four wheel contact points and rolls the wheels.

Argument Description
Where Ground position of the car centre, world metres.
YawDeg Heading, degrees (Unreal yaw).
Dt Frame time, s (0 on the first placement).
bTeleport True when jumping (spawn, wrap-around), so the physics body gets no velocity from the move.
void Place(const FVector2D& Where, double YawDeg, double Dt, bool bTeleport);

AAcresNpcVehicle#

class AAcresNpcVehicle : public AActor

A kinematic farm vehicle: one of our tractors repainted, or a pickup truck.

Behaviour loop: parked at its spot -> tractors drive to an empty field and till it in five passes, pickups drive to a service point -> drive back -> park. Speed follows the path with limits on acceleration and heading change; it yields to anything ahead (AAcresNpcDirector::Blocked). The body follows the ground (height and slope) each frame.

AAcresNpcVehicle::Tick#

Advances the behaviour and moves the vehicle along its path.

virtual void Tick(float Dt) override;

AAcresNpcVehicle::Init#

Builds the visuals and puts the vehicle in its parking spot. Call once, right after spawning.

Argument Description
InDirector The director that owns the roads and parking.
bTractor True for a tractor (copied from the player's tractor meshes), false for a pickup.
Spot Parking spot index (see AAcresNpcDirector::ParkingSpots).
Paint Body colour.
Seed Random seed for wait times and choices.
bStayParked True for a vehicle that stays in its spot all session (staff cars in the lot).
void Init(AAcresNpcDirector* InDirector, bool bTractor, int Spot, const FLinearColor& Paint, int Seed, bool bStayParked = false);

AAcresNpcVehicle::Footprint#

Current footprint: centre (world m), unit heading, half length and half width (m).

void Footprint(FVector2D& Centre, FVector2D& Forward, double& HalfLengthM, double& HalfWidthM) const;

AAcresNpcWorker#

class AAcresNpcWorker : public AActor

A farm worker who walks a beat (road shoulder or crop edge) and pauses to idle or inspect.

If the player's tractor overlaps the worker's position (tractor footprint about 5.4 x 2.9 m) at more than 0.7 m/s, the worker dies: physics ragdoll with an impulse along the tractor's path, a spreading blood decal, and an incident report through the director.

AAcresNpcWorker::Tick#

Walks the beat, checks for the player's tractor, and grows the blood pool after death.

virtual void Tick(float Dt) override;

AAcresNpcWorker::Init#

Sets up the meshes and the walking beat. Call once, right after spawning.

Argument Description
InDirector The director (ground height, blocking checks, incident log).
Beat Points to walk between, world metres; the worker loops through them.
bInspector True for a crop scout (long pauses, "inspect" animation), false for a road walker.
Seed Random seed for pause lengths.
void Init(AAcresNpcDirector* InDirector, const TArray<FVector2D>& Beat, bool bInspector, int Seed);

AAcresNpcWorker::IsDead#

True once the worker has been struck.

bool IsDead() const ;