teleportToLastRoadCallback
Definition
-- @/lua/ge/spawn.lua:636
local function teleportToLastRoadCallback(data, options)
local mapData = map.getMap()
local legalSide = map.getRoadRules().rightHandDrive and -1 or 1
local veh = getPlayerVehicle(0)
local pos, rot
if tableIsEmpty(mapData.nodes) then
pos = veh:getPosition()
rot = quatFromDir(veh:getDirectionVector(), veh:getDirectionVectorUp())
end
if not pos and data then
-- Find the last recovery position on a road and teleport to that road
for i = data.tail, data.head, -1 do
local recoveryPoint = data[i]
if not recoveryPoint then break end
local n1Id, n2Id, dist = map.findClosestRoad(recoveryPoint.pos)
if n1Id then
local n1 = mapData.nodes[n1Id]
local n2 = mapData.nodes[n2Id]
if dist <= (n1.radius+n2.radius)/2 then
-- Found a recovery point on a road
local oneWay = mapData.nodes[n1Id].links[n2Id].oneWay
local segmentDir = (n2.pos - n1.pos)
local drivingDir = segmentDir
if options.destinationPos then
-- if there is a destinationPos then always put the vehicle in that direction regardless of other rules
local routePlanner = require('gameplay/route/route')()
routePlanner:setupPath(n1.pos, options.destinationPos)
if routePlanner.path and routePlanner.path[2] then
if drivingDir:dot(routePlanner.path[2].pos - n1.pos) < 0 then
drivingDir = -drivingDir
end
end
oneWay = true
-- if the road is oneWay, flip the drivingDir if it is incorrect
elseif oneWay and (mapData.nodes[n1Id].links[n2Id].inNode ~= n1Id) then
drivingDir = -drivingDir
end
local perpendicular = drivingDir:cross(n1.normal)
-- In a oneWay road, always put the vehicle on the legal driving side, otherwise check which side is closer
local roadSide
if oneWay then
roadSide = legalSide
else
-- if there are groundmarkers active then choose the side in the direction of the route
if core_groundMarkers.currentlyHasTarget() then
core_groundMarkers.routePlanner:trackPosition(recoveryPoint.pos)
if core_groundMarkers.routePlanner.path[2] then
local routeDir = core_groundMarkers.routePlanner.path[2].pos - getPlayerVehicle(0):getPosition()
roadSide = drivingDir:dot(routeDir) > 0 and legalSide or -legalSide
end
end
if not roadSide then
roadSide = perpendicular:dot(recoveryPoint.pos - n1.pos) > 0 and 1 or -1
end
end
-- Project the recovery point on the road segment
local segLenSq = segmentDir:length()^2
local scalarProjection = 0
if segLenSq > 0 then
scalarProjection = clamp(segmentDir:dot((recoveryPoint.pos - n1.pos)) / segLenSq, 0, 1)
end
local projectedPosition = n1.pos + segmentDir * scalarProjection
pos = projectedPosition + perpendicular:normalized() * roadSide * (lerp(n1.radius, n2.radius, scalarProjection) - veh.initialNodePosBB:getExtents().x/2)
-- Find the rotation that puts the vehicle correctly in the driving direction
rot = quatFromDir(drivingDir * legalSide * roadSide, n1.normal)
break
end
end
end
end
-- If none of the recovery points are on a road, try to find the closest road to the current position
-- TODO this puts the player in the middle of the road
if not pos then
local n1Id, n2Id, dist = map.findClosestRoad(veh:getPosition())
local n1 = mapData.nodes[n1Id]
local n2 = mapData.nodes[n2Id]
if dist < 50 then
pos = n1.pos
rot = quatFromDir(n1.pos - n2.pos, n1.normal)
end
end
if not pos then
pos = veh:getPosition()
rot = quatFromDir(veh:getDirectionVector(), veh:getDirectionVectorUp())
end
safeTeleport(veh, pos, rot, nil, nil, nil, true, options.resetVehicle)
end
Callers