Key Required

Key Required
LocoOfficial Uno Script FIRST SCRIPT WORK OPENSOURCE
Lua Script•1197 lines (29301 chars)
--[[
UNO_LocoHub.lua v1
Place: 8571687919 — LOCOfficial!
IA adaptative aux house rules · vise la victoire
Remotes: PlayCard / ChooseColor / ChoosePlayer / CallOfficial / SlapOnSix
Toggle UI: End
]]
repeat
task.wait()
until game:IsLoaded()
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
local HttpService = game:GetService("HttpService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CoreGui = game:GetService("CoreGui")
local PLACE_ID = 8571687919
local LP = Players.LocalPlayer
local PG = LP:WaitForChild("PlayerGui")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local PlayCard = Remotes:WaitForChild("PlayCard")
local ChooseColor = Remotes:WaitForChild("ChooseColor")
local ChoosePlayer = Remotes:WaitForChild("ChoosePlayer")
local CallOfficial = Remotes:WaitForChild("CallOfficial")
local SlapOnSix = Remotes:WaitForChild("SlapOnSix")
local Modules = ReplicatedStorage:FindFirstChild("Modules")
local CanPlayCardMod = Modules and Modules:FindFirstChild("CanPlayCard")
local CanStackCardMod = Modules and Modules:FindFirstChild("CanStackCard")
local CanPlayCardFn = CanPlayCardMod and (select(1, pcall(require, CanPlayCardMod))) or nil
local CanStackCardFn = CanStackCardMod and (select(1, pcall(require, CanStackCardMod))) or nil
if type(CanPlayCardFn) ~= "function" then
CanPlayCardFn = nil
end
if type(CanStackCardFn) ~= "function" then
CanStackCardFn = nil
end
local Theme = {
bg = Color3.fromRGB(14, 12, 18),
panel = Color3.fromRGB(24, 18, 28),
card = Color3.fromRGB(36, 28, 40),
accent = Color3.fromRGB(224, 48, 96),
good = Color3.fromRGB(70, 210, 120),
warn = Color3.fromRGB(253, 169, 47),
text = Color3.fromRGB(245, 236, 240),
muted = Color3.fromRGB(150, 130, 145),
off = Color3.fromRGB(52, 42, 55),
danger = Color3.fromRGB(180, 45, 55),
}
local ScriptAlive = true
local Connections = {}
local GuiRef, ShellRef = nil, nil
local UI = { toggles = {}, info = nil, status = nil, rules = nil }
local State = {
ai = false,
jumpIn = true,
slap = true,
autoUno = true,
autoCallout = false,
aggressive = true,
status = "prêt — AI OFF",
lastPlay = 0,
lastDraw = 0,
lastSlap = 0,
lastUno = 0,
lastColor = 0,
lastPick = 0,
busy = false,
}
local PendingSwapUntil = 0
local COLORS = { "Red", "Green", "Yellow", "Blue" }
local ACTION = {
["+2"] = true,
["Forward +2"] = true,
["Choice +2"] = true,
Cancel = true,
Reflect = true,
Redirect = true,
["7"] = true,
["0"] = true,
}
local WILD = {
Wild = true,
["Loco +5 - 1"] = true,
["Forward Loco +5 - 1"] = true,
["Loco +2"] = true,
["Loco +99"] = true,
["Draw Til Loco"] = true,
["Loco Smite +4"] = true,
["Loco 8"] = true,
}
local function track(c)
table.insert(Connections, c)
return c
end
local function hardUnload()
local function wipe(parent)
if not parent then
return
end
for _, c in ipairs(parent:GetChildren()) do
local n = c.Name
if n:find("Hub", 1, true)
or n:find("UNO_", 1, true)
or n:find("ArenaAI", 1, true)
or n:find("CAMELEON", 1, true)
or n:find("PassOrExplode", 1, true)
then
pcall(function()
c:Destroy()
end)
end
end
end
wipe(PG)
pcall(function()
wipe(CoreGui)
end)
_G.UNO_LOCO_HUB = nil
end
hardUnload()
if game.PlaceId ~= PLACE_ID then
warn("[UNO Loco] placeId=", game.PlaceId, "attendu", PLACE_ID)
end
----------------------------------------------------------------
-- Match / rules / hand
----------------------------------------------------------------
local function getMatchId()
local id = LP:GetAttribute("MatchId")
if id == nil then
return nil
end
return tostring(id)
end
local function getMatch()
local mid = getMatchId()
if not mid then
return nil
end
local ga = workspace:FindFirstChild("GameAssets")
return ga and ga:FindFirstChild(mid) or nil
end
local function getPile(match)
match = match or getMatch()
return match and match:FindFirstChild("CardPile") or nil
end
local function attr(inst, key, fallback)
if not inst then
return fallback
end
local v = inst:GetAttribute(key)
if v == nil then
return fallback
end
return v
end
local function decodeRules()
local raw = LP:GetAttribute("SavedHouseRules")
local deck = "DefaultDeck"
local rules = {
Stacking = true,
["Anything Stacks"] = false,
Defense = false,
["Jump In"] = true,
["7-0"] = true,
["Slap on 6"] = true,
["Force Play"] = true,
["No Bluffing"] = false,
["Draw Til Match"] = false,
AllowEventPurchases = true,
["Starting Card Count"] = 5,
["Win Condition"] = 0,
DeckName = deck,
}
if type(raw) == "string" and #raw > 2 then
local ok, data = pcall(HttpService.JSONDecode, HttpService, raw)
if ok and type(data) == "table" then
local pack = data[deck] or data.DefaultDeck
if type(pack) ~= "table" then
for k, v in pairs(data) do
if type(v) == "table" then
pack = v
deck = tostring(k)
break
end
end
end
if type(pack) == "table" then
for k, v in pairs(pack) do
rules[k] = v
end
rules.DeckName = deck
end
end
end
-- UI house rules display overrides if present
local gui = PG:FindFirstChild("cards")
local list = gui
and gui:FindFirstChild("Container")
and gui.Container:FindFirstChild("HouseRulesDisplay")
and gui.Container.HouseRulesDisplay:FindFirstChild("HouseRules")
and gui.Container.HouseRulesDisplay.HouseRules:FindFirstChild("RulesList")
if list then
local known = {
["Jump In"] = true,
["Force Play"] = true,
["Slap on 6"] = true,
["7-0"] = true,
Stacking = true,
Defense = true,
["Anything Stacks"] = true,
["No Bluffing"] = true,
["Draw Til Match"] = true,
}
for name in pairs(known) do
rules[name] = list:FindFirstChild(name) ~= nil
end
end
return rules
end
local function getTop(match)
match = match or getMatch()
local pile = getPile(match)
local color = attr(match, "Color") or attr(pile, "Color")
local symbol = attr(match, "Symbol") or attr(pile, "Symbol")
if color == nil or symbol == nil then
return nil
end
return { Color = tostring(color), Symbol = tostring(symbol) }
end
local function mySeat(match)
match = match or getMatch()
if not match then
return nil
end
for i = 1, 12 do
local name = attr(match, "Player_" .. i)
if name and tostring(name) == LP.Name then
return i
end
end
return nil
end
local function isMyTurn(match)
match = match or getMatch()
if not match then
return false
end
local seat = mySeat(match)
if not seat then
return false
end
local turn = tonumber(attr(match, "CurrentTurn")) or tonumber(attr(match, "ActualCurrentTurn"))
return turn == seat
end
local function canAct(match)
match = match or getMatch()
if not match or LP:GetAttribute("InMatch") ~= true then
return false
end
return isMyTurn(match)
end
local function getHandConfigs()
local folder = ReplicatedStorage:FindFirstChild("ClientCards")
local out = {}
if not folder then
return out
end
for _, c in ipairs(folder:GetChildren()) do
local color = c:GetAttribute("Color")
local symbol = c:GetAttribute("Symbol")
if color and symbol then
table.insert(out, {
inst = c,
Color = tostring(color),
Symbol = tostring(symbol),
attrs = c:GetAttributes(),
})
end
end
return out
end
local function getOpponentCounts(match)
match = match or getMatch()
local mid = getMatchId()
local out = {}
if not mid then
return out
end
local cd = workspace:FindFirstChild("GameAssets") and workspace.GameAssets:FindFirstChild("CardDisplays/" .. mid)
if not cd then
return out
end
for _, folder in ipairs(cd:GetChildren()) do
local seat, name = string.match(folder.Name, "^(%d+)/(.+)$")
if seat and name then
table.insert(out, {
seat = tonumber(seat),
name = name,
count = tonumber(folder:GetAttribute("CurrentCardCount")) or 99,
isMe = name == LP.Name,
})
end
end
table.sort(out, function(a, b)
return a.count < b.count
end)
return out
end
local function lowestEnemy(counts)
for _, p in ipairs(counts) do
if not p.isMe then
return p
end
end
return nil
end
local function highestEnemy(counts)
local best = nil
for _, p in ipairs(counts) do
if not p.isMe then
best = p
end
end
return best
end
local function myCount(counts)
for _, p in ipairs(counts) do
if p.isMe then
return p.count
end
end
return #getHandConfigs()
end
local function canPlayLocal(top, card)
if not top or not card then
return false
end
if CanPlayCardFn then
local ok, res = pcall(CanPlayCardFn, top, card)
if ok then
return res and true or false
end
end
if card.Color == "Wild" or top.Color == "Wild" then
return true
end
return card.Color == top.Color or tostring(card.Symbol) == tostring(top.Symbol)
end
local function canStackLocal(stackSymbol, top, card, rules)
if CanStackCardFn then
local ok, res = pcall(CanStackCardFn, stackSymbol, top, card, rules)
if ok then
return res and true or false
end
end
if not rules.Stacking and not rules["Anything Stacks"] then
return false
end
if tostring(card.Symbol) == tostring(stackSymbol) then
return canPlayLocal(top, card)
end
if rules.Defense and (card.Symbol == "Reflect" or card.Symbol == "Cancel" or card.Symbol == "Redirect") then
return canPlayLocal(top, card)
end
if rules["Anything Stacks"] and type(card.Symbol) == "string" and string.find(card.Symbol, "+", 1, true) then
return canPlayLocal(top, card)
end
return false
end
local function colorCounts(hand)
local t = { Red = 0, Green = 0, Yellow = 0, Blue = 0 }
for _, c in ipairs(hand) do
if t[c.Color] ~= nil then
t[c.Color] += 1
end
end
return t
end
local function bestColor(hand)
local counts = colorCounts(hand)
local best, n = "Red", -1
for _, col in ipairs(COLORS) do
if counts[col] > n then
best, n = col, counts[col]
end
end
return best
end
local function isWildCard(card)
return card.Color == "Wild" or WILD[tostring(card.Symbol)] == true
end
local function isDrawAction(sym)
sym = tostring(sym)
return string.find(sym, "+", 1, true) ~= nil
end
local function scoreCard(card, hand, top, rules, counts, stacking)
local score = 10
local sym = tostring(card.Symbol)
local mine = myCount(counts)
local threat = lowestEnemy(counts)
local threatN = threat and threat.count or 99
if stacking then
score += 40
end
if isWildCard(card) then
score -= (mine <= 2) and -25 or 35
elseif ACTION[sym] or isDrawAction(sym) then
score += 18
if threatN <= 2 then
score += 30
end
if sym == "Cancel" or sym == "Reflect" or sym == "Redirect" then
score += 8
end
else
local cc = colorCounts(hand)
score += (cc[card.Color] or 0) * 3
local num = tonumber(sym)
if num then
score += (9 - math.abs(num - 4)) * 0.2
end
end
if rules["7-0"] then
if sym == "7" then
if mine >= 4 and threatN <= 3 then
score += 45
elseif mine <= 2 then
score -= 10
else
score += 12
end
elseif sym == "0" then
score += (mine >= 5) and 15 or 5
end
end
if rules["Slap on 6"] and sym == "6" then
score += State.slap and 6 or -4
end
if State.aggressive and threatN <= 1 and (isDrawAction(sym) or sym == "Cancel") then
score += 50
end
-- dump same color as top to keep control
if top and card.Color == top.Color and not isWildCard(card) then
score += 6
end
return score
end
local function pickBestPlay(match, rules)
local hand = getHandConfigs()
local top = getTop(match)
if not top or #hand == 0 then
return nil, hand, top
end
local stacking = attr(match, "IsStacking") == true
local stackCount = tonumber(attr(match, "StackCount")) or 0
local stackSym = tostring(top.Symbol)
local counts = getOpponentCounts(match)
local best, bestScore = nil, -1e9
for _, card in ipairs(hand) do
local legal = false
if stacking and stackCount > 0 and (rules.Stacking or rules["Anything Stacks"] or rules.Defense) then
legal = canStackLocal(stackSym, top, card, rules)
else
legal = canPlayLocal(top, card)
end
if legal then
local s = scoreCard(card, hand, top, rules, counts, stacking)
if s > bestScore then
bestScore = s
best = card
end
end
end
return best, hand, top, counts
end
local function exactJumpCandidates(match, rules)
if not rules["Jump In"] then
return {}
end
local pile = getPile(match)
if attr(match, "CanJumpIn") ~= true and attr(pile, "CanJumpIn") ~= true then
return {}
end
local top = getTop(match)
if not top then
return {}
end
local out = {}
for _, card in ipairs(getHandConfigs()) do
if tostring(card.Symbol) == tostring(top.Symbol) and (card.Color == top.Color or card.Color == "Wild") then
table.insert(out, card)
end
end
return out
end
----------------------------------------------------------------
-- Actions
----------------------------------------------------------------
local function firePlay(attrs)
return pcall(function()
PlayCard:FireServer(attrs)
end)
end
local function playCard(card)
if not card or not card.attrs then
return false
end
local now = os.clock()
if now - State.lastPlay < 0.28 then
return false
end
State.lastPlay = now
local ok = firePlay(card.attrs)
if ok then
State.status = ("joue %s/%s"):format(card.Color, card.Symbol)
if tostring(card.Symbol) == "7" then
PendingSwapUntil = os.clock() + 2.5
end
end
return ok
end
local function drawCard()
local now = os.clock()
if now - State.lastDraw < 0.45 then
return false
end
State.lastDraw = now
local ok = firePlay({ DrawCard = true })
if ok then
State.status = "pioche…"
end
return ok
end
local function keepDrawn()
return firePlay("Keep")
end
local function tryPlayDrawnForce(rules)
local gui = PG:FindFirstChild("cards")
local frame = gui and gui:FindFirstChild("Container") and gui.Container:FindFirstChild("PlayDrawnCard")
if not frame or not frame.Visible then
return false
end
-- Force Play: jouer la carte piochée si possible
local hand = getHandConfigs()
local last = hand[#hand]
if last and (rules["Force Play"] or true) then
return playCard(last)
end
return false
end
local function doSlap()
if not State.slap then
return false
end
local now = os.clock()
if now - State.lastSlap < 0.15 then
return false
end
local gui = PG:FindFirstChild("cards")
local slap = gui and gui.Container and gui.Container:FindFirstChild("SlapButton")
local match = getMatch()
local need = (slap and slap.Visible) or attr(match, "IsSlapping") == true
if not need then
local top = getTop(match)
if top and tostring(top.Symbol) == "6" and decodeRules()["Slap on 6"] then
need = true
end
end
if not need then
return false
end
State.lastSlap = now
local ok = pcall(function()
SlapOnSix:FireServer()
end)
if slap and slap:FindFirstChild("Button") then
pcall(function()
slap.Button:Activate()
end)
end
if ok then
State.status = "SLAP 6!"
end
return ok
end
local function doUno()
if not State.autoUno then
return false
end
local now = os.clock()
if now - State.lastUno < 0.35 then
return false
end
local gui = PG:FindFirstChild("cards")
local btn = gui and gui.Container and gui.Container:FindFirstChild("OfficialButton")
local counts = getOpponentCounts()
local mine = myCount(counts)
local visible = btn and btn.Visible
if not visible and mine > 1 then
return false
end
if mine > 1 and not visible then
return false
end
State.lastUno = now
local ok = pcall(function()
CallOfficial:FireServer()
end)
if btn and btn:FindFirstChild("Button") then
pcall(function()
btn.Button:Activate()
end)
end
if ok then
State.status = "OFFICIAL!"
end
return ok
end
local function doCallout()
if not State.autoCallout then
return false
end
local gui = PG:FindFirstChild("cards")
local btn = gui and gui.Container and gui.Container:FindFirstChild("CalloutButton")
local challenge = gui and gui.Container and gui.Container:FindFirstChild("ChallengingFrame")
if challenge and challenge.Visible and challenge:FindFirstChild("Challenge") then
pcall(function()
challenge.Challenge:Activate()
end)
firePlay("Callout")
State.status = "challenge +4"
return true
end
if btn and btn.Visible then
firePlay("Callout")
pcall(function()
if btn.Button then
btn.Button:Activate()
end
end)
State.status = "callout"
return true
end
return false
end
local function doChooseColor(hand)
if workspace:GetAttribute("PickingColor") ~= true then
return false
end
local now = os.clock()
if now - State.lastColor < 0.25 then
return false
end
State.lastColor = now
local col = bestColor(hand or getHandConfigs())
local ok = pcall(function()
ChooseColor:FireServer(col)
end)
if ok then
State.status = "couleur " .. col
end
return ok
end
local function pickSwapTarget(counts)
local mine = myCount(counts)
if mine >= 4 then
return lowestEnemy(counts)
end
return highestEnemy(counts)
end
local function doChoosePlayer(counts)
local now = os.clock()
if now - State.lastPick < 0.35 then
return false
end
local picking = workspace:GetAttribute("PickingPlayer") == true
or workspace:GetAttribute("ChoosingPlayer") == true
or now < PendingSwapUntil
if not picking then
return false
end
local target = pickSwapTarget(counts or getOpponentCounts())
if not target then
return false
end
State.lastPick = now
local ok = pcall(function()
ChoosePlayer:FireServer(target.name)
end)
if ok then
State.status = "swap → " .. target.name
PendingSwapUntil = 0
end
return ok
end
track(ChooseColor.OnClientEvent:Connect(function()
if not State.ai or not ScriptAlive then
return
end
task.defer(function()
task.wait(0.05)
doChooseColor()
end)
end))
----------------------------------------------------------------
-- AI tick
----------------------------------------------------------------
local function aiTick()
if not State.ai or not ScriptAlive or State.busy then
return
end
if LP:GetAttribute("InMatch") ~= true then
State.status = "hors partie"
return
end
State.busy = true
local ok, err = pcall(function()
local match = getMatch()
local rules = decodeRules()
local hand = getHandConfigs()
local counts = getOpponentCounts(match)
doSlap()
doUno()
doCallout()
doChooseColor(hand)
doChoosePlayer(counts)
-- Jump-in
if State.jumpIn and rules["Jump In"] and not isMyTurn(match) then
local jumps = exactJumpCandidates(match, rules)
if #jumps > 0 then
local best, bs = jumps[1], -1e9
for _, c in ipairs(jumps) do
local s = scoreCard(c, hand, getTop(match), rules, counts, false) + 20
if s > bs then
best, bs = c, s
end
end
playCard(best)
doUno()
return
end
end
tryPlayDrawnForce(rules)
if not canAct(match) and not isMyTurn(match) then
State.status = "attente tour"
return
end
local stacking = attr(match, "IsStacking") == true
local best = pickBestPlay(match, rules)
if best then
playCard(best)
task.delay(0.2, function()
if ScriptAlive then
doUno()
doChooseColor()
doChoosePlayer()
end
end)
else
if stacking then
drawCard()
elseif isMyTurn(match) or canAct(match) then
drawCard()
end
end
end)
State.busy = false
if not ok then
State.status = "err"
warn("[UNO Loco]", err)
end
end
----------------------------------------------------------------
-- UI
----------------------------------------------------------------
local function corner(o, r)
local c = Instance.new("UICorner")
c.CornerRadius = UDim.new(0, r or 10)
c.Parent = o
return c
end
local function stroke(o, col, th, tr)
local s = Instance.new("UIStroke")
s.Color = col or Theme.muted
s.Thickness = th or 1
s.Transparency = tr or 0.45
s.Parent = o
return s
end
local function setToggleVisual(sw, on)
sw.BackgroundColor3 = on and Theme.good or Theme.off
local knob = sw:FindFirstChild("Knob")
if knob then
TweenService:Create(knob, TweenInfo.new(0.15), {
Position = on and UDim2.new(1, -22, 0.5, -9) or UDim2.new(0, 4, 0.5, -9),
BackgroundColor3 = on and Color3.fromRGB(240, 255, 245) or Color3.fromRGB(180, 170, 185),
}):Play()
end
end
local function unload()
ScriptAlive = false
for _, c in ipairs(Connections) do
pcall(function()
c:Disconnect()
end)
end
table.clear(Connections)
if GuiRef then
pcall(function()
GuiRef:Destroy()
end)
end
GuiRef, ShellRef = nil, nil
_G.UNO_LOCO_HUB = nil
end
local function buildUI()
local gui = Instance.new("ScreenGui")
gui.Name = "UNO_LocoHub"
gui.ResetOnSpawn = false
gui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
gui.DisplayOrder = 120
pcall(function()
gui.Parent = CoreGui
end)
if not gui.Parent then
gui.Parent = PG
end
GuiRef = gui
local shell = Instance.new("Frame")
shell.Name = "Shell"
shell.Size = UDim2.fromOffset(320, 470)
shell.Position = UDim2.new(0, 18, 0.5, -235)
shell.BackgroundColor3 = Theme.bg
shell.BorderSizePixel = 0
shell.Active = true
shell.Parent = gui
corner(shell, 16)
stroke(shell, Theme.accent, 1.2, 0.35)
ShellRef = shell
do
local dragging, dragStart, startPos
track(shell.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
dragging = true
dragStart = input.Position
startPos = shell.Position
end
end))
track(shell.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
dragging = false
end
end))
track(UserInputService.InputChanged:Connect(function(input)
if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
local d = input.Position - dragStart
shell.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + d.X, startPos.Y.Scale, startPos.Y.Offset + d.Y)
end
end))
end
local header = Instance.new("Frame")
header.Size = UDim2.new(1, 0, 0, 64)
header.BackgroundColor3 = Theme.panel
header.BorderSizePixel = 0
header.Parent = shell
corner(header, 16)
local cover = Instance.new("Frame")
cover.Size = UDim2.new(1, 0, 0, 20)
cover.Position = UDim2.new(0, 0, 1, -20)
cover.BackgroundColor3 = Theme.panel
cover.BorderSizePixel = 0
cover.Parent = header
local brand = Instance.new("TextLabel")
brand.BackgroundTransparency = 1
brand.Position = UDim2.fromOffset(16, 10)
brand.Size = UDim2.new(1, -90, 0, 22)
brand.Font = Enum.Font.GothamBold
brand.TextSize = 18
brand.TextXAlignment = Enum.TextXAlignment.Left
brand.TextColor3 = Theme.accent
brand.Text = "UNO LOCO"
brand.Parent = header
local sub = Instance.new("TextLabel")
sub.BackgroundTransparency = 1
sub.Position = UDim2.fromOffset(16, 34)
sub.Size = UDim2.new(1, -90, 0, 18)
sub.Font = Enum.Font.Gotham
sub.TextSize = 12
sub.TextXAlignment = Enum.TextXAlignment.Left
sub.TextColor3 = Theme.muted
sub.Text = "Hub v1 · End pour cacher"
sub.Parent = header
local closeBtn = Instance.new("TextButton")
closeBtn.Size = UDim2.fromOffset(32, 32)
closeBtn.Position = UDim2.new(1, -44, 0, 16)
closeBtn.BackgroundColor3 = Theme.danger
closeBtn.Text = "×"
closeBtn.Font = Enum.Font.GothamBold
closeBtn.TextSize = 18
closeBtn.TextColor3 = Theme.text
closeBtn.Parent = header
corner(closeBtn, 8)
track(closeBtn.Activated:Connect(unload))
local infoCard = Instance.new("Frame")
infoCard.Size = UDim2.new(1, -32, 0, 72)
infoCard.Position = UDim2.fromOffset(16, 76)
infoCard.BackgroundColor3 = Theme.card
infoCard.BorderSizePixel = 0
infoCard.Parent = shell
corner(infoCard, 10)
local info = Instance.new("TextLabel")
info.BackgroundTransparency = 1
info.Size = UDim2.new(1, -16, 1, -12)
info.Position = UDim2.fromOffset(8, 6)
info.Font = Enum.Font.Gotham
info.TextSize = 12
info.TextColor3 = Theme.muted
info.TextXAlignment = Enum.TextXAlignment.Left
info.TextYAlignment = Enum.TextYAlignment.Top
info.TextWrapped = true
info.Text = "…"
info.Parent = infoCard
UI.info = info
local rulesLbl = Instance.new("TextLabel")
rulesLbl.BackgroundTransparency = 1
rulesLbl.Position = UDim2.fromOffset(16, 156)
rulesLbl.Size = UDim2.new(1, -32, 0, 36)
rulesLbl.Font = Enum.Font.Gotham
rulesLbl.TextSize = 11
rulesLbl.TextColor3 = Theme.warn
rulesLbl.TextXAlignment = Enum.TextXAlignment.Left
rulesLbl.TextYAlignment = Enum.TextYAlignment.Top
rulesLbl.TextWrapped = true
rulesLbl.Text = "Règles…"
rulesLbl.Parent = shell
UI.rules = rulesLbl
local y = 198
local function sectionLabel(text)
local l = Instance.new("TextLabel")
l.BackgroundTransparency = 1
l.Position = UDim2.fromOffset(18, y)
l.Size = UDim2.new(1, -36, 0, 16)
l.Font = Enum.Font.GothamBold
l.TextSize = 11
l.TextColor3 = Theme.accent
l.TextXAlignment = Enum.TextXAlignment.Left
l.Text = string.upper(text)
l.Parent = shell
y += 20
end
local function toggleRow(label, key, defaultOn, onChange)
local row = Instance.new("Frame")
row.Size = UDim2.new(1, -32, 0, 34)
row.Position = UDim2.fromOffset(16, y)
row.BackgroundColor3 = Theme.card
row.BorderSizePixel = 0
row.Parent = shell
corner(row, 8)
local lbl = Instance.new("TextLabel")
lbl.BackgroundTransparency = 1
lbl.Position = UDim2.fromOffset(12, 0)
lbl.Size = UDim2.new(1, -70, 1, 0)
lbl.Font = Enum.Font.GothamMedium
lbl.TextSize = 13
lbl.TextColor3 = Theme.text
lbl.TextXAlignment = Enum.TextXAlignment.Left
lbl.Text = label
lbl.Parent = row
local sw = Instance.new("TextButton")
sw.Size = UDim2.fromOffset(44, 22)
sw.Position = UDim2.new(1, -54, 0.5, -11)
sw.BackgroundColor3 = Theme.off
sw.Text = ""
sw.Parent = row
corner(sw, 11)
local knob = Instance.new("Frame")
knob.Name = "Knob"
knob.Size = UDim2.fromOffset(18, 18)
knob.Position = UDim2.new(0, 4, 0.5, -9)
knob.BackgroundColor3 = Color3.fromRGB(180, 170, 185)
knob.BorderSizePixel = 0
knob.Parent = sw
corner(knob, 9)
local on = defaultOn and true or false
setToggleVisual(sw, on)
UI.toggles[key] = {
get = function()
return on
end,
set = function(v)
on = v and true or false
setToggleVisual(sw, on)
end,
}
track(sw.Activated:Connect(function()
on = not on
setToggleVisual(sw, on)
pcall(onChange, on)
end))
y += 40
end
sectionLabel("Intelligence")
toggleRow("Auto-play (gagner)", "ai", false, function(on)
State.ai = on
State.status = on and "AI ON — chasse la win" or "AI OFF"
end)
toggleRow("À la volée (Jump-in)", "jump", true, function(on)
State.jumpIn = on
end)
toggleRow("Frappe le 6", "slap", true, function(on)
State.slap = on
end)
toggleRow("Call Official (UNO)", "uno", true, function(on)
State.autoUno = on
end)
toggleRow("Challenge bluff (+4)", "callout", false, function(on)
State.autoCallout = on
end)
toggleRow("Mode agressif", "aggro", true, function(on)
State.aggressive = on
end)
local status = Instance.new("TextLabel")
status.BackgroundTransparency = 1
status.Position = UDim2.fromOffset(16, y + 4)
status.Size = UDim2.new(1, -32, 0, 36)
status.Font = Enum.Font.GothamMedium
status.TextSize = 12
status.TextColor3 = Theme.good
status.TextXAlignment = Enum.TextXAlignment.Left
status.TextWrapped = true
status.Text = State.status
status.Parent = shell
UI.status = status
track(UserInputService.InputBegan:Connect(function(input, gp)
if gp then
return
end
if input.KeyCode == Enum.KeyCode.End then
shell.Visible = not shell.Visible
end
end))
end
local function refreshUI()
if not UI.info then
return
end
local match = getMatch()
local rules = decodeRules()
local top = getTop(match)
local hand = getHandConfigs()
local counts = getOpponentCounts(match)
local seat = mySeat(match)
local turn = match and attr(match, "CurrentTurn")
local parts = {}
table.insert(parts, ("Match %s · siège %s · tour %s"):format(tostring(getMatchId() or "?"), tostring(seat or "?"), tostring(turn or "?")))
if top then
table.insert(parts, ("Pile: %s/%s · main: %d"):format(top.Color, top.Symbol, #hand))
else
table.insert(parts, ("Main: %d"):format(#hand))
end
local opp = {}
for _, p in ipairs(counts) do
if not p.isMe then
table.insert(opp, ("%s:%d"):format(p.name, p.count))
end
end
if #opp > 0 then
table.insert(parts, table.concat(opp, " "))
end
if attr(match, "IsStacking") then
table.insert(parts, ("STACK x%s"):format(tostring(attr(match, "StackCount"))))
end
UI.info.Text = table.concat(parts, "\n")
local rbits = {}
for _, key in ipairs({ "Stacking", "Jump In", "7-0", "Slap on 6", "Force Play", "Defense", "Anything Stacks", "No Bluffing" }) do
if rules[key] then
table.insert(rbits, key)
end
end
UI.rules.Text = "Règles: " .. (#rbits > 0 and table.concat(rbits, " · ") or "aucune")
if UI.status then
UI.status.Text = State.status
end
end
buildUI()
track(RunService.Heartbeat:Connect(function()
if not ScriptAlive then
return
end
end))
task.spawn(function()
while ScriptAlive do
refreshUI()
if State.ai then
aiTick()
end
task.wait(0.18)
end
end)
_G.UNO_LOCO_HUB = {
unload = unload,
state = State,
version = "1.0.0",
}
print("[UNO Loco] Hub v1 prêt — active Auto-play")Features & Information
Free ! Boycot ObF
AutoPlay !! Free Win ! <3
By Fr
Community Comments (0)
No comments yet for this script.
