-- ега педик
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