I personally suspect it's either something with the lighting system or weather (maybe improved particles for stuff like rain too?)
I wonder if the devs decided to put extra emphasis on improving the optimization during this run to minimize potential FPS drops that come with the possible lighting system revamp.
I'd imagine they would put heavy emphesis on making sure this lighting update doesn't turn everyone's computers into instant air friers.
Code for a working taxi system. C:\Program Files (x86)\Steam\steamapps\common\BeamNG.drive\lua\ge\extensions\gameplay
Could someone please message me to help get it working? Code: -- This Source Code Form is subject to the terms of the bCDDL, v. 1.1. -- If a copy of the bCDDL was not distributed with this -- file, You can obtain one at http://beamng.com/bCDDL-1.1.txt local M = {} -- taxi management local taxiIdsList = {} local ignoreTaxiIdsList = {} local nearestTaxiId = nil local currentTaxiId = nil local maxDistanceToTaxi = 20 local destinationPos = nil -- to manage walking away from the taxi local maxDistToTaxiForAbandon = math.huge local wiggleRoom = 6 -- to manage pulling over at the destination local almostArrivedDist = 100 local pullOverDistToDestination = 30 local delayToOpenBigMap = 0.4 -- blinker system local maxPullOverSpeed = 2 --km/h local maxTaxiSpeed = 150 local blinkersDuration = 3 local blinkerStates = {} -- idle camera system local idleCameraDelay = 7 -- seconds local idleCameraActive = false local previousCameraName local disableIdleCamera = false local fadeToBlackDuration = 0.5 local distanceToTarget = 150 local skipPosition = nil local skipRotation = nil local accelerationTime = 1 -- seconds -- makes it easier to manage the different stages of a taxi ride local steps = { nothing = {id = 0, name = "Nothing"}, taxiCalled = {id = 1, name = "Taxi Called"}, chooseDestination = {id = 2, name = "Choose Destination"}, taxiDriving = {id = 3, name = "Taxi Driving"}, taxiPullingOver = {id = 4, name = "Taxi Pulling Over"}, } local currentStep = steps.nothing local function resetData() currentStep = steps.nothing disableIdleCamera = false end local function showMessage(message, clear) if clear == nil then clear = true end local helper = { ttl = 2, msg = message, category = "taxiNearby", clear = clear } guihooks.trigger('Message',helper) end local function activateSignal(veh, rightForRightHand) veh:queueLuaCommand('electrics.stop_turn_signal()') local isRightHand = map.getRoadRules().rightHandDrive local useRight = (isRightHand and rightForRightHand) or (not isRightHand and not rightForRightHand) veh:queueLuaCommand('electrics.toggle_' .. (useRight and 'left' or 'right') .. '_signal()') end local function activatePullOverBlinkers(veh) activateSignal(veh, true) end local function activateMergeBlinkers(veh) core_jobsystem.create(function(job) activateSignal(veh, false) job.sleep(blinkersDuration) veh:queueLuaCommand('electrics.stop_turn_signal()') end, 1) end local function getNearestRoadSpeedLimit(pos) if not pos then return nil end local closestNode1, closestNode2 = map.findClosestRoad(pos) if not (closestNode1 and closestNode2) then return nil end local nodes = map.getMap().nodes if not (nodes[closestNode1] and nodes[closestNode2]) then return nil end -- Get the connection/link between the two nodes local connection = nodes[closestNode1].links[closestNode2] or nodes[closestNode2].links[closestNode1] if not connection then return nil end -- Speed limit is in m/s, convert to km/h if needed return connection.speedLimit and (connection.speedLimit * 3.6) or nil end local function notifyBlinkerSysOfPullOver(vehId) blinkerStates[vehId] = "pullingOver" activatePullOverBlinkers(getObjectByID(vehId)) end local function setIdleCamera(value) if not core_camera then return end idleCameraActive = value if value then core_jobsystem.create(function(job) previousCameraName = core_camera.getActiveCamName() ui_fadeScreen.start(fadeToBlackDuration) job.sleep(fadeToBlackDuration+0.1) core_camera.setByName(0, "external") ui_fadeScreen.stop(fadeToBlackDuration) end, 1) else core_camera.setByName(0, previousCameraName) end end local function setCurrentStep(step) currentStep = step if currentStep == steps.taxiPullingOver then setIdleCamera(false) disableIdleCamera = true end end local function updateBlinkerSys() local taxisToDiscard = {} for vehId, state in pairs(blinkerStates) do local veh = getObjectByID(vehId) local taxiSpeed = veh:getVelocity():len() * 3.6 if state == "pullingOver" and taxiSpeed < maxPullOverSpeed then veh:queueLuaCommand('electrics.set_warn_signal(1)') if currentStep == steps.taxiPullingOver then showMessage("You can climb out of the taxi now", false) end blinkerStates[vehId] = "stopped" elseif state == "stopped" and taxiSpeed > maxPullOverSpeed then activateMergeBlinkers(veh) table.insert(taxisToDiscard, vehId) end end for _, vehId in ipairs(taxisToDiscard) do blinkerStates[vehId] = nil end end local function checkIdleCamera() if not core_camera then return end local timeSinceRotation = core_camera.timeSinceLastRotation() -- Check if camera has been idle for longer than our delay if timeSinceRotation / 1000 > idleCameraDelay then if not idleCameraActive and not disableIdleCamera then setIdleCamera(true) end else if idleCameraActive then setIdleCamera(false) end end end local function getAiPath(path, veh) local aiPath = {} if not veh then return nil end local firstWpAdded = false local vehPos = veh:getPosition() local vehFwd = veh:getDirectionVector() local bestDist = math.huge local prevDot = nil local prevWp = nil local startDist = path[1].distToTarget -- find the first valid waypoint for i, marker in ipairs(path) do if marker.wp then if (marker.distToTarget < distanceToTarget) and not skipPosition then skipPosition = marker.pos if path[i+1] and path[i+1].pos then local direction = (path[i+1].pos - marker.pos):normalized() skipRotation = quatFromDir(direction, vec3(0, 0, 1)) end end if not firstWpAdded then local toWp = (marker.pos - vehPos):normalized() local dot = toWp:dot(vehFwd) -- If we have a previous dot product and this one is lower, we found our local maximum if prevDot and dot < prevDot and prevDot > 0 then --log('I', 'quickaccess', 'Adding waypoint ' .. prevWp .. ' because it is the local maximum, dot: ' .. dot .. ', prevDot: ' .. prevDot .. ', startDist: ' .. startDist .. ', marker.distToTarget: ' .. marker.distToTarget) table.insert(aiPath, prevWp) firstWpAdded = true end prevDot = dot prevWp = marker.wp else table.insert(aiPath, marker.wp) end end end -- If we haven't found a local maximum but have a positive dot product, use the last one if not firstWpAdded and prevDot and prevDot > 0 then table.insert(aiPath, prevWp) firstWpAdded = true end -- fallback: if no waypoint is in front of vehicle, use the first waypoint that's 25m away and all other waypoints if not firstWpAdded then for _, marker in ipairs(path) do if marker.wp and startDist - marker.distToTarget > 25 then table.insert(aiPath, marker.wp) end end end return aiPath end local function getCurrentRoute(veh) local rp = core_groundMarkers.routePlanner if not rp or not rp.path or not rp.path[1] then return end local aiPath = getAiPath(rp.path, veh) destinationPos = rp.path[#rp.path].pos local str = '{wpTargetList = '..serialize(aiPath) str = str..', noOfLaps = 1, aggression = 0.3, avoidCars = "on", driveInLane = "on", speedMode = "limit"}' return str end local function startTaxiWithCurrentRoute(skipWait) if skipWait == nil then skipWait = false end core_jobsystem.create(function(job) freeroam_bigMapMode.exitBigMap(false, true, true) local plVeh = be:getPlayerVehicle(0) if not plVeh then return end local routeStr = getCurrentRoute(plVeh) if not routeStr then return end freeroam_bigMapMode.setNavFocus(nil) if not skipWait then job.sleep(2) end plVeh:queueLuaCommand('ai.driveUsingPath('..routeStr..')') setCurrentStep(steps.taxiDriving) end, 1) end local function isTaxi(vehId) local obj = scenetree.findObjectById(vehId) if not obj then return false end local configName = obj.partConfig or "" -- Check if "taxi" appears anywhere in the config name for now return string.find(string.lower(configName), "taxi") ~= nil end local function extractTaxiIds() for vehId, _ in pairs(map.objects) do if isTaxi(vehId) then taxiIdsList[vehId] = true end end end local function checkAndFindNearestTaxi() local playerPos = be:getPlayerVehicle(0):getPosition() local nearestDist = math.huge local found = false local missingVehIds = {} for vehId, _ in pairs(taxiIdsList) do if not ignoreTaxiIdsList[vehId] then if vehId ~= be:getPlayerVehicleID(0) then local veh = map.objects[vehId] if veh then local vehPos = veh.pos local dist = playerPos:distance(vehPos) if dist < nearestDist and dist < maxDistanceToTaxi and getNearestRoadSpeedLimit(vehPos) < maxTaxiSpeed then nearestDist = dist nearestTaxiId = vehId found = true end end else table.insert(missingVehIds, vehId) end end end if not found then nearestTaxiId = nil end for _, vehId in ipairs(missingVehIds) do taxiIdsList[vehId] = nil end end local function setPullOver(veh) notifyBlinkerSysOfPullOver(veh:getID()) veh:queueLuaCommand('ai.setPullOver(true)') end local function setTrafficMode(veh) veh:queueLuaCommand('ai.setPullOver(false)') veh:queueLuaCommand('ai.setState({mode = "traffic"})') end local function callAndStopTaxi() -- simply stop the AI for now if not nearestTaxiId then return end currentTaxiId = nearestTaxiId local veh = getObjectByID(currentTaxiId) if not veh then return end local trafficVeh = gameplay_traffic.getTrafficData()[currentTaxiId] if trafficVeh and trafficVeh.role then setPullOver(veh) end -- make the taxi climbable gameplay_walk.removeVehicleFromBlacklist(currentTaxiId) getObjectByID(currentTaxiId).playerUsable = true showMessage("Taxi heard you and is pulling over", false) setCurrentStep(steps.taxiCalled) end local function leaveTaxi(message) local veh = getObjectByID(currentTaxiId) if not veh then return end setTrafficMode(veh) ignoreTaxiIdsList[currentTaxiId] = true gameplay_walk.addVehicleToBlacklist(currentTaxiId) getObjectByID(currentTaxiId).playerUsable = false if message then showMessage(message, false) end setCurrentStep(steps.nothing) maxDistToTaxiForAbandon = math.huge currentTaxiId = nil end local function makeTaxiPullOverWhileDriving(message) if not currentTaxiId then return end local veh = getObjectByID(currentTaxiId) if not veh then return end local trafficVeh = gameplay_traffic.getTrafficData()[currentTaxiId] if trafficVeh and trafficVeh.role then setTrafficMode(veh) setPullOver(veh) setCurrentStep(steps.taxiPullingOver) if message then showMessage(message, false) end end end local function isTaxiDrivingWithPlayer() if not currentTaxiId then return false end local veh = getObjectByID(currentTaxiId) if not veh then return false end return veh:getVelocity():len() > 5 and currentStep == steps.taxiDriving end local function isTaxiAvailable() return currentStep == steps.nothing and gameplay_walk.isWalking() and nearestTaxiId end local function onUpdate(dtReal, dtSim, dtRaw) if not be:getPlayerVehicle(0) then return end extractTaxiIds() checkAndFindNearestTaxi() updateBlinkerSys() if isTaxiAvailable() then showMessage("There's a taxi in service. Press [action=gameplay_interact] to stop it", false) end if currentStep == steps.taxiCalled and gameplay_walk.isWalking() and getObjectByID(currentTaxiId):getVelocity():len() < 1 then local dist = be:getPlayerVehicle(0):getPosition():distance(map.objects[currentTaxiId].pos) local newMaxDistToTaxiForAbandon = dist + wiggleRoom if newMaxDistToTaxiForAbandon < maxDistToTaxiForAbandon then maxDistToTaxiForAbandon = newMaxDistToTaxiForAbandon end if dist > maxDistToTaxiForAbandon then leaveTaxi("Taxi has abandoned you and is driving away") end end if currentTaxiId and currentStep == steps.taxiDriving then checkIdleCamera() local distToDest = map.objects[currentTaxiId].pos:distance(destinationPos) if currentStep == steps.taxiDriving and distToDest < almostArrivedDist then showMessage("You have almost arrived at your destination", false) end if currentStep == steps.taxiDriving and distToDest < pullOverDistToDestination then makeTaxiPullOverWhileDriving("Taxi has arrived at your destination") end end if isTaxiDrivingWithPlayer() then showMessage("Press [action=gameplay_interact] to stop the taxi", false) end end local function onVehicleSwitched(oldId, newId) -- player entered the taxi if newId == currentTaxiId then core_jobsystem.create(function(job) job.sleep(delayToOpenBigMap) setCurrentStep(steps.chooseDestination) freeroam_bigMapMode.enterBigMap({mode = "taxi"}) end, 1) end -- player exited the taxi if oldId == currentTaxiId then leaveTaxi() end end local function onChangeDestinationCalled() if currentStep == steps.taxiDriving then setIdleCamera(false) freeroam_bigMapMode.enterBigMap({mode = "taxi"}) end end local function onHurryUpCalled() if currentStep == steps.taxiDriving then end end local function onSkipCalled() if currentStep == steps.taxiDriving then core_jobsystem.create(function(job) ui_fadeScreen.start(fadeToBlackDuration) job.sleep(fadeToBlackDuration + 0.1) setIdleCamera(false) job.sleep(0.1) disableIdleCamera = true freeroam_bigMapMode.setNavFocus(destinationPos) startTaxiWithCurrentRoute(true) spawn.safeTeleport(getObjectByID(currentTaxiId), skipPosition, skipRotation, true, nil, false) be:setPhysicsSpeedFactor(2) --so that the taxi gets up to speed faster job.sleep(accelerationTime) be:setPhysicsSpeedFactor(0) ui_fadeScreen.stop(fadeToBlackDuration) end, 1) end end local function onGameplayInteract() if isTaxiDrivingWithPlayer() then makeTaxiPullOverWhileDriving("Taxi is pulling over ...") elseif isTaxiAvailable() then callAndStopTaxi() end end local function onTrafficVehicleRespawned(id) ignoreTaxiIdsList[id] = nil end M.startTaxiWithCurrentRoute = startTaxiWithCurrentRoute M.onChangeDestinationCalled = onChangeDestinationCalled M.onHurryUpCalled = onHurryUpCalled M.onSkipCalled = onSkipCalled M.onTrafficVehicleRespawned = onTrafficVehicleRespawned M.onVehicleSwitched = onVehicleSwitched M.onGameplayInteract = onGameplayInteract M.onUpdate = onUpdate return M
Add this line M.callAndStopTaxi = callAndStopTaxi under M.startTaxiWithCurrentRoute = startTaxiWithCurrentRoute save the file, press ctrl+L. Spawn traffic make sure a taxi spawns, get near a taxi and put this into the console extensions.gameplay_taxi.callAndStopTaxi() once you get in and you set a route put this into the console extensions.gameplay_taxi.startTaxiWithCurrentRoute()
Times up, no teaser for today. This def going to be big Update, something taking this long to tease can only mean a whole rework on something (like when they changed from cry engine to torque3d, but oriented to skybox and all about weather update), taking enough time to have the whole team working. Also think about a new day-night cycle, they might be working on lights to show up at night on the main maps as WCU. It will worth the wait. I guess. It always do.
The sudden radio silence from the devs is working on me. These dudes are marketing geniuses, I'm convinced. They put so much anticipation and hype in my bones. Very Steve Jobs-esque. Bravo.