local screen = { guiGetScreenSize() } local resW, resH = 1920, 1080 function cX(pos) local Diferenca = resW - pos return screen[1] - Diferenca end function cY(pos, height) local Divisao = resH / 2 local Total = Divisao - height local Convertido = pos - Total return (screen[2] / 2) - height + Convertido end --[[ -- Sliders configuration - SIMPLIFICADO: range menor, precisão de 0.001 local sliders = { {name = "xPosOffset", label = "xPosOffset - 0%", value = 800, min = 0, max = 1000, realMin = -0.800, realMax = 0.800}, {name = "yPosOffset", label = "yPosOffset - 0%", value = 800, min = 0, max = 1000, realMin = -0.800, realMax = 0.800}, {name = "zPosOffset", label = "zPosOffset - 0%", value = 800, min = 0, max = 1000, realMin = -0.800, realMax = 0.800}, {name = "xRotOffset", label = "xRotOffset - 0%", value = 3590, min = 0, max = 7180, realMin = -359, realMax = 359}, {name = "yRotOffset", label = "yRotOffset - 0%", value = 3590, min = 0, max = 7180, realMin = -359, realMax = 359}, {name = "zRotOffset", label = "zRotOffset - 0%", value = 3590, min = 0, max = 7180, realMin = -359, realMax = 359}, } local function getSliderRealValue(slider) if slider.name:find("Pos") then -- Para posição: converte de [0, 1998] para [-0.999, 0.999] return CONFIG.Position.Min + (slider.value * CONFIG.Position.Step) else -- Para rotação: mantém o cálculo original return (slider.value - 3590) * 0.1 end end]] -- ==================== CONFIGURAÇÕES ==================== local CONFIG = { -- Ranges para Position (x, y, z) - AJUSTÁVEL Position = { Min = -0.999, Max = 0.999, Step = 0.001, -- Precisão de 3 casas decimais }, -- Ranges para Rotation (mantém o original) Rotation = { Min = -359, Max = 359, Step = 0.1, }, } -- Calcula o range interno para posições local posRange = (CONFIG.Position.Max - CONFIG.Position.Min) / CONFIG.Position.Step -- (0.999 - (-0.999)) / 0.001 = 1998 local posCenter = posRange / 2 -- Valor central (0) -- Sliders configuration local sliders = { -- Posições: agora vão de 0 a 1998, onde 999 = 0.000 {name = "xPosOffset", label = "xPosOffset - 0%", value = posCenter, min = 0, max = posRange, realMin = CONFIG.Position.Min, realMax = CONFIG.Position.Max}, {name = "yPosOffset", label = "yPosOffset - 0%", value = posCenter, min = 0, max = posRange, realMin = CONFIG.Position.Min, realMax = CONFIG.Position.Max}, {name = "zPosOffset", label = "zPosOffset - 0%", value = posCenter, min = 0, max = posRange, realMin = CONFIG.Position.Min, realMax = CONFIG.Position.Max}, -- Rotações: mantém o original (0 a 7180, onde 3590 = 0) {name = "xRotOffset", label = "xRotOffset - 0%", value = 3590, min = 0, max = 7180, realMin = -359, realMax = 359}, {name = "yRotOffset", label = "yRotOffset - 0%", value = 3590, min = 0, max = 7180, realMin = -359, realMax = 359}, {name = "zRotOffset", label = "zRotOffset - 0%", value = 3590, min = 0, max = 7180, realMin = -359, realMax = 359}, } -- Função para converter valor interno para real local function getSliderRealValue(slider) if slider.name:find("Pos") then -- Para posição: converte de [0, 1998] para [-0.999, 0.999] return CONFIG.Position.Min + (slider.value * CONFIG.Position.Step) else -- Para rotação: mantém o cálculo original return (slider.value - 3590) * 0.1 end end --[[ local function getSliderRealValue(slider) if slider.name:find("Pos") then -- Para posição: cada unidade = 0.001 return (slider.value - 800) * 0.001 else -- Para rotação: cada unidade = 0.1 return (slider.value - 3590) * 0.1 end end ]] -- Função para definir valor real no slider local function setSliderRealValue(slider, realValue) if slider.name:find("Pos") then -- Para posição realValue = math.max(-0.800, math.min(0.800, realValue)) slider.value = math.floor(realValue / 0.001 + 500.5) else -- Para rotação realValue = math.max(-359, math.min(359, realValue)) slider.value = math.floor(realValue / 0.1 + 3590.5) end end local currentSlider = nil local mouseStartX = 0 local sliderStartValue = 0 local isDragging = false local Preview = false local Object = nil local size = 1.0 local boneID = 1 VALID_BONES = { [0] = "BONE_ROOT", [1] = "BONE_PELVIS1", [2] = "BONE_PELVIS", [3] = "BONE_SPINE1", [4] = "BONE_UPPERTORSO", [5] = "BONE_NECK", [6] = "BONE_HEAD2", [7] = "BONE_HEAD1", [8] = "BONE_HEAD", [22] = "BONE_RIGHTSHOULDER", [23] = "BONE_RIGHTELBOW", [24] = "BONE_RIGHTWRIST", [25] = "BONE_RIGHTHAND", [26] = "BONE_RIGHTTHUMB", [31] = "BONE_LEFTUPPERTORSO", [32] = "BONE_LEFTSHOULDER", [33] = "BONE_LEFTELBOW", [34] = "BONE_LEFTWRIST", [35] = "BONE_LEFTHAND", [36] = "BONE_LEFTTHUMB", [41] = "BONE_LEFTHIP", [42] = "BONE_LEFTKNEE", [43] = "BONE_LEFTANKLE", [44] = "BONE_LEFTFOOT", [51] = "BONE_RIGHTHIP", [52] = "BONE_RIGHTKNEE", [53] = "BONE_RIGHTANKLE", [54] = "BONE_RIGHTFOOT", [201] = "BONE_BELLY", [301] = "BONE_RIGHTBREAST", [302] = "BONE_LEFTBREAST", } addCommandHandler("preview", function(cmd, id, scale, isNotIMG) if Preview then Preview = false showCursor(false) destroyElement(Object) else if id and tonumber(id) then if (isNotIMG) then Object = createObject(id, 0, 0, 0) else Object = createObject(1337, 0, 0, 0) end if Object then Preview = true size = tonumber(scale) or 1.0 if not texture then texture = dxCreateTexture("fodase.jpg") end if not shader then shader = dxCreateShader([[ texture gTexture; technique simple { pass P0 { Texture[0] = gTexture; AlphaBlendEnable = FALSE; } } ]]) end dxSetShaderValue(shader, "gTexture", texture) -- Set object ID if it's not a default object if (not isNotIMG) then if (not isDefaultID("object", id)) then setElementID(Object, id) end end exports.pAttach:attach(Object, localPlayer, boneID, 0, 0, 0, 0, 0, 0) setTimer(function(Object, shader) local TexturesNames = engineGetModelTextureNames(getElementModel(Object)) for _, textureName in pairs(TexturesNames) do engineApplyShaderToWorldTexture(shader, textureName, Object) end end, 20, 1, Object, shader) showCursor(true) setObjectScale(Object, size) end end end end) -- Add missing functions function isDefaultObjectID(id) if id >= 30000 and id <= 30541 then return false end if id < 321 or id > 18630 then return false end if id >= 374 and id <= 614 then return false end if id >= 11682 and id <= 12799 then return false end if id >= 15065 and id <= 15999 then return false end return true end function isDefaultID(elementType, id) id = tonumber(id) if not id then return false end if not elementType then if isDefaultObjectID(id) then return true end elseif elementType == "object" or elementType == "pickup" then return isDefaultObjectID(id) end return false end -- Input fields for bone ID and size local inputBoneID = "1" local inputSize = "1.0" local editingBoneID = false local editingSize = false -- Panel dimensions local panelX = cX(1350) local panelY = cY(362, 500) local panelWidth = 500 local panelHeight = 500 function drawPanel() if not Preview then return end -- Panel background with gradient effect dxDrawRectangle(panelX, panelY, panelWidth, panelHeight, tocolor(20, 20, 20, 230)) -- Panel border dxDrawBorderedRectangle(panelX, panelY, panelWidth, panelHeight, 2, tocolor(60, 60, 60, 255)) -- Title with gradient background dxDrawRectangle(panelX, panelY, panelWidth, 50, tocolor(40, 40, 40, 255)) dxDrawText("Preview pAttach By : ST", panelX + 10, panelY + 10, panelX + panelWidth - 10, panelY + 40, tocolor(255, 255, 255, 255), 1.2, "default-bold", "center", "center") -- Bone ID input field local boneIDColor = tocolor(60, 60, 60, 255) if editingBoneID then boneIDColor = tocolor(100, 100, 255, 255) end dxDrawRectangle(panelX + 20, panelY + 60, 150, 25, tocolor(40, 40, 40, 255)) dxDrawText("Bone ID:", panelX + 20, panelY + 60, panelX + 170, panelY + 85, tocolor(255, 255, 255, 255), 1.0, "default-bold", "left", "center") dxDrawRectangle(panelX + 180, panelY + 60, 80, 25, boneIDColor) dxDrawText(inputBoneID, panelX + 180, panelY + 60, panelX + 260, panelY + 85, tocolor(255, 255, 255, 255), 1.0, "default-bold", "center", "center") -- Size input field local sizeColor = tocolor(60, 60, 60, 255) if editingSize then sizeColor = tocolor(100, 100, 255, 255) end dxDrawRectangle(panelX + 20, panelY + 95, 150, 25, tocolor(40, 40, 40, 255)) dxDrawText("Size:", panelX + 20, panelY + 95, panelX + 170, panelY + 120, tocolor(255, 255, 255, 255), 1.0, "default-bold", "left", "center") dxDrawRectangle(panelX + 180, panelY + 95, 80, 25, sizeColor) dxDrawText(inputSize, panelX + 180, panelY + 95, panelX + 260, panelY + 120, tocolor(255, 255, 255, 255), 1.0, "default-bold", "center", "center") -- Draw sliders local sliderY = panelY + 130 local sliderHeight = 35 local sliderSpacing = 45 for i, slider in ipairs(sliders) do local currentY = sliderY + (i-1) * sliderSpacing -- Slider container background dxDrawRectangle(panelX + 15, currentY, panelWidth - 30, sliderHeight, tocolor(30, 30, 30, 200)) -- Slider track local trackWidth = panelWidth - 140 local trackX = panelX + 50 dxDrawRectangle(trackX, currentY + 8, trackWidth, sliderHeight - 16, tocolor(50, 50, 50, 255)) -- Slider handle with glow effect local handleWidth = 25 local normalizedValue = (slider.value - slider.min) / (slider.max - slider.min) local handleX = trackX + (normalizedValue * trackWidth) - handleWidth/2 local handleColor = tocolor(255, 100, 100, 255) if i > 3 then handleColor = tocolor(100, 255, 100, 255) end -- Handle glow dxDrawRectangle(handleX - 2, currentY + 6, handleWidth + 4, sliderHeight - 12, tocolor(255, 255, 255, 100)) dxDrawRectangle(handleX, currentY + 8, handleWidth, sliderHeight - 16, handleColor) -- Update label with current value local currentValue = getSliderRealValue(slider) local percentage = math.floor(normalizedValue * 100) slider.label = slider.name .. " - " .. percentage .. "%" -- Label dxDrawText(slider.label, panelX + 20, currentY, panelX + panelWidth - 20, currentY + sliderHeight, tocolor(255, 255, 255, 255), 1.0, "default-bold", "left", "center") -- Value display dxDrawRectangle(panelX + panelWidth - 110, currentY + 5, 90, sliderHeight - 10, tocolor(40, 40, 40, 200)) if i <= 3 then -- Para posições (x, y, z) - 3 casas decimais dxDrawText(string.format("%.3f", currentValue), panelX + panelWidth - 105, currentY, panelX + panelWidth - 15, currentY + sliderHeight, tocolor(255, 255, 255, 255), 1.0, "default-bold", "center", "center") else -- Para rotações - 1 casa decimal dxDrawText(string.format("%.1f", currentValue), panelX + panelWidth - 105, currentY, panelX + panelWidth - 15, currentY + sliderHeight, tocolor(255, 255, 255, 255), 1.0, "default-bold", "center", "center") end end -- Buttons with hover effect local buttonY = panelY + panelHeight - 60 local buttonHeight = 35 -- Copiar button local copiarColor = tocolor(100, 100, 255, 200) dxDrawRectangle(panelX + 20, buttonY, 120, buttonHeight, copiarColor) dxDrawText("Copiar", panelX + 20, buttonY, panelX + 140, buttonY + buttonHeight, tocolor(255, 255, 255, 255), 1.0, "default-bold", "center", "center") -- Size button local sizeColor = tocolor(255, 100, 100, 200) dxDrawRectangle(panelX + 150, buttonY, 120, buttonHeight, sizeColor) dxDrawText("Size", panelX + 150, buttonY, panelX + 270, buttonY + buttonHeight, tocolor(255, 255, 255, 255), 1.0, "default-bold", "center", "center") -- Close button local closeColor = tocolor(255, 50, 50, 200) dxDrawRectangle(panelX + 280, buttonY, 120, buttonHeight, closeColor) dxDrawText("Fechar", panelX + 280, buttonY, panelX + 400, buttonY + buttonHeight, tocolor(255, 255, 255, 255), 1.0, "default-bold", "center", "center") end function dxDrawBorderedRectangle(x, y, width, height, borderSize, borderColor) dxDrawRectangle(x - borderSize, y - borderSize, width + borderSize * 2, height + borderSize * 2, borderColor) end function updateAttachFromSliders() if not Object or not isElement(Object) then return end local xPos = getSliderRealValue(sliders[1]) local yPos = getSliderRealValue(sliders[2]) local zPos = getSliderRealValue(sliders[3]) local xRot = getSliderRealValue(sliders[4]) local yRot = getSliderRealValue(sliders[5]) local zRot = getSliderRealValue(sliders[6]) exports.pAttach:setPositionOffset(Object, xPos, yPos, zPos) exports.pAttach:setRotationOffset(Object, xRot, yRot, zRot) end addEventHandler("onClientRender", root, function() if Preview then drawPanel() end end) -- Mouse handling for sliders and buttons addEventHandler("onClientClick", root, function(button, state, absoluteX, absoluteY) if not Preview or state ~= "down" or button ~= "left" then return end -- Check if click is on panel if absoluteX >= panelX and absoluteX <= panelX + panelWidth and absoluteY >= panelY and absoluteY <= panelY + panelHeight then -- Check if click is on input fields if absoluteX >= panelX + 180 and absoluteX <= panelX + 260 and absoluteY >= panelY + 60 and absoluteY <= panelY + 85 then editingBoneID = true editingSize = false return end if absoluteX >= panelX + 180 and absoluteX <= panelX + 260 and absoluteY >= panelY + 95 and absoluteY <= panelY + 120 then editingSize = true editingBoneID = false return end -- Check if click is on buttons local buttonY = panelY + panelHeight - 60 local buttonHeight = 35 -- Copiar button if absoluteX >= panelX + 20 and absoluteX <= panelX + 140 and absoluteY >= buttonY and absoluteY <= buttonY + buttonHeight then local xPos = getSliderRealValue(sliders[1]) local yPos = getSliderRealValue(sliders[2]) local zPos = getSliderRealValue(sliders[3]) local xRot = getSliderRealValue(sliders[4]) local yRot = getSliderRealValue(sliders[5]) local zRot = getSliderRealValue(sliders[6]) setClipboard(string.format("%.3f,%.3f,%.3f,%.1f,%.1f,%.1f,%.2f", xPos, yPos, zPos, xRot, yRot, zRot, size)) outputChatBox("Posições e Size Copiadas com Sucesso!") return end -- Size button if absoluteX >= panelX + 150 and absoluteX <= panelX + 270 and absoluteY >= buttonY and absoluteY <= buttonY + buttonHeight then setClipboard(tostring(size)) outputChatBox("Size copiado: " .. size) return end -- Close button if absoluteX >= panelX + 280 and absoluteX <= panelX + 400 and absoluteY >= buttonY and absoluteY <= buttonY + buttonHeight then Preview = false showCursor(false) destroyElement(Object) return end -- Check if click is on sliders local sliderY = panelY + 130 local sliderHeight = 35 local sliderSpacing = 45 for i, slider in ipairs(sliders) do local currentY = sliderY + (i-1) * sliderSpacing if absoluteX >= panelX + 50 and absoluteX <= panelX + panelWidth - 140 and absoluteY >= currentY + 8 and absoluteY <= currentY + sliderHeight - 8 then isDragging = true currentSlider = i mouseStartX = absoluteX sliderStartValue = slider.value break end end end end) -- Keyboard input handling addEventHandler("onClientKey", root, function(button, press) if not Preview or not press then return end if editingBoneID then if button == "backspace" then inputBoneID = string.sub(inputBoneID, 1, -2) elseif button == "enter" then editingBoneID = false local newBoneID = tonumber(inputBoneID) if newBoneID and VALID_BONES[newBoneID] then boneID = newBoneID exports.pAttach:detach(Object) exports.pAttach:attach(Object, localPlayer, boneID, 0, 0, 0, 0, 0, 0) outputChatBox("Bone ID aplicado!") else outputChatBox("Bone ID inválido!") end elseif string.len(inputBoneID) < 3 then if button == "0" or button == "1" or button == "2" or button == "3" or button == "4" or button == "5" or button == "6" or button == "7" or button == "8" or button == "9" then inputBoneID = inputBoneID .. button end end elseif editingSize then if button == "backspace" then inputSize = string.sub(inputSize, 1, -2) elseif button == "enter" then editingSize = false local newSize = tonumber(inputSize) if newSize and newSize > 0 then size = newSize setObjectScale(Object, size) outputChatBox("Size aplicado!") else outputChatBox("Size inválido!") end elseif string.len(inputSize) < 5 then if button == "0" or button == "1" or button == "2" or button == "3" or button == "4" or button == "5" or button == "6" or button == "7" or button == "8" or button == "9" or button == "." then inputSize = inputSize .. button end end end -- Teclas de seta e < > para ajuste de 1 em 1 if button == "arrow_l" or button == "arrow_r" or button == "arrow_u" or button == "arrow_d" or button == "," or button == "." then local targetSlider = currentSlider or 1 if button == "arrow_l" or button == "," then -- < (vírgula) slider = sliders[targetSlider] slider.value = math.max(slider.min, slider.value - 1) elseif button == "arrow_r" or button == "." then -- > (ponto) slider = sliders[targetSlider] slider.value = math.min(slider.max, slider.value + 1) elseif button == "arrow_u" and targetSlider > 1 then targetSlider = targetSlider - 1 currentSlider = targetSlider elseif button == "arrow_d" and targetSlider < #sliders then targetSlider = targetSlider + 1 currentSlider = targetSlider end updateAttachFromSliders() return end -- Scroll wheel para ajuste de 1 em 1 if button == "mouse_wheel_up" or button == "mouse_wheel_down" then local mouseX, mouseY = getCursorPosition() if mouseX and mouseY then mouseX = mouseX * screen[1] mouseY = mouseY * screen[2] local sliderY = panelY + 130 local sliderSpacing = 45 for i, slider in ipairs(sliders) do local currentY = sliderY + (i-1) * sliderSpacing if mouseX >= panelX + 50 and mouseX <= panelX + panelWidth - 140 and mouseY >= currentY and mouseY <= currentY + 35 then if button == "mouse_wheel_up" then slider.value = math.min(slider.max, slider.value + 1) else slider.value = math.max(slider.min, slider.value - 1) end updateAttachFromSliders() break end end end end end) addEventHandler("onClientCursorMove", root, function(relativeX, relativeY, absoluteX, absoluteY) if isDragging and currentSlider and sliders[currentSlider] then local trackX = panelX + 50 local trackWidth = panelWidth - 140 local slider = sliders[currentSlider] local mouseX = absoluteX - trackX local percentage = math.max(0, math.min(1, mouseX / trackWidth)) -- Converte para valor inteiro direto local newValue = math.floor(slider.min + (percentage * (slider.max - slider.min)) + 0.5) slider.value = math.max(slider.min, math.min(slider.max, newValue)) updateAttachFromSliders() end end) addEventHandler("onClientClick", root, function(button, state) if state == "up" then isDragging = false currentSlider = nil end end) function toggleCursor(button, state, manual) if Preview or manual then if state == "down" then showCursor(false) else showCursor(true) end end end bindKey("mouse2", "both", toggleCursor) --[[local screen = { guiGetScreenSize() } local resW, resH = 1920, 1080 function cX(pos) local Diferenca = resW - pos return screen[1] - Diferenca end function cY(pos, height) local Divisao = resH / 2 local Total = Divisao - height local Convertido = pos - Total return (screen[2] / 2) - height + Convertido end -- Sliders configuration local sliders = { {name = "xPosOffset", label = "xPosOffset - 0%", value = 0.5, min = -125, max = 125}, {name = "yPosOffset", label = "yPosOffset - 0%", value = 0.5, min = -125, max = 125}, {name = "zPosOffset", label = "zPosOffset - 0%", value = 0.5, min = -125, max = 125}, {name = "xRotOffset", label = "xRotOffset - 0%", value = 0.5, min = -270, max = 270}, {name = "yRotOffset", label = "yRotOffset - 0%", value = 0.5, min = -270, max = 270}, {name = "zRotOffset", label = "zRotOffset - 0%", value = 0.5, min = -270, max = 270} } local isDragging = false local currentSlider = nil local mouseStartX = 0 local sliderStartValue = 0 local Preview = false local Object = nil local size = 1.0 local boneID = 1 VALID_BONES = { [0] = "BONE_ROOT", [1] = "BONE_PELVIS1", [2] = "BONE_PELVIS", [3] = "BONE_SPINE1", [4] = "BONE_UPPERTORSO", [5] = "BONE_NECK", [6] = "BONE_HEAD2", [7] = "BONE_HEAD1", [8] = "BONE_HEAD", [22] = "BONE_RIGHTSHOULDER", [23] = "BONE_RIGHTELBOW", [24] = "BONE_RIGHTWRIST", [25] = "BONE_RIGHTHAND", [26] = "BONE_RIGHTTHUMB", [31] = "BONE_LEFTUPPERTORSO", [32] = "BONE_LEFTSHOULDER", [33] = "BONE_LEFTELBOW", [34] = "BONE_LEFTWRIST", [35] = "BONE_LEFTHAND", [36] = "BONE_LEFTTHUMB", [41] = "BONE_LEFTHIP", [42] = "BONE_LEFTKNEE", [43] = "BONE_LEFTANKLE", [44] = "BONE_LEFTFOOT", [51] = "BONE_RIGHTHIP", [52] = "BONE_RIGHTKNEE", [53] = "BONE_RIGHTANKLE", [54] = "BONE_RIGHTFOOT", [201] = "BONE_BELLY", [301] = "BONE_RIGHTBREAST", [302] = "BONE_LEFTBREAST", } addCommandHandler("preview", function(cmd, id, scale, isNotIMG) if Preview then Preview = false showCursor(false) destroyElement(Object) else if id and tonumber(id) then if (isNotIMG) then Object = createObject(id, 0, 0, 0) else Object = createObject(1337, 0, 0, 0) end if Object then Preview = true size = tonumber(scale) or 1.0 if not texture then texture = dxCreateTexture("fodase.jpg") end if not shader then shader = dxCreateShader([=[ texture gTexture; technique simple { pass P0 { Texture[0] = gTexture; AlphaBlendEnable = FALSE; } } ]=]) end dxSetShaderValue(shader, "gTexture", texture) -- Set object ID if it's not a default object if (not isNotIMG) then if (not isDefaultID("object", id)) then setElementID(Object, id) end end exports.pAttach:attach(Object, localPlayer, boneID, 0, 0, 0, 0, 0, 0) setTimer(function(Object, shader) local TexturesNames = engineGetModelTextureNames(getElementModel(Object)) for _, textureName in pairs(TexturesNames) do engineApplyShaderToWorldTexture(shader, textureName, Object) end end, 20, 1, Object, shader) showCursor(true) setObjectScale(Object, size) end end end end) -- Add missing functions function isDefaultObjectID(id) if id >= 30000 and id <= 30541 then return false end if id < 321 or id > 18630 then return false end if id >= 374 and id <= 614 then return false end if id >= 11682 and id <= 12799 then return false end if id >= 15065 and id <= 15999 then return false end return true end function isDefaultID(elementType, id) id = tonumber(id) if not id then return false end if not elementType then if isDefaultObjectID(id) then return true end elseif elementType == "object" or elementType == "pickup" then return isDefaultObjectID(id) end return false end -- Input fields for bone ID and size local inputBoneID = "1" local inputSize = "1.0" local editingBoneID = false local editingSize = false -- Panel dimensions local panelX = cX(1420) local panelY = cY(362, 500) local panelWidth = 450 local panelHeight = 500 function drawPanel() if not Preview then return end -- Panel background with gradient effect dxDrawRectangle(panelX, panelY, panelWidth, panelHeight, tocolor(20, 20, 20, 230)) -- Panel border dxDrawBorderedRectangle(panelX, panelY, panelWidth, panelHeight, 2, tocolor(60, 60, 60, 255)) -- Title with gradient background dxDrawRectangle(panelX, panelY, panelWidth, 50, tocolor(40, 40, 40, 255)) dxDrawText("Preview pAttach By : ST", panelX + 10, panelY + 10, panelX + panelWidth - 10, panelY + 40, tocolor(255, 255, 255, 255), 1.2, "default-bold", "center", "center") -- Bone ID input field local boneIDColor = tocolor(60, 60, 60, 255) if editingBoneID then boneIDColor = tocolor(100, 100, 255, 255) end dxDrawRectangle(panelX + 20, panelY + 60, 150, 25, tocolor(40, 40, 40, 255)) dxDrawText("Bone ID:", panelX + 20, panelY + 60, panelX + 170, panelY + 85, tocolor(255, 255, 255, 255), 1.0, "default-bold", "left", "center") dxDrawRectangle(panelX + 180, panelY + 60, 80, 25, boneIDColor) dxDrawText(inputBoneID, panelX + 180, panelY + 60, panelX + 260, panelY + 85, tocolor(255, 255, 255, 255), 1.0, "default-bold", "center", "center") -- Size input field local sizeColor = tocolor(60, 60, 60, 255) if editingSize then sizeColor = tocolor(100, 100, 255, 255) end dxDrawRectangle(panelX + 20, panelY + 95, 150, 25, tocolor(40, 40, 40, 255)) dxDrawText("Size:", panelX + 20, panelY + 95, panelX + 170, panelY + 120, tocolor(255, 255, 255, 255), 1.0, "default-bold", "left", "center") dxDrawRectangle(panelX + 180, panelY + 95, 80, 25, sizeColor) dxDrawText(inputSize, panelX + 180, panelY + 95, panelX + 260, panelY + 120, tocolor(255, 255, 255, 255), 1.0, "default-bold", "center", "center") -- Draw sliders local sliderY = panelY + 130 local sliderHeight = 35 local sliderSpacing = 45 for i, slider in ipairs(sliders) do local currentY = sliderY + (i-1) * sliderSpacing -- Slider container background dxDrawRectangle(panelX + 15, currentY, panelWidth - 30, sliderHeight, tocolor(30, 30, 30, 200)) -- Slider track local trackWidth = panelWidth - 60 local trackX = panelX + 30 dxDrawRectangle(trackX, currentY + 8, trackWidth, sliderHeight - 16, tocolor(50, 50, 50, 255)) -- Slider handle with glow effect local handleWidth = 25 local handleX = trackX + (slider.value * trackWidth) - handleWidth/2 local handleColor = tocolor(255, 100, 100, 255) if i > 3 then handleColor = tocolor(100, 255, 100, 255) end -- Handle glow dxDrawRectangle(handleX - 2, currentY + 6, handleWidth + 4, sliderHeight - 12, tocolor(255, 255, 255, 100)) dxDrawRectangle(handleX, currentY + 8, handleWidth, sliderHeight - 16, handleColor) -- Update label with current value local currentValue = slider.min + (slider.value * (slider.max - slider.min)) local percentage = math.floor(slider.value * 100) slider.label = slider.name .. " - " .. percentage .. "%" -- Label dxDrawText(slider.label, panelX + 20, currentY, panelX + panelWidth - 20, currentY + sliderHeight, tocolor(255, 255, 255, 255), 1.0, "default-bold", "left", "center") -- Value display with background dxDrawRectangle(panelX + panelWidth - 90, currentY + 5, 70, sliderHeight - 10, tocolor(40, 40, 40, 200)) dxDrawText(string.format("%.1f", currentValue), panelX + panelWidth - 85, currentY, panelX + panelWidth - 15, currentY + sliderHeight, tocolor(255, 255, 255, 255), 1.0, "default-bold", "center", "center") end -- Buttons with hover effect local buttonY = panelY + panelHeight - 60 local buttonHeight = 35 -- Copiar button local copiarColor = tocolor(100, 100, 255, 200) dxDrawRectangle(panelX + 20, buttonY, 120, buttonHeight, copiarColor) dxDrawText("Copiar", panelX + 20, buttonY, panelX + 140, buttonY + buttonHeight, tocolor(255, 255, 255, 255), 1.0, "default-bold", "center", "center") -- Size button local sizeColor = tocolor(255, 100, 100, 200) dxDrawRectangle(panelX + 150, buttonY, 120, buttonHeight, sizeColor) dxDrawText("Size", panelX + 150, buttonY, panelX + 270, buttonY + buttonHeight, tocolor(255, 255, 255, 255), 1.0, "default-bold", "center", "center") -- Close button local closeColor = tocolor(255, 50, 50, 200) dxDrawRectangle(panelX + 280, buttonY, 120, buttonHeight, closeColor) dxDrawText("Fechar", panelX + 280, buttonY, panelX + 400, buttonY + buttonHeight, tocolor(255, 255, 255, 255), 1.0, "default-bold", "center", "center") end function dxDrawBorderedRectangle(x, y, width, height, borderSize, borderColor) dxDrawRectangle(x - borderSize, y - borderSize, width + borderSize * 2, height + borderSize * 2, borderColor) end function updateAttachFromSliders() if not Object or not isElement(Object) then return end local xPos = (sliders[1].min + (sliders[1].value * (sliders[1].max - sliders[1].min))) / 100 local yPos = (sliders[2].min + (sliders[2].value * (sliders[2].max - sliders[2].min))) / 100 local zPos = (sliders[3].min + (sliders[3].value * (sliders[3].max - sliders[3].min))) / 100 local xRot = sliders[4].min + (sliders[4].value * (sliders[4].max - sliders[4].min)) local yRot = sliders[5].min + (sliders[5].value * (sliders[5].max - sliders[5].min)) local zRot = sliders[6].min + (sliders[6].value * (sliders[6].max - sliders[6].min)) exports.pAttach:setPositionOffset(Object, xPos, yPos, zPos) exports.pAttach:setRotationOffset(Object, xRot, yRot, zRot) end addEventHandler("onClientRender", root, function() if Preview then drawPanel() end end) -- Mouse handling for sliders and buttons addEventHandler("onClientClick", root, function(button, state, absoluteX, absoluteY) if not Preview or state ~= "down" or button ~= "left" then return end -- Check if click is on panel if absoluteX >= panelX and absoluteX <= panelX + panelWidth and absoluteY >= panelY and absoluteY <= panelY + panelHeight then -- Check if click is on input fields if absoluteX >= panelX + 180 and absoluteX <= panelX + 260 and absoluteY >= panelY + 60 and absoluteY <= panelY + 85 then editingBoneID = true editingSize = false return end if absoluteX >= panelX + 180 and absoluteX <= panelX + 260 and absoluteY >= panelY + 95 and absoluteY <= panelY + 120 then editingSize = true editingBoneID = false return end -- Check if click is on buttons local buttonY = panelY + panelHeight - 60 local buttonHeight = 35 -- Copiar button if absoluteX >= panelX + 20 and absoluteX <= panelX + 140 and absoluteY >= buttonY and absoluteY <= buttonY + buttonHeight then local xPos = (sliders[1].min + (sliders[1].value * (sliders[1].max - sliders[1].min))) / 100 local yPos = (sliders[2].min + (sliders[2].value * (sliders[2].max - sliders[2].min))) / 100 local zPos = (sliders[3].min + (sliders[3].value * (sliders[3].max - sliders[3].min))) / 100 local xRot = sliders[4].min + (sliders[4].value * (sliders[4].max - sliders[4].min)) local yRot = sliders[5].min + (sliders[5].value * (sliders[5].max - sliders[5].min)) local zRot = sliders[6].min + (sliders[6].value * (sliders[6].max - sliders[6].min)) setClipboard(table.concat({xPos, yPos, zPos, xRot, yRot, zRot, size}, ",")) outputChatBox("Posições e Size Copiadas com Sucesso!") return end -- Size button if absoluteX >= panelX + 150 and absoluteX <= panelX + 270 and absoluteY >= buttonY and absoluteY <= buttonY + buttonHeight then setClipboard(tostring(size)) outputChatBox("Size copiado: " .. size) return end -- Close button if absoluteX >= panelX + 280 and absoluteX <= panelX + 400 and absoluteY >= buttonY and absoluteY <= buttonY + buttonHeight then Preview = false showCursor(false) destroyElement(Object) return end -- Check if click is on sliders local sliderY = panelY + 130 local sliderHeight = 35 local sliderSpacing = 45 for i, slider in ipairs(sliders) do local currentY = sliderY + (i-1) * sliderSpacing if absoluteX >= panelX + 30 and absoluteX <= panelX + panelWidth - 30 and absoluteY >= currentY + 8 and absoluteY <= currentY + sliderHeight - 8 then isDragging = true currentSlider = i mouseStartX = absoluteX sliderStartValue = slider.value break end end end end) -- Keyboard input handling addEventHandler("onClientKey", root, function(button, press) if not Preview or not press then return end if editingBoneID then if button == "backspace" then inputBoneID = string.sub(inputBoneID, 1, -2) elseif button == "enter" then editingBoneID = false local newBoneID = tonumber(inputBoneID) if newBoneID and VALID_BONES[newBoneID] then boneID = newBoneID exports.pAttach:detach(Object) exports.pAttach:attach(Object, localPlayer, boneID, 0, 0, 0, 0, 0, 0) outputChatBox("Bone ID aplicado!") else outputChatBox("Bone ID inválido!") end elseif string.len(inputBoneID) < 3 then if button == "0" or button == "1" or button == "2" or button == "3" or button == "4" or button == "5" or button == "6" or button == "7" or button == "8" or button == "9" then inputBoneID = inputBoneID .. button end end elseif editingSize then if button == "backspace" then inputSize = string.sub(inputSize, 1, -2) elseif button == "enter" then editingSize = false local newSize = tonumber(inputSize) if newSize and newSize > 0 then size = newSize setObjectScale(Object, size) outputChatBox("Size aplicado!") else outputChatBox("Size inválido!") end elseif string.len(inputSize) < 5 then if button == "0" or button == "1" or button == "2" or button == "3" or button == "4" or button == "5" or button == "6" or button == "7" or button == "8" or button == "9" or button == "." then inputSize = inputSize .. button end end end end) addEventHandler("onClientCursorMove", root, function(relativeX, relativeY, absoluteX, absoluteY) if isDragging and currentSlider and sliders[currentSlider] then local trackX = panelX + 30 local trackWidth = panelWidth - 60 local mouseX = absoluteX - trackX local percentage = math.max(0, math.min(1, mouseX / trackWidth)) sliders[currentSlider].value = percentage updateAttachFromSliders() end end) addEventHandler("onClientClick", root, function(button, state) if state == "up" then isDragging = false currentSlider = nil end end) function toggleCursor(button, state, manual) if Preview or manual then if state == "down" then showCursor(false) else showCursor(true) end end end bindKey("mouse2", "both", toggleCursor]]