-- PROTOTYPE: throwaway, lives only on branch prototype/vehicle-probe. -- Every INTERVAL it logs every player-owned road vehicle (segment, lane, position, speed). -- All experiments (timeToIgnore, jump, set-line, segment rebuild, GUI position flip) are in git history and -- docs/research/vehicle-probe.md; none moved a vehicle past another on a single-lane road. -- ponytail: module-local timer, not GameScriptState; fine for a probe (state resets between calls anyway). local TAG = "[overtake_probe] " local INTERVAL = 2.0 local elapsed = 0.0 local ticks = 0 local function p(s : string) print(TAG .. s) end local function edgeAt(mp : Engine.Component.MovePath) : EdgeId, boolean -- path.edges is 1-based, elements are EdgeIdDir userdata (tealdef says {EdgeId, boolean}) local e = (mp.path.edges as {any})[mp.dyn.pathPos.edgeIndex + 1] as UtilPathfinding.EdgeIdDir if e == nil then return nil, nil end return e.edgeId, e.dir end local function turnaround(edge : EdgeId) : integer local tn = api.engine.getComponent(edge.entity, api.type.ComponentType.TRANSPORT_NETWORK) as Engine.Component.TransportNetwork if tn == nil or tn.turnaroundEdges == nil then return nil end return tn.turnaroundEdges[edge.index + 1] end -- short street template name of a segment, so passing-lane use on the prototype road can be told apart local function roadOf(seg : integer) : string local be = api.engine.getComponent(seg, api.type.ComponentType.BASE_EDGE) as Engine.Component.BaseEdge if be == nil then return "?" end return (tostring(be.roadTemplate):match("([^/]+)%.street_template$")) or tostring(be.roadTemplate) end -- lane connections at both nodes of a segment, to check whether crossing-tool edits exist where vehicles enter local function nodeLog(seg : integer) local be = api.engine.getComponent(seg, api.type.ComponentType.BASE_EDGE) as Engine.Component.BaseEdge if be == nil then return end for _, node in ipairs({ be.node0, be.node1 }) do local cfg = api.engine.getComponent(node, api.type.ComponentType.BASE_NODE_CONFIG) as Engine.Component.BaseNodeConfig if cfg == nil then p(string.format("NODE seg=%d node=%d no BaseNodeConfig (default connections)", seg, node)) else local conns : {string} = {} for _, lc in ipairs(cfg.laneConnections) do if lc.segment0 == seg or lc.segment1 == seg then table.insert(conns, string.format("%d:%d->%d:%d", lc.segment0, lc.lane0, lc.segment1, lc.lane1)) end end p(string.format("NODE seg=%d node=%d userModified=%s conns=%s", seg, node, tostring(cfg.userModifiedLaneConnections), table.concat(conns, " "))) end end end local function dump(dt : number) local player = api.engine.util.getPlayer() local vehicles = api.engine.getEntitiesWithComponent(api.type.ComponentType.TRANSPORT_VEHICLE, { requireOwnedByPlayer = player }) p(string.format("tick=%d dt=%s playerVehicles=%d", ticks, tostring(dt), #vehicles)) local protoSegs : {integer : boolean} = {} for _, v in ipairs(vehicles) do local lv = api.engine.getComponent(v, api.type.ComponentType.LAND_VEHICLE) as Engine.Component.LandVehicle local mp = api.engine.getComponent(v, api.type.ComponentType.MOVE_PATH) as Engine.Component.MovePath local tv = api.engine.getComponent(v, api.type.ComponentType.TRANSPORT_VEHICLE) as Engine.Component.TransportVehicle if lv ~= nil and not lv.isTram and mp ~= nil then local edge, dir = edgeAt(mp) p(string.format( "veh=%d road=%s seg=%d lane=%s dir=%s turnaround=%s edgeIndex=%d/%d pos=%.1f speed=%.2f state=%s tvState=%s line=%s standing=%.1f", v, edge and roadOf(edge.entity) or "-", edge and edge.entity or -1, tostring(edge and edge.index), tostring(dir), tostring(edge and turnaround(edge)), mp.dyn.pathPos.edgeIndex, #(mp.path.edges as {any}), mp.dyn.pathPos.pos, mp.dyn.speed, tostring(mp.state), tostring(tv and tv.state), tostring(tv and tv.line), mp.dyn.timeStanding)) if edge ~= nil and roadOf(edge.entity) == "overtake_proto_b" then protoSegs[edge.entity] = true end end end for seg, _ in pairs(protoSegs) do nodeLog(seg) end end local ret : GameScript