Nemesis actors are the vehicles of a race that are not race players: the trucks of Survival, the cars of the attack modes and the helicopters. The game builds them at race start from the mode file's 24 selection slots, each naming a template file in GameLogic/Nemesis/. Survival's file names eight TruckTemplate.params and seven DemolitionTemplate.params; a Quick Race's names twenty-four None. The templates are offered in every mode, so a script can ask any race for trucks. An actor is a live object. Actors only exist within a race.

Asking for actors#

TypeFieldRead-only?Description
table ss.race.nemesis_slots No A list of template file names, applied by the hook when the next race builds its actors. nil restores the mode file's own slots. The list is kept until it is changed.

The list is set from main.lua, or from a state handler before the race loads; a list set during a race takes effect at the next one. Unknown names are skipped with a log line. There is no mid-race spawn: the actors need the setup context that only exists while the race is being built.

The choices are the fourteen files in GameLogic/Nemesis/: TruckTemplate.params (Survival's trucks), DemolitionTemplate.params (the attack modes' cars), HelicopterTemplate.params, TruckSurvivalRace.params and the rest. Any mode's race accepts any of them.

Static members#

These elements are static to the class itself and can be accessed like so:

local actors = ss.nemesis.all()

Static functions#

FunctionReturn ValuesDescription
ss.nemesis[integer index] actor actor Returns the actor at the given index, 0-based. Returns nil if there is no such actor.
ss.nemesis.count integer count The number of actors in the running race. 0 outside a race.
ss.nemesis.all() table of actor actors Returns a table of references to all actors in the running race.
ss.nemesis.each() function iterator Returns an iterator over all actors in the running race, for use in a for loop.

Instance members#

Instance members must be accessed through a reference to a specific actor object.

for n in ss.nemesis.each() do
	ss.log(n.kind, n.position, n.speed)
end
WARNING: Attempting to call instance members statically will result in an error!

Instance Fields#

TypeFieldRead-only?Description
boolean valid Yes Validates that the actor object exists in the running race.
string kind Yes truck, car or helicopter.
integer index Yes The actor's index, 0-based.
integer slot Yes A truck's physics slot.
vector position Yes The actor's position in metres. A truck's comes from its keyframed physics component, a car's from the pool vehicle its engine component keeps.
vector velocity Yes The actor's velocity in metres per second, on the world axes.
number speed Yes The length of the actor's velocity, in metres per second.
NOTE: Nothing on an actor is writable yet, and ss.nemesis is empty outside a race.
NOTE: A demolition car asked for in a mode that is not its own, such as a plain Race, reports no body: its position reads nil components, and distance on such a vector results in an error. Check n.position.x before measuring to a car. The trucks are unaffected. (?)

Instance Memory Offsets#

These offsets can be manipulated by the instance's mem method. They are relative to address, the 0x1a4-byte actor record.

WARNING: Be careful when manipulating memory offsets directly! Doing so may yield unexpected results.
FieldFieldtypeDescription
0x4 int The number of the actor's components.
0x8 pointer The actor's components.
0x8c int The actor's type: 0 helicopter, 1 truck, 2 car. Use field kind

Verified behaviour#

On the airport track, the Survival mode file alone built 15 actors, 8 trucks and 7 cars, each with its full component set. A plain Race asked for four trucks and two cars through ss.race.nemesis_slots received exactly those, and the trucks drove the circuit at about 20 m/s for the whole two minutes of the run, sweeping from one end of the track to the other, 8 m to 1 km from the player.

Example#

The Trucks sample asks every race for four of Survival's trucks and reports the nearest one:

ss.race.nemesis_slots = { "TruckTemplate.params", "TruckTemplate.params", "TruckTemplate.params", "TruckTemplate.params" }

ss.on("race_start", function()
	ss.log("%d actors on the track", ss.nemesis.count)
end)

ss.every(10, function()
	local car = ss.vehicle
	if not car then return end
	local nearest, dist
	for truck in ss.nemesis.each() do
		if truck.kind == "truck" then
			local d = truck.position:distance(car.position)
			if not dist or d < dist then nearest, dist = truck, d end
		end
	end
	if nearest then
		ss.log("nearest truck %d: %.0f m away at %.0f km/h", nearest.index, dist, nearest.speed * 3.6)
	end
end)