Advertisement
bootyeater69420

Keno Script

Jun 26th, 2025 (edited)
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.40 KB | None | 0 0
  1. -- SERVICES --
  2. local TweenService = game:GetService("TweenService")
  3. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  4. local Players = game:GetService("Players")
  5.  
  6. -- PLAYER REFERENCE --
  7. local player = Players.LocalPlayer -- Reference to local player to access in-game currency (leaderstats)
  8.  
  9. -- UI ELEMENT REFERENCES --
  10. local submitBet = script.Parent
  11. local kenoFrame = submitBet:FindFirstAncestor("KenoFrame")
  12. local tilesFolder = kenoFrame.Menu:WaitForChild("Tiles")
  13. local betInput = kenoFrame.PaymentBar.CashFrame:WaitForChild("BetInput")
  14. local riskOptions = kenoFrame.PaymentBar:WaitForChild("RiskOptions")
  15.  
  16. -- SOUND REFERENCES --
  17. local gemSound = kenoFrame.Menu:WaitForChild("Gem")
  18. local otherSound = kenoFrame.Menu:WaitForChild("Other")
  19.  
  20. -- REMOTE EVENTS --
  21. local deductCash = ReplicatedStorage:WaitForChild("DeductCash")
  22. local addCash = ReplicatedStorage:WaitForChild("AddCash")
  23.  
  24. -- CONSTANTS & UI COLORS --
  25. local COLORS = {
  26. defaultText = Color3.fromRGB(255, 255, 255),
  27. defaultBlock = Color3.fromRGB(47, 69, 83),
  28. missedBlock = Color3.fromRGB(7, 29, 42),
  29. redText = Color3.fromRGB(255, 0, 0),
  30. shadeDefault = Color3.fromRGB(33, 55, 67),
  31. shadeSelected = Color3.fromRGB(113, 0, 199),
  32. blockSelected = Color3.fromRGB(155, 41, 251),
  33. }
  34.  
  35. local jumpOffset = UDim2.new(0, 0, -0.02, 0) -- Offset for a subtle 'jump' animation on selection
  36. local maxSelections = 10 -- Limit how many tiles can be selected per round
  37. local Multipliers = require(script.Multipliers) -- Loaded from external ModuleScript for scalability
  38.  
  39. -- RUNTIME STATE --
  40. local debounce = false -- Prevents input spamming (used during animations)
  41. local animatingRound = false -- Blocks interaction mid-round
  42. local selectedTiles = {} -- Array of user-chosen tiles
  43. local selectedRisk = nil -- Current selected risk difficulty
  44. local lastTweenTime = {} -- Time tracking to prevent frequent animation spam on same element
  45.  
  46. ---------------------------------------------------------------------------------------------------
  47. -- RISK BUTTON HANDLING
  48.  
  49. -- Resets all risk buttons to default appearance
  50. local function resetRiskButtons()
  51. for _, btn in ipairs(riskOptions:GetChildren()) do
  52. if btn:IsA("TextButton") then
  53. btn.BackgroundColor3 = COLORS.defaultBlock
  54. end
  55. end
  56. end
  57.  
  58. -- Visually activates a selected risk button and stores choice
  59. local function setRiskButton(btn)
  60. selectedRisk = btn.Name
  61. btn.BackgroundColor3 = COLORS.blockSelected
  62. end
  63.  
  64. -- Handles a player clicking a risk button
  65. local function handleRiskButtonClick(btn)
  66. -- Guard clause: Ignore clicks during animation or if button is disabled
  67. if animatingRound or not btn.Active then return end
  68.  
  69. resetRiskButtons()
  70. setRiskButton(btn)
  71. end
  72.  
  73. -- Attach handler to each risk option
  74. for _, btn in ipairs(riskOptions:GetChildren()) do
  75. if btn:IsA("TextButton") then
  76. btn.MouseButton1Click:Connect(function()
  77. handleRiskButtonClick(btn)
  78. end)
  79. end
  80. end
  81.  
  82. ---------------------------------------------------------------------------------------------------
  83. -- TILE INTERACTION
  84.  
  85. -- Animates selected shade and block to highlight user selection
  86. local function playSelectAnimation(shade, block)
  87. TweenService:Create(shade, TweenInfo.new(0.2), {BackgroundColor3 = COLORS.shadeSelected}):Play()
  88. TweenService:Create(block, TweenInfo.new(0.2), {BackgroundColor3 = COLORS.blockSelected}):Play()
  89. end
  90.  
  91. -- Reverts visual feedback on deselection
  92. local function playDeselectAnimation(shade, block)
  93. TweenService:Create(shade, TweenInfo.new(0.2), {BackgroundColor3 = COLORS.shadeDefault}):Play()
  94. TweenService:Create(block, TweenInfo.new(0.2), {BackgroundColor3 = COLORS.defaultBlock}):Play()
  95. end
  96.  
  97. -- Simulates a 'jump' when a tile is selected
  98. local function animateJump(block)
  99. local origPos = block.Position
  100. local tweenUp = TweenService:Create(block, TweenInfo.new(0.1), {Position = origPos + jumpOffset})
  101. local tweenDown = TweenService:Create(block, TweenInfo.new(0.1), {Position = origPos})
  102. tweenUp:Play()
  103. tweenUp.Completed:Wait()
  104. tweenDown:Play()
  105. end
  106.  
  107. -- Handles logic when a tile is clicked: toggles selection
  108. local function handleTileClick(shade, block)
  109. if debounce or animatingRound then return end
  110.  
  111. -- Prevent repeated rapid animation
  112. local now = tick()
  113. if lastTweenTime[block] and now - lastTweenTime[block] < 0.3 then return end
  114. lastTweenTime[block] = now
  115.  
  116. local index = table.find(selectedTiles, block)
  117.  
  118. if index then
  119. table.remove(selectedTiles, index)
  120. playDeselectAnimation(shade, block)
  121. if block:FindFirstChild("Gem") then block.Gem.Visible = false end
  122. return
  123. end
  124.  
  125. if #selectedTiles >= maxSelections then return end
  126.  
  127. table.insert(selectedTiles, block)
  128. playSelectAnimation(shade, block)
  129. animateJump(block)
  130. end
  131.  
  132. -- Connect all clickable tiles to the handler
  133. for _, shade in ipairs(tilesFolder:GetChildren()) do
  134. if shade:IsA("Frame") and shade.Name == "ShadeColor" then
  135. local block = shade:FindFirstChild("Block")
  136. if block and block:IsA("TextButton") then
  137. block.MouseButton1Click:Connect(function()
  138. handleTileClick(shade, block)
  139. end)
  140. end
  141. end
  142. end
  143.  
  144. ---------------------------------------------------------------------------------------------------
  145. -- GAME LOGIC UTILITIES
  146.  
  147. -- Ensures all conditions are met before allowing a round to start
  148. local function validatePlay(bet)
  149. if debounce or animatingRound then return false end
  150. if not bet or bet <= 0 or not selectedRisk then return false end
  151. if #selectedTiles < 1 or #selectedTiles > 10 then return false end
  152.  
  153. local stats = player:FindFirstChild("leaderstats")
  154. local cash = stats and stats:FindFirstChild("Cash")
  155.  
  156. return cash and cash.Value >= bet
  157. end
  158.  
  159. -- Temporarily disables all risk buttons during a round
  160. local function toggleRiskButtons(state)
  161. for _, btn in ipairs(riskOptions:GetChildren()) do
  162. if btn:IsA("TextButton") then
  163. btn.AutoButtonColor = state
  164. btn.Active = state
  165. end
  166. end
  167. end
  168.  
  169. -- Randomly selects a number of blocks for "winning" tiles
  170. local function getRandomBlocks(count)
  171. local pool = {}
  172.  
  173. for _, shade in ipairs(tilesFolder:GetChildren()) do
  174. local block = shade:FindFirstChild("Block")
  175. if block then
  176. table.insert(pool, block)
  177. end
  178. end
  179.  
  180. local selected = {}
  181.  
  182. while #selected < count and #pool > 0 do
  183. local index = math.random(1, #pool)
  184. table.insert(selected, table.remove(pool, index))
  185. end
  186.  
  187. return selected
  188. end
  189.  
  190. -- Enlarges and restores block to simulate bounce when a gem is revealed
  191. local function playGemAnimation(block)
  192. -- WHY no second parameter in Instance.new:
  193. -- Avoids race conditions or unnecessary rendering between creation and configuration
  194. local scale = block:FindFirstChild("UIScale") or Instance.new("UIScale")
  195. scale.Scale = 1
  196. scale.Parent = block
  197.  
  198. local up = TweenService:Create(scale, TweenInfo.new(0.1), {Scale = 1.15})
  199. local down = TweenService:Create(scale, TweenInfo.new(0.1), {Scale = 1})
  200. up:Play()
  201. up.Completed:Wait()
  202. down:Play()
  203. end
  204.  
  205. -- Calculates how much to pay out based on current tiles and hits
  206. local function calculatePayout(bet, hits)
  207. local tiles = #selectedTiles
  208. local tier = Multipliers[selectedRisk]
  209. if not tier or not tier[tiles] then return 0 end
  210. local multiplier = tier[tiles][hits] or 0
  211. return bet * multiplier
  212. end
  213.  
  214. -- Handles visual feedback for each selected gem tile
  215. local function revealTiles(gemTiles)
  216. local hits = 0
  217.  
  218. for _, block in ipairs(gemTiles) do
  219. task.wait(0.2)
  220. playGemAnimation(block)
  221.  
  222. local isHit = table.find(selectedTiles, block)
  223.  
  224. if isHit then
  225. if block:FindFirstChild("Gem") then
  226. block.Gem.Visible = true
  227. end
  228. gemSound:Play()
  229. hits += 1
  230. else
  231. block.BackgroundColor3 = COLORS.missedBlock
  232. if block:FindFirstChild("Number") then
  233. block.Number.TextColor3 = COLORS.redText
  234. end
  235. otherSound:Play()
  236. end
  237. end
  238.  
  239. return hits
  240. end
  241.  
  242. ---------------------------------------------------------------------------------------------------
  243. -- MAIN GAME HANDLER
  244.  
  245. submitBet.MouseButton1Click:Connect(function()
  246. local bet = tonumber(betInput.Text)
  247. if not validatePlay(bet) then return end
  248.  
  249. debounce = true
  250. animatingRound = true
  251. toggleRiskButtons(false)
  252.  
  253. deductCash:FireServer(bet) -- Trust server to handle balance deduction
  254.  
  255. local gemTiles = getRandomBlocks(10)
  256. local hits = revealTiles(gemTiles)
  257. local payout = calculatePayout(bet, hits)
  258.  
  259. if payout > 0 then
  260. addCash:FireServer(payout)
  261. end
  262.  
  263. toggleRiskButtons(true)
  264. animatingRound = false
  265. debounce = false
  266. end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement