DUXPLIMA Documentation

Dealerships

Storefronts, who may open them, what they stock, and the sale prices.

A dealership is a storefront: a title, a way to open it, an optional access gate and a stock list. You can have as many as you like.

Dealerships = {
    {
        Id = "general",
        Title = "Vehicle Dealership",
        General = true,
        OpenKey = Enum.KeyCode.G,
        PromptPartName = "DealershipZone",
    },
    {
        Id = "civilian",
        Title = "Civilian Dealership",
        PromptPartName = "CivilianDealer",
    },
    {
        Id = "police",
        Title = "Police Dealership",
        PromptPartName = "PoliceDealer",
        Access = {
            Teams = { "Police" },
            GroupId = 0,
            GroupMinRank = 1,
            GamepassId = 0,
            OwnerOnly = false,
        },
    },
},
FieldDoes
IdThe internal name. Referenced by VehicleData.Dealerships
TitleThe panel heading, and the text on the proximity prompt
GeneralMarks the fallback storefront. Exactly one should have it
OpenKeyA keyboard shortcut that opens this storefront anywhere
PromptPartNameA part in the world folder that gets an E prompt
AccessWho may open it

Opening one

Three ways in:

RouteApplies to
The OpenKeyAny dealership that sets one. Ships as G on the general storefront
A proximity promptAny dealership with a PromptPartName
The on-screen buttonOpens the general storefront

The prompt is created on any part in the world folder whose name matches, including parts added after the server starts, so an NPC that spawns later still gets its prompt.

One prompt per part

A part that already has a ProximityPrompt is skipped. If you want your own prompt styling, add the prompt yourself and the system leaves it alone, but nothing will open the panel: the handler is attached to the prompt it creates.

Restyle the created prompt instead, or use a differently named part.

Who may open it

Access gates the whole storefront. Every configured dimension must pass.

FieldPasses when
TeamsThe player is on one of the named teams
GroupId and GroupMinRankThey are in the group at that rank or above
GamepassIdThey own the pass
OwnerOnlyThey are the game creator, or rank 255 in the owning group

0 and false mean "skip this check". A dealership with no Access table is open to everybody.

Two entries make an OR

There is no OR inside one Access table. To let either police or medics into the same showroom, define two dealership entries pointing at the same PromptPartName, one gated on each team.

Both prompts are created on the same part; only the one the player passes will open.

What each one stocks

A vehicle appears in a dealership when its Dealerships list names that dealership's Id. A vehicle with no Dealerships list appears only in the general storefront.

Vehicle rowSold in
Dealerships = { "general", "civilian" }Both of those
Dealerships = { "police" }The police storefront only
No Dealerships fieldThe general storefront only

The stock check runs on the server for both the listing and the purchase, so a client that asks to buy a police car from the civilian storefront is refused.

The panel

AreaShows
Top barBalance, garage slot counter, close
LeftThe vehicle list, search, filters, sort, an owned-only toggle
CentreThe 3D preview, the purchase button, the test drive button
RightName, category, description, price, the stat sheet, swatches, the plate button

Filters cover Type, Brand, Sort and Owned. Sort offers price low to high, price high to low, name and speed.

Discounts

Three sources, and the biggest one wins. They do not stack.

SourceConfigApplies to
VIPVip.GamepassId, DiscountPercentEverything, for pass owners
Daily dealDailyDeal.DiscountPercentOne car a day, the same for everybody
Flash saleFlashSale.DiscountPercentA rotating car, for a window
Vip = { GamepassId = 0, DiscountPercent = 10 },
DailyDeal = { Enabled = true, DiscountPercent = 25 },
FlashSale = { Enabled = true, DiscountPercent = 40, IntervalSeconds = 1800, DurationSeconds = 300 },

How the rotation is picked

Both rotations are derived from the clock rather than stored, so every server in your game agrees without talking to each other.

Daily dealThe day number since the epoch, modulo the number of eligible cars
Flash saleThe current interval window, modulo the same list

The eligible list is every car with OnSale = true and a price above zero, sorted by id.

Adding a car reshuffles both rotations

The list is indexed by position, not by id. Adding or removing a catalog row shifts everything after it, so today's deal changes the moment you publish.

Harmless day to day. Worth knowing if you have advertised tomorrow's deal.

With the shipped 1800 and 300, a flash sale runs for five minutes at the top of every half hour, on a different car each time. The countdown is shown on the card.

Trade-in

TradeIn = { Enabled = true, RefundPercent = 50 },

Selling an owned car back returns that percentage of its catalog price, rounded. Not of what the player paid: a car bought in a 40 percent flash sale and sold back at 50 percent returns more than it cost.

Discounts plus trade-in can be a money printer

Buy at 60 percent during a flash sale, sell back at 50 percent, and each cycle loses 10 percent. That is fine. Raise RefundPercent to 70, or stack a VIP discount on top of a deal, and the loop turns a profit for the player.

Keep RefundPercent comfortably below 100 minus your deepest discount.

Selling frees the garage slot. The saved paint, plate, fuel level and trunk contents stay on the profile under that vehicle id, so buying the same car again restores all of it.