Как сделать отрисовку 3D модели персонажа с сохранением корд и тд.

d3sync

Активный
Автор темы
114
66
Как сделать скрипт?
Условно я становлюсь в определенное место, прописываю команду и на этом месте создается моя моделька с сохранением координат, направления взгляда, стойки.

Чтобы я через время смог встать ровно в это же место и это же положение персонажа?
Буду очень благодарен за помощь
 
Решение
Lua:
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 -...

undefineders

Участник
44
23
Lua:
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
)
 

Вложения

  • 1778162730542.png
    1778162730542.png
    1.4 MB · Просмотры: 25