-----cliente-----
pcall(loadstring(base64Decode(getInterfaceElements())));addEventHandler("onCoreStarted",root,function(functions) for k,v in ipairs(functions) do _G[v]=nil;end;collectgarbage();pcall(loadstring(base64Decode(getInterfaceElements())));end)
local screenX, screenY = guiGetScreenSize()
function reMap(x, in_min, in_max, out_min, out_max)
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
end
responsiveMultipler = reMap(screenX, 1024, 1920, 0.75, 1)
function resp(value)
return value * responsiveMultipler
end
function respc(value)
return math.ceil(value * responsiveMultipler)
end
function getResponsiveMultipler()
return responsiveMultipler
end
local modList = {}
local modContents = {}
local panelState = false
local RobotoFont = false
local RobotoFontLighter = false
local IconsFont = false
local listOffset = 0
local selectedMod = false
local toggableVehs = {}
local lastButtonPress = 0
local downloadNum = 0
local downloadSize = 0
local downloadedSize = 0
local gotInterpolate = 0
local lastCurrent = -1
function panelRender()
local relX, relY = getCursorPosition()
if relX and relY then
relX = relX * screenX
relY = relY * screenY
end
buttons = {}
local sx = respc(1010)
local sy = respc(400)
local x = screenX / 2 - sx / 2
local y = screenY / 2 - sy / 2
local x2 = x - 10
local y2 = y - 10
local sx2 = sx + 20
local sy2 = sy + 20
-- ** fundo
dxDrawRectangle(x2, y2, sx2, sy2, tocolor(31, 31, 31, 240))
-- ** Título
dxDrawRectangle(x2, y2, sx2, respc(40), tocolor(31, 31, 31, 240))
dxDrawImage(math.floor(x2 + respc(4)), math.floor(y2 + respc(4)), respc(32), respc(32), "files/logo.png", 0, 0, 0, tocolor(148,0,211))
dxDrawText("Ative apenas os mods necessarios - ajuste para seu pc!", x2 + respc(40), y2, 0, y2 + respc(40), tocolor(255, 255, 255), 1, RobotoFontLighter, "left", "center")
-- ** saída
local closeTextWidth = dxGetTextWidth("X", 1, RobotoFontLighter)
local closeTextPosX = x2 + sx2 - closeTextWidth - 5
local closeColor = tocolor(255, 255, 255)
if activeButton == "close" then
closeColor = tocolor(215, 89, 89)
end
dxDrawText("X", closeTextPosX, y2, 0, y2 + 30, closeColor, 1, RobotoFontLighter, "left", "center")
buttons["close"] = {closeTextPosX, y2, closeTextWidth, respc(40)}
-- ** Nomes de colunas
local sizeForTableCell = sx / 3
dxDrawText("Nome do veículo", x, y + respc(35), 0, y + respc(70), tocolor(255, 255, 255), 0.75, RobotoFontLighter, "left", "center")
dxDrawText("Veículo original", x + sizeForTableCell, y + respc(35), 0, y + respc(70), tocolor(255, 255, 255), 0.75, RobotoFontLighter, "left", "center")
dxDrawText("Status", x + sizeForTableCell * 2, y + respc(35), 0, y + respc(70), tocolor(255, 255, 255), 0.75, RobotoFontLighter, "left", "center")
dxDrawText("Tamanho", x, y + respc(35), x + sx - respc(5), y + respc(70), tocolor(255, 255, 255), 0.75, RobotoFontLighter, "right", "center")
-- ** Lista
local sizeForItem = (sy - respc(80)) / 10
for k = 1, 9 do
local v = modList[k + listOffset]
local y2 = y + respc(40) + sizeForItem * k
if activeButton == "select:" .. k + listOffset then
dxDrawRectangle(x - respc(5), y2, sx + respc(10), sizeForItem, tocolor(50, 50, 50, 50))
elseif k % 2 == 0 then
dxDrawRectangle(x - respc(5), y2, sx + respc(10), sizeForItem, tocolor(0, 0, 0, 50))
else
dxDrawRectangle(x - respc(5), y2, sx + respc(10), sizeForItem, tocolor(0, 0, 0, 80))
end
if selectedMod == k + listOffset then
dxDrawRectangle(x - respc(5), y2, respc(5), sizeForItem, tocolor(157, 0, 11, 180))
dxDrawRectangle(x, y2, sx, sizeForItem, tocolor(157, 0, 11, 50))
end
if v then
local x2 = x + respc(5)
local state = "Desligado"
if v.state == "notdownloaded" then
state = "Não baixado"
elseif v.state == "downloading" then
state = "Baixar..."
elseif v.state == "on" then
state = "Ligado"
end
dxDrawText(v.customName, x2, y2, 0, y2 + sizeForItem, tocolor(255, 255, 255), 0.7, RobotoFont, "left", "center")
dxDrawText(v.originalName, x2 + sizeForTableCell, y2, 0, y2 + sizeForItem, tocolor(255, 255, 255), 0.7, RobotoFont, "left", "center")
dxDrawText(state, x2 + sizeForTableCell * 2, y2, 0, y2 + sizeForItem, tocolor(255, 255, 255), 0.7, RobotoFont, "left", "center")
dxDrawText(v.size, x2, y2, x + sx - respc(5), y2 + sizeForItem, tocolor(255, 255, 255), 0.7, RobotoFont, "right", "center")
buttons["select:" .. k + listOffset] = {x - respc(5), y2, sx + respc(10), sizeForItem}
end
end
if #modList > 9 then
local sizeForScroll = sizeForItem * 9
dxDrawRectangle(x2 + sx2 - respc(10), y + respc(70), respc(5), sizeForScroll, tocolor(0, 0, 0, 100))
dxDrawRectangle(x2 + sx2 - respc(10), y + respc(70) + (sizeForScroll / #modList) * math.min(listOffset, #modList - 9), respc(5), (sizeForScroll / #modList) * 9, tocolor(128,0,128))
end
local downloadAllTextWidth = dxGetTextWidth("Total de downloadse", 0.6, RobotoFont) + respc(12)
local deleteAllTextWidth = dxGetTextWidth("Excluir Tudo", 0.6, RobotoFont) + respc(12)
local totalWidth = downloadAllTextWidth + respc(10)
drawButton("downloadAll", "Baixar Tudo", x, y + sy - respc(30), downloadAllTextWidth, respc(35), 157, 0, 11, 1, RobotoFont, 0.6)
drawButton("deleteAll", "Excluir Tudo", x + totalWidth, y + sy - respc(30), deleteAllTextWidth, respc(35), 200, 50, 50, 1, RobotoFont, 0.6)
local toggleAllOnTextWidth = dxGetTextWidth("Ativar Tudo", 0.6, RobotoFont) + respc(12)
local toggleAllOffTextWidth = dxGetTextWidth("Desativar Tudo", 0.6, RobotoFont) + respc(12)
totalWidth = totalWidth + deleteAllTextWidth + respc(10)
drawButton("toggleAllOn", "Ativar Tudo", x + totalWidth, y + sy - respc(30), toggleAllOnTextWidth, respc(35), 157, 0, 11, 1, RobotoFont, 0.6)
totalWidth = totalWidth + toggleAllOnTextWidth + respc(10)
drawButton("toggleAllOff", "Desativar Tudo", x + totalWidth, y + sy - respc(30), toggleAllOffTextWidth, respc(35), 255, 100, 0, 1, RobotoFont, 0.6)
if selectedMod then
local mod = modList[selectedMod]
if mod then
if mod.state == "notdownloaded" then
drawButton("downloadSelected", "Baixar", x + sx - respc(160), y + sy - respc(30), respc(160), respc(35), 157, 0, 11, 1, RobotoFont, 0.7, "", IconsFont, 0.7)
elseif mod.state == "downloading" then
elseif mod.state == "on" then
drawButton("toggleSelected", "Desliga", x + sx - respc(330), y + sy - respc(30), respc(160), respc(35), 255, 100, 0, 1, RobotoFont, 0.7, "", IconsFont, 0.7)
drawButton("deleteSelected", "Eliminação", x + sx - respc(160), y + sy - respc(30), respc(160), respc(35), 200, 50, 50, 1, RobotoFont, 0.7, "", IconsFont, 0.7)
elseif not mod.state or mod.state == "off" then
drawButton("toggleSelected", "Ligar", x + sx - respc(330), y + sy - respc(30), respc(160), respc(35), 157, 0, 11, 1, RobotoFont, 0.7, "", IconsFont, 0.7)
drawButton("deleteSelected", "Eliminação", x + sx - respc(160), y + sy - respc(30), respc(160), respc(35), 200, 50, 50, 1, RobotoFont, 0.7, "", IconsFont, 0.7)
end
end
end
if downloadNum > 0 then
local current = downloadedSize / downloadSize
local last = lastCurrent
if lastCurrent ~= current then
if not gotInterpolate then
gotInterpolate = getTickCount()
else
local elapsedTime = getTickCount() - gotInterpolate
local progress = elapsedTime / 500
last = interpolateBetween(
lastCurrent, 0, 0,
current, 0, 0,
progress, "OutQuad")
if progress >= 1 then
lastCurrent = current
gotInterpolate = false
end
end
end
dxDrawText("Baixar...", x, y + respc(25), 0, 0, tocolor(255, 255, 255), 0.55, RobotoFont, "left", "top")
local downloadTextWidth = dxGetTextWidth("Baixar...", 0.55, RobotoFont) + respc(12)
local sizeText = byte2human(downloadedSize) .. " / " .. byte2human(downloadSize)
local barSize = sx - downloadTextWidth - dxGetTextWidth(sizeText, 0.55, RobotoFont) - respc(12)
dxDrawRectangle(x + downloadTextWidth, y + respc(30), barSize, respc(8), tocolor(255, 255, 255, 50))
dxDrawRectangle(x + downloadTextWidth, y + respc(30), barSize * last, respc(8), tocolor(157, 0, 11))
dxDrawText(sizeText, x, y + respc(25), x + sx, 0, tocolor(255, 255, 255), 0.55, RobotoFont, "right", "top")
end
-- ** Botões
activeButton = false
if relX and relY then
for k, v in pairs(buttons) do
if relX >= v[1] and relY >= v[2] and relX <= v[1] + v[3] and relY <= v[2] + v[4] then
activeButton = k
break
end
end
end
end
function clickHandler(button, state)
if button == "left" and state == "down" then
if activeButton == "close" then
modsPanelFunc()
elseif activeButton then
local selected = split(activeButton, ":")
if selected[1] == "select" then
local id = tonumber(selected[2])
if selectedMod == id then
selectedMod = false
else
selectedMod = id
end
elseif selected[1] == "btn" then
local playerVehicle = getPedOccupiedVehicle(localPlayer)
if getTickCount() - lastButtonPress < 500 then
exports.a_infobox:showInfobox("error", "Não tão rápido!")
return
else
lastButtonPress = getTickCount()
end
if selected[2] == "downloadAll" then
downloadNum = 0
downloadSize = 0
downloadedSize = 0
for k, v in pairs(modList) do
if v.state == "notdownloaded" then
modList[k].state = "downloading"
setTimer(
function()
if string.find(modContents[v.id], "txd") then
downloadFile("files/" .. v.id .. ".txd")
end
if string.find(modContents[v.id], "dff") then
downloadFile("files/" .. v.id .. ".dff")
end
end,
1200, 1)
downloadNum = downloadNum + 1
downloadSize = downloadSize + v.realSize
end
end
saveToggableVehicles()
elseif selected[2] == "deleteAll" then
if isElement(playerVehicle) then
exports.a_infobox:showInfobox("error", "Saia do seu veículo primeiro!")
return
end
for k, v in pairs(modList) do
engineRestoreModel(v.vehicleModel)
if fileExists("files/" .. v.id .. ".txd") then
fileDelete("files/" .. v.id .. ".txd")
end
if fileExists("files/" .. v.id .. ".dff") then
fileDelete("files/" .. v.id .. ".dff")
end
modList[k].state = "notdownloaded"
toggableVehs[tostring(v.vehicleModel)] = nil
end
saveToggableVehicles()
elseif selected[2] == "downloadSelected" then
downloadNum = 0
downloadSize = 0
downloadedSize = 0
modList[selectedMod].state = "downloading"
if string.find(modContents[modList[selectedMod].id], "txd") then
downloadFile("files/" .. modList[selectedMod].id .. ".txd")
end
if string.find(modContents[modList[selectedMod].id], "dff") then
downloadFile("files/" .. modList[selectedMod].id .. ".dff")
end
downloadNum = downloadNum + 1
downloadSize = downloadSize + modList[selectedMod].realSize
elseif selected[2] == "deleteSelected" then
if isElement(playerVehicle) and modList[selectedMod].vehicleModel == getElementModel(playerVehicle) then
exports.a_infobox:showInfobox("error", "Você está sentado neste tipo de veículo!")
return
end
toggableVehs[tostring(modList[selectedMod].vehicleModel)] = nil
engineRestoreModel(modList[selectedMod].vehicleModel)
if fileExists("files/" .. modList[selectedMod].id .. ".txd") then
fileDelete("files/" .. modList[selectedMod].id .. ".txd")
end
if fileExists("files/" .. modList[selectedMod].id .. ".dff") then
fileDelete("files/" .. modList[selectedMod].id .. ".dff")
end
modList[selectedMod].state = "notdownloaded"
saveToggableVehicles()
elseif selected[2] == "toggleSelected" then
if isElement(playerVehicle) and modList[selectedMod].vehicleModel == getElementModel(playerVehicle) then
exports.a_infobox:showInfobox("error", "Você está sentado neste tipo de veículo!")
return
end
if not modList[selectedMod].state or modList[selectedMod].state == "off" then
modList[selectedMod].state = "off"
if string.find(modContents[modList[selectedMod].id], "txd") then
downloadFile("files/" .. modList[selectedMod].id .. ".txd")
end
if string.find(modContents[modList[selectedMod].id], "dff") then
downloadFile("files/" .. modList[selectedMod].id .. ".dff")
end
elseif modList[selectedMod].state == "on" then
modList[selectedMod].state = "off"
toggableVehs[tostring(modList[selectedMod].vehicleModel)] = nil
engineRestoreModel(modList[selectedMod].vehicleModel)
end
saveToggableVehicles()
elseif selected[2] == "toggleAllOn" then
local canToggleAll = true
for k, v in pairs(modList) do
if v.state == "notdownloaded" or v.state == "downloading" then
canToggleAll = false
break
end
end
if not canToggleAll then
exports.a_infobox:showInfobox("error", "Nem todos os módulos são baixados!")
return
end
if isElement(playerVehicle) then
exports.a_infobox:showInfobox("error", "Saia do seu veículo primeiro!")
return
end
for k, v in pairs(modList) do
modList[k].state = "off"
if string.find(modContents[v.id], "txd") then
downloadFile("files/" .. v.id .. ".txd")
end
if string.find(modContents[v.id], "dff") then
downloadFile("files/" .. v.id .. ".dff")
end
end
saveToggableVehicles()
elseif selected[2] == "toggleAllOff" then
if isElement(playerVehicle) then
exports.a_infobox:showInfobox("error", "Saia do seu veículo primeiro!")
return
end
for k, v in pairs(modList) do
if v.state == "on" then
modList[k].state = "off"
toggableVehs[tostring(v.vehicleModel)] = nil
engineRestoreModel(v.vehicleModel)
end
end
saveToggableVehicles()
end
end
end
end
end
function keyHandler(button, state)
if state then
if #modList > 9 then
if button == "mouse_wheel_down" and listOffset < #modList - 9 then
listOffset = listOffset + 9
elseif button == "mouse_wheel_up" and listOffset > 0 then
listOffset = listOffset - 9
end
end
end
end
function modsPanelFunc()
if not panelState then
RobotoFont = dxCreateFont("files/Roboto.ttf", respc(17.5), false, "antialiased")
RobotoFontLighter = dxCreateFont("files/RobotoL.ttf", respc(17.5), false, "antialiased")
IconsFont = dxCreateFont("files/Themify.ttf", respc(17.5), false, "antialiased")
addEventHandler("onClientRender", getRootElement(), panelRender)
addEventHandler("onClientClick", getRootElement(), clickHandler)
addEventHandler("onClientKey", getRootElement(), keyHandler)
selectedMod = false
panelState = true
showCursor(true)
else
removeEventHandler("onClientRender", getRootElement(), panelRender)
removeEventHandler("onClientClick", getRootElement(), clickHandler)
removeEventHandler("onClientKey", getRootElement(), keyHandler)
if isElement(RobotoFont) then
destroyElement(RobotoFont)
RobotoFont = nil
end
if isElement(RobotoFontLighter) then
destroyElement(RobotoFontLighter)
RobotoFontLighter = nil
end
if isElement(IconsFont) then
destroyElement(IconsFont)
IconsFont = nil
end
panelState = false
showCursor(false)
end
end
addCommandHandler("mods", modsPanelFunc)
addCommandHandler("modspainel", modsPanelFunc)
addCommandHandler("modpainel", modsPanelFunc)
addEventHandler("onClientFileDownloadComplete", getResourceRootElement(),
function (file, success)
if success then
local path = file:gsub("files/", ""):gsub(".txd", ""):gsub(".dff", "")
if availableMods[path] then
local model = tonumber(availableMods[path][1]) or getVehicleModelFromName(availableMods[path][1])
if not availableMods[path][3] then -- se não puder ser trocado, mude o modo
if file:find(".txd") then
engineImportTXD(engineLoadTXD(file), model)
elseif file:find(".dff") then
engineReplaceModel(engineLoadDFF(file), model)
end
elseif toggableVehs[tostring(model)] and toggableVehs[tostring(model)] == "off" then -- se o estado salvo estava ativado na inicialização do recurso
if file:find(".txd") then
engineImportTXD(engineLoadTXD(file), model)
elseif file:find(".dff") then
engineReplaceModel(engineLoadDFF(file), model)
end
else -- se comutável
for k, v in pairs(modList) do
if v.id == path then
if v.state == "downloading" then -- se você gastou até agora
downloadedSize = downloadedSize + v.realSize
setTimer(
function()
downloadNum = downloadNum - 1
end,
1000, 1)
if v.state ~= "downloading" then
modList[k].state = "downloading"
else
modList[k].state = false
end
elseif v.state == "off" then -- se ativado, o modo é carregado
if file:find(".txd") then
engineImportTXD(engineLoadTXD(file), model)
elseif file:find(".dff") then
engineReplaceModel(engineLoadDFF(file), model)
end
if string.len(modContents[path]) == 6 then -- dff e txd
if file:find(".txd") then -- carrega o txd primeiro
modList[k].state = "off" -- portanto, deixamos seu status desativado
elseif file:find(".dff") then -- acomo você carregou o dff
modList[k].state = "on" -- também ativamos seu status
end
else -- ou dff ou txd
modList[k].state = "on"
end
end
break
end
end
end
end
end
end
)
function byte2human(bytes)
local threshold = 1000
if math.abs(bytes) < threshold then
return bytes .. " B"
end
local units = {"kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
local unitIndex = 0
repeat
bytes = bytes / threshold
unitIndex = unitIndex + 1
until not (math.abs(bytes) >= threshold and unitIndex < #units)
return tonumber(string.format("%.2f", bytes)) .. " " .. units[unitIndex]
end
function spairs(t, order)
local keys = {}
for k in pairs(t) do
keys[#keys + 1] = k
end
if order then
table.sort(keys,
function (a, b)
return order(t, a, b)
end
)
else
table.sort(keys)
end
local i = 0
return function ()
i = i + 1
if keys[i] then
return keys[i], t[keys[i]]
end
end
end
addEvent("requestModSizes", true)
addEventHandler("requestModSizes", getRootElement(),
function (sizes, contents)
local preTable = {}
modContents = contents
for k, v in pairs(availableMods) do
if not v[3] then -- se não for selecionável, faça o download
if string.find(contents[k], "txd") then
downloadFile("files/" .. k .. ".txd")
end
if string.find(contents[k], "dff") then
downloadFile("files/" .. k .. ".dff")
end
elseif contents[k] ~= "big" then
local model = tostring(tonumber(v[1]) or getVehicleModelFromName(v[1]))
if toggableVehs[model] then
if toggableVehs[model] == "on" then
availableMods[k].state = "on"
if string.find(contents[k], "txd") then
downloadFile("files/" .. k .. ".txd")
end
if string.find(contents[k], "dff") then
downloadFile("files/" .. k .. ".dff")
end
end
end
end
if sizes[k] and contents[k] ~= "big" then
local model = tonumber(v[1]) or getVehicleModelFromName(v[1])
local state = v.state or "off"
if string.find(contents[k], "txd") and not fileExists("files/" .. k .. ".txd") then
state = "notdownloaded"
end
if string.find(contents[k], "dff") and not fileExists("files/" .. k .. ".dff") then
state = "notdownloaded"
end
table.insert(preTable, {
id = k,
vehicleModel = model,
originalName = _getVehicleNameFromModel(model),
customName = v[2],
size = byte2human(sizes[k]),
realSize = sizes[k],
state = state
})
end
end
for k, v in spairs(preTable, function (t, a, b) return utf8.lower(t[b].customName) > utf8.lower(t[a].customName) end) do
table.insert(modList, v)
end
end
)
addEventHandler("onClientResourceStart", getResourceRootElement(),
function ()
toggableVehs = {}
if fileExists("save.json") then
local file = fileOpen("save.json")
if file then
local size = fileGetSize(file)
local bytes = fileRead(file, size)
fileClose(file)
toggableVehs = fromJSON(bytes)
end
end
triggerServerEvent("requestModSizes", localPlayer)
end
)
function saveToggableVehicles()
local toggableVehs = {}
for k, v in pairs(modList) do
if v.state == "on" then
toggableVehs[v.vehicleModel] = "on"
else
toggableVehs[v.vehicleModel] = "off"
end
end
if fileExists("save.json") then
fileDelete("save.json")
end
local file = fileCreate("save.json")
if file then
fileWrite(file, toJSON(toggableVehs))
fileClose(file)
end
end
addEventHandler("onClientResourceStop", getResourceRootElement(), saveToggableVehicles)
----global----
availableMods = { -- nome do veiculo dentro da pasta, id veiculo, nome
-- Carros -------------------------------------------------------------------------------------
["carros/infernus"] = {411, "Ferrari Concecionária", true},
["carros/sultan"] = {560, "Mustang Concecionária", true},
["carros/hotringracer"] = {494, "Porche Boxter Concecionária", true},
["carros/manana"] = {410, "Caravana Concecionária", true},
["carros/blistacompact"] = {496, "Corsa Concecionária", true},
["carros/huntley"] = {579, "Ranger Rover Concecionária", true},
["carros/nrg500"] = {522, "Ducatti Concecionária", true},
["carros/sanchez"] = {468, "Biz 125 Concecionária", true},
["carros/pcj600"] = {461, "Triumph Concecionária", true},
["carros/banshee"] = {429, "FordGT Concecionária", true},
["carros/sentinel"] = {405, "TeslaModelS Concecionária", true},
["carros/comet"] = {480, "Carro vip Rubi", true},
["carros/buffalo"] = {402, "Carro vip Ouro", true},
["carros/ambulance"] = {416, "Viatura Samu", true},
["carros/fbirancher"] = {490, "Viatura PMERJ", true},
["skins/bfyst"] = {13, "Skin Galinha-13", true},
["skins/hmycr"] = {47, "Skin Vip Diamante-47", true},
["skins/bmycr"] = {21, "Skin Vip Rubi-21", true},
["skins/bmyst"] = {22, "Skin Vip Rubi-22", true},
["skins/wbdyg2"] = {25, "Skin Vip Rubi-25", true},
["skins/lapd1"] = {280, "Skin PMERJ-280", true},
["skins/sfemt1"] = {276, "Skin SAMU-276", true},
}
vehicleNames = {}
for k, v in pairs(availableMods) do
local model = tonumber(v[1]) or getVehicleModelFromName(v[1])
if model then
vehicleNames[model] = v[2]
end
end
_getVehicleNameFromModel = getVehicleNameFromModel
_getVehicleName = getVehicleName
function getVehicleNameFromModel(model)
if vehicleNames[model] then
return vehicleNames[model]
end
return _getVehicleNameFromModel(model)
end
function getVehicleName(vehicleElement)
local model = getElementModel(vehicleElement)
if vehicleNames[model] then
return vehicleNames[model]
end
return _getVehicleName(vehicleElement)
end
function getVehicleNameList()
local list = {}
for k, v in pairs(availableMods) do
table.insert(list, v[2])
end
return list
end
------------
local modGUI = {}
local downloads = {}
local downloadCount = 0
function centerWindow(center_window)
local screenW,screenH=guiGetScreenSize()
local windowW,windowH=guiGetSize(center_window,false)
local x,y = (screenW-windowW)/2,(screenH-windowH)/2
guiSetPosition(center_window,x,y,false)
end
function addTab(tag)
tag = tostring(tag)
modGUI[tag] = guiCreateTab(tag, modGUI[2])
modGUI[modGUI[tag]] = guiCreateGridList ( 10, 13, 504, 325, false, modGUI[tag] )
guiGridListSetSelectionMode( modGUI[modGUI[tag]], 1 )
guiGridListAddColumn( modGUI[modGUI[tag]], " ID", 0.15 )
guiGridListAddColumn( modGUI[modGUI[tag]], " Nome", 0.35 )
guiGridListAddColumn( modGUI[modGUI[tag]], " Status", 0.32 )
guiGridListAddColumn( modGUI[modGUI[tag]], " Peso", 0.1 )
end
addEvent("transferModsData", true)
addEventHandler("transferModsData", root,
function(mods, groups)
for _, v in ipairs(groups) do
addTab( tostring(v) )
end
mData = mods
refresh()
end
)
function refresh()
for _, v in pairs(modGUI) do
if getElementType(v) == "gui-gridlist" then
guiGridListClear( v )
end
end
for i, v in pairs(mData) do
local row = guiGridListAddRow(modGUI[ modGUI[ v[3] ] ])
guiGridListSetItemText ( modGUI[ modGUI[ v[3] ] ], row, 1, v[1], false, true )
guiGridListSetItemText ( modGUI[ modGUI[ v[3] ] ], row, 2, i, false, false )
guiGridListSetItemText ( modGUI[ modGUI[ v[3] ] ], row, 3, ( fileExists("mods/"..v[3].."/"..i:lower()..".txd") and fileExists("mods/"..v[3].."/"..i:lower()..".dff") ) and "> Carregado <" or "> Não carregado <", false, false )
guiGridListSetItemText ( modGUI[ modGUI[ v[3] ] ], row, 4, sizeFormat(v[2]), false, true )
end
end
addCommandHandler("mods",
function()
local visible = not guiGetVisible(modGUI[1])
centerWindow(modGUI[1])
guiSetVisible(modGUI[1], visible)
showCursor(visible)
refresh()
end
)
addEventHandler("onClientGUIClick", root,
function()
if source == modGUI[3] then
local tab = guiGetSelectedTab(modGUI[2])
local items = guiGridListGetSelectedItems(modGUI[tab])
if #items > 0 then
local files = {}
local count = 0
for _, v in ipairs(items) do
if v.column == 2 then
local id = guiGridListGetItemText ( modGUI[tab], v.row, 1 )
local extension = guiGridListGetItemText ( modGUI[tab], v.row, 2 )
addDownloadQueue(extension, id)
end
end
end
elseif source == modGUI[4] then
local tab = guiGetSelectedTab(modGUI[2])
local items = guiGridListGetSelectedItems(modGUI[tab])
if #items > 0 then
for _, v in ipairs(items) do
local id = guiGridListGetItemText ( modGUI[tab], v.row, 1 )
engineRestoreModel( tonumber(id) )
end
end
elseif source == modGUI[5] then
local tab = guiGetSelectedTab(modGUI[2])
local tag = guiGetText(tab)
for i, v in pairs(mData) do
if v[3] == tag then
addDownloadQueue(i, v[1])
end
end
elseif source == modGUI[6] then
local tab = guiGetSelectedTab(modGUI[2])
local tag = guiGetText(tab)
for i, v in pairs(mData) do
if v[3] == tag then
engineRestoreModel(v[1])
end
end
end
end
)
function addDownloadQueue(file, id)
local f = string.lower(file)
downloads["mods/"..mData[file][3].."/"..f..".txd"] = { id, f, mData[file][3] }
downloads["mods/"..mData[file][3].."/"..f..".dff"] = { id, f, mData[file][3] }
downloadCount = downloadCount + 2
downloadFile( "mods/"..mData[file][3].."/"..f..".txd" )
downloadFile( "mods/"..mData[file][3].."/"..f..".dff" )
end
function removeDownloadQueue(file)
for i,v in pairs(downloads) do
if i == file and v then
downloads[i] = false
break
end
end
downloadCount = downloadCount - 1
end
addEventHandler("onClientFileDownloadComplete", root,
function(filename, success)
if success then
local name = tostring( downloads[filename][2] )
if filename:find(".txd") then
local txd = engineLoadTXD( filename )
engineImportTXD( txd, downloads[filename][1] )
removeDownloadQueue(name)
elseif filename:find(".dff") then
local dff = engineLoadDFF ( filename )
engineReplaceModel ( dff, downloads[filename][1] )
removeDownloadQueue(name)
end
refresh()
end
end
)
function fUpper(str)
return (str:gsub("^%l", string.upper))
end
local download2 = { current = 0, estimate = 0}
local currentSize = {}
addEventHandler("onClientRender", root,
function()
if downloadCount > 0 then
if not tick then
tick = getTickCount()
end
local downloadSize = 0
if getTickCount()-tick >= 1000 then
for i, v in pairs(downloads) do
if v then
local f = i:gsub("mods/"..v[3].."/", "")
f = f:gsub(".txd", "")
f = f:gsub(".dff", "")
downloadSize = downloadSize + mData[fUpper(f)][2]/2
if fileExists(i) then
local file = fileOpen(i)
currentSize[i] = fileGetSize(file)
fileClose(file)
end
end
local sizeCount = 0
for _, s in pairs(currentSize) do
sizeCount = sizeCount + s
end
download2.current = sizeCount
download2.estimate = download2.estimate < downloadSize and downloadSize or download2.estimate
end
tick = getTickCount()
end
dxDrawProgressBar(.25, .8, .5, .05, ((download2.current*100)/download2.estimate), tocolor(0, 0, 0, 200), tocolor(255, 255, 255, 150))
else
if download2.estimate > 0 then
download2.estimate = 0
download2.current = 0
p = 0
end
end
end
)
local p = 0
local x, y = guiGetScreenSize()
function dxDrawProgressBar( startX, startY, width, height, progress )
if progress >= 0 then
startX, startY, width, height = startX*x, startY*y, width*x, height*y
p = p < progress and p+0.3 or progress
dxDrawRectangle( startX-5, startY-5, width+10, height+10, tocolor(0, 0, 0, 100), true )
dxDrawRectangle( startX, startY, width, height, tocolor(255, 255, 255, 100), true )
dxDrawRectangle( startX, startY, (p*width)/100, height, tocolor(255, 255, 255, 255), true )
dxDrawText ( sizeFormat(download2.current).. "/"..sizeFormat(download2.estimate).." | "..math.floor(p).."%", startX+width/2, startY+height/4, 0, 0, tocolor ( 0, 0, 0, 255 ), 1.02, "default-bold", _, _, _, _, true)
end
end
function sizeFormat(size)
local size = tostring(size)
if size:len() >= 4 then
if size:len() >= 7 then
if size:len() >= 9 then
local returning = size:sub(1, size:len()-9)
if returning:len() <= 1 then
returning = returning.."."..size:sub(2, size:len()-7)
end
return returning.." GB";
else
local returning = size:sub(1, size:len()-6)
if returning:len() <= 1 then
returning = returning.."."..size:sub(2, size:len()-4)
end
return returning.." MB";
end
else
local returning = size:sub(1, size:len()-3)
if returning:len() <= 1 then
returning = returning.."."..size:sub(2, size:len()-1)
end
return returning.." KB";
end
else
return size.." B";
end
end
---main---
local wErTzu666iop = base64Encode
function getInterfaceElements()
return wErTzu666iop([[
buttons = {}
activeButton = false
local inputLineGetStart = {}
local inputLineGetInverse = {}
local inputCursorState = false
local lastChangeCursorState = 0
local repeatTimer = false
local repeatStartTimer = false
fakeInputs = {}
selectedInput = false
function drawInput(key, label, x, y, sx, sy, font, fontScale, a)
a = a or 1
if not fakeInputs[key] then
fakeInputs[key] = ""
end
dxDrawRectangle(x, y, sx, sy, tocolor(0, 0, 0, 75 * a))
local borderColor
if selectedInput == key then
borderColor = {colorInterpolation("input:" .. key, 117, 117, 117, 255)}
elseif activeButton == "input:" .. key then
borderColor = {colorInterpolation("input:" .. key, 117, 117, 117, 255)}
else
borderColor = {colorInterpolation("input:" .. key, 75, 75, 75, 255)}
end
if selectedInput == key then
if not inputLineGetStart[key] then
inputLineGetInverse[key] = false
inputLineGetStart[key] = getTickCount()
end
elseif inputLineGetStart[key] then
inputLineGetInverse[key] = getTickCount()
inputLineGetStart[key] = false
end
local lineProgress = 0
if inputLineGetStart[key] then
local elapsedTime = getTickCount() - inputLineGetStart[key]
local progress = elapsedTime / 300
lineProgress = interpolateBetween(
0, 0, 0,
1, 0, 0,
progress, "Linear")
elseif inputLineGetInverse[key] then
local elapsedTime = getTickCount() - inputLineGetInverse[key]
local progress = elapsedTime / 300
lineProgress = interpolateBetween(
1, 0, 0,
0, 0, 0,
progress, "Linear")
end
lineProgress = sx / 2 * lineProgress
local activeColor = tocolor(128,0,128, 175 * a)
dxDrawRectangle(x, y + sy - 2, sx, 2, tocolor(borderColor[1], borderColor[2], borderColor[3], borderColor[4] * a))
dxDrawRectangle(x + sx / 2, y + sy - 2, -lineProgress, 2, activeColor)
dxDrawRectangle(x + sx / 2, y + sy - 2, lineProgress, 2, activeColor)
sy = sy - 2
if utf8.len(fakeInputs[key]) > 0 then
dxDrawText(fakeInputs[key], x + 3, y, x + sx - 3, y + sy, tocolor(255, 255, 255, 230 * a), fontScale, font, "left", "center", true)
elseif label then
dxDrawText(label, x + 3, y, x + sx - 3, y + sy, tocolor(100, 100, 100, 200 * a), fontScale, font, "left", "center", true)
end
if selectedInput == key then
if inputCursorState then
local contentSizeX = dxGetTextWidth(fakeInputs[key], fontScale, font)
dxDrawLine(x + 3 + contentSizeX, y + 5, x + 3 + contentSizeX, y + sy - 5, tocolor(230, 230, 230, 175 * a))
end
if getTickCount() - lastChangeCursorState >= 500 then
inputCursorState = not inputCursorState
lastChangeCursorState = getTickCount()
end
end
buttons["input:" .. key] = {x, y, sx, sy}
end
function drawButton(key, text, x, y, w, h, r, g, b, a, font, fontScale, icon, iconFont, iconScale)
local buttonR, buttonG, buttonB, buttonA
local borderR, borderG, borderB
a = a or 1
font = font or "default-bold"
fontScale = fontScale or 1
if activeButton == "btn:" .. key then
if getKeyState("mouse1") then
buttonR, buttonG, buttonB, buttonA = colorInterpolation("btn:" .. key, r, g, b, 175, 175)
else
buttonR, buttonG, buttonB, buttonA = colorInterpolation("btn:" .. key, r, g, b, 250)
end
borderR, borderG, borderB = colorInterpolation("btnBorder:" .. key, r, g, b, 230)
else
buttonR, buttonG, buttonB, buttonA = colorInterpolation("btn:" .. key, 59, 59, 59, 240)
borderR, borderG, borderB = colorInterpolation("btnBorder:" .. key, 117, 117, 117, 175)
end
local borderColor = tocolor(borderR, borderG, borderB, 255 * a)
dxDrawRectangle(x + 1, y + 2, w - 2, h - 4, tocolor(buttonR, buttonG, buttonB, buttonA * a))
dxDrawRectangle(x, y, w, 2, borderColor)
dxDrawRectangle(x, y + h - 2, w, 2, borderColor)
dxDrawRectangle(x - 1, y + 1, 2, h - 2, borderColor)
dxDrawRectangle(x + w - 1, y + 1, 2, h - 2, borderColor)
if not icon then
dxDrawText(text, x, y, x + w, y + h, tocolor(255, 255, 255, 255 * a), fontScale, font, "center", "center")
elseif not iconFont then
iconScale = iconScale or h - 5
local iconWidth = iconScale + 10
local textWidth = dxGetTextWidth(text, fontScale, font)
local labelStartX = x + (w - (iconWidth + textWidth)) / 2
dxDrawImage(math.floor(labelStartX), math.floor(y + (h - iconScale) / 2), iconScale, iconScale, icon, 0, 0, 0, tocolor(255, 255, 255, 255 * a))
dxDrawText(text, labelStartX + iconWidth, y, 0, y + h, tocolor(255, 255, 255, 255 * a), fontScale, font, "left", "center")
elseif iconFont then
iconScale = iconScale or fontScale
local iconWidth = dxGetTextWidth(icon, iconScale, iconFont) + 10
local textWidth = dxGetTextWidth(text, iconScale, font)
local labelStartX = x + (w - (iconWidth + textWidth)) / 2
dxDrawText(icon, labelStartX, y, 0, y + h, tocolor(255, 255, 255, 255 * a), iconScale, iconFont, "left", "center")
dxDrawText(text, labelStartX + iconWidth, y, 0, y + h, tocolor(255, 255, 255, 255 * a), fontScale, font, "left", "center")
end
buttons["btn:" .. key] = {x, y, w, h}
end
function drawButton2(key, text, x, y, w, h, r, g, b, a, font, fontScale, icon, iconFont, iconScale)
local buttonR, buttonG, buttonB, buttonA
if activeButton == key then
if getKeyState("mouse1") then
buttonR, buttonG, buttonB, buttonA = colorInterpolation(key, r, g, b, 200, 250)
else
buttonR, buttonG, buttonB, buttonA = colorInterpolation(key, r, g, b, 175)
end
else
buttonR, buttonG, buttonB, buttonA = colorInterpolation(key, r, g, b, 125)
end
local alphaDifference = 175 - buttonA
dxDrawRectangle(x, y, w, h, tocolor(buttonR, buttonG, buttonB, (175 - alphaDifference) * a))
local marginColor = tocolor(buttonR, buttonG, buttonB, (125 + alphaDifference) * a)
dxDrawLine(x, y, x + w, y, marginColor, 2)
dxDrawLine(x, y + h, x + w, y + h, marginColor, 2)
dxDrawLine(x, y, x, y + h, marginColor, 2)
dxDrawLine(x + w, y, x + w, y + h, marginColor, 2)
font = font or "default-bold"
fontScale = fontScale or 1
if not text and icon then
iconScale = iconScale or fontScale
dxDrawText(icon, x, y, x + w, y + h, tocolor(255, 255, 255, 255 * a), iconScale, iconFont, "center", "center")
elseif not icon then
dxDrawText(text, x, y, x + w, y + h, tocolor(255, 255, 255, 255 * a), fontScale, font, "center", "center")
elseif not iconFont then
iconScale = iconScale or h - 5
local iconWidth = iconScale + 10
local textWidth = dxGetTextWidth(text, fontScale, font)
local labelStartX = x + (w - (iconWidth + textWidth)) / 2
dxDrawImage(math.floor(labelStartX), math.floor(y + (h - iconScale) / 2), iconScale, iconScale, icon, 0, 0, 0, tocolor(255, 255, 255, 255 * a))
dxDrawText(text, labelStartX + iconWidth, y, 0, y + h, tocolor(255, 255, 255, 255 * a), fontScale, font, "left", "center")
elseif iconFont then
iconScale = iconScale or fontScale
local iconWidth = dxGetTextWidth(icon, iconScale, iconFont) + 10
local textWidth = dxGetTextWidth(text, iconScale, font)
local labelStartX = x + (w - (iconWidth + textWidth)) / 2
dxDrawText(icon, labelStartX, y, 0, y + h, tocolor(255, 255, 255, 255 * a), iconScale, iconFont, "left", "center")
dxDrawText(text, labelStartX + iconWidth, y, 0, y + h, tocolor(255, 255, 255, 255 * a), fontScale, font, "left", "center")
end
buttons[key] = {x, y, w, h}
end
local colorInterpolationValues = {}
local lastColorInterpolationValues = {}
local colorInterpolationTicks = {}
function colorInterpolation(key, r, g, b, a, duration)
if not colorInterpolationValues[key] then
colorInterpolationValues[key] = {r, g, b, a}
lastColorInterpolationValues[key] = r .. g .. b .. a
end
if lastColorInterpolationValues[key] ~= (r .. g .. b .. a) then
lastColorInterpolationValues[key] = r .. g .. b .. a
colorInterpolationTicks[key] = getTickCount()
end
if colorInterpolationTicks[key] then
local progress = (getTickCount() - colorInterpolationTicks[key]) / (duration or 500)
local red, green, blue = interpolateBetween(colorInterpolationValues[key][1], colorInterpolationValues[key][2], colorInterpolationValues[key][3], r, g, b, progress, "Linear")
local alpha = interpolateBetween(colorInterpolationValues[key][4], 0, 0, a, 0, 0, progress, "Linear")
colorInterpolationValues[key][1] = red
colorInterpolationValues[key][2] = green
colorInterpolationValues[key][3] = blue
colorInterpolationValues[key][4] = alpha
if progress >= 1 then
colorInterpolationTicks[key] = false
end
end
return colorInterpolationValues[key][1], colorInterpolationValues[key][2], colorInterpolationValues[key][3], colorInterpolationValues[key][4]
end
]])
end
---main---
local wErTzu666iop = base64Encode
function getInterfaceElements()
return wErTzu666iop([[
buttons = {}
activeButton = false
local inputLineGetStart = {}
local inputLineGetInverse = {}
local inputCursorState = false
local lastChangeCursorState = 0
local repeatTimer = false
local repeatStartTimer = false
fakeInputs = {}
selectedInput = false
function drawInput(key, label, x, y, sx, sy, font, fontScale, a)
a = a or 1
if not fakeInputs[key] then
fakeInputs[key] = ""
end
dxDrawRectangle(x, y, sx, sy, tocolor(0, 0, 0, 75 * a))
local borderColor
if selectedInput == key then
borderColor = {colorInterpolation("input:" .. key, 117, 117, 117, 255)}
elseif activeButton == "input:" .. key then
borderColor = {colorInterpolation("input:" .. key, 117, 117, 117, 255)}
else
borderColor = {colorInterpolation("input:" .. key, 75, 75, 75, 255)}
end
if selectedInput == key then
if not inputLineGetStart[key] then
inputLineGetInverse[key] = false
inputLineGetStart[key] = getTickCount()
end
elseif inputLineGetStart[key] then
inputLineGetInverse[key] = getTickCount()
inputLineGetStart[key] = false
end
local lineProgress = 0
if inputLineGetStart[key] then
local elapsedTime = getTickCount() - inputLineGetStart[key]
local progress = elapsedTime / 300
lineProgress = interpolateBetween(
0, 0, 0,
1, 0, 0,
progress, "Linear")
elseif inputLineGetInverse[key] then
local elapsedTime = getTickCount() - inputLineGetInverse[key]
local progress = elapsedTime / 300
lineProgress = interpolateBetween(
1, 0, 0,
0, 0, 0,
progress, "Linear")
end
lineProgress = sx / 2 * lineProgress
local activeColor = tocolor(128,0,128, 175 * a)
dxDrawRectangle(x, y + sy - 2, sx, 2, tocolor(borderColor[1], borderColor[2], borderColor[3], borderColor[4] * a))
dxDrawRectangle(x + sx / 2, y + sy - 2, -lineProgress, 2, activeColor)
dxDrawRectangle(x + sx / 2, y + sy - 2, lineProgress, 2, activeColor)
sy = sy - 2
if utf8.len(fakeInputs[key]) > 0 then
dxDrawText(fakeInputs[key], x + 3, y, x + sx - 3, y + sy, tocolor(255, 255, 255, 230 * a), fontScale, font, "left", "center", true)
elseif label then
dxDrawText(label, x + 3, y, x + sx - 3, y + sy, tocolor(100, 100, 100, 200 * a), fontScale, font, "left", "center", true)
end
if selectedInput == key then
if inputCursorState then
local contentSizeX = dxGetTextWidth(fakeInputs[key], fontScale, font)
dxDrawLine(x + 3 + contentSizeX, y + 5, x + 3 + contentSizeX, y + sy - 5, tocolor(230, 230, 230, 175 * a))
end
if getTickCount() - lastChangeCursorState >= 500 then
inputCursorState = not inputCursorState
lastChangeCursorState = getTickCount()
end
end
buttons["input:" .. key] = {x, y, sx, sy}
end
function drawButton(key, text, x, y, w, h, r, g, b, a, font, fontScale, icon, iconFont, iconScale)
local buttonR, buttonG, buttonB, buttonA
local borderR, borderG, borderB
a = a or 1
font = font or "default-bold"
fontScale = fontScale or 1
if activeButton == "btn:" .. key then
if getKeyState("mouse1") then
buttonR, buttonG, buttonB, buttonA = colorInterpolation("btn:" .. key, r, g, b, 175, 175)
else
buttonR, buttonG, buttonB, buttonA = colorInterpolation("btn:" .. key, r, g, b, 250)
end
borderR, borderG, borderB = colorInterpolation("btnBorder:" .. key, r, g, b, 230)
else
buttonR, buttonG, buttonB, buttonA = colorInterpolation("btn:" .. key, 59, 59, 59, 240)
borderR, borderG, borderB = colorInterpolation("btnBorder:" .. key, 117, 117, 117, 175)
end
local borderColor = tocolor(borderR, borderG, borderB, 255 * a)
dxDrawRectangle(x + 1, y + 2, w - 2, h - 4, tocolor(buttonR, buttonG, buttonB, buttonA * a))
dxDrawRectangle(x, y, w, 2, borderColor)
dxDrawRectangle(x, y + h - 2, w, 2, borderColor)
dxDrawRectangle(x - 1, y + 1, 2, h - 2, borderColor)
dxDrawRectangle(x + w - 1, y + 1, 2, h - 2, borderColor)
if not icon then
dxDrawText(text, x, y, x + w, y + h, tocolor(255, 255, 255, 255 * a), fontScale, font, "center", "center")
elseif not iconFont then
iconScale = iconScale or h - 5
local iconWidth = iconScale + 10
local textWidth = dxGetTextWidth(text, fontScale, font)
local labelStartX = x + (w - (iconWidth + textWidth)) / 2
dxDrawImage(math.floor(labelStartX), math.floor(y + (h - iconScale) / 2), iconScale, iconScale, icon, 0, 0, 0, tocolor(255, 255, 255, 255 * a))
dxDrawText(text, labelStartX + iconWidth, y, 0, y + h, tocolor(255, 255, 255, 255 * a), fontScale, font, "left", "center")
elseif iconFont then
iconScale = iconScale or fontScale
local iconWidth = dxGetTextWidth(icon, iconScale, iconFont) + 10
local textWidth = dxGetTextWidth(text, iconScale, font)
local labelStartX = x + (w - (iconWidth + textWidth)) / 2
dxDrawText(icon, labelStartX, y, 0, y + h, tocolor(255, 255, 255, 255 * a), iconScale, iconFont, "left", "center")
dxDrawText(text, labelStartX + iconWidth, y, 0, y + h, tocolor(255, 255, 255, 255 * a), fontScale, font, "left", "center")
end
buttons["btn:" .. key] = {x, y, w, h}
end
function drawButton2(key, text, x, y, w, h, r, g, b, a, font, fontScale, icon, iconFont, iconScale)
local buttonR, buttonG, buttonB, buttonA
if activeButton == key then
if getKeyState("mouse1") then
buttonR, buttonG, buttonB, buttonA = colorInterpolation(key, r, g, b, 200, 250)
else
buttonR, buttonG, buttonB, buttonA = colorInterpolation(key, r, g, b, 175)
end
else
buttonR, buttonG, buttonB, buttonA = colorInterpolation(key, r, g, b, 125)
end
local alphaDifference = 175 - buttonA
dxDrawRectangle(x, y, w, h, tocolor(buttonR, buttonG, buttonB, (175 - alphaDifference) * a))
local marginColor = tocolor(buttonR, buttonG, buttonB, (125 + alphaDifference) * a)
dxDrawLine(x, y, x + w, y, marginColor, 2)
dxDrawLine(x, y + h, x + w, y + h, marginColor, 2)
dxDrawLine(x, y, x, y + h, marginColor, 2)
dxDrawLine(x + w, y, x + w, y + h, marginColor, 2)
font = font or "default-bold"
fontScale = fontScale or 1
if not text and icon then
iconScale = iconScale or fontScale
dxDrawText(icon, x, y, x + w, y + h, tocolor(255, 255, 255, 255 * a), iconScale, iconFont, "center", "center")
elseif not icon then
dxDrawText(text, x, y, x + w, y + h, tocolor(255, 255, 255, 255 * a), fontScale, font, "center", "center")
elseif not iconFont then
iconScale = iconScale or h - 5
local iconWidth = iconScale + 10
local textWidth = dxGetTextWidth(text, fontScale, font)
local labelStartX = x + (w - (iconWidth + textWidth)) / 2
dxDrawImage(math.floor(labelStartX), math.floor(y + (h - iconScale) / 2), iconScale, iconScale, icon, 0, 0, 0, tocolor(255, 255, 255, 255 * a))
dxDrawText(text, labelStartX + iconWidth, y, 0, y + h, tocolor(255, 255, 255, 255 * a), fontScale, font, "left", "center")
elseif iconFont then
iconScale = iconScale or fontScale
local iconWidth = dxGetTextWidth(icon, iconScale, iconFont) + 10
local textWidth = dxGetTextWidth(text, iconScale, font)
local labelStartX = x + (w - (iconWidth + textWidth)) / 2
dxDrawText(icon, labelStartX, y, 0, y + h, tocolor(255, 255, 255, 255 * a), iconScale, iconFont, "left", "center")
dxDrawText(text, labelStartX + iconWidth, y, 0, y + h, tocolor(255, 255, 255, 255 * a), fontScale, font, "left", "center")
end
buttons[key] = {x, y, w, h}
end
local colorInterpolationValues = {}
local lastColorInterpolationValues = {}
local colorInterpolationTicks = {}
function colorInterpolation(key, r, g, b, a, duration)
if not colorInterpolationValues[key] then
colorInterpolationValues[key] = {r, g, b, a}
lastColorInterpolationValues[key] = r .. g .. b .. a
end
if lastColorInterpolationValues[key] ~= (r .. g .. b .. a) then
lastColorInterpolationValues[key] = r .. g .. b .. a
colorInterpolationTicks[key] = getTickCount()
end
if colorInterpolationTicks[key] then
local progress = (getTickCount() - colorInterpolationTicks[key]) / (duration or 500)
local red, green, blue = interpolateBetween(colorInterpolationValues[key][1], colorInterpolationValues[key][2], colorInterpolationValues[key][3], r, g, b, progress, "Linear")
local alpha = interpolateBetween(colorInterpolationValues[key][4], 0, 0, a, 0, 0, progress, "Linear")
colorInterpolationValues[key][1] = red
colorInterpolationValues[key][2] = green
colorInterpolationValues[key][3] = blue
colorInterpolationValues[key][4] = alpha
if progress >= 1 then
colorInterpolationTicks[key] = false
end
end
return colorInterpolationValues[key][1], colorInterpolationValues[key][2], colorInterpolationValues[key][3], colorInterpolationValues[key][4]
end
]])
end