findSpawnPoint
Definition
-- @/lua/ge/extensions/gameplay/traffic/trafficUtils.lua:462
local function findSpawnPointOnRoute(startPos, startDir, minDist, maxDist, targetDist, options) -- returns a spawn point, from a route that starts at the origin
-- all args are optional, will use camera transform by default
options = options or {}
startPos, startDir, minDist, maxDist, targetDist = getDefaultValues(startPos, startDir, minDist, maxDist, targetDist)
local spawnData = {pos = vec3(), dir = vec3()}
local valid = false
local mapNodes = map.getMap().nodes
local currDist = minDist
options.gap = options.gap or 20
options.usePrivateRoads = options.usePrivateRoads and true or false
options.minDrivability = options.minDrivability or M.defaults.drivability
options.minRadius = options.minRadius or M.defaults.halfWidth
options.pathRandomization = options.pathRandomization or 0.5
if M.debugMode then
log('I', logTag, string.format('Spawn search params: minDist = %d, maxDist = %d, targetDist = %d', minDist, maxDist, targetDist))
end
route:clear()
route.dirMult = 1
--[[
---- ROUTE SEARCH ----
A path will be generated along the road ahead, and points between the minimum distance and maximum distance will be tested and validated.
]]--
local n1, n2 = map.findClosestRoad(startPos)
if n1 then
p1:set(mapNodes[n1].pos)
p2:set(mapNodes[n2].pos)
tempDir:setSub2(p2, p1)
if tempDir:dot(startDir) < 0 then -- if true, swap the nodes
n1, n2 = n2, n1
p1:set(mapNodes[n1].pos)
p2:set(mapNodes[n2].pos)
end
if options.route then
-- perhaps this should exist outside of the initial if statement?
route:setupPathMultiWaypoints(options.route)
else
-- spawn point is along path in direction set by startDir, with possible branching
local path = map.getGraphpath():getRandomPathG(n1, startDir, maxDist, options.pathRandomization, 1, false)
--route:setupPathMultiWaypoints(path)
for _, wp in ipairs(path) do
table.insert(route.path, {pos = map.getMap().nodes[wp].pos, wp = wp, linkCount = map.getNodeLinkCount(wp)}) -- optimized route path creation
end
route:calcDistance()
end
if M.debugMode then
if route.path[1] then
log('I', logTag, string.format('Spawn search route length: %0.2f', route.path[1].distToTarget))
else
log('W', logTag, 'Failed to generate valid route')
end
end
local firstDist = minDist
if route.path[1] and route.path[2] then
local xnorm = clamp(startPos:xnormOnLine(route.path[1].pos, route.path[2].pos), 0, 1)
firstDist = firstDist + (route.path[1].distToTarget - route.path[2].distToTarget) * xnorm
end
local road = route:stepAhead(firstDist, true) or {} -- if nil, uses previous values as safety
n1 = road.n1 or n1
n2 = road.n2 or n2
spawnData.pos:set(road.pos or firstPos)
spawnData.dir:set((mapNodes[n2].pos - mapNodes[n1].pos):normalized())
else
return spawnData, valid
end
repeat
if checkRoad(n1, n2, options) then
p1:set(mapNodes[n1].pos)
p2:set(mapNodes[n2].pos)
if currDist >= targetDist or checkRayCast(spawnData.pos, startPos) then
if checkSpawnPoint(spawnData.pos, nil, minDist) then
spawnData.n1, spawnData.n2 = n1, n2
valid = true
if M.debugMode then
log('I', logTag, string.format('Spawn point found at distance: %d', math.floor(spawnData.pos:distance(startPos))))
end
end
end
end
if not valid then
local gap = options.gap
if options.safeGap then -- uses speed limit to determine gap
local link = mapNodes[n1].links[n2] or mapNodes[n2].links[n1]
if link and link.speedLimit then
gap = clamp(link.speedLimit * 1.08, 20, 50)
end
end
local road = route:stepAhead(gap) or {}
if road then
n1 = road.n1 or n1
n2 = road.n2 or n2
spawnData.pos:set(road.pos)
spawnData.dir:set((mapNodes[n2].pos - mapNodes[n1].pos):normalized())
end
end
currDist = currDist + options.gap
until (valid or currDist > maxDist)
if not valid and M.debugMode then
log('W', logTag, 'Failed to validate spawn point (route method)')
end
return spawnData, valid
end
Callers