Skip to main content

Shop System

This example shows a simple shop system using Reheaven.

The shop has coins, a selected item, and a purchase message.

Key Point

Shop actions change state. The UI reacts automatically.

Shop State

ShopState.lua
local signal = Reheaven.signal
local computed = Reheaven.computed

local coins, setCoins = signal(250)
local selectedItem, setSelectedItem = signal(nil)
local message, setMessage = signal("")

local itemCost = computed(function()
local item = selectedItem()

if item == "Sword" then
return 100
elseif item == "Shield" then
return 150
end

return 0
end)

local canBuy = computed(function()
return selectedItem() ~= nil and coins() >= itemCost()
end)

Shop Actions

ShopActions.lua
local function selectItem(itemName)
setSelectedItem(itemName)
setMessage(`Selected {itemName}`)
end

local function buySelectedItem()
if not canBuy() then
setMessage("Not enough coins")
return
end

Reheaven.batch(function()
setCoins(coins() - itemCost())
setMessage(`Purchased {selectedItem()}!`)
setSelectedItem(nil)
end)
end

Shop UI

ShopUI.lua
local effect = Reheaven.effect

effect(function()
coinsLabel.Text = `Coins: {coins()}`
end)

effect(function()
local item = selectedItem()

selectedItemLabel.Text = if item then `Selected: {item}` else "No item selected"
priceLabel.Text = `Price: {itemCost()}`
buyButton.Active = canBuy()
buyButton.AutoButtonColor = canBuy()
end)

effect(function()
messageLabel.Text = message()
end)

Button Input

ShopButtons.lua
swordButton.MouseButton1Click:Connect(function()
selectItem("Sword")
end)

shieldButton.MouseButton1Click:Connect(function()
selectItem("Shield")
end)

buyButton.MouseButton1Click:Connect(function()
buySelectedItem()
end)

Shop Flow

Button clicked

Shop action runs

Shop state changes

Computed values update

UI reacts
Server Authority

For real purchases, validate the purchase on the server.

The client can show shop UI, but the server should decide whether the player actually owns enough currency.