Aliveskan Autopaa
A car dealership mod for My Winter Car built on MSCLoader. It adds a dealership building to the world and a public API so other mods can list cars for sale.
What it does
- Spawns a functional dealership building near highway
Dealership.RegisterCar()so other mods can list cars for sale.- Each registered car is placed on a parking spot, made kinematic, and has its ignition FSMs disabled until purchased.
- A window sticker is spawned on the car. Hovering it shows the car name and subtitle.
- On purchase the car is unfrozen, the sticker is removed, and your
onPurchasecallback fires.
Installation
Requirements
- MSCLoader 1.3.3 or newer
Steps
- Place
Aliveskan_Autopaa.dllinMods/. - Place
dealership.unity3dinMods/Assets/Aliveskan_Autopaa/. - Launch the game. The dealership appears automatically when a save is loaded.
Registering a Car
Call Dealership.RegisterCar() from your mod's OnLoad(). The dealership handles placement, sticker spawning, freeze state, and the purchase flow.
private void Mod_OnLoad()
{
GameObject myCar = GameObject.Find("MYCAR");
string texPath = Path.Combine(
ModLoader.GetModAssetsFolder(this), "listing.png");
Dealership.RegisterCar(
mod: this,
carID: "mymod_mycar",
carName: "1994 Rivett Coupe",
subtitleText: "1994 Rivett Coupe - 45 000 mk",
price: 45000f,
listingTexturePath: texPath,
carObject: myCar,
lotRotation: Quaternion.Euler(0f, -90f, 0f),
stickerLocalPosition: new Vector3(0f, 0.6f, 0.42f),
stickerLocalRotation: Quaternion.Euler(0f, 0f, 0f),
stickerScaleX: 0.28f,
stickerScaleY: 0.28f,
onPurchase: OnCarPurchased
);
}
private void OnCarPurchased(ParkingSpot spot)
{
Dealership.UnfreezeCarOnPurchase(myCar);
}
Sticker Positioning
The window sticker is parented to your car. You adjust its position, rotation, and scale through the parameters of RegisterCar().
| Parameter | Type | Description |
|---|---|---|
stickerLocalPosition | Vector3 | Position relative to the car root. |
stickerLocalRotation | Quaternion | Rotation relative to the car root. |
stickerScaleX | float | Horizontal scale of the sticker quad. |
stickerScaleY | float | Vertical scale of the sticker quad. |
Use a PNG with a transparent background so it blends with the glass, we reccomend Delicious Handrawn Font for custom text.
Freeze and Ignition Lock
The dealership automatically freezes registered cars and locks their ignition on load. You are responsible for calling the unfreeze helper when the player buys the car.
What happens automatically
- When
RegisterCar()is called, the car is moved to its spot, set kinematic, and itsStarter,Engine, andIgnitionPlayMaker FSMs are disabled. - After all mods finish loading,
PostLoadFlush()re-applies the freeze and ignition lock to all unsold registered cars.
What you must do
Call this inside your onPurchase callback:
Dealership.UnfreezeCarOnPurchase(myCar);
UnfreezeCarOnPurchase() the car stays frozen after purchase and the player cannot drive it.Manual helpers
Both helpers can be called at any time outside of the purchase flow:
Dealership.FreezeCarForSale(car);
Dealership.UnfreezeCarOnPurchase(car);
FSMs that are locked
The lock disables every PlayMakerFSM on the car (including children) whose FsmName is one of:
StarterEngineIgnition
If your car uses different FSM names for its start logic, disable and re-enable those yourself in addition to calling the helpers.
Purchase Callback
The onPurchase delegate fires the moment a player confirms a purchase. Its signature is:
Action<ParkingSpot> onPurchase
The ParkingSpot argument is the spot the car was on. You can read its WorldPosition or SpotIndex if needed.
private void OnCarPurchased(ParkingSpot spot)
{
Dealership.UnfreezeCarOnPurchase(myCar);
GiveKeyToPlayer();
ModConsole.Log("sold at spot " + spot.SpotIndex);
}
Dealership.RegisterCar
public static DealerListing RegisterCar(
Mod mod,
string carID,
string carName,
string subtitleText,
float price,
string listingTexturePath,
GameObject carObject,
Quaternion lotRotation,
Vector3 stickerLocalPosition,
Quaternion stickerLocalRotation,
float stickerScaleX,
float stickerScaleY,
Action<ParkingSpot> onPurchase
)
Registers a car for sale at the dealership.
| Parameter | Type | Required | Description |
|---|---|---|---|
mod | Mod | Yes | Your mod instance (this). Used for the mod ID. |
carID | string | Yes | Unique identifier for this car. Use a namespaced string like "mymod_mycar". |
carName | string | Yes | Display name shown in GUIinteraction when hovering the sticker. |
subtitleText | string | Yes | Caption text shown below the crosshair when the player looks at the sticker. |
price | float | Yes | Price in markka. Deducted from PlayerMoney on purchase. |
listingTexturePath | string | Yes | Absolute path to a PNG used as the sticker texture. |
carObject | GameObject | Yes | The car root. Moved to the parking spot immediately on registration. |
lotRotation | Quaternion | Yes | World rotation the car will have when parked on the lot. |
stickerLocalPosition | Vector3 | Yes | Local position of the sticker quad relative to the car root. |
stickerLocalRotation | Quaternion | Yes | Local rotation of the sticker quad. |
stickerScaleX | float | Yes | Horizontal scale of the sticker quad. |
stickerScaleY | float | Yes | Vertical scale of the sticker quad. |
onPurchase | Action<ParkingSpot> | Yes | Callback fired when the player buys the car. Call UnfreezeCarOnPurchase() here. |
Returns a DealerListing reference, or null if validation failed. Check the MSCLoader console for error messages.
Dealership.FreezeCarForSale
public static void FreezeCarForSale(GameObject car)
Sets isKinematic = true on the car's Rigidbody and disables its Starter, Engine, and Ignition PlayMaker FSMs. Called automatically by RegisterCar() and PostLoadFlush(). Call manually if you need to re-freeze the car at a later point.
| Parameter | Type | Description |
|---|---|---|
car | GameObject | The car root GameObject. |
Dealership.UnfreezeCarOnPurchase
public static void UnfreezeCarOnPurchase(GameObject car)
Sets isKinematic = false and re-enables the Starter, Engine, and Ignition FSMs. Call this inside your onPurchase callback.
| Parameter | Type | Description |
|---|---|---|
car | GameObject | The car root GameObject. |
Dealership.GetListings
public static List<DealerListing> GetListings()
Returns all registered DealerListing objects, including sold ones. Use this if you need to read the current inventory from another mod.
DealerListing
Data class representing one car for sale. Returned by RegisterCar().
| Field | Type | Description |
|---|---|---|
ModID | string | ID of the mod that registered this car. |
CarID | string | Unique car identifier. |
CarName | string | Display name. |
SubtitleText | string | Yellow GUI caption text. |
Price | float | Price in markka. |
ListingTexture | Texture2D | Loaded sticker texture. |
CarObject | GameObject | The car root GameObject. |
LotRotation | Quaternion | Rotation the car has when parked on the lot. |
StickerLocalPosition | Vector3 | Local position of the sticker. |
StickerLocalRotation | Quaternion | Local rotation of the sticker. |
StickerScaleX | float | Horizontal scale of the sticker. |
StickerScaleY | float | Vertical scale of the sticker. |
SpotIndex | int | Index of the assigned parking spot (0 to 9). Assigned automatically. you cannot choose it. |
Purchased | bool | true after the player has bought this car. |
OnPurchase | Action<ParkingSpot> | Your purchase callback. |
ParkingSpot
MonoBehaviour attached to each numbered spot transform in the dealership prefab.
| Member | Type | Description |
|---|---|---|
SpotIndex | int | Zero-based index of this spot (0 to 9). |
Listing | DealerListing | The listing assigned to this spot, or null if empty. |
WorldPosition | Vector3 | World position of the spot transform. |
IsOccupied | bool | true if a listing is assigned to this spot. |
FAQ
RegisterCar() from OnLoad(). The dealership freezes cars at load time but only the ones it knows about. If your car is not in the hardcoded freeze list, add a kinematic lock in your own PreLoad() by calling FreezeCarForSale() there. Then call RegisterCar() in OnLoad() as normal.listingTexturePath points to a PNG that exists on disk. Check the MSCLoader console for a warning from [Aliveskan]. If the path is correct but the sticker is blank, make sure the PNG is in RGBA format and is not corrupted.Starter, Engine, or Ignition. If your car uses different FSM names for its start logic, disable those FSMs yourself in OnLoad() and re-enable them in your onPurchase callback.Dealership.UnfreezeCarOnPurchase(myCar) inside your onPurchase callback. The dealership does not call this for you.