require "lib.moonloader"
local imgui = require 'mimgui'
local encoding = require 'encoding'
encoding.default = 'CP1251'
u8 = encoding.UTF8
local main_window_state = imgui.new.bool(false)
local clones = {}
local config_path = getWorkingDirectory() .. "\\config\\clone.json"
local edit_mode = {}
function main()
if not isSampLoaded() or not isSampfuncsLoaded() then return end
while not isSampAvailable() do wait(100) end
sampRegisterChatCommand("clone", function()
main_window_state[0] = not main_window_state[0]
end)
sampRegisterChatCommand("addclone", cmd_addclone)
sampRegisterChatCommand("clearclones", cmd_clearclones)
loadConfig()
sampAddChatMessage("[Clone] {FFFFFF}Скрипт загружен. /clone - меню, /addclone - создать клон", 0x00FF00)
wait(-1)
end
function cmd_addclone()
if not isCharOnFoot(PLAYER_PED) then
sampAddChatMessage("[Clone] {FFFFFF}Вы должны быть на ногах!", 0xFF0000)
return
end
local x, y, z = getCharCoordinates(PLAYER_PED)
local angle = getCharHeading(PLAYER_PED)
local skinId = getCharModel(PLAYER_PED)
z = z - 1.0
local camX, camY, camZ = getActiveCameraCoordinates()
local camTargetX, camTargetY, camTargetZ = getActiveCameraPointAt()
local headAngleZ = math.atan2(camTargetY - camY, camTargetX - camX) * 180 / math.pi
local distance = math.sqrt((camTargetX - camX)^2 + (camTargetY - camY)^2)
local headAngleX = math.atan2(camTargetZ - camZ, distance) * 180 / math.pi
local animLib, animName = "", ""
if isCharPlayingAnim(PLAYER_PED, "FALL_FALL") or isCharPlayingAnim(PLAYER_PED, "IDLE_STANCE") then
animLib = ""
animName = ""
else
animLib = ""
animName = ""
end
local clone = {
x = x,
y = y,
z = z,
angle = angle,
headAngleX = headAngleX,
headAngleZ = headAngleZ,
skinId = skinId,
animLib = animLib,
animName = animName,
actorHandle = nil
}
table.insert(clones, clone)
createCloneActor(#clones)
saveConfig()
sampAddChatMessage(string.format("[Clone] {FFFFFF}Клон #%d создан! Координаты: %.2f, %.2f, %.2f", #clones, x, y, z), 0x00FF00)
end
function cmd_clearclones()
for i, clone in ipairs(clones) do
if clone.actorHandle and doesCharExist(clone.actorHandle) then
deleteChar(clone.actorHandle)
end
end
clones = {}
edit_mode = {}
saveConfig()
sampAddChatMessage("[Clone] {FFFFFF}Все клоны удалены!", 0x00FF00)
end
function createCloneActor(index)
local clone = clones[index]
if not clone then return end
if clone.actorHandle and doesCharExist(clone.actorHandle) then
deleteChar(clone.actorHandle)
end
if not hasModelLoaded(clone.skinId) then
requestModel(clone.skinId)
loadAllModelsNow()
end
clone.actorHandle = createChar(4, clone.skinId, clone.x, clone.y, clone.z)
setCharHeading(clone.actorHandle, clone.angle)
setCharCollision(clone.actorHandle, false)
freezeCharPosition(clone.actorHandle, true)
if clone.headAngleX and clone.headAngleZ then
lua_thread.create(function()
while doesCharExist(clone.actorHandle) do
wait(100)
local lookX = clone.x + math.cos(math.rad(clone.headAngleZ)) * 5
local lookY = clone.y + math.sin(math.rad(clone.headAngleZ)) * 5
local lookZ = clone.z + 1.0 + math.tan(math.rad(clone.headAngleX)) * 2
pcall(function()
taskLookAtCoord(clone.actorHandle, lookX, lookY, lookZ, -1)
end)
end
end)
end
if clone.animLib ~= "" and clone.animName ~= "" then
lua_thread.create(function()
wait(100)
if doesCharExist(clone.actorHandle) then
requestAnimation(clone.animLib)
loadAllModelsNow()
taskPlayAnim(clone.actorHandle, clone.animName, clone.animLib, 4.0, true, false, false, false, -1)
end
end)
end
end
function loadConfig()
local file = io.open(config_path, "r")
if file then
local content = file:read("*a")
file:close()
local success, result = pcall(decodeJson, content)
if success and result then
clones = result
for i = 1, #clones do
createCloneActor(i)
end
sampAddChatMessage(string.format("[Clone] {FFFFFF}Загружено клонов: %d", #clones), 0x00FF00)
end
end
end
function saveConfig()
local dir = getWorkingDirectory() .. "\\config"
if not doesDirectoryExist(dir) then
createDirectory(dir)
end
local file = io.open(config_path, "w")
if file then
local saveData = {}
for i, clone in ipairs(clones) do
table.insert(saveData, {
x = clone.x,
y = clone.y,
z = clone.z,
angle = clone.angle,
headAngleX = clone.headAngleX,
headAngleZ = clone.headAngleZ,
skinId = clone.skinId,
animLib = clone.animLib,
animName = clone.animName
})
end
file:write(encodeJson(saveData))
file:close()
end
end
local frame = imgui.OnFrame(
function() return main_window_state[0] end,
function(player)
imgui.SetNextWindowPos(imgui.ImVec2(500, 500), imgui.Cond.FirstUseEver, imgui.ImVec2(0.5, 0.5))
imgui.SetNextWindowSize(imgui.ImVec2(600, 500), imgui.Cond.FirstUseEver)
imgui.Begin(u8"Управление клонами", main_window_state, imgui.WindowFlags.NoResize)
imgui.Text(u8"Всего клонов: " .. #clones)
imgui.Separator()
if imgui.Button(u8"Создать клон на текущей позиции", imgui.ImVec2(250, 30)) then
cmd_addclone()
end
imgui.SameLine()
if imgui.Button(u8"Удалить все клоны", imgui.ImVec2(250, 30)) then
cmd_clearclones()
end
imgui.Separator()
imgui.Text(u8"Список клонов:")
imgui.BeginChild("##clones_list", imgui.ImVec2(580, 380), true)
for i, clone in ipairs(clones) do
local status = u8"Не создан"
if clone.actorHandle and doesCharExist(clone.actorHandle) then
status = u8"Активен"
end
imgui.Text(u8(string.format("Клон #%d", i, status)))
imgui.Text(u8(string.format(" Координаты: %.2f, %.2f, %.2f", clone.x, clone.y, clone.z)))
imgui.Text(u8(string.format(" Угол тела: %.2f | Скин ID: %d", clone.angle, clone.skinId)))
if clone.headAngleX and clone.headAngleZ then
imgui.Text(u8(string.format(" Угол головы: X=%.2f Z=%.2f", clone.headAngleX, clone.headAngleZ)))
end
if not edit_mode[i] then
edit_mode[i] = {
headAngleX = imgui.new.float(clone.headAngleX or 0),
headAngleZ = imgui.new.float(clone.headAngleZ or 0)
}
end
if imgui.SliderFloat(u8"Угол X (вверх/вниз)##" .. i, edit_mode[i].headAngleX, -90, 90) then
clone.headAngleX = edit_mode[i].headAngleX[0]
saveConfig()
end
if imgui.SliderFloat(u8"Угол Z (влево/вправо)##" .. i, edit_mode[i].headAngleZ, -180, 180) then
clone.headAngleZ = edit_mode[i].headAngleZ[0]
saveConfig()
end
if imgui.Button(u8"Пересоздать##" .. i, imgui.ImVec2(120, 25)) then
createCloneActor(i)
end
imgui.SameLine()
if imgui.Button(u8"Удалить##" .. i, imgui.ImVec2(120, 25)) then
if clone.actorHandle and doesCharExist(clone.actorHandle) then
deleteChar(clone.actorHandle)
end
table.remove(clones, i)
edit_mode[i] = nil
saveConfig()
end
imgui.Separator()
end
imgui.EndChild()
imgui.End()
end
)