
Keyless
--[[ loadstring(game:HttpGet("https://gist.githubusercontent.com/hasanhluong-stack/13e9a9fd47f7e90e8e12127f23714967/raw/7472a0f6f6352af5ece95290ac58adc7ae9a7dea/Script"))() ]]
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
-- ================= Biến lưu trữ dữ liệu & Trạng thái =================
local lastTarget1, lastTarget2, lastDir
local currentVec1, currentVec2 = Vector3.zero, Vector3.zero
local listenState = 0
local tempStart1, tempStart2, tempEnd1, tempEnd2
local inputsLeft, inputsRight = {}, {}
local settingsData = {
repeatCount = 1,
buildDir = Vector3.new(0, 1, 0),
thickness = 1,
buildDelay = 0.05,
baseSize = "1x1",
baseLayers = 2,
baseOffset = 0.5,
pillarHeight = 25,
wallHeight = 10,
wallLength = 5,
autoSnapYaw = false,
}
local snapYawConnection = nil
-- ================= Hàm hỗ trợ Làm tròn & Utility =================
local function round2(num)
return num and math.floor(num * 100 + 0.5) / 100 or 0
end
local function roundVec2(vec)
return Vector3.new(round2(vec.X), round2(vec.Y), round2(vec.Z))
end
local function formatNumStr(num)
return string.format("%.2f", round2(num))
end
local function formatTextBoxTo2Decimals(textBox)
local num = tonumber(textBox.Text)
if num then textBox.Text = formatNumStr(num) end
end
local function setVectorToInputs(inputs, vec, startIndex)
startIndex = startIndex or 1
inputs[startIndex].Text = formatNumStr(vec.X)
inputs[startIndex + 1].Text = formatNumStr(vec.Y)
inputs[startIndex + 2].Text = formatNumStr(vec.Z)
end
local function parseVector3(str, defaultVec)
if not str or str == "" then return defaultVec end
local coords = {}
for num in string.gmatch(str, "[^,]+") do
local p = tonumber(num)
if p then table.insert(coords, round2(p)) end
end
return #coords >= 3 and Vector3.new(coords[1], coords[2], coords[3]) or defaultVec
end
-- Hàm tạo UI Element nhanh để tránh lặp code Instance
local function create(className, props)
local inst = Instance.new(className)
for k, v in pairs(props) do
inst[k] = v
end
return inst
end
-- ================= ESP 4 vị trí ván =================
local plankESPFolder = create("Folder", { Name = "PlankPositionESP", Parent = workspace })
local plankESPParts = {}
local function sameVector(a, b)
return a and b and a.X == b.X and a.Y == b.Y and a.Z == b.Z
end
local function destroyPlankMarker(number)
if plankESPParts[number] and plankESPParts[number].part then
plankESPParts[number].part:Destroy()
end
plankESPParts[number] = nil
end
local function createPlankMarker(number, position)
position = roundVec2(position)
local existing = plankESPParts[number]
if existing and existing.part and existing.part.Parent and sameVector(existing.position, position) then
return
end
destroyPlankMarker(number)
local part = create("Part", {
Name = "ESP_Number_Part_" .. number,
Anchored = true, CanCollide = false, CanTouch = false, CanQuery = false,
Transparency = 1, Size = Vector3.new(0.2, 0.2, 0.2),
CFrame = CFrame.new(position), Parent = plankESPFolder
})
local billboard = create("BillboardGui", {
Name = "ESP_Number_" .. number, Adornee = part, AlwaysOnTop = true,
LightInfluence = 0, MaxDistance = math.huge, Size = UDim2.fromOffset(42, 42),
StudsOffsetWorldSpace = Vector3.new(0, 0.15, 0), Enabled = true, Parent = part
})
local label = create("TextLabel", {
Name = "Number", BackgroundTransparency = 1, BorderSizePixel = 0,
Size = UDim2.fromScale(1, 1), Font = Enum.Font.GothamBlack,
Text = tostring(number), TextColor3 = Color3.fromRGB(255, 220, 60),
TextSize = 23, TextStrokeColor3 = Color3.fromRGB(0, 0, 0), TextStrokeTransparency = 0, Parent = billboard
})
plankESPParts[number] = { part = part, billboard = billboard, label = label, position = position }
end
local function getInputVector(inputs, startIndex)
if not inputs then return nil end
local x, y, z = tonumber(inputs[startIndex] and inputs[startIndex].Text), tonumber(inputs[startIndex+1] and inputs[startIndex+1].Text), tonumber(inputs[startIndex+2] and inputs[startIndex+2].Text)
return (x and y and z) and roundVec2(Vector3.new(x, y, z)) or nil
end
local function refreshESPFromInputs()
local positions = {
getInputVector(inputsLeft, 1), getInputVector(inputsLeft, 4),
getInputVector(inputsRight, 1), getInputVector(inputsRight, 4),
}
for i = 1, 4 do
local pos = positions[i]
if pos then
local existing = plankESPParts[i]
if existing and existing.part and existing.part.Parent then
if not sameVector(existing.position, pos) then
existing.part.CFrame = CFrame.new(pos)
existing.position = pos
end
else
createPlankMarker(i, pos)
end
else
destroyPlankMarker(i)
end
end
end
-- ================= Hiệu ứng & Màu sắc =================
local TWEEN_FAST = TweenInfo.new(0.12, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local function tw(instance, tweenInfo, properties)
local tween = TweenService:Create(instance, tweenInfo, properties)
tween:Play()
return tween
end
local THEME = { border = Color3.fromRGB(64, 71, 92), accentA = Color3.fromRGB(86, 163, 255) }
local COLOR = {
ink = Color3.fromRGB(20, 23, 31), surface = Color3.fromRGB(30, 34, 48), surface2 = Color3.fromRGB(38, 43, 61),
border = Color3.fromRGB(58, 64, 85), text = Color3.fromRGB(242, 239, 234), textMuted = Color3.fromRGB(144, 152, 176),
accent = Color3.fromRGB(232, 163, 61), stepBg = Color3.fromRGB(48, 54, 76), listening = Color3.fromRGB(200, 120, 30),
baseplateBg = Color3.fromRGB(60, 110, 80), pillarBg = Color3.fromRGB(120, 70, 160), wallBg = Color3.fromRGB(180, 80, 60),
settingsBg = Color3.fromRGB(25, 28, 40), offRed = Color3.fromRGB(160, 50, 50), onGreen = Color3.fromRGB(50, 160, 70),
}
local function addPress(button)
local scale = create("UIScale", { Parent = button })
local function animate(input, targetScale)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
tw(scale, TWEEN_FAST, { Scale = targetScale })
end
end
button.InputBegan:Connect(function(input) animate(input, 0.94) end)
button.InputEnded:Connect(function(input) animate(input, 1) end)
end
-- ================= ScreenGui & Panels =================
local screenGui = create("ScreenGui", { Name = "FloatingPanelGui", ResetOnSpawn = false, ZIndexBehavior = Enum.ZIndexBehavior.Sibling, Parent = playerGui })
local panel = create("Frame", {
Name = "Panel", AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.fromScale(0.4, 0.5),
Size = UDim2.fromOffset(480, 340), BackgroundColor3 = COLOR.surface, BorderSizePixel = 0,
Visible = false, ZIndex = 10, Parent = screenGui
})
create("UICorner", { CornerRadius = UDim.new(0, 10), Parent = panel })
create("UIStroke", { Color = COLOR.border, Thickness = 1, Parent = panel })
create("UIPadding", { PaddingTop = UDim.new(0, 10), PaddingBottom = UDim.new(0, 10), PaddingLeft = UDim.new(0, 12), PaddingRight = UDim.new(0, 12), Parent = panel })
local title = create("TextLabel", {
Name = "TitleHeader", BackgroundTransparency = 1, Size = UDim2.new(1, 0, 0, 20),
Font = Enum.Font.GothamBold, TextSize = 12, TextColor3 = COLOR.textMuted,
TextXAlignment = Enum.TextXAlignment.Left, Text = "BuildPlank Auto Builder (Hold to Drag)", ZIndex = 11, Parent = panel
})
-- Side GUI Settings
local settingsPanel = create("Frame", {
Name = "SettingsPanel", Size = UDim2.new(0, 240, 1, 0), Position = UDim2.new(1, 10, 0, 0),
BackgroundColor3 = COLOR.settingsBg, BorderSizePixel = 0, ZIndex = 10, Parent = panel
})
create("UICorner", { CornerRadius = UDim.new(0, 10), Parent = settingsPanel })
create("UIStroke", { Color = COLOR.border, Thickness = 1, Parent = settingsPanel })
create("UIPadding", { PaddingTop = UDim.new(0, 10), PaddingBottom = UDim.new(0, 10), PaddingLeft = UDim.new(0, 10), PaddingRight = UDim.new(0, 10), Parent = settingsPanel })
create("TextLabel", {
BackgroundTransparency = 1, Size = UDim2.new(1, 0, 0, 20), Font = Enum.Font.GothamBold,
TextSize = 13, TextColor3 = COLOR.accent, TextXAlignment = Enum.TextXAlignment.Left,
Text = "⚙ Settings", ZIndex = 11, Parent = settingsPanel
})
local settingsContent = create("ScrollingFrame", {
BackgroundTransparency = 1, Size = UDim2.new(1, 0, 1, -25), Position = UDim2.new(0, 0, 0, 25),
CanvasSize = UDim2.new(0, 0, 0, 500), ScrollBarThickness = 3, ScrollBarImageColor3 = COLOR.accent,
BorderSizePixel = 0, ZIndex = 11, Parent = settingsPanel
})
create("UIListLayout", { FillDirection = Enum.FillDirection.Vertical, Padding = UDim.new(0, 6), SortOrder = Enum.SortOrder.LayoutOrder, Parent = settingsContent })
local function createPairRow(layoutOrder)
local row = create("Frame", { BackgroundTransparency = 1, Size = UDim2.new(1, -6, 0, 42), LayoutOrder = layoutOrder, ZIndex = 11, Parent = settingsContent })
create("UIListLayout", { FillDirection = Enum.FillDirection.Horizontal, Padding = UDim.new(0, 8), SortOrder = Enum.SortOrder.LayoutOrder, Parent = row })
return row
end
local function createSingleSettingItem(parent, labelText, defaultVal, widthScale, layoutOrder)
local container = create("Frame", { BackgroundTransparency = 1, Size = UDim2.new(widthScale or 0.48, -4, 1, 0), LayoutOrder = layoutOrder, ZIndex = 11, Parent = parent })
create("TextLabel", { BackgroundTransparency = 1, Size = UDim2.new(1, 0, 0, 14), Font = Enum.Font.GothamMedium, TextSize = 9, TextColor3 = COLOR.textMuted, TextXAlignment = Enum.TextXAlignment.Left, Text = labelText, ZIndex = 11, Parent = container })
local boxFrame = create("Frame", { Size = UDim2.new(1, 0, 0, 24), Position = UDim2.new(0, 0, 0, 16), BackgroundColor3 = COLOR.surface2, BorderSizePixel = 0, ZIndex = 11, Parent = container })
create("UICorner", { CornerRadius = UDim.new(0, 5), Parent = boxFrame })
create("UIStroke", { Color = COLOR.border, Thickness = 1, Parent = boxFrame })
return create("TextBox", { BackgroundTransparency = 1, Size = UDim2.fromScale(1, 1), Font = Enum.Font.Gotham, TextSize = 10, TextColor3 = COLOR.text, Text = defaultVal, ClearTextOnFocus = false, ZIndex = 12, Parent = boxFrame })
end
local function createToggleButton(parent, labelText, defaultState, layoutOrder)
local container = create("Frame", { BackgroundTransparency = 1, Size = UDim2.new(1, -6, 0, 42), LayoutOrder = layoutOrder or 6, ZIndex = 11, Parent = parent })
create("TextLabel", { BackgroundTransparency = 1, Size = UDim2.new(1, 0, 0, 14), Font = Enum.Font.GothamMedium, TextSize = 9, TextColor3 = COLOR.textMuted, TextXAlignment = Enum.TextXAlignment.Left, Text = labelText, ZIndex = 11, Parent = container })
local btn = create("TextButton", {
Size = UDim2.new(1, 0, 0, 24), Position = UDim2.new(0, 0, 0, 16),
BackgroundColor3 = defaultState and COLOR.onGreen or COLOR.offRed, Font = Enum.Font.GothamBold,
TextSize = 10, TextColor3 = COLOR.text, Text = defaultState and "Snap Yaw: ON" or "Snap Yaw: OFF", ZIndex = 11, Parent = container
})
create("UICorner", { CornerRadius = UDim.new(0, 5), Parent = btn })
create("UIStroke", { Color = COLOR.border, Thickness = 1, Parent = btn })
return btn
end
-- Generates Settings UI Rows
local row1, row2, row3, row4, row5 = createPairRow(1), createPairRow(2), createPairRow(3), createPairRow(4), createPairRow(5)
local setLoopInput = createSingleSettingItem(row1, "Loop Count:", "1", 0.5)
local setThickInput = createSingleSettingItem(row1, "Thickness (1-10):", "1", 0.5)
local setSpeedInput = createSingleSettingItem(row2, "Speed (Delay):", "0.05", 0.5)
local setDirInput = createSingleSettingItem(row2, "Vector (Dir):", "0, 1, 0", 0.5)
local setBaseSizeInput = createSingleSettingItem(row3, "Base Size:", "1x1", 0.5)
local setBaseLayerInput = createSingleSettingItem(row3, "Base Layers:", "2", 0.5)
local setBaseOffsetInput = createSingleSettingItem(row4, "Base Offset:", "0.5", 0.5)
local setPillarHeightInput= createSingleSettingItem(row4, "Pillar Height:", "25", 0.5)
local setWallHeightInput = createSingleSettingItem(row5, "Wall Height (x0.5):", "10", 0.5)
local setWallLengthInput = createSingleSettingItem(row5, "Wall Length:", "5", 0.5)
local snapYawBtn = createToggleButton(settingsContent, "Snap Character (90°):", false, 6)
local function updateSettingsFromUI()
settingsData.repeatCount = tonumber(setLoopInput.Text) or 1
settingsData.buildDir = parseVector3(setDirInput.Text, Vector3.new(0, 1, 0))
settingsData.thickness = math.clamp(math.floor(tonumber(setThickInput.Text) or 1), 1, 10)
settingsData.buildDelay = math.clamp(tonumber(setSpeedInput.Text) or 0.05, 0.001, 1)
settingsData.baseSize = setBaseSizeInput.Text ~= "" and setBaseSizeInput.Text or "1x1"
settingsData.baseLayers = math.clamp(tonumber(setBaseLayerInput.Text) or 2, 1, 2)
settingsData.baseOffset = tonumber(setBaseOffsetInput.Text) or 0.5
settingsData.pillarHeight = tonumber(setPillarHeightInput.Text) or 25
settingsData.wallHeight = tonumber(setWallHeightInput.Text) or 10
settingsData.wallLength = tonumber(setWallLengthInput.Text) or 5
end
for _, input in ipairs({setLoopInput, setDirInput, setThickInput, setSpeedInput, setBaseSizeInput, setBaseLayerInput, setBaseOffsetInput, setPillarHeightInput, setWallHeightInput, setWallLengthInput}) do
input.FocusLost:Connect(updateSettingsFromUI)
end
-- Logic Snap Yaw
snapYawBtn.MouseButton1Click:Connect(function()
settingsData.autoSnapYaw = not settingsData.autoSnapYaw
snapYawBtn.BackgroundColor3 = settingsData.autoSnapYaw and COLOR.onGreen or COLOR.offRed
snapYawBtn.Text = settingsData.autoSnapYaw and "Snap Yaw: ON" or "Snap Yaw: OFF"
if snapYawConnection then snapYawConnection:Disconnect() snapYawConnection = nil end
if settingsData.autoSnapYaw then
snapYawConnection = RunService.RenderStepped:Connect(function()
local hrp = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
if hrp then
local yaw = math.deg(math.atan2(-hrp.CFrame.LookVector.X, -hrp.CFrame.LookVector.Z))
hrp.CFrame = CFrame.new(hrp.Position) * CFrame.Angles(0, math.rad(math.round(yaw / 90) * 90), 0)
end
end)
end
end)
-- Drag Logic cho Main Panel
local panelDragging, panelDragStart, panelStartPos
title.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
panelDragging, panelDragStart, panelStartPos = true, input.Position, panel.Position
input.Changed:Connect(function()
if input.UserInputState == Enum.UserInputState.End then panelDragging = false end
end)
end
end)
UserInputService.InputChanged:Connect(function(input)
if panelDragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
local delta = input.Position - panelDragStart
panel.Position = UDim2.new(panelStartPos.X.Scale, panelStartPos.X.Offset + delta.X, panelStartPos.Y.Scale, panelStartPos.Y.Offset + delta.Y)
end
end)
-- Inputs Column Generation
local function createSlotInput(parent, layoutOrder, placeholderText)
local slot = create("Frame", { Name = "Slot", Size = UDim2.new(1, 0, 0, 30), LayoutOrder = layoutOrder, BackgroundColor3 = COLOR.surface2, BorderSizePixel = 0, ZIndex = 11, Parent = parent })
create("UICorner", { CornerRadius = UDim.new(0, 6), Parent = slot })
create("UIStroke", { Color = COLOR.border, Thickness = 1, Parent = slot })
local textBox = create("TextBox", {
Name = "Input", BackgroundTransparency = 1, Size = UDim2.fromScale(1, 1),
Font = Enum.Font.Gotham, TextSize = 11, TextColor3 = COLOR.text,
PlaceholderColor3 = COLOR.textMuted, PlaceholderText = placeholderText, Text = "",
ClearTextOnFocus = false, ZIndex = 12, Parent = slot
})
textBox.FocusLost:Connect(function() formatTextBoxTo2Decimals(textBox) end)
return textBox
end
local function createColumn6(labelText, xScale, storageTable)
local column = create("Frame", { BackgroundTransparency = 1, Size = UDim2.new(0.48, 0, 0, 240), Position = UDim2.new(xScale, 0, 0, 25), ZIndex = 11, Parent = panel })
create("UIListLayout", { FillDirection = Enum.FillDirection.Vertical, Padding = UDim.new(0, 4), SortOrder = Enum.SortOrder.LayoutOrder, Parent = column })
create("TextLabel", { BackgroundTransparency = 1, Size = UDim2.new(1, 0, 0, 14), LayoutOrder = 0, Font = Enum.Font.GothamBold, TextSize = 11, TextColor3 = COLOR.accent, TextXAlignment = Enum.TextXAlignment.Left, Text = labelText, Parent = column })
local placeholders = { "Start X", "Start Y", "Start Z", "End X", "End Y", "End Z" }
for i = 1, 6 do
if i == 4 then
create("TextLabel", { BackgroundTransparency = 1, Size = UDim2.new(1, 0, 0, 12), LayoutOrder = 3.5, Font = Enum.Font.GothamMedium, TextSize = 10, TextColor3 = COLOR.textMuted, TextXAlignment = Enum.TextXAlignment.Left, Text = "TO:", Parent = column })
end
storageTable[i] = createSlotInput(column, i <= 3 and i or i + 1, placeholders[i])
end
end
createColumn6("Plank 1 (Left)", 0, inputsLeft)
createColumn6("Plank 2 (Right)", 0.52, inputsRight)
refreshESPFromInputs()
RunService.RenderStepped:Connect(refreshESPFromInputs)
-- ================= Bottom Action Buttons =================
local bottomFrame = create("Frame", { BackgroundTransparency = 1, Size = UDim2.new(1, 0, 0, 32), Position = UDim2.new(0, 0, 1, -32), ZIndex = 11, Parent = panel })
create("UIListLayout", { FillDirection = Enum.FillDirection.Horizontal, Padding = UDim.new(0, 4), SortOrder = Enum.SortOrder.LayoutOrder, Parent = bottomFrame })
local function createBottomBtn(text, sizeScale, bgCol, textCol, order)
local btn = create("TextButton", { Size = UDim2.new(sizeScale, 0, 1, 0), LayoutOrder = order, BackgroundColor3 = bgCol, Font = Enum.Font.GothamBold, TextSize = 9, TextColor3 = textCol, Text = text, ZIndex = 11, Parent = bottomFrame })
create("UICorner", { CornerRadius = UDim.new(0, 6), Parent = btn })
return btn
end
local updateButton = createBottomBtn("Update", 0.16, COLOR.accent, COLOR.ink, 1)
local actionButton = create("Frame", { Size = UDim2.new(0.24, 0, 1, 0), LayoutOrder = 2, BackgroundColor3 = COLOR.stepBg, BorderSizePixel = 0, ZIndex = 11, Parent = bottomFrame })
create("UICorner", { CornerRadius = UDim.new(0, 6), Parent = actionButton })
create("UIStroke", { ApplyStrokeMode = Enum.ApplyStrokeMode.Border, Color = COLOR.border, Thickness = 1, Transparency = 0.15, Parent = actionButton })
local actionSingleButton = create("TextButton", { Size = UDim2.fromScale(1, 1), BackgroundTransparency = 1, BorderSizePixel = 0, AutoButtonColor = false, Font = Enum.Font.GothamBold, TextSize = 9, TextColor3 = COLOR.text, Text = "Record Size", ZIndex = 12, Parent = actionButton })
local actionUndoButton = create("TextButton", { Size = UDim2.new(0.5, 0, 1, 0), BackgroundColor3 = COLOR.stepBg, BorderSizePixel = 0, AutoButtonColor = false, Font = Enum.Font.GothamBold, TextSize = 9, TextColor3 = COLOR.text, Text = "Undo", ZIndex = 12, Visible = false, Parent = actionButton })
local actionContinueButton = create("TextButton", { Size = UDim2.new(0.5, 0, 1, 0), Position = UDim2.new(0.5, 0, 0, 0), BackgroundColor3 = COLOR.accent, BorderSizePixel = 0, AutoButtonColor = false, Font = Enum.Font.GothamBold, TextSize = 9, TextColor3 = COLOR.ink, Text = "Continue", ZIndex = 12, Visible = false, Parent = actionButton })
create("UICorner", { CornerRadius = UDim.new(0, 6), Parent = actionUndoButton })
create("UICorner", { CornerRadius = UDim.new(0, 6), Parent = actionContinueButton })
local actionDivider = create("Frame", { Size = UDim2.new(0, 1, 1, -6), Position = UDim2.new(0.5, 0, 0, 3), BackgroundColor3 = COLOR.border, BackgroundTransparency = 0.35, BorderSizePixel = 0, ZIndex = 13, Visible = false, Parent = actionButton })
local function setActionSingle(text, backgroundColor, textColor)
actionSingleButton.Visible = true
actionSingleButton.Text = text or ""
actionSingleButton.TextColor3 = textColor or COLOR.text
actionButton.BackgroundColor3 = backgroundColor or COLOR.stepBg
actionUndoButton.Visible, actionContinueButton.Visible, actionDivider.Visible = false, false, false
end
local function setActionSplit(backgroundLeft, backgroundRight, continueText)
actionSingleButton.Visible = false
actionUndoButton.Visible, actionContinueButton.Visible, actionDivider.Visible = true, true, true
actionUndoButton.BackgroundColor3 = backgroundLeft or COLOR.stepBg
actionContinueButton.BackgroundColor3 = backgroundRight or COLOR.accent
actionContinueButton.Text = continueText or "Continue"
actionButton.BackgroundColor3 = backgroundLeft or COLOR.stepBg
end
local baseplateButton = createBottomBtn("Baseplate", 0.2, COLOR.baseplateBg, COLOR.text, 3)
local pillarButton = createBottomBtn("Build Pillar", 0.18, COLOR.pillarBg, COLOR.text, 4)
local wallButton = createBottomBtn("Build Wall", 0.18, COLOR.wallBg, COLOR.text, 5)
-- ================= Metamethod Hook =================
local oldNamecall
oldNamecall = hookmetamethod(game, "__namecall", newcclosure(function(self, ...)
local method = getnamecallmethod()
local args = {...}
if (method == "FireServer" or method == "InvokeServer") and self.Name == "BuildPlank" then
if #args >= 2 and typeof(args[1]) == "Vector3" and typeof(args[2]) == "Vector3" then
local v1, v2 = roundVec2(args[1]), roundVec2(args[2])
currentVec1, currentVec2 = v1, v2
setVectorToInputs(inputsLeft, v1, 1)
setVectorToInputs(inputsRight, v2, 1)
if #args == 5 then
lastTarget1, lastTarget2, lastDir = args[3], args[4], args[5]
else
lastDir = args[3]
end
if listenState == 1 then
tempStart1, tempStart2 = v1, v2
listenState = 2
setActionSplit(COLOR.surface2, COLOR.accent, "Continue")
elseif listenState == 3 then
tempEnd1, tempEnd2 = v1, v2
local altEnd = (tempEnd1 + tempEnd2) * 0.5
setVectorToInputs(inputsLeft, tempStart1, 4)
setVectorToInputs(inputsRight, altEnd, 4)
listenState = 4
setActionSplit(COLOR.surface2, COLOR.accent, "Create")
end
args[1], args[2] = v1, v2
end
end
return oldNamecall(self, unpack(args))
end))
-- ================= Build Executions =================
local function ensureBuildContext(hammer, event, timeout)
if lastTarget1 and lastTarget2 then return true end
timeout = timeout or 1.0
pcall(function()
if hammer and hammer:IsA("Tool") then hammer:Activate() end
end)
local deadline = os.clock() + timeout
while os.clock() < deadline do
if lastTarget1 and lastTarget2 then return true end
task.wait()
end
return lastTarget1 ~= nil and lastTarget2 ~= nil
end
local function executeBuild(start1, end1, start2, end2, callback)
updateSettingsFromUI()
local char = player.Character
local hammer = char and char:FindFirstChild("Hammer")
local event = hammer and hammer:FindFirstChild("BuildPlank")
if not event or (not lastTarget1 and not ensureBuildContext(hammer, event, 1.0)) then
if callback then callback(false, not event and "No Hammer!" or "BuildPlank context not ready!") end
return
end
local diff1, diff2 = end1 - start1, end2 - start2
local maxDist = math.max(math.abs(diff1.X), math.abs(diff1.Y), math.abs(diff1.Z), math.abs(diff2.X), math.abs(diff2.Y), math.abs(diff2.Z))
local steps = math.max(1, math.floor((maxDist / 0.5) + 0.5))
local finalDir = settingsData.buildDir or lastDir or Vector3.new(0, 1, 0)
task.spawn(function()
for _ = 1, settingsData.repeatCount do
local prevP1, prevP2
for i = 0, steps do
local alpha = i / steps
local curr1, curr2 = roundVec2(start1:Lerp(end1, alpha)), roundVec2(start2:Lerp(end2, alpha))
local function firePlank(p1, p2)
if lastTarget1 and lastTarget2 then
event:FireServer(p1, p2, lastTarget1, lastTarget2, finalDir)
return true
end
return false
end
if not firePlank(curr1, curr2) then
if callback then callback(false, "BuildPlank context lost!") end
return
end
local thickness = math.clamp(math.floor(settingsData.thickness or 1), 1, 10)
if thickness >= 2 and prevP1 and prevP2 then
for t = 1, thickness - 1 do
local ratio = t / thickness
firePlank(roundVec2(prevP1:Lerp(curr1, ratio)), roundVec2(prevP2:Lerp(curr2, ratio)))
end
end
prevP1, prevP2 = curr1, curr2
task.wait(settingsData.buildDelay)
end
task.wait(0.05)
end
if callback then callback(true) end
end)
end
-- Helper lấy phẳng Character Look/Right Vector
local function getCharOrientation(hrp)
local rawLook = hrp.CFrame.LookVector
local flatLook = Vector3.new(rawLook.X, 0, rawLook.Z)
flatLook = flatLook.Magnitude < 0.001 and Vector3.new(0, 0, -1) or flatLook.Unit
return flatLook, Vector3.new(-flatLook.Z, 0, flatLook.X)
end
-- Helper kiểm tra Nhân vật
local function getHrpAndHumanoid(btn, defaultText)
local char = player.Character
local hrp, humanoid = char and char:FindFirstChild("HumanoidRootPart"), char and char:FindFirstChildOfClass("Humanoid")
if not hrp or not humanoid then
btn.Text = "No Char!"
task.delay(1, function() btn.Text = defaultText end)
return nil, nil
end
return hrp, humanoid
end
-- ================= Logic các Nút Xây =================
updateButton.MouseButton1Click:Connect(function()
for i = 1, 6 do
formatTextBoxTo2Decimals(inputsLeft[i])
formatTextBoxTo2Decimals(inputsRight[i])
end
local start1 = Vector3.new(tonumber(inputsLeft[1].Text) or 0, tonumber(inputsLeft[2].Text) or 0, tonumber(inputsLeft[3].Text) or 0)
local end1 = Vector3.new(tonumber(inputsLeft[4].Text) or start1.X, tonumber(inputsLeft[5].Text) or start1.Y, tonumber(inputsLeft[6].Text) or start1.Z)
local start2 = Vector3.new(tonumber(inputsRight[1].Text) or 0, tonumber(inputsRight[2].Text) or 0, tonumber(inputsRight[3].Text) or 0)
local end2 = Vector3.new(tonumber(inputsRight[4].Text) or start2.X, tonumber(inputsRight[5].Text) or start2.Y, tonumber(inputsRight[6].Text) or start2.Z)
refreshESPFromInputs()
executeBuild(start1, end1, start2, end2, function(success, msg)
updateButton.Text = success and "Done!" or (msg or "Error!")
task.delay(1, function() updateButton.Text = "Update" end)
end)
end)
baseplateButton.MouseButton1Click:Connect(function()
updateSettingsFromUI()
local hrp, humanoid = getHrpAndHumanoid(baseplateButton, "Baseplate")
if not hrp then return end
local rows, cols = 1, 1
local rStr, cStr = string.match(settingsData.baseSize or "", "(%d+)[xX](%d+)")
if rStr and cStr then
rows, cols = math.max(1, tonumber(rStr) or 1), math.max(1, tonumber(cStr) or 1)
else
local singleNum = string.match(settingsData.baseSize or "", "%d+")
if singleNum then rows = math.max(1, tonumber(singleNum) or 1); cols = rows end
end
baseplateButton.Text = "Calculating..."
local footPos = hrp.Position - Vector3.new(0, (hrp.Size.Y / 2) + humanoid.HipHeight + settingsData.baseOffset, 0)
local curX, curY, curZ = math.floor((footPos.X / 2) + 0.5) * 2, math.floor((footPos.Y / 2) + 0.5) * 2, math.floor((footPos.Z / 2) + 0.5) * 2
local totalWidthX, totalWidthZ = rows * 6, cols * 6
local xCount, zCount = math.ceil(totalWidthX / 2), math.ceil(totalWidthZ / 2)
local flatLook, rightVector = getCharOrientation(hrp)
local baseCenter = Vector3.new(curX, curY, curZ)
local halfWidthX, halfWidthZ = totalWidthX * 0.5, totalWidthZ * 0.5
task.spawn(function()
local function buildLayer(layerNum, isLayer2)
baseplateButton.Text = string.format("Layer %d (%dx%d)...", layerNum, rows, cols)
local count = isLayer2 and xCount or zCount
for i = 0, count - 1 do
local l1 = (isLayer2 and -halfWidthX or -halfWidthZ) + (i * 2)
local l2 = math.min(l1 + 2, isLayer2 and halfWidthX or halfWidthZ)
if l1 > (isLayer2 and halfWidthX or halfWidthZ) - 2 then l1 = (isLayer2 and halfWidthX or halfWidthZ) - 2 end
local dir1 = isLayer2 and rightVector or flatLook
local dir2 = isLayer2 and flatLook or rightVector
local span = isLayer2 and halfWidthZ or halfWidthX
local c1, c2 = baseCenter + dir1 * l1, baseCenter + dir1 * l2
local s1, e1 = c1 - dir2 * span, c1 + dir2 * span
local s2, e2 = c2 - dir2 * span, c2 + dir2 * span
setVectorToInputs(inputsLeft, s1, 1); setVectorToInputs(inputsLeft, e1, 4)
setVectorToInputs(inputsRight, s2, 1); setVectorToInputs(inputsRight, e2, 4)
local completedEvent = Instance.new("BindableEvent")
executeBuild(s1, e1, s2, e2, function() completedEvent:Fire() end)
completedEvent.Event:Wait()
completedEvent:Destroy()
task.wait(0.02)
end
end
buildLayer(1, false)
if settingsData.baseLayers >= 2 then buildLayer(2, true) end
baseplateButton.Text = "Completed!"
task.delay(1, function() baseplateButton.Text = "Baseplate" end)
end)
end)
pillarButton.MouseButton1Click:Connect(function()
updateSettingsFromUI()
local hrp, humanoid = getHrpAndHumanoid(pillarButton, "Build Pillar")
if not hrp then return end
pillarButton.Text = "Building..."
local footPos = roundVec2(hrp.Position - Vector3.new(0, (hrp.Size.Y / 2) + humanoid.HipHeight, 0))
local _, rightVector = getCharOrientation(hrp)
local centerPos = Vector3.new(round2(footPos.X), round2(footPos.Y), round2(footPos.Z))
local pos1, pos2 = centerPos - rightVector, centerPos + rightVector
local start1 = Vector3.new(round2(pos1.X), round2(footPos.Y), round2(pos1.Z))
local end1 = Vector3.new(round2(pos1.X), round2(footPos.Y + settingsData.pillarHeight), round2(pos1.Z))
local start2 = Vector3.new(round2(pos2.X), round2(footPos.Y), round2(pos2.Z))
local end2 = Vector3.new(round2(pos2.X), round2(footPos.Y + settingsData.pillarHeight), round2(pos2.Z))
setVectorToInputs(inputsLeft, start1, 1); setVectorToInputs(inputsLeft, end1, 4)
setVectorToInputs(inputsRight, start2, 1); setVectorToInputs(inputsRight, end2, 4)
executeBuild(start1, end1, start2, end2, function(success, msg)
pillarButton.Text = success and "Completed!" or (msg or "Error!")
task.delay(1, function() pillarButton.Text = "Build Pillar" end)
end)
end)
wallButton.MouseButton1Click:Connect(function()
updateSettingsFromUI()
local hrp, humanoid = getHrpAndHumanoid(wallButton, "Build Wall")
if not hrp then return end
wallButton.Text = "Building..."
local footPos = roundVec2(hrp.Position - Vector3.new(0, (hrp.Size.Y / 2) + humanoid.HipHeight, 0))
local wallHeightOffset, halfLength = settingsData.wallHeight * 0.5, settingsData.wallLength * 0.5
local _, rightVector = getCharOrientation(hrp)
local lengthVec = rightVector * halfLength
local pos1, pos2 = footPos - lengthVec, footPos + lengthVec
local start1 = Vector3.new(round2(pos1.X), round2(footPos.Y), round2(pos1.Z))
local end1 = Vector3.new(round2(pos1.X), round2(footPos.Y + wallHeightOffset), round2(pos1.Z))
local start2 = Vector3.new(round2(pos2.X), round2(footPos.Y), round2(pos2.Z))
local end2 = Vector3.new(round2(pos2.X), round2(footPos.Y + wallHeightOffset), round2(pos2.Z))
setVectorToInputs(inputsLeft, start1, 1); setVectorToInputs(inputsLeft, end1, 4)
setVectorToInputs(inputsRight, start2, 1); setVectorToInputs(inputsRight, end2, 4)
executeBuild(start1, end1, start2, end2, function(success, msg)
wallButton.Text = success and "Completed!" or (msg or "Error!")
task.delay(1, function() wallButton.Text = "Build Wall" end)
end)
end)
-- ================= Logic Quy Trình Lắng Nghe (Action State Machine) =================
local function resetActionButton()
listenState = 0
setActionSingle("Record Size", COLOR.stepBg, COLOR.text)
tempStart1, tempStart2, tempEnd1, tempEnd2 = nil, nil, nil, nil
end
actionUndoButton.MouseButton1Click:Connect(function()
if listenState == 2 then
resetActionButton()
elseif listenState == 4 then
tempEnd1, tempEnd2 = nil, nil
listenState = 2
setActionSingle("End Position", COLOR.surface2, COLOR.text)
end
end)
actionContinueButton.MouseButton1Click:Connect(function()
if listenState == 2 then
listenState = 3
setActionSingle("Listening End...", COLOR.listening, COLOR.text)
elseif listenState == 4 then
setActionSingle("Create", COLOR.accent, COLOR.ink)
listenState = 5
end
end)
actionSingleButton.MouseButton1Click:Connect(function()
if listenState == 0 then
listenState = 1
setActionSingle("Listening Start...", COLOR.listening, COLOR.text)
elseif listenState == 2 or listenState == 3 then
listenState = 3
setActionSingle("Listening End...", COLOR.listening, COLOR.text)
elseif listenState == 5 then
if not tempStart1 or not tempEnd1 or not tempStart2 or not tempEnd2 then
setActionSingle("Missing Pos!", COLOR.stepBg, COLOR.text)
task.delay(1, function() if listenState == 5 then setActionSingle("Create", COLOR.accent, COLOR.ink) end end)
return
end
setActionSingle("Building...", COLOR.accent, COLOR.ink)
executeBuild(tempStart1, tempEnd1, tempStart2, tempEnd2, function(success, msg)
setActionSingle(success and "Completed!" or (msg or "Error!"), COLOR.accent, COLOR.ink)
task.wait(success and 0.8 or 1)
resetActionButton()
end)
end
end)
-- ================= Menu Handle Toggle & Drag =================
local handle = create("TextButton", { Name = "Handle", Size = UDim2.fromOffset(50, 32), Position = UDim2.new(1, -70, 1, -50), BackgroundColor3 = COLOR.ink, BorderSizePixel = 0, AutoButtonColor = false, Text = "", ZIndex = 20, Parent = screenGui })
create("UICorner", { CornerRadius = UDim.new(0, 8), Parent = handle })
local handleStroke = create("UIStroke", { Name = "HandleBorder", ApplyStrokeMode = Enum.ApplyStrokeMode.Border, Color = THEME.border, Thickness = 2, Transparency = 0, Parent = handle })
for _, btn in ipairs({handle, actionSingleButton, actionUndoButton, actionContinueButton}) do addPress(btn) end
local dotsHolder = create("Frame", { BackgroundTransparency = 1, Size = UDim2.fromOffset(16, 10), Position = UDim2.new(0.5, -8, 0.5, -5), ZIndex = 21, Parent = handle })
create("UIGridLayout", { CellSize = UDim2.fromOffset(3, 3), CellPadding = UDim2.fromOffset(3, 3), FillDirectionMaxCells = 3, Parent = dotsHolder })
local dots = {}
for i = 1, 6 do
local dot = create("Frame", { Size = UDim2.fromOffset(3, 3), BackgroundColor3 = COLOR.textMuted, BorderSizePixel = 0, ZIndex = 21, Parent = dotsHolder })
create("UICorner", { CornerRadius = UDim.new(1, 0), Parent = dot })
dots[i] = dot
end
local panelOpen = false
local function setOpen(open)
panelOpen = open
panel.Visible = open
tw(handleStroke, TWEEN_FAST, { Color = open and THEME.accentA or THEME.border })
for _, dot in ipairs(dots) do
tw(dot, TWEEN_FAST, { BackgroundColor3 = open and THEME.accentA or COLOR.textMuted })
end
end
local dragging, moved, dragInput, dragStart, startPos = false, false
local DRAG_THRESHOLD = 5
handle.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
dragging, moved, dragStart, startPos = true, false, input.Position, handle.Position
input.Changed:Connect(function()
if input.UserInputState == Enum.UserInputState.End then
dragging = false
if not moved then setOpen(not panelOpen) end
end
end)
end
end)
handle.InputChanged:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then
dragInput = input
end
end)
UserInputService.InputChanged:Connect(function(input)
if dragging and input == dragInput then
local delta = input.Position - dragStart
if not moved and delta.Magnitude > DRAG_THRESHOLD then moved = true end
if moved then
handle.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y)
end
end
end)No comments yet for this script.


