script_name("ObjEditor")
script_author("Milei")
local imgui = require 'mimgui'
local ffi = require 'ffi'
local bit = require 'bit'
local inicfg = require 'inicfg'
local new = imgui.new
local sampev = require 'samp.events'
-- ===== Configuración =====
local SLOT_PREVIEW = 9 -- slot de la vista previa del editor
local MAX_SLOTS = 9 -- proyectos activos usan slots 0..8
local ARCHIVO_INI = "obj_proyectos.ini"
local ALPHA_MIN = 0.55
-- ===== Variables del editor =====
local ventana = new.bool(false)
local panelProy = new.bool(false)
local nombre = new.char[64]("")
local modelo = new.int(19078)
local hueso = new.int(0)
local pos = new.float[3](0.0, 0.0, 0.0)
local rot = new.float[3](0.0, 0.0, 0.0)
local escala = new.float[3](1.0, 1.0, 1.0)
local paso = new.float(0.01)
local uniforme = new.bool(true)
-- Colores de material
local usarCol1 = new.bool(false)
local usarCol2 = new.bool(false)
local color1 = new.float[4](1.0, 1.0, 1.0, 1.0)
local color2 = new.float[4](1.0, 1.0, 1.0, 1.0)
-- Opacidad / visibilidad
local opacidad = new.float(100.0) -- 0..100
local visible = new.bool(true)
-- Fake skin
local fakeSkinId = new.int(0)
local fakeSkinOn = false
local skinReal = nil
local RPC_SETSKIN = 153
local previewOn = false
local editando = 0
local ultimoEnvio = {}
local data = { proyectos = {} }
local huesos = {
"Columna", "Cabeza", "Brazo izq.", "Brazo der.", "Mano izq.", "Mano der.",
"Muslo izq.", "Muslo der.", "Pie izq.", "Pie der.", "Pantorrilla der.",
"Pantorrilla izq.", "Antebrazo izq.", "Antebrazo der.", "Clavícula izq.",
"Clavícula der.", "Cuello", "Mandíbula"
}
local huesosC = new['const char*'][#huesos](huesos)
local function msg(t) sampAddChatMessage("{00FF00}[Obj]{FFFFFF} " .. t, -1) end
-- ===== Helpers para conversion INI =====
local function parseFloats(str)
if not str or str == "" then return nil end
local t = {}
for num in string.gmatch(str, "[^,]+") do
table.insert(t, tonumber(num) or 0.0)
end
return #t > 0 and t or nil
end
-- ===== Archivo INI =====
local function guardarArchivo()
local cfg = {
General = {
fakeSkin_id = fakeSkinId[0],
fakeSkin_activo = fakeSkinOn,
total_proyectos = #data.proyectos
}
}
for i, p in ipairs(data.proyectos) do
local sec = "Proyecto_" .. i
cfg[sec] = {
nombre = p.nombre or "",
modelo = p.modelo or 19078,
hueso = p.hueso or 0,
pos = string.format("%.3f,%.3f,%.3f", p.pos[1] or 0, p.pos[2] or 0, p.pos[3] or 0),
rot = string.format("%.1f,%.1f,%.1f", p.rot[1] or 0, p.rot[2] or 0, p.rot[3] or 0),
escala = string.format("%.3f,%.3f,%.3f", p.escala[1] or 1, p.escala[2] or 1, p.escala[3] or 1),
uniforme = p.uniforme and true or false,
col1 = p.col1 and string.format("%.2f,%.2f,%.2f,%.2f", p.col1[1], p.col1[2], p.col1[3], p.col1[4]) or "",
col2 = p.col2 and string.format("%.2f,%.2f,%.2f,%.2f", p.col2[1], p.col2[2], p.col2[3], p.col2[4]) or "",
opacidad = p.opacidad or 100.0,
visible = p.visible ~= false,
activo = p.activo == true
}
end
inicfg.save(cfg, ARCHIVO_INI)
end
local function cargarArchivo()
local cfg = inicfg.load(nil, ARCHIVO_INI)
if not cfg then return end
if cfg.General then
fakeSkinId[0] = tonumber(cfg.General.fakeSkin_id) or 0
fakeSkinOn = cfg.General.fakeSkin_activo == true or cfg.General.fakeSkin_activo == "true"
end
data.proyectos = {}
local total = tonumber(cfg.General and cfg.General.total_proyectos) or 0
for i = 1, math.max(total, 100) do
local sec = cfg["Proyecto_" .. i]
if sec and sec.nombre then
local p = {
nombre = sec.nombre,
modelo = tonumber(sec.modelo) or 19078,
hueso = tonumber(sec.hueso) or 0,
pos = parseFloats(sec.pos) or {0.0, 0.0, 0.0},
rot = parseFloats(sec.rot) or {0.0, 0.0, 0.0},
escala = parseFloats(sec.escala) or {1.0, 1.0, 1.0},
uniforme = sec.uniforme == true or sec.uniforme == "true",
col1 = parseFloats(sec.col1),
col2 = parseFloats(sec.col2),
opacidad = tonumber(sec.opacidad) or 100.0,
visible = sec.visible == true or sec.visible == "true" or sec.visible == nil,
activo = sec.activo == true or sec.activo == "true"
}
table.insert(data.proyectos, p)
end
end
end
-- ===== Attach local =====
local RPC_ATTACH = 113
local function miId()
local _, id = sampGetPlayerIdByCharHandle(PLAYER_PED)
return id
end
local function curvaAlpha(op)
if op <= 0.005 then return 0 end
return ALPHA_MIN + (1 - ALPHA_MIN) * math.min(1, op)
end
local function colorFinal(c, op)
op = op or 1.0
if type(c) ~= "table" then
if op >= 0.999 then return 0 end
c = { 1.0, 1.0, 1.0, 1.0 }
end
local function b(v) return math.floor(math.max(0, math.min(1, v or 1)) * 255 + 0.5) end
local a = curvaAlpha((c[4] or 1.0) * op)
return bit.bor(bit.lshift(b(a), 24), bit.lshift(b(c[3]), 16), bit.lshift(b(c[2]), 8), b(c[1]))
end
local function enviarAttach(slot, d, forzar)
if d and d.visible == false then d = nil end
local firma = "nil"
local c1, c2 = 0, 0
if d then
local op = (tonumber(d.opacidad) or 100) / 100
c1, c2 = colorFinal(d.col1, op), colorFinal(d.col2, op)
firma = string.format("%d|%d|%.3f|%.3f|%.3f|%.1f|%.1f|%.1f|%.3f|%.3f|%.3f|%d|%d",
d.modelo, d.hueso, d.pos[1], d.pos[2], d.pos[3], d.rot[1], d.rot[2], d.rot[3],
d.escala[1], d.escala[2], d.escala[3], c1, c2)
end
if not forzar and ultimoEnvio[slot] == firma then return end
ultimoEnvio[slot] = firma
local bs = raknetNewBitStream()
raknetBitStreamWriteInt16(bs, miId())
raknetBitStreamWriteInt32(bs, slot)
raknetBitStreamWriteBool(bs, d ~= nil)
if d then
raknetBitStreamWriteInt32(bs, d.modelo)
raknetBitStreamWriteInt32(bs, d.hueso + 1)
for i = 1, 3 do raknetBitStreamWriteFloat(bs, d.pos[i]) end
for i = 1, 3 do raknetBitStreamWriteFloat(bs, d.rot[i]) end
for i = 1, 3 do raknetBitStreamWriteFloat(bs, d.escala[i]) end
raknetBitStreamWriteInt32(bs, c1)
raknetBitStreamWriteInt32(bs, c2)
end
raknetEmulRpcReceiveBitStream(RPC_ATTACH, bs)
raknetDeleteBitStream(bs)
end
-- ===== Fake skin =====
local ponerTodosRef
local aplicandoSkin = false
local function emularSkin(id)
local bs = raknetNewBitStream()
raknetBitStreamWriteInt32(bs, miId())
raknetBitStreamWriteInt32(bs, id)
aplicandoSkin = true
raknetEmulRpcReceiveBitStream(RPC_SETSKIN, bs)
aplicandoSkin = false
raknetDeleteBitStream(bs)
lua_thread.create(function()
wait(300)
if ponerTodosRef then ponerTodosRef() end
end)
end
local function activarFakeSkin()
local id = fakeSkinId[0]
if id < 0 or id > 311 or id == 74 then msg("{FF5555}ID de skin invalido.") return end
if not skinReal then skinReal = getCharModel(PLAYER_PED) end
fakeSkinOn = true
emularSkin(id)
guardarArchivo()
msg("Fake skin " .. id .. " activada (solo vos la ves).")
end
local function quitarFakeSkin()
fakeSkinOn = false
if skinReal then emularSkin(skinReal) end
guardarArchivo()
msg("Fake skin desactivada.")
end
-- ===== Datos del editor =====
local function capturar(n)
return {
nombre = n, modelo = modelo[0], hueso = hueso[0],
pos = { pos[0], pos[1], pos[2] },
rot = { rot[0], rot[1], rot[2] },
escala = { escala[0], escala[1], escala[2] },
uniforme = uniforme[0],
col1 = usarCol1[0] and { color1[0], color1[1], color1[2], color1[3] } or nil,
col2 = usarCol2[0] and { color2[0], color2[1], color2[2], color2[3] } or nil,
opacidad = opacidad[0],
visible = visible[0]
}
end
local function aplicar(p)
imgui.StrCopy(nombre, p.nombre or "")
modelo[0] = p.modelo; hueso[0] = p.hueso
for i = 0, 2 do
pos[i] = p.pos[i + 1]; rot[i] = p.rot[i + 1]; escala[i] = p.escala[i + 1]
end
uniforme[0] = p.uniforme and true or false
usarCol1[0] = type(p.col1) == "table"
usarCol2[0] = type(p.col2) == "table"
for i = 0, 3 do
color1[i] = usarCol1[0] and (p.col1[i + 1] or 1.0) or 1.0
color2[i] = usarCol2[0] and (p.col2[i + 1] or 1.0) or 1.0
end
opacidad[0] = tonumber(p.opacidad) or 100.0
visible[0] = p.visible ~= false
end
local function resetColores()
usarCol1[0], usarCol2[0] = false, false
for i = 0, 3 do color1[i] = 1.0; color2[i] = 1.0 end
opacidad[0] = 100.0
visible[0] = true
end
local function editSlot()
local p = data.proyectos[editando]
if p and p.activo and p.slot then return p.slot end
return SLOT_PREVIEW
end
local function actualizar(forzar)
if previewOn then enviarAttach(editSlot(), capturar(""), forzar) end
end
local function slotLibre()
local usados = {}
for _, p in ipairs(data.proyectos) do
if p.activo and p.slot then usados[p.slot] = true end
end
for s = 0, MAX_SLOTS - 1 do
if not usados[s] then return s end
end
end
local function soltarEdicion()
local p = data.proyectos[editando]
if p and p.activo and p.slot then
enviarAttach(p.slot, p, true)
elseif previewOn then
enviarAttach(SLOT_PREVIEW, nil, true)
end
previewOn = false
end
-- ===== Proyectos =====
local function activarProyecto(i)
local p = data.proyectos[i]
local s = slotLibre()
if not s then
msg("{FF5555}Llegaste al maximo de " .. MAX_SLOTS .. " proyectos activos. Desactiva uno.")
return
end
p.activo, p.slot = true, s
if editando == i and previewOn then
enviarAttach(SLOT_PREVIEW, nil, true)
enviarAttach(s, capturar(""), true)
else
enviarAttach(s, p, true)
end
guardarArchivo()
msg("Proyecto '" .. p.nombre .. "' activado.")
end
local function desactivarProyecto(i)
local p = data.proyectos[i]
if p.slot then enviarAttach(p.slot, nil, true) end
p.activo, p.slot = false, nil
if editando == i then previewOn = false end
guardarArchivo()
msg("Proyecto '" .. p.nombre .. "' desactivado.")
end
local function editarProyecto(i)
if editando ~= i then soltarEdicion() end
editando = i
local p = data.proyectos[i]
aplicar(p)
previewOn = true
actualizar(true)
msg("Editando '" .. p.nombre .. "'. Toca Guardar proyecto para aplicar cambios.")
end
local function borrarProyecto(i)
local p = data.proyectos[i]
if p.activo and p.slot then enviarAttach(p.slot, nil, true) end
if editando == i then
if not p.activo and previewOn then enviarAttach(SLOT_PREVIEW, nil, true) end
previewOn = false; editando = 0
elseif editando > i then
editando = editando - 1
end
table.remove(data.proyectos, i)
guardarArchivo()
msg("Proyecto '" .. p.nombre .. "' borrado.")
end
local function alternarVisible(i)
local p = data.proyectos[i]
p.visible = (p.visible == false)
if editando == i then visible[0] = p.visible end
if p.activo and p.slot then
if editando == i and previewOn then enviarAttach(p.slot, capturar(""), true)
else enviarAttach(p.slot, p, true) end
end
guardarArchivo()
msg("Proyecto '" .. p.nombre .. "' " .. (p.visible and "visible." or "oculto."))
end
local function guardarProyecto()
local n = ffi.string(nombre):gsub("^%s+", ""):gsub("%s+$", "")
if n == "" then msg("{FF5555}Pone un nombre antes de guardar.") return end
local idx
for i, p in ipairs(data.proyectos) do
if p.nombre == n then idx = i break end
end
if (idx and idx ~= editando) or (not idx and editando > 0) then
local wasPreview = previewOn
soltarEdicion()
previewOn = wasPreview
end
local nuevo = capturar(n)
if idx then
local viejo = data.proyectos[idx]
nuevo.activo, nuevo.slot = viejo.activo, viejo.slot
data.proyectos[idx] = nuevo
msg("Proyecto '" .. n .. "' actualizado.")
else
nuevo.activo = false
table.insert(data.proyectos, nuevo)
idx = #data.proyectos
msg("Proyecto '" .. n .. "' guardado.")
end
editando = idx
if nuevo.activo and nuevo.slot then
if previewOn then enviarAttach(SLOT_PREVIEW, nil, true) end
enviarAttach(nuevo.slot, nuevo, true)
previewOn = true
elseif previewOn then
enviarAttach(SLOT_PREVIEW, capturar(""), true)
end
guardarArchivo()
end
-- ===== Interfaz =====
imgui.OnInitialize(function()
imgui.GetIO().IniFilename = nil
end)
local ejes = { "X", "Y", "Z" }
local mainPos, mainSize = imgui.ImVec2(0, 0), imgui.ImVec2(420, 760)
imgui.OnFrame(function() return ventana[0] end, function()
local sw, sh = getScreenResolution()
imgui.SetNextWindowPos(imgui.ImVec2(sw / 2 - 150, sh / 2), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
imgui.SetNextWindowSize(imgui.ImVec2(420, 760), imgui.Cond.FirstUseEver)
imgui.Begin("Editor de Objetos By Milei", ventana)
mainPos, mainSize = imgui.GetWindowPos(), imgui.GetWindowSize()
local ed = data.proyectos[editando]
if ed then
imgui.TextColored(imgui.ImVec4(1.0, 0.85, 0.3, 1.0), "Editando: " .. ed.nombre)
else
imgui.TextDisabled("Proyecto nuevo (sin guardar)")
end
-- Generar
imgui.Text("Generar objeto")
imgui.Separator()
if imgui.InputInt("ID Objeto", modelo) then actualizar() end
if imgui.Combo("Hueso", hueso, huesosC, #huesos) then actualizar(true) end
if imgui.Button("Generar", imgui.ImVec2(120, 25)) then previewOn = true; actualizar(true) end
imgui.SameLine()
if imgui.Button("Eliminar", imgui.ImVec2(120, 25)) then
if ed and ed.activo then desactivarProyecto(editando)
else enviarAttach(SLOT_PREVIEW, nil, true); previewOn = false end
end
imgui.SameLine()
if imgui.Button("Nuevo", imgui.ImVec2(120, 25)) then
soltarEdicion()
editando = 0
imgui.StrCopy(nombre, "")
for i = 0, 2 do pos[i] = 0; rot[i] = 0; escala[i] = 1 end
resetColores()
end
-- Editar
imgui.Spacing()
imgui.Text("Editar objeto")
imgui.Separator()
imgui.SliderFloat("Sensibilidad", paso, 0.001, 0.1, "%.3f")
if imgui.DragFloat3("Posición (X Y Z)", pos, paso[0], -5.0, 5.0, "%.3f") then
actualizar()
end
if imgui.Button("Resetear valores", imgui.ImVec2(-1, 22)) then
for i = 0, 2 do pos[i] = 0; rot[i] = 0; escala[i] = 1 end
resetColores()
actualizar(true)
end
imgui.Spacing()
imgui.Text("Rotación")
for i = 0, 2 do
imgui.PushIDInt(i)
imgui.PushItemWidth(170)
local tmp = new.float(rot[i])
if imgui.DragFloat("Rot " .. ejes[i + 1], tmp, paso[0] * 100, -360.0, 360.0, "%.1f") then
rot[i] = tmp[0]
actualizar()
end
imgui.PopItemWidth()
imgui.SameLine()
if imgui.Button("-90") then rot[i] = rot[i] - 90; actualizar(true) end
imgui.SameLine()
if imgui.Button("+90") then rot[i] = rot[i] + 90; actualizar(true) end
imgui.SameLine()
if imgui.Button("0") then rot[i] = 0; actualizar(true) end
imgui.PopID()
end
imgui.Spacing()
imgui.Text("Tamaño")
if imgui.Checkbox("Tamaño uniforme (mismo en X, Y y Z)", uniforme) then
if uniforme[0] then escala[1] = escala[0]; escala[2] = escala[0]; actualizar(true) end
end
if uniforme[0] then
local tmp = new.float(escala[0])
if imgui.DragFloat("Tamaño", tmp, paso[0], 0.01, 10.0, "%.3f") then
for i = 0, 2 do escala[i] = tmp[0] end
actualizar()
end
else
if imgui.DragFloat3("Tamaño (X Y Z)", escala, paso[0], 0.01, 10.0, "%.3f") then
actualizar()
end
end
-- Color
imgui.Spacing()
imgui.Text("Color de texturas")
imgui.Separator()
local colFlags = imgui.ColorEditFlags.AlphaBar
local mats = { { usarCol1, color1 }, { usarCol2, color2 } }
for idx, m in ipairs(mats) do
imgui.PushIDInt(100 + idx)
if imgui.Checkbox("Material " .. idx, m[1]) then actualizar(true) end
if m[1][0] then
imgui.SameLine()
imgui.PushItemWidth(-1)
if imgui.ColorEdit4("##col", m[2], colFlags) then
actualizar()
end
imgui.PopItemWidth()
end
imgui.PopID()
end
-- Opacidad
imgui.Spacing()
imgui.Text("Opacidad")
imgui.Separator()
if imgui.SliderFloat("Opacidad", opacidad, 0.0, 100.0, "%.0f%%") then
actualizar()
end
if imgui.Button("0%", imgui.ImVec2(60, 22)) then opacidad[0] = 0; actualizar(true) end
imgui.SameLine()
if imgui.Button("50%", imgui.ImVec2(60, 22)) then opacidad[0] = 50; actualizar(true) end
imgui.SameLine()
if imgui.Button("100%", imgui.ImVec2(60, 22)) then opacidad[0] = 100; actualizar(true) end
if imgui.Button(visible[0] and "Ocultar objeto" or "Mostrar objeto", imgui.ImVec2(-1, 22)) then
visible[0] = not visible[0]
actualizar(true)
end
if not visible[0] then
imgui.TextColored(imgui.ImVec4(1.0, 0.5, 0.3, 1.0), "Objeto oculto (guardá para que quede así)")
end
-- Fake skin
imgui.Spacing()
imgui.Text("Fake Skin (solo visible para vos)")
imgui.Separator()
imgui.PushItemWidth(150)
imgui.InputInt("ID Skin", fakeSkinId)
imgui.PopItemWidth()
imgui.SameLine()
if imgui.Button("Aplicar skin", imgui.ImVec2(100, 22)) then activarFakeSkin() end
imgui.SameLine()
if imgui.Button("Quitar", imgui.ImVec2(-1, 22)) then quitarFakeSkin() end
if fakeSkinOn then
imgui.TextColored(imgui.ImVec4(0.3, 1.0, 0.3, 1.0),
"Activa: " .. fakeSkinId[0] .. " (real: " .. tostring(skinReal or "?") .. ")")
end
-- Guardado
imgui.Spacing()
imgui.Text("Guardado")
imgui.Separator()
imgui.InputText("Nombre", nombre, ffi.sizeof(nombre))
if imgui.Button("Guardar proyecto", imgui.ImVec2(-1, 25)) then guardarProyecto() end
imgui.Spacing()
if imgui.Button(panelProy[0] and "Ocultar proyectos" or "Proyectos guardados", imgui.ImVec2(-1, 25)) then
panelProy[0] = not panelProy[0]
end
imgui.End()
-- ===== Panel derecho: proyectos =====
if panelProy[0] then
imgui.SetNextWindowPos(imgui.ImVec2(mainPos.x + mainSize.x + 5, mainPos.y), imgui.Cond.Always)
imgui.SetNextWindowSize(imgui.ImVec2(320, mainSize.y), imgui.Cond.Always)
imgui.Begin("Proyectos guardados", panelProy,
imgui.WindowFlags.NoMove + imgui.WindowFlags.NoResize + imgui.WindowFlags.NoCollapse)
local activos = 0
for _, p in ipairs(data.proyectos) do if p.activo then activos = activos + 1 end end
imgui.Text(string.format("Activos: %d / %d", activos, MAX_SLOTS))
imgui.SameLine()
if imgui.SmallButton("Activar todos") then
for i, p in ipairs(data.proyectos) do
if not p.activo then
if not slotLibre() then
msg("{FF5555}Se llego al maximo de " .. MAX_SLOTS .. " proyectos activos.")
break
end
activarProyecto(i)
end
end
end
imgui.SameLine()
if imgui.SmallButton("Desactivar todos") then
for i, p in ipairs(data.proyectos) do if p.activo then desactivarProyecto(i) end end
end
imgui.Separator()
if #data.proyectos == 0 then
imgui.TextDisabled("Todavía no guardaste ningún proyecto.")
end
local borrar
for i, p in ipairs(data.proyectos) do
imgui.PushIDInt(i)
if p.activo then
imgui.TextColored(imgui.ImVec4(0.3, 1.0, 0.3, 1.0), "[ON] " .. p.nombre)
else
imgui.Text(p.nombre)
end
if p.visible == false then
imgui.SameLine()
imgui.TextColored(imgui.ImVec4(1.0, 0.5, 0.3, 1.0), "(oculto)")
end
imgui.TextDisabled(string.format("ID %d - %s - %d%%", p.modelo, huesos[p.hueso + 1] or "?",
math.floor((tonumber(p.opacidad) or 100) + 0.5)))
if type(p.col1) == "table" then
imgui.SameLine()
imgui.ColorButton("##c1", imgui.ImVec4(p.col1[1], p.col1[2], p.col1[3], p.col1[4]), 0, imgui.ImVec2(14, 14))
end
if type(p.col2) == "table" then
imgui.SameLine()
imgui.ColorButton("##c2", imgui.ImVec4(p.col2[1], p.col2[2], p.col2[3], p.col2[4]), 0, imgui.ImVec2(14, 14))
end
if p.activo then
if imgui.Button("Desactivar", imgui.ImVec2(70, 22)) then desactivarProyecto(i) end
else
if imgui.Button("Activar", imgui.ImVec2(70, 22)) then activarProyecto(i) end
end
imgui.SameLine()
if imgui.Button(p.visible == false and "Mostrar" or "Ocultar", imgui.ImVec2(70, 22)) then alternarVisible(i) end
imgui.SameLine()
if imgui.Button("Editar", imgui.ImVec2(70, 22)) then editarProyecto(i) end
imgui.SameLine()
if imgui.Button("Borrar", imgui.ImVec2(70, 22)) then borrar = i end
imgui.Separator()
imgui.PopID()
end
if borrar then borrarProyecto(borrar) end
imgui.End()
end
end)
-- ===== Poner todos los activos =====
local function ponerTodos()
for _, p in ipairs(data.proyectos) do
if p.activo and p.slot then enviarAttach(p.slot, p, false) end
end
if previewOn then enviarAttach(editSlot(), capturar(""), false) end
end
ponerTodosRef = ponerTodos
-- ===== Main =====
function main()
while not isSampAvailable() do wait(100) end
cargarArchivo()
sampRegisterChatCommand("obj", function() ventana[0] = not ventana[0] end)
sampRegisterChatCommand("fskin", function(arg)
local id = tonumber(arg)
if id then fakeSkinId[0] = id; activarFakeSkin() else quitarFakeSkin() end
end)
msg("Cargado. Usa /obj para abrir el panel.")
while not sampIsLocalPlayerSpawned() do wait(500) end
wait(1000)
local n = 0
for _, p in ipairs(data.proyectos) do
if p.activo then
local s = slotLibre()
if s then p.slot = s; n = n + 1 else p.activo = false end
end
end
ponerTodos()
if n > 0 then msg(n .. " proyecto(s) restaurado(s).") end
skinReal = getCharModel(PLAYER_PED)
if fakeSkinOn then emularSkin(fakeSkinId[0]) end
local estabaMuerto = false
function sampev.onSetPlayerSkin(playerid, skinId)
if aplicandoSkin then return end
if playerid == miId() then
skinReal = skinId
if fakeSkinOn then
lua_thread.create(function() wait(200); emularSkin(fakeSkinId[0]) end)
return false
end
end
end
function sampev.onSetPlayerAttachedObject(playerid, index, create, model, bone, offset, rotation, scale, color1, color2)
local myId = miId()
if playerid == myId and index >= 0 and index < MAX_SLOTS then
local ocupado = false
for _, p in ipairs(data.proyectos) do
if p.activo and p.slot == index then
ocupado = true
break
end
end
if ocupado then return false end
end
end
sampRegisterChatCommand("objrefresh", function()
ponerTodos()
msg("Objetos restaurados.")
end)
while true do
wait(100)
if isCharDead(PLAYER_PED) or not sampIsLocalPlayerSpawned() then
estabaMuerto = true
elseif estabaMuerto then
estabaMuerto = false
wait(1500)
ponerTodos()
if fakeSkinOn then emularSkin(fakeSkinId[0]) end
end
end
end
To embed this project on your website, copy the following code and paste it into your website's HTML: