Skip to content

Garage CarCatalog Profile

Bartholomew Ho edited this page Nov 9, 2026 · 1 revision

Garage, CarCatalog and Profile

Three small classes for your cars and your save: CarCatalog finds any car in the game by name, Garage gives you cars and picks your current one, and Profile reads and writes the profile's values.

Thread: Garage and Profile: game thread only (Game.Tick, Game.Run, an ANNA entry). CarCatalog: any thread, even before the game starts.

Example

A console command that finds a car by name and puts it in your garage.

protected override void OnInit()
{
    AddCommand("givecar", "adds a car to your garage, by name", query =>
    {
        var car = CarCatalog.Find(query).FirstOrDefault();
        if (car is null) return "no car called " + query;
        Game.Run(() =>
        {
            int garageId = Garage.Add(car);
            Log(garageId > 0 ? $"added {car.FullName}" : "the game didn't add it");
        });
        return "adding " + car.FullName;
    });
}
Protected Overrides Sub OnInit()
    AddCommand("givecar", "adds a car to your garage, by name",
        Function(query)
            Dim car = CarCatalog.Find(query).FirstOrDefault()
            If car Is Nothing Then Return "no car called " & query
            Game.Run(
                Sub()
                    Dim garageId = Garage.Add(car)
                    Log(If(garageId > 0, $"added {car.FullName}", "the game didn't add it"))
                End Sub)
            Return "adding " & car.FullName
        End Function)
End Sub

CarCatalog

Every car in the game, by name. It reads the game's own (English) car names from its files, so it works anywhere, on any thread, even before the game starts.

Member What it does
All (property, get, IReadOnlyList<CarInfo>) All the cars, sorted by name. Empty if the game's files couldn't be read.
Get(int id) → CarInfo? The car with id, or null.
Find(string query) → IReadOnlyList<CarInfo> Cars whose names contain every word of query ("camaro ss"), ignoring case. If query is a number, the car with that id.

CarInfo

A car the game has. It's a record: CarInfo(int Id, string ShortName, string FullName).

Member What it does
Id (property, get, int) The car's id, as Vehicle.ModelId and Garage.Add use it.
ShortName (property, get, string) The short name, for example "Chevy Camaro SS".
FullName (property, get, string) The full name, for example "Camaro SS Coupe".
ToString() → string The short name and id, as "ShortName (Id)".

Garage

Your cars: give one, and make one your current car, the way the game's own gift cars and Pause > My Cars do.

Member What it does
Add(CarInfo car, int colour = 0) → int Adds car to your garage, free (as a gift is). Returns its garage id, or 0 if the game didn't add it. ⚠️ Not tested much in the game yet.
Add(int carId, int colour = 0) → int The same, by car id. ⚠️ Not tested much in the game yet.
SetCurrent(int garageId) Makes the car with garageId your current car, as Pause > My Cars does.
Give(CarInfo car, int colour = 0) → int Adds car and makes it your current car. Returns its garage id, or 0.

Profile

The current profile's values, by the game's own keys: "Main/Credits", "Main/Level", "Main/NumSkillTokens", "Main/CareerCar", "Main/TractionControl", "Main/TopSpeed"... (the game has about 200).

Member What it does
IsLoaded (property, get, bool) True when a profile is loaded (you're past the title screen).
GetInt(string key) → int The number under key ("Main/Credits"). 0 if the profile doesn't have that key.
SetInt(string key, int number) Sets the number under key.

Notes

  • Garage.Add, SetCurrent, Give, Profile.GetInt and Profile.SetInt throw an InvalidOperationException when no profile is loaded yet (still on the title screen). Check Profile.IsLoaded first.
  • SetCurrent (and so Give) makes the car current, as My Cars does, but doesn't swap the car you're driving there and then. That happens the next time the game loads your car: a house, a race, fast travel (or at once with Extra Options' "change car anywhere").
  • Garage ids (from Add, Player.CurrentGarageId) are not the same as car ids (CarInfo.Id, Vehicle.ModelId).
  • Profile values are whole numbers only. Writing one changes the save the next time the game saves it.
  • Some profile keys the game keeps in step with other data. Change those through the classes that know them (Player, Garage) rather than with SetInt.
  • CarCatalog names are always in English, whatever the game's language.
  • Using Garage or Profile off the game thread throws an InvalidOperationException that says to use Game.Tick or Game.Run.
  • On a game build the SDK doesn't know, the Game class is off (see Game), so Garage and Profile can't be used; platform.log says why. CarCatalog still works.

See also

Clone this wiki locally