Documentation

Casino

Rollhaus, the online casino in the laptop's browser.

Rollhaus (rollhaus.gg) is an online casino built into the browser: in-house originals, live tables, PvP games, cases and case battles, a live bets feed and a wallet. Players deposit bank money as credits, play with them and withdraw them back to the bank. It is a built-in clearnet site, so it needs an internet connection like any other site and shows up in search results and LS Pages.

Everything is under Config.Settings.casino in shared/unlocked/config.lua, and each game has its own file in shared/unlocked/casino/. See Config for every key.

#Turning It Off

Set Config.Settings.casino.enabled = false, for example on servers with young players or where even simulated gambling isn't allowed. The site is then gone from the browser, search and LS Pages, every casino request is refused, nothing of it runs on the server and none of its tables are created. The IsCasinoEnabled export still answers, with false.

To remove a single game, set enabled = false in its own file, such as shared/unlocked/casino/dice.lua.

#Games

GameSectionFileWhat it is
DiceOriginalsdice.luaA roll from 0.00 to 99.99, bet on over or under a target. 1% edge.
LimboOriginalslimbo.luaPick a target multiplier, win when the result reaches it. 1% edge.
MinesOriginalsmines.luaA 5×5 board with 1 to 24 mines, cash out after any gem. 1% edge.
PlinkoOriginalsplinko.luaA ball falls through 8 to 16 rows of pegs into a bucket. Payout tables return 99%.
KenoOriginalskeno.luaPick 1 to 10 of 40 numbers, the server draws 10. Payout tables return about 99%.
HiloOriginalshilo.luaGuess whether the next card is higher or lower, cash out after one correct guess. 1% edge per guess.
TowerOriginalstower.luaClimb nine floors by picking a safe tile on each. 2% edge. Rounds stay open until the player cashes out or falls.
WheelOriginalswheel.luaA wheel of 10 to 50 multiplier segments, low to high risk. 1% edge.
CrashLivecrash.luaOne shared round for the server: a multiplier climbs until it crashes, cash out before it does. 1% edge.
RouletteLiveroulette.luaOne shared European single-zero spin for the server, every bet paid at table odds. 2.70% edge.
BlackjackLiveblackjack.luaLive tables with several seats against one dealer from a shared shoe.
CoinflipPvPcoinflip.luaPick a side and a stake, another player or a bot takes the other side. 5% rake.
CasesCasescases.luaOpen 1 to 4 of a case at once. Won items go to the player's vault.
Case BattlesCasesbattles.luaEvery seat opens the same cases, the best total takes every item. Modes 1v1, 1v1v1, 1v1v1v1, 2v2 and 3v3, plus "crazy" and "terminal".

Each file holds the game's enabled, its edge or rake, minBet and maxBet in credits, maxProfit where it applies, and the game's own settings, each explained in a comment. Payouts round down to whole cents, so stakes below 1 credit return a little less than the edge suggests.

Blackjack's tables are listed under tables in blackjack.lua, each with its own limits and 5 to 7 seats. With playerTables.enabled, players open their own tables from the lobby to play with friends, optionally behind a password; these never get bots and close once nobody has sat at them for closeSeconds. The house rules (decks, 3:2 payout, soft 17, doubling, splits, insurance, surrender) are under rules.

#Money

Credits are kept as whole cents in the database, by the character, so every character has their own wallet. creditRate is the dollars one credit costs, 1.0 by default. On the first visit a player picks a username, 3 to 16 letters, digits or underscores, and can hide it from the public feeds in the site's settings.

  • Deposit checks the bank and takes whole dollars from it in one step, then adds the credits and their ledger row in one transaction. If that transaction fails, the dollars go back to the bank. deposit.min and deposit.max limit one deposit.
  • Withdraw takes the credits and writes the ledger row first, then pays whole dollars into the bank. Cents left over stay on the site. The credits are only refunded when the player is gone before the payment is made, never after it. withdraw.min, withdraw.max and withdraw.cooldown (seconds between two withdrawals) limit it.
  • Bets take the stake when a round starts and pay out when it settles. Each step is one database transaction.
  • Restarts: a round still open when the resource stops is settled on the next start by its game, such as a Tower round with a floor cleared being cashed out at that floor, or refunded.

