Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- SERVICES --
- local TweenService = game:GetService("TweenService")
- local ReplicatedStorage = game:GetService("ReplicatedStorage")
- local Players = game:GetService("Players")
- -- PLAYER REFERENCE --
- local player = Players.LocalPlayer -- Reference to local player to access in-game currency (leaderstats)
- -- UI ELEMENT REFERENCES --
- local submitBet = script.Parent
- local kenoFrame = submitBet:FindFirstAncestor("KenoFrame")
- local tilesFolder = kenoFrame.Menu:WaitForChild("Tiles")
- local betInput = kenoFrame.PaymentBar.CashFrame:WaitForChild("BetInput")
- local riskOptions = kenoFrame.PaymentBar:WaitForChild("RiskOptions")
- -- SOUND REFERENCES --
- local gemSound = kenoFrame.Menu:WaitForChild("Gem")
- local otherSound = kenoFrame.Menu:WaitForChild("Other")
- -- REMOTE EVENTS --
- local deductCash = ReplicatedStorage:WaitForChild("DeductCash")
- local addCash = ReplicatedStorage:WaitForChild("AddCash")
- -- CONSTANTS & UI COLORS --
- local COLORS = {
- defaultText = Color3.fromRGB(255, 255, 255),
- defaultBlock = Color3.fromRGB(47, 69, 83),
- missedBlock = Color3.fromRGB(7, 29, 42),
- redText = Color3.fromRGB(255, 0, 0),
- shadeDefault = Color3.fromRGB(33, 55, 67),
- shadeSelected = Color3.fromRGB(113, 0, 199),
- blockSelected = Color3.fromRGB(155, 41, 251),
- }
- local jumpOffset = UDim2.new(0, 0, -0.02, 0) -- Offset for a subtle 'jump' animation on selection
- local maxSelections = 10 -- Limit how many tiles can be selected per round
- local Multipliers = require(script.Multipliers) -- Loaded from external ModuleScript for scalability
- -- RUNTIME STATE --
- local debounce = false -- Prevents input spamming (used during animations)
- local animatingRound = false -- Blocks interaction mid-round
- local selectedTiles = {} -- Array of user-chosen tiles
- local selectedRisk = nil -- Current selected risk difficulty
- local lastTweenTime = {} -- Time tracking to prevent frequent animation spam on same element
- ---------------------------------------------------------------------------------------------------
- -- RISK BUTTON HANDLING
- -- Resets all risk buttons to default appearance
- local function resetRiskButtons()
- for _, btn in ipairs(riskOptions:GetChildren()) do
- if btn:IsA("TextButton") then
- btn.BackgroundColor3 = COLORS.defaultBlock
- end
- end
- end
- -- Visually activates a selected risk button and stores choice
- local function setRiskButton(btn)
- selectedRisk = btn.Name
- btn.BackgroundColor3 = COLORS.blockSelected
- end
- -- Handles a player clicking a risk button
- local function handleRiskButtonClick(btn)
- -- Guard clause: Ignore clicks during animation or if button is disabled
- if animatingRound or not btn.Active then return end
- resetRiskButtons()
- setRiskButton(btn)
- end
- -- Attach handler to each risk option
- for _, btn in ipairs(riskOptions:GetChildren()) do
- if btn:IsA("TextButton") then
- btn.MouseButton1Click:Connect(function()
- handleRiskButtonClick(btn)
- end)
- end
- end
- ---------------------------------------------------------------------------------------------------
- -- TILE INTERACTION
- -- Animates selected shade and block to highlight user selection
- local function playSelectAnimation(shade, block)
- TweenService:Create(shade, TweenInfo.new(0.2), {BackgroundColor3 = COLORS.shadeSelected}):Play()
- TweenService:Create(block, TweenInfo.new(0.2), {BackgroundColor3 = COLORS.blockSelected}):Play()
- end
- -- Reverts visual feedback on deselection
- local function playDeselectAnimation(shade, block)
- TweenService:Create(shade, TweenInfo.new(0.2), {BackgroundColor3 = COLORS.shadeDefault}):Play()
- TweenService:Create(block, TweenInfo.new(0.2), {BackgroundColor3 = COLORS.defaultBlock}):Play()
- end
- -- Simulates a 'jump' when a tile is selected
- local function animateJump(block)
- local origPos = block.Position
- local tweenUp = TweenService:Create(block, TweenInfo.new(0.1), {Position = origPos + jumpOffset})
- local tweenDown = TweenService:Create(block, TweenInfo.new(0.1), {Position = origPos})
- tweenUp:Play()
- tweenUp.Completed:Wait()
- tweenDown:Play()
- end
- -- Handles logic when a tile is clicked: toggles selection
- local function handleTileClick(shade, block)
- if debounce or animatingRound then return end
- -- Prevent repeated rapid animation
- local now = tick()
- if lastTweenTime[block] and now - lastTweenTime[block] < 0.3 then return end
- lastTweenTime[block] = now
- local index = table.find(selectedTiles, block)
- if index then
- table.remove(selectedTiles, index)
- playDeselectAnimation(shade, block)
- if block:FindFirstChild("Gem") then block.Gem.Visible = false end
- return
- end
- if #selectedTiles >= maxSelections then return end
- table.insert(selectedTiles, block)
- playSelectAnimation(shade, block)
- animateJump(block)
- end
- -- Connect all clickable tiles to the handler
- for _, shade in ipairs(tilesFolder:GetChildren()) do
- if shade:IsA("Frame") and shade.Name == "ShadeColor" then
- local block = shade:FindFirstChild("Block")
- if block and block:IsA("TextButton") then
- block.MouseButton1Click:Connect(function()
- handleTileClick(shade, block)
- end)
- end
- end
- end
- ---------------------------------------------------------------------------------------------------
- -- GAME LOGIC UTILITIES
- -- Ensures all conditions are met before allowing a round to start
- local function validatePlay(bet)
- if debounce or animatingRound then return false end
- if not bet or bet <= 0 or not selectedRisk then return false end
- if #selectedTiles < 1 or #selectedTiles > 10 then return false end
- local stats = player:FindFirstChild("leaderstats")
- local cash = stats and stats:FindFirstChild("Cash")
- return cash and cash.Value >= bet
- end
- -- Temporarily disables all risk buttons during a round
- local function toggleRiskButtons(state)
- for _, btn in ipairs(riskOptions:GetChildren()) do
- if btn:IsA("TextButton") then
- btn.AutoButtonColor = state
- btn.Active = state
- end
- end
- end
- -- Randomly selects a number of blocks for "winning" tiles
- local function getRandomBlocks(count)
- local pool = {}
- for _, shade in ipairs(tilesFolder:GetChildren()) do
- local block = shade:FindFirstChild("Block")
- if block then
- table.insert(pool, block)
- end
- end
- local selected = {}
- while #selected < count and #pool > 0 do
- local index = math.random(1, #pool)
- table.insert(selected, table.remove(pool, index))
- end
- return selected
- end
- -- Enlarges and restores block to simulate bounce when a gem is revealed
- local function playGemAnimation(block)
- -- WHY no second parameter in Instance.new:
- -- Avoids race conditions or unnecessary rendering between creation and configuration
- local scale = block:FindFirstChild("UIScale") or Instance.new("UIScale")
- scale.Scale = 1
- scale.Parent = block
- local up = TweenService:Create(scale, TweenInfo.new(0.1), {Scale = 1.15})
- local down = TweenService:Create(scale, TweenInfo.new(0.1), {Scale = 1})
- up:Play()
- up.Completed:Wait()
- down:Play()
- end
- -- Calculates how much to pay out based on current tiles and hits
- local function calculatePayout(bet, hits)
- local tiles = #selectedTiles
- local tier = Multipliers[selectedRisk]
- if not tier or not tier[tiles] then return 0 end
- local multiplier = tier[tiles][hits] or 0
- return bet * multiplier
- end
- -- Handles visual feedback for each selected gem tile
- local function revealTiles(gemTiles)
- local hits = 0
- for _, block in ipairs(gemTiles) do
- task.wait(0.2)
- playGemAnimation(block)
- local isHit = table.find(selectedTiles, block)
- if isHit then
- if block:FindFirstChild("Gem") then
- block.Gem.Visible = true
- end
- gemSound:Play()
- hits += 1
- else
- block.BackgroundColor3 = COLORS.missedBlock
- if block:FindFirstChild("Number") then
- block.Number.TextColor3 = COLORS.redText
- end
- otherSound:Play()
- end
- end
- return hits
- end
- ---------------------------------------------------------------------------------------------------
- -- MAIN GAME HANDLER
- submitBet.MouseButton1Click:Connect(function()
- local bet = tonumber(betInput.Text)
- if not validatePlay(bet) then return end
- debounce = true
- animatingRound = true
- toggleRiskButtons(false)
- deductCash:FireServer(bet) -- Trust server to handle balance deduction
- local gemTiles = getRandomBlocks(10)
- local hits = revealTiles(gemTiles)
- local payout = calculatePayout(bet, hits)
- if payout > 0 then
- addCash:FireServer(payout)
- end
- toggleRiskButtons(true)
- animatingRound = false
- debounce = false
- end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement