Repository navigation
Garage CarCatalog 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.
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 SubEvery 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. |
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)". |
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. |
Add(int carId, int colour = 0) → int
|
The same, by car id. |
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. |
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. |
-
Garage.Add,SetCurrent,Give,Profile.GetIntandProfile.SetIntthrow anInvalidOperationExceptionwhen no profile is loaded yet (still on the title screen). CheckProfile.IsLoadedfirst. -
SetCurrent(and soGive) 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 withSetInt. -
CarCatalognames are always in English, whatever the game's language. - Using
GarageorProfileoff the game thread throws anInvalidOperationExceptionthat says to useGame.TickorGame.Run. - On a game build the SDK doesn't know, the
Gameclass is off (see Game), soGarageandProfilecan't be used;platform.logsays why.CarCatalogstill works.
Playing
Getting started
Writing mods
The FH2 classes
- Game
- Player
- Vehicle
- World
- Garage, CarCatalog, Profile
- UI and Hud
- Camera
- Audio
- ANNA
- Skills
- DebugOverlay
- Controller
- GameInput
- GameWindow
- Menus and UiElement
- SettingsTile
- ButtonIcons and Picture
- MapView, PhotoCamera, GarageCamera
More