189 lines
5.7 KiB
Lua
189 lines
5.7 KiB
Lua
function aiGetClosestNode(x,y,z,path)
|
|
local cDist = nil
|
|
local cNode = nil
|
|
local cNodeID = nil
|
|
|
|
for i,node in ipairs(path) do
|
|
local dist = getDistanceBetweenPoints3D(x,y,z,node.x,node.y,node.z)
|
|
if cDist == nil then
|
|
cDist = dist
|
|
cNodeID = i
|
|
cNode = node
|
|
end
|
|
|
|
if dist < cDist then
|
|
cDist = dist
|
|
cNodeID = i
|
|
cNode = node
|
|
end
|
|
end
|
|
|
|
return cNodeID,cNode
|
|
end
|
|
|
|
function aiGetNextNode(path,nodeID,minDist)
|
|
minDist = minDist or 0
|
|
local prevX = path[nodeID].x
|
|
local prevY = path[nodeID].y
|
|
local prevZ = path[nodeID].z
|
|
local dist = 0
|
|
nodeID = nodeID + 1
|
|
local length = #path
|
|
while nodeID <= length do
|
|
local x = path[nodeID].x
|
|
local y = path[nodeID].y
|
|
local z = path[nodeID].z
|
|
dist = dist + getDistanceBetweenPoints3D(x,y,z,prevX,prevY,prevZ)
|
|
if dist >= minDist then
|
|
return nodeID,path[nodeID]
|
|
end
|
|
prevX = x
|
|
prevY = y
|
|
prevZ = z
|
|
nodeID = nodeID + 1
|
|
end
|
|
|
|
nodeID = length
|
|
return nodeID,path[nodeID]
|
|
end
|
|
|
|
function handleGpsAi(driver)
|
|
local gx = getElementData(driver,"gps-ai.x")
|
|
local gy = getElementData(driver,"gps-ai.y")
|
|
local gz = getElementData(driver,"gps-ai.z")
|
|
local veh = getPedOccupiedVehicle(driver)
|
|
local x,y,z = getElementPosition(veh)
|
|
local rx,ry,rz = getElementRotation(veh)
|
|
local speed = getElementSpeed(veh)
|
|
|
|
if not getElementData(driver,"gps-ai.path") then
|
|
local path = calculatePathByCoords(x,y,z,gx,gy,gz)
|
|
if not path then return end
|
|
setElementData(driver,"gps-ai.path",path,false)
|
|
end
|
|
|
|
local path = getElementData(driver,"gps-ai.path")
|
|
local closestNodeID,closestNode = aiGetClosestNode(x,y,z,path)
|
|
local checkNodeOneID,checkNodeOne = aiGetNextNode(path,closestNodeID,20 + ((speed * 0.15) * (speed * 0.01)))
|
|
local checkNodeTwoID,checkNodeTwo = aiGetNextNode(path,closestNodeID,20 + ((speed * 0.8) * (speed * 0.008)))
|
|
|
|
--[[ hit = processLineOfSight(x,y,z,checkNodeOne.x,checkNodeOne.y,checkNodeOne.z + 0.5,true,false,false,true,false,false,false,false,nil,false,false)
|
|
if hit then
|
|
checkNodeOneID,checkNodeOne = aiGetNextNode(path,closestNodeID)
|
|
end ]]--
|
|
|
|
local reqzOne = findRotation(x,y,checkNodeOne.x,checkNodeOne.y)
|
|
local reqzTwo = findRotation(x,y,checkNodeTwo.x,checkNodeTwo.y)
|
|
|
|
reqzOneLocal = rz - reqzOne
|
|
if reqzOneLocal > 180 then reqzOneLocal = reqzOneLocal - 360 end
|
|
if reqzOneLocal < -180 then reqzOneLocal = reqzOneLocal + 360 end
|
|
|
|
reqzTwoLocal = rz - reqzTwo
|
|
if reqzTwoLocal > 180 then reqzTwoLocal = reqzTwoLocal - 360 end
|
|
if reqzTwoLocal < -180 then reqzTwoLocal = reqzTwoLocal + 360 end
|
|
|
|
local steeringAngleOne = reqzOneLocal
|
|
if steeringAngleOne < 0 then
|
|
steeringAngleOne = 0 - steeringAngleOne
|
|
end
|
|
steeringAmountOne = steeringAngleOne / 180
|
|
|
|
local steeringAngleTwo = reqzTwoLocal
|
|
if steeringAngleTwo < 0 then
|
|
steeringAngleTwo = 0 - steeringAngleTwo
|
|
end
|
|
steeringAmountTwo = steeringAngleTwo / 180
|
|
|
|
local brake = false
|
|
--[[ if steeringAngleOne > steeringAngleTwo then
|
|
regzTwo = regzOne
|
|
regzTwoLocal = regzOneLocal
|
|
steeringAngleTwo = steeringAngleOne
|
|
steeringAmountTwo = steeringAmountOne
|
|
brake = true
|
|
end ]]--
|
|
|
|
local maxSpeed = getElementData(driver,"gps-ai.maxSpeed")
|
|
if steeringAngleTwo > 10 then
|
|
local owo = steeringAmountTwo * 2.5
|
|
if owo > 1 then owo = 1 end
|
|
local nMaxSpeed = 15 + (130 * (1 - owo))
|
|
if nMaxSpeed < maxSpeed then maxSpeed = nMaxSpeed end
|
|
end
|
|
|
|
if brake then maxSpeed = maxSpeed * 0.5 end
|
|
|
|
if speed < maxSpeed then
|
|
setPedControlState(driver,"accelerate",true)
|
|
setPedAnalogControlState(driver,"brake_reverse",0)
|
|
else
|
|
setPedControlState(driver,"accelerate",false)
|
|
end
|
|
|
|
if speed > maxSpeed + 5 then
|
|
setPedAnalogControlState(driver,"brake_reverse",0.8)
|
|
end
|
|
|
|
local currentSteer = getPedAnalogControlState(driver,"vehicle_right") - getPedAnalogControlState(driver,"vehicle_left")
|
|
local steerSpeed = 0.2
|
|
|
|
if reqzOneLocal < 0 then
|
|
currentSteer = currentSteer - steerSpeed
|
|
end
|
|
|
|
if reqzOneLocal > 0 then
|
|
currentSteer = currentSteer + steerSpeed
|
|
end
|
|
steerLimit = steeringAngleOne / 10
|
|
|
|
if steerLimit < 0.4 then steerLimit = 0.4 end
|
|
if steerLimit > 1 then steerLimit = 1 end
|
|
if currentSteer > steerLimit then currentSteer = steerLimit end
|
|
if currentSteer < 0 - steerLimit then currentSteer = 0 - steerLimit end
|
|
|
|
if currentSteer > 0 then
|
|
setPedAnalogControlState(driver,"vehicle_left",0)
|
|
setPedAnalogControlState(driver,"vehicle_right",currentSteer)
|
|
end
|
|
|
|
if currentSteer < 0 then
|
|
setPedAnalogControlState(driver,"vehicle_right",0)
|
|
setPedAnalogControlState(driver,"vehicle_left",0 - currentSteer)
|
|
end
|
|
|
|
-- DEBUG --
|
|
local resx,resy = guiGetScreenSize()
|
|
dxDrawLine3D(x,y,z,checkNodeOne.x,checkNodeOne.y,checkNodeOne.z + 1,tocolor(255,0,0,128),10)
|
|
dxDrawLine3D(x,y,z,checkNodeTwo.x,checkNodeTwo.y,checkNodeTwo.z + 1,tocolor(255,255,0,128),10)
|
|
|
|
local debugText = ""
|
|
debugText = debugText .. "Required Z 1: " ..reqzOne
|
|
debugText = debugText .. "\nRequired Z 2: " ..reqzTwo
|
|
debugText = debugText .. "\n"
|
|
debugText = debugText .. "\nRequired Z 1 - LOCAL: " ..reqzOneLocal
|
|
debugText = debugText .. "\nMax speed: " ..maxSpeed.. " (" ..steeringAmountTwo.. ")"
|
|
local px,py,pz = getElementPosition(driver)
|
|
local dbx,dby,dbz = getScreenFromWorldPosition(px,py,pz + 1)
|
|
dxDrawText(debugText,dbx + 1,dby + 1,dbx + 1,dby + 1,tocolor(0,0,0),1,"default-bold","center","center",false,true,true)
|
|
dxDrawText(debugText,dbx,dby,dbx,dby,tocolor(255,255,0),1,"default-bold","center","center",false,true,true)
|
|
end
|
|
|
|
function handleGpsAiFrame()
|
|
for _,ped in ipairs(getElementsByType("ped")) do
|
|
if getElementData(ped,"gps-ai.x") then
|
|
handleGpsAi(ped)
|
|
end
|
|
end
|
|
end
|
|
|
|
addEventHandler("onClientRender",root,handleGpsAiFrame)
|
|
|
|
function getElementSpeed(theElement)
|
|
return (Vector3(getElementVelocity(theElement)) * 180).length
|
|
end
|
|
|
|
function findRotation( x1, y1, x2, y2 )
|
|
local t = -math.deg( math.atan2( x2 - x1, y2 - y1 ) )
|
|
return t < 0 and t + 360 or t
|
|
end |