local Players = game:GetService("Players") local VirtualInputManager = game:GetService("VirtualInputManager") local player = Players.LocalPlayer local ALT_USERNAME = "YourAltUsername" local CONTROLLER_USERNAME = "YourMainUsername" local IS_ALT = (player.Name == ALT_USERNAME) local function getKeyCode(keyString) keyString = keyString:upper() -- adding this because roblox stupid enum just doesnt uses numbers.. local numberMap = { ["1"] = "One", ["2"] = "Two", ["3"] = "Three", ["4"] = "Four", ["5"] = "Five", ["6"] = "Six", ["7"] = "Seven", ["8"] = "Eight", ["9"] = "Nine", ["0"] = "Zero" } -- Arrow because same reason as before. local arrowMap = { ["UP"] = "Up", ["DOWN"] = "Down", ["LEFT"] = "Left", ["RIGHT"] = "Right" } -- Esc if keyString == "ESC" then return Enum.KeyCode.Escape end -- F1–F12 if keyString:match("^F%d+$") then local number = tonumber(keyString:sub(2)) if number and number >= 1 and number <= 12 then return Enum.KeyCode[keyString] end end if numberMap[keyString] then return Enum.KeyCode[numberMap[keyString]] end if arrowMap[keyString] then return Enum.KeyCode[arrowMap[keyString]] end return Enum.KeyCode[keyString] end local function pressKey(keyString) local keyEnum = getKeyCode(keyString) if not keyEnum then return end VirtualInputManager:SendKeyEvent(true, keyEnum, false, game) task.wait(0.1) VirtualInputManager:SendKeyEvent(false, keyEnum, false, game) end local function holdKey(keyString, duration) local keyEnum = getKeyCode(keyString) if not keyEnum then return end VirtualInputManager:SendKeyEvent(true, keyEnum, false, game) task.wait(duration) VirtualInputManager:SendKeyEvent(false, keyEnum, false, game) end local function handleChat(plr, message) if plr.Name ~= CONTROLLER_USERNAME then return end if not IS_ALT then return end local pressPrefix = "!key press " local holdPrefix = "!key hold " if message:sub(1, #pressPrefix):lower() == pressPrefix then local key = message:sub(#pressPrefix + 1) if key ~= "" then pressKey(key) end return end if message:sub(1, #holdPrefix):lower() == holdPrefix then local args = message:sub(#holdPrefix + 1) local split = string.split(args, " ") local key = split[1] local duration = tonumber(split[2]) if key and duration then holdKey(key, duration) end end end for _, plr in pairs(Players:GetPlayers()) do plr.Chatted:Connect(function(message) handleChat(plr, message) end) end Players.PlayerAdded:Connect(function(plr) plr.Chatted:Connect(function(message) handleChat(plr, message) end) end)