Every balance change writes a row with the balance after it to zyke_laptop_casino_ledger, as deposit, withdraw, bet, payout, refund, sell or adjust. The ledger is never deleted. Settled bets and revealed round seeds are kept for historyDays, for the player's history and bet details.

The server console prints [casino] lines for failed bank payments, refunds and rounds that could not be settled. Deposits, withdrawals and credit adjustments by other resources are also sent as Discord logs through zyke_lib.

#Age Check

minAge is the age in years a character must be, worked out from the date of birth the framework stores. 0, the default, turns the check off. Characters without a readable date of birth are let in.

#Your Own Rules

CanUseCasino(plyId) in server/unlocked/hooks.lua runs before every casino action. Return false and a locale key to keep a player out, for example to require a job or a licence. casino:error:notAllowed is shown when no key is given. See Can-Check Hooks.

lua
-- my_licences stands for your own licence resource
function CanUseCasino(plyId)
    if (exports.my_licences:HasLicence(plyId, "gambling")) then return true end

    return false, "casino:error:notAllowed"
end

minAge is checked separately, after the hook. A player also needs their laptop on and online.

#Bots

bots fills the seats a real site would have other people in. Their money is the house's: nobody is paid when a bot wins.

KeyEffect
enabledTurns every bot off when false.
feedMixes bot bets into the live bets feed, never into anyone's history. feedInterval is the seconds between two.
coinflipLets a coinflip's creator call a bot to take the other side.
battlesLets bots fill the empty seats of a case battle.
blackjackBots playing basic strategy at the live blackjack tables, off by default. botSeats in blackjack.lua caps the seats they take.
crashBots betting in each Crash round. Their count is in crash.lua.

Roulette's bots are set in roulette.lua and also need bots.enabled.

#Live Bets Feed

The feed shows All bets, High rollers and the player's own bets. feed.size is the rows each list keeps, and feed.highRoller the stake in credits that counts as a high roller.

#Fairness

Every result is decided on the server; the client only sends the player's choices. Results are provably fair, the way crypto casinos do it:

  • Each player has a secret server seed, shown to them only as its SHA-256 hash, a client seed they can change, and a nonce that counts their bets. A result comes from HMAC_SHA256(serverSeed, "clientSeed:nonce:cursor"), four bytes per number between 0 and 1.
  • Rotating the seed in the site's Fairness window reveals the old server seed, so the player can check every bet made with it against the hash they were shown. The window has a verifier that recomputes any result. Rotating is refused while an open round still uses the seed.
  • Shared rounds (Crash, Roulette, Blackjack, Coinflip and Case Battles) commit a round seed and show its hash before the result, then reveal it.

#Cases & Items

The cases are Config.Casino.cases in shared/unlocked/casino/cases.lua, below the game's settings, and the items they drop are Config.Casino.items in shared/unlocked/casino/items.lua.

  • A case is {id, label, price, image, drops}, its price in credits. Each drop is {item, weight}. The weights are relative, and each default case totals about 100000, so a weight of 1 is a 0.001% chance.
  • An item is id = {label, category, rarity, value, image}, its value in credits. The rarities are common, uncommon, rare, epic, legendary and mythic.
  • Images are paths under the casino's NUI folder, such as cases/tech_drop.webp and items/cut_ruby.webp.
  • Keep each case's expected value, the sum of weight * value over its total weight, at about 92% of its price. A case worth more than it costs gives credits away.

Won items stay in the player's vault on the site and sell back for the value they had when they were won. They are not inventory items. demo = true offers free demo spins that show what a case can drop. vaultLimit is the items the vault page lists.

A drop naming an item that isn't in items.lua, or with a weight below 1, leaves its whole case out, with a warning in the server console.

#Exports

Other resources read and change wallets on the server:

ExportDescription
IsCasinoEnabledWhether the casino is on.
GetCasinoBalanceCredits in a wallet, in cents, by server id or character identifier.
AdjustCasinoCreditsGives or takes credits in cents, written to the ledger with a reason.

The server events zyke_laptop:CasinoDeposited, zyke_laptop:CasinoWithdrawn and zyke_laptop:CasinoCreditsAdjusted fire on every deposit, withdrawal and adjustment. See Exports & Events.