-- LocalScript: put this inside StarterGui (Roblox Studio) local Players = game:GetService("Players") local UserInputService = game:GetService("UserInputService") local TweenService = game:GetService("TweenService") local player = Players.LocalPlayer -- Theme local COLORS = { bg = Color3.fromRGB(24, 24, 28), screen = Color3.fromRGB(14, 14, 17), number = Color3.fromRGB(52, 52, 60), func = Color3.fromRGB(86, 86, 98), op = Color3.fromRGB(255, 149, 0), text = Color3.new(1, 1, 1), dim = Color3.fromRGB(150, 150, 160), } local MAX_DIGITS = 12 -- GUI local gui = Instance.new("ScreenGui") gui.Name = "Calculator" gui.ResetOnSpawn = false gui.Parent = player:WaitForChild("PlayerGui") local frame = Instance.new("Frame") frame.Size = UDim2.fromOffset(272, 400) frame.Position = UDim2.fromScale(0.5, 0.5) frame.AnchorPoint = Vector2.new(0.5, 0.5) frame.BackgroundColor3 = COLORS.bg frame.Active = true frame.Draggable = true frame.Parent = gui Instance.new("UICorner", frame).CornerRadius = UDim.new(0, 14) local title = Instance.new("TextLabel") title.Size = UDim2.new(1, -28, 0, 30) title.Position = UDim2.fromOffset(14, 0) title.BackgroundTransparency = 1 title.Text = "Calculator" title.TextColor3 = COLORS.dim title.TextXAlignment = Enum.TextXAlignment.Left title.Font = Enum.Font.GothamMedium title.TextSize = 14 title.Parent = frame local history = Instance.new("TextLabel") history.Size = UDim2.new(1, -24, 0, 18) history.Position = UDim2.fromOffset(12, 34) history.BackgroundTransparency = 1 history.Text = "" history.TextColor3 = COLORS.dim history.TextXAlignment = Enum.TextXAlignment.Right history.Font = Enum.Font.Code history.TextSize = 14 history.Parent = frame local display = Instance.new("TextLabel") display.Size = UDim2.new(1, -24, 0, 50) display.Position = UDim2.fromOffset(12, 54) display.BackgroundColor3 = COLORS.screen display.TextColor3 = COLORS.text display.TextXAlignment = Enum.TextXAlignment.Right display.TextScaled = true display.Font = Enum.Font.Code display.Text = "0" display.Parent = frame Instance.new("UICorner", display) local pad = Instance.new("UIPadding", display) pad.PaddingRight = UDim.new(0, 10) pad.PaddingTop = UDim.new(0, 6) pad.PaddingBottom = UDim.new(0, 6) -- Calculator logic local current, stored, op, fresh = "0", nil, nil, false local OP_LABEL = { ["+"] = "+", ["-"] = "−", ["×"] = "×", ["÷"] = "÷" } local function fmt(n) if n ~= n or n == math.huge or n == -math.huge then return "Error" end local a = math.abs(n) if a >= 1e12 or (a < 1e-9 and n ~= 0) then return string.format("%.6g", n) end return string.format("%.10g", n) end local function compute(a, b, o) if o == "+" then return a + b end if o == "-" then return a - b end if o == "×" then return a * b end if o == "÷" then if b == 0 then return nil end return a / b end end local function render() display.Text = current end local function fail() current, stored, op, fresh = "0", nil, nil, true history.Text = "" display.Text = "Error" end local function clearAll() current, stored, op, fresh = "0", nil, nil, false history.Text = "" render() end local function press(key) if display.Text == "Error" then clearAll() end if tonumber(key) then if fresh or current == "0" then current = key fresh = false elseif #current:gsub("[%-%.]", "") < MAX_DIGITS then current ..= key end render() elseif key == "." then if fresh then current = "0." fresh = false elseif not current:find("%.") then current ..= "." end render() elseif key == "C" then clearAll() elseif key == "⌫" then if fresh then return end current = current:sub(1, -2) if current == "" or current == "-" then current = "0" end render() elseif key == "±" then if current ~= "0" then current = current:sub(1, 1) == "-" and current:sub(2) or ("-" .. current) end render() elseif key == "%" then current = fmt(tonumber(current) / 100) fresh = true render() elseif key == "=" then if op and stored then local b = tonumber(current) local result = compute(stored, b, op) if result == nil then fail() return end history.Text = fmt(stored) .. " " .. OP_LABEL[op] .. " " .. fmt(b) .. " =" current = fmt(result) stored, op, fresh = nil, nil, true render() end else -- operator: + - × ÷ if op and stored and not fresh then local result = compute(stored, tonumber(current), op) if result == nil then fail() return end stored = result current = fmt(result) render() elseif not (op and fresh) then stored = tonumber(current) end op = key fresh = true history.Text = fmt(stored) .. " " .. OP_LABEL[key] end end -- Buttons local layout = { { "C", "⌫", "%", "÷" }, { "7", "8", "9", "×" }, { "4", "5", "6", "-" }, { "1", "2", "3", "+" }, { "±", "0", ".", "=" }, } local buttons = {} local function baseColor(key) if tonumber(key) or key == "." then return COLORS.number end if key == "C" or key == "⌫" or key == "%" or key == "±" then return COLORS.func end return COLORS.op end local function tweenColor(btn, color) TweenService:Create(btn, TweenInfo.new(0.1), { BackgroundColor3 = color }):Play() end local function flash(key) local btn = buttons[key] if not btn then return end local base = baseColor(key) btn.BackgroundColor3 = base:Lerp(Color3.new(1, 1, 1), 0.35) tweenColor(btn, base) end for row, keys in ipairs(layout) do for col, key in ipairs(keys) do local btn = Instance.new("TextButton") btn.Size = UDim2.fromOffset(56, 48) btn.Position = UDim2.fromOffset(12 + (col - 1) * 64, 114 + (row - 1) * 56) btn.Text = OP_LABEL[key] or key btn.TextSize = 22 btn.Font = Enum.Font.GothamBold btn.TextColor3 = COLORS.text btn.AutoButtonColor = false btn.BackgroundColor3 = baseColor(key) btn.Parent = frame Instance.new("UICorner", btn).CornerRadius = UDim.new(0, 10) buttons[key] = btn btn.MouseEnter:Connect(function() tweenColor(btn, baseColor(key):Lerp(Color3.new(1, 1, 1), 0.15)) end) btn.MouseLeave:Connect(function() tweenColor(btn, baseColor(key)) end) btn.Activated:Connect(function() flash(key) press(key) end) end end -- Keyboard support (works while the calculator is open) local KEYMAP = { [Enum.KeyCode.Period] = ".", [Enum.KeyCode.KeypadPeriod] = ".", [Enum.KeyCode.Return] = "=", [Enum.KeyCode.KeypadEnter] = "=", [Enum.KeyCode.Equals] = "=", [Enum.KeyCode.Minus] = "-", [Enum.KeyCode.KeypadMinus] = "-", [Enum.KeyCode.Slash] = "÷", [Enum.KeyCode.KeypadDivide] = "÷", [Enum.KeyCode.KeypadMultiply] = "×", [Enum.KeyCode.Asterisk] = "×", [Enum.KeyCode.KeypadPlus] = "+", [Enum.KeyCode.Plus] = "+", [Enum.KeyCode.Backspace] = "⌫", [Enum.KeyCode.Delete] = "C", [Enum.KeyCode.Escape] = "C", } local DIGITS = { "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" } for i, name in ipairs(DIGITS) do KEYMAP[Enum.KeyCode[name]] = tostring(i - 1) KEYMAP[Enum.KeyCode["Keypad" .. name]] = tostring(i - 1) end UserInputService.InputBegan:Connect(function(input, processed) if processed or not frame.Visible then return end local key = KEYMAP[input.KeyCode] if not key then return end local shift = UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) or UserInputService:IsKeyDown(Enum.KeyCode.RightShift) if shift and input.KeyCode == Enum.KeyCode.Equals then key = "+" end if shift and input.KeyCode == Enum.KeyCode.Eight then key = "×" end flash(key) press(key) end)