Обойти машину

Okak_Pon

Активный
Автор темы
370
75
Версия MoonLoader
Другое
Как обойти машину которая перед игроком ?
Ну типо сбоку (метод убрать коллизию не подойдёт)
 
  • Грустно
Реакции: qdIbp

uqowivad

Известный
33
44
я уверен что можно как то проще, но чота так поебать
код рабочий
не смотрел на самолётах
часть дописала иишка, что получилось удачно

Lua:
-- ега педик

require 'lib.moonloader'

local KEY_B = 0x42
local MAX_DIST = 8.0    -- радиус поиска (м)
local MARGIN_SIDE = 1.0    -- запас сбоку (м)
local MARGIN_FRONT = 1.5    -- запас вперёд (м)
local GROUND_OFFSET = 0.1   -- подъём над землёй (м)
local RUN_MODE = 7      -- 7
local TIMEOUT = -1    

function main()
    while not isSampAvailable() do wait(0) end
    sampAddChatMessage('loaded', -1)

    while true do
        wait(0)
        if isKeyJustPressed(KEY_B) and not isCharInAnyCar(PLAYER_PED) then
            bypassSide()
        end
    end
end

-- ищет ближайшую машину
local function getNearestVehicle(ped)
    local px, py, pz = getCharCoordinates(ped)
    local bestCar, bestD = 0, MAX_DIST

    local vehicles = getAllVehicles()
    if not vehicles or #vehicles == 0 then return 0 end

    for _, car in ipairs(vehicles) do
        if doesVehicleExist(car) then
            local cx, cy, cz = getCarCoordinates(car)
            local d = getDistanceBetweenCoords3d(px, py, pz, cx, cy, cz)
            if d < bestD then bestCar, bestD = car, d end
        end
    end
    return bestCar
end

-- фикс Z (fallback)
local function fixZ(x, y, refZ, ped)
    local z = getGroundZFor3dCoord(x, y, refZ + 2.0) + GROUND_OFFSET
    if z == 0 or z == -10000 then z = select(3, getCharCoordinates(ped)) + GROUND_OFFSET end
    return z
end

-- бег к точке
local function runToPoint(ped, x, y, z, mode, timeout)
    local px, py, pz = getCharCoordinates(ped)

    local dx, dy = x - px, y - py
    local heading = math.deg(math.atan2(dy, dx)) - 90
    setCharHeading(ped, heading)

    local groundZ = getGroundZFor3dCoord(x, y, z + 2.0) + GROUND_OFFSET
    if groundZ ~= 0 and groundZ ~= -10000 then z = groundZ end

    clearCharTasks(ped)
    taskGoStraightToCoord(ped, x, y, z, mode, timeout)

    local prevDist = getDistanceBetweenCoords3d(px, py, pz or 0, x, y, z)  -- fallback на 0 если pz nil
    local stallCount = 0  -- счётчик застоя
    while true do
        wait(0)
        local cx, cy, cz = getCharCoordinates(ped)
        local currDist = getDistanceBetweenCoords3d(cx, cy, cz or 0, x, y, z)

        if currDist < 0.5 or isCharStopped(ped) then break end

        if currDist >= prevDist then
            stallCount = stallCount + 1
            if stallCount >= 3 then  -- количество раз, через сколько будет пропущена точка
                sampAddChatMessage('пропускаем', -1)
                break
            end
            heading = heading + 5  -- поворот
            setCharHeading(ped, heading)
        else
            stallCount = 0
        end
        prevDist = currDist
    end
end

function bypassSide()
    local ped = PLAYER_PED
    local vehicle = getNearestVehicle(ped)

    if vehicle == 0 or not doesVehicleExist(vehicle) then
        sampAddChatMessage('машина не найдёна', -1)
        return
    end

    -- получаем размер и модель машины
    local model = getCarModel(vehicle)
    local minX, minY, minZ, maxX, maxY, maxZ = getModelDimensions(model)
    local sizeX = math.abs(maxX - minX)
    local sizeY = math.abs(maxY - minY)

    if sizeX == 0 or sizeY == 0 then
        sizeX, sizeY = 4.0, 5.0
        sampAddChatMessage('fallback.', -1)
    else
        sampAddChatMessage('новые размеры: ширина ' .. sizeX .. ', длина ' .. sizeY, -1)
    end

    -- для не стандартных машин
    local sideScale = sizeY > 6 and 0.15 or 0.2  -- меньше боковой для больших
    local frontScale = sizeY > 6 and 0.4 or 0.3  -- больше вперёд для больших
    if sizeY > 6 then sampAddChatMessage('найден не стандарт кар', -1) end

    local sideOffset = (sizeX / 2) + MARGIN_SIDE + (sizeX * sideScale)
    local frontOffset = (sizeY / 2) + MARGIN_FRONT + (sizeY * frontScale)

    -- получаем координаты
    local cx, cy, cz = getCarCoordinates(vehicle)
    local fx, fy = getCarForwardX(vehicle), getCarForwardY(vehicle)
    local sx, sy = -fy, fx  -- влево | вправо: fy, -fx

    local tx1 = cx + sx * sideOffset
    local ty1 = cy + sy * sideOffset
    local tz1 = fixZ(tx1, ty1, cz, ped)

    local tx2 = tx1 + fx * (frontOffset / 2)
    local ty2 = ty1 + fy * (frontOffset / 2)
    local tz2 = fixZ(tx2, ty2, cz, ped)

    local tx3 = cx + fx * (sizeY / 2 + 1.0)
    local ty3 = cy + fy * (sizeY / 2 + 1.0)
    local tz3 = fixZ(tx3, ty3, cz, ped)

    local tx4 = tx3 + fx * (frontOffset / 2)
    local ty4 = ty3 + fy * (frontOffset / 2)
    local tz4 = fixZ(tx4, ty4, cz, ped)

    -- ваши комментарии с отладкой 
    -- sampAddChatMessage('Точка 1: X=' .. tx1 .. ', Y=' .. ty1 .. ', Z=' .. tz1, -1)
    -- sampAddChatMessage('Точка 2: X=' .. tx2 .. ', Y=' .. ty2 .. ', Z=' .. tz2, -1)
    -- sampAddChatMessage('Точка 3 : X=' .. tx3 .. ', Y=' .. ty3 .. ', Z=' .. tz3, -1)
    -- sampAddChatMessage('Точка 4: X=' .. tx4 .. ', Y=' .. ty4 .. ', Z=' .. tz4, -1)

    -- бегаем
    lua_thread.create(function()
        if not doesVehicleExist(vehicle) then return end
        runToPoint(ped, tx1, ty1, tz1, RUN_MODE, TIMEOUT)  -- к точке 1
        if not doesVehicleExist(vehicle) then return end
        runToPoint(ped, tx2, ty2, tz2, RUN_MODE, TIMEOUT)  -- к точке 2
        if not doesVehicleExist(vehicle) then return end
        runToPoint(ped, tx3, ty3, tz3, RUN_MODE, TIMEOUT)  -- к точке 3
        if not doesVehicleExist(vehicle) then return end
        runToPoint(ped, tx4, ty4, tz4, RUN_MODE, TIMEOUT)  -- к точке 4
        clearCharTasks(ped)
        sampAddChatMessage('закончил', -1)
    end)
end