LimeCasino deployment math
Last updated
May be stale
This page was last updated ago, on 1 October 2026. Check what it says against the code before relying on it.
How CityRP’s pCasino machines are tuned, how to place them, and how players read the odds.
In-universe, the operator is LimeCasino: see the lore page.
Canonical machine configs live in addons/pcasino/presets/*.json. Runtime copies are generated into addons/pcasino/lua/perfectcasino/config/sh_presets.lua by the math toolkit. Do not hand-edit the Lua file.
Targets
| Machine | Bet | Volatility | Cash RTP |
|---|---|---|---|
| Classic Slots — Low | $500 | low-medium | 95% |
| Classic Slots — Mid | $1,000 | low-medium | 95% |
| Classic Slots — High | $2,500 | medium | 95% |
| Wheel Slots — Low | $5,000 | medium | 95% |
| Wheel Slots — Mid | $10,000 | medium-high | 95% |
| Wheel Slots — High | $25,000 | medium-high | 95% |
| Mystery Wheel | free spin only | high | n/a (prize wheel) |
Cash RTP is expected cash returned per dollar wagered over the long run, including:
- line / pair pays
- jackpot pot payouts (player
betAddcontributions and thestartValuere-seed pCasino injects after every jackpot hit) - mini-wheel cash and mini-wheel jackpots
- the cash expected value of Mystery Wheel spins earned as mini-wheel prizes
Non-tradable item prizes (cars, Dragon’s Breath, etc.) are $0 toward cash RTP. They are prestige odds, tracked separately.
House edge on cash is therefore ~5%. Items do not inflate the money supply when won.
How pCasino RNG actually works
There are no reel strips and no built-in RTP field.
- Slots build a weighted bag from
chanceweights and pick three symbols independently (table.Random). - Combos are matched with “best pay / jackpot preferred” rules in
CheckForCombo. - Cash line payout is
bet * (1 + p)(stake returned plus profit multiplierp). - Mini-wheel (advanced) and Mystery Wheel are uniform:
math.random(12)/math.random(20). Rarity = fewer segments of that prize, not weighted slices.
So “higher bet → better chance at a Big Wheel spin” is done by putting more prize_wheel segments on that machine’s mini-wheel (1 / 2 / 3 of 12), with chest rates climbing modestly as well.
Mystery Wheel layout (20 × 5%)
Free spins only (buySpin.buy = false).
| Kind | Count | Notes |
|---|---|---|
| Nothing | 4 | |
| Cash | 9 | $1 … $100,000 |
| Spin Again | 1 | recursive; raises cash EV slightly |
| Consolation items | 2 | Trabbi, Golden Vape |
| Grand prizes | 3 | Dragon’s Breath, BMW M3 GTR, Kawasaki Ninja |
| Extra car | 1 | BMW i8 |
Expected cash from one spin is about $10,211 (items excluded). That figure is folded into advanced-slot RTP when a mini-wheel awards prize_wheel.
Grand prize odds on the wheel itself: 5% per named segment (1 in 20). Getting onto the wheel is the scarce part — see each advanced machine’s “Big Wheel chance / spin” in /odds.
Mini-wheel design
| Advanced machine | Big Wheel segments | Jackpot segments | Rest |
|---|---|---|---|
| $5,000 | 1/12 | 1/12 | cash + nothing |
| $10,000 | 2/12 | 1/12 | cash + nothing |
| $25,000 | 3/12 | 1/12 | cash + nothing |
Mini-wheel cash amounts are multiples of that machine’s bet. Items stay on the big wheel so the prize hierarchy stays clear.
Jackpot startValue footgun
After a jackpot pays, pCasino resets the pot to startValue. That seed is new money created each cycle, not player contributions. Exact RTP must include P(jackpot award) × startValue / bet on top of the betAdd contribution rate. Ignoring it makes advanced machines look “95%” on paper while simulating well over 100% cash return.
Presets keep startValue modest (about 5× bet on classic, 1× bet on wheel slots) so the seed does not dominate.
Placing machines (staff)
- Equip the pCasino toolgun → right-click to open the config menu.
- Pick the entity type (Slot Machine / Wheel Slot Machine / Mystery Wheel).
- Open Load LimeCasino Preset and click the matching preset.
- Left-click to place. Settings are saved into
pcasino_entsas usual.
JSON under addons/pcasino/presets/ is the hand-config recipe if you ever need to type values manually.
Player transparency
/odds opens a browser of the published presets: bet, volatility, cash RTP, paylines with probabilities, mini-wheel segments, and Mystery Wheel segments. It reads the same data the toolgun loads — not live entity drift — so what players see matches what we intended to deploy.
Proving the math
Player-facing guide (Lua ↔ Python mapping, item hunts, FAQ):
addons/pcasino/tools/README.md
From that folder:
python3 casino_math.py --spins 500000
python3 casino_math.py --hunt bmwm3gtr46 --skip-rtp
python3 casino_math.py --list-items
The toolkit:
- enumerates every weighted reel outcome (exact RTP / hit rate)
- folds mini-wheel + Mystery Wheel cash EV into advanced RTP
- Monte Carlo–checks cash return and house net
--hunt <item_id>— expected spins / $ wagered / net cash to a Mystery prize on each advanced machine- runs a rough multi-machine floor stress mix
Regenerate sh_presets.lua whenever you edit a JSON preset:
python3 casino_math.py --emit-lua ../lua/perfectcasino/config/sh_presets.lua --skip-rtp
Hunt equalization (advanced machines)
Single-segment Mystery items (M3 GTR, Ninja, Dragon’s Breath, Rolex, Police Uniform, i8, …) are tuned so **expected cash cost is the same** on Adv Low / Mid / High ($7.5M wagered, ~$375k expected net loss at 95% RTP). Magical Cake has two wheel segments, so it is roughly twice as likely. Per-spin odds still rise with bet (1 → 2 → 3 Big Wheel mini-segments, plus chest rate).
Casino-granted i8 / Rolex / Police Uniform / Magical Cake stacks carry hidden tradable=false metadata and cannot be given, dropped, or inventory-sold. Trabbi stays tradable.
Economy notes
- Cars / Dragon’s Breath are bound / non-tradable — flashy without a cash secondary market.
- Mystery Wheel cash is real money; it is budgeted inside the 95% advanced RTP, not stacked on top.
- Expect session variance: published RTP is long-run. Short samples on high-volatility wheel slots will swing around 95%.
- Access tag
Pand/selfexcludestill gate play — but only new bets. An advanced machine's pending Big Wheel spin (won on a bet placed before an exclusion landed) can still be claimed;pcasino_wheel_slot_machine:Use()lets that claim through before the bet-gate check runs.
Session gambling monitoring
gamemode/core/plugins/pcasino/sv_init.lua keeps two per-sitting tallies for every player, fed by pCasinoMoneyChanged (all machine types, since every cash movement routes through PerfectCasino.Config.AddMoney):
- Net loss (
cityrp.pcasino.SessionNet) — stakes minus payouts, floored at zero. What the player is actually down. - Turnover (
cityrp.pcasino.SessionWagered) — everything staked, however it resolved. Catches the long grinder whom variance kept afloat.
Non-cash prizes (Mystery Wheel items) move neither tally, so a player who wins an expensive item still reads as down whatever cash they staked for it.
- Warning tiers (
cityrp.pcasino.WarningTiers) escalate on a single shared ladder that either tally can advance: $100k net loss or $2M staked → in-game reminder pointing at/selfexclude; $200k / $4M → second reminder, which also logs to the admin hub. Each tier fires once per session and the notice names whichever tally actually tripped. The loss floor sits well above a single top-tier spin (advanced_high stakes $25,000) so one unlucky bet never reads as a loss pattern — tier 1 needs 4 full losses back to back. - Auto-exclusion tiers (
cityrp.pcasino.AutoExcludeTiers) escalate on their own single shared ladder the same way: $250k net loss or $5M staked → 15 minutes; $750k / $15M → 1 hour; $1.25M / $25M → 24 hours (played time). Each fires via the samecityrp.access.selfTakeAccesspath/selfexcludeuses and alerts staff. Neither tally is reset when a tier fires, so a player who keeps playing once a short exclusion lifts escalates straight to the next tier instead of restarting the clock.
Both ladders are shared rather than per-tally, so a player can be notified at most twice by warnings and excluded at most three times total — reaching a tier via loss and later via turnover doesn't fire it twice.
The turnover thresholds sit at 20× their matching loss thresholds, which is roughly where an average-luck player at the published 95% RTP would be down the loss figure — so on typical luck the two ladders reach a tier at about the same time, the loss ladder fires first for an unlucky player, and the turnover ladder still eventually catches a lucky one.
Both tallies reset on disconnect — this is a same-sitting safeguard, not a persistent affordability check. Tune the thresholds if machine bets/RTP change enough that normal variance starts tripping them.