private void BaseSimulationStep(ushort vehicleId, ref Vehicle data, Vector3 physicsLodRefPos) { if ((data.m_flags & Vehicle.Flags.WaitingPath) != Vehicle.Flags.None) { PathManager instance = Singleton <PathManager> .instance; byte pathFindFlags = instance.m_pathUnits.m_buffer[(int)((UIntPtr)data.m_path)].m_pathFindFlags; if ((pathFindFlags & 4) != 0) { data.m_pathPositionIndex = 255; data.m_flags &= ~Vehicle.Flags.WaitingPath; data.m_flags &= ~Vehicle.Flags.Arriving; PathfindSuccess(vehicleId, ref data); TrySpawn(vehicleId, ref data); } else if ((pathFindFlags & 8) != 0) { data.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(data.m_path); data.m_path = 0u; PathfindFailure(vehicleId, ref data); return; } } else if ((data.m_flags & Vehicle.Flags.WaitingSpace) != Vehicle.Flags.None) { TrySpawn(vehicleId, ref data); } Vector3 lastFramePosition = data.GetLastFramePosition(); int lodPhysics; if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1210000f) { lodPhysics = 2; } else if ( Vector3.SqrMagnitude(Singleton <SimulationManager> .instance.m_simulationView.m_position - lastFramePosition) >= 250000f) { lodPhysics = 1; } else { lodPhysics = 0; } SimulationStep(vehicleId, ref data, vehicleId, ref data, lodPhysics); if (data.m_leadingVehicle == 0 && data.m_trailingVehicle != 0) { VehicleManager instance2 = Singleton <VehicleManager> .instance; ushort num = data.m_trailingVehicle; int num2 = 0; while (num != 0) { ushort trailingVehicle = instance2.m_vehicles.m_buffer[num].m_trailingVehicle; VehicleInfo info = instance2.m_vehicles.m_buffer[num].Info; info.m_vehicleAI.SimulationStep(num, ref instance2.m_vehicles.m_buffer[num], vehicleId, ref data, lodPhysics); num = trailingVehicle; if (++num2 > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } int maxBlockCounter = (m_info.m_class.m_service > ItemClass.Service.Office) ? 150 : 100; if ((data.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace)) == Vehicle.Flags.None && data.m_cargoParent == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if (data.m_blockCounter >= maxBlockCounter && Options.enableDespawning) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if (data.m_leadingVehicle == 0 && CustomVehicleAI.ShouldRecalculatePath(vehicleId, ref data, maxBlockCounter)) { CustomVehicleAI.MarkPathRecalculation(vehicleId); InvalidPath(vehicleId, ref data, vehicleId, ref data); } }
/// <summary> /// Lightweight simulation step method. /// This method is occasionally being called for different cars. /// </summary> /// <param name="vehicleId"></param> /// <param name="vehicleData"></param> /// <param name="physicsLodRefPos"></param> public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { PathManager pathMan = Singleton <PathManager> .instance; #if DEBUG /*if (!Options.disableSomething1) { * Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}) called. flags: {vehicleData.m_flags} pfFlags: {pathMan.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags}"); * }*/ #endif if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) { PathManager pathManager = Singleton <PathManager> .instance; byte pathFindFlags = pathManager.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags; #if USEPATHWAITCOUNTER if ((pathFindFlags & (PathUnit.FLAG_READY | PathUnit.FLAG_FAILED)) != 0) { VehicleState state = VehicleStateManager.Instance()._GetVehicleState(vehicleId); state.PathWaitCounter = 0; // NON-STOCK CODE } #endif if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { vehicleData.m_pathPositionIndex = 255; vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; vehicleData.m_flags &= ~Vehicle.Flags.Arriving; this.PathfindSuccess(vehicleId, ref vehicleData); this.TrySpawn(vehicleId, ref vehicleData); } else if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0) // path == 0: non-stock code! { vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } #if USEPATHWAITCOUNTER else { VehicleState state = VehicleStateManager.Instance()._GetVehicleState(vehicleId); state.PathWaitCounter = (ushort)Math.Min(ushort.MaxValue, (int)state.PathWaitCounter + 1); // NON-STOCK CODE } #endif } else { if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { this.TrySpawn(vehicleId, ref vehicleData); } } /// NON-STOCK CODE START /// VehicleStateManager vehStateManager = VehicleStateManager.Instance(); if (Options.prioritySignsEnabled || Options.timedLightsEnabled) { try { vehStateManager.UpdateVehiclePos(vehicleId, ref vehicleData); } catch (Exception e) { Log.Error("CarAI CustomSimulationStep Error: " + e.ToString()); } } if (!Options.isStockLaneChangerUsed()) { try { vehStateManager.LogTraffic(vehicleId, ref vehicleData, true); } catch (Exception e) { Log.Error("CarAI CustomSimulationStep Error: " + e.ToString()); } } /// NON-STOCK CODE END /// Vector3 lastFramePosition = vehicleData.GetLastFramePosition(); int lodPhysics; if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1210000f) { lodPhysics = 2; } else if (Vector3.SqrMagnitude(Singleton <SimulationManager> .instance.m_simulationView.m_position - lastFramePosition) >= 250000f) { lodPhysics = 1; } else { lodPhysics = 0; } this.SimulationStep(vehicleId, ref vehicleData, vehicleId, ref vehicleData, lodPhysics); if (vehicleData.m_leadingVehicle == 0 && vehicleData.m_trailingVehicle != 0) { VehicleManager instance2 = Singleton <VehicleManager> .instance; ushort num = vehicleData.m_trailingVehicle; int num2 = 0; while (num != 0) { ushort trailingVehicle = instance2.m_vehicles.m_buffer[(int)num].m_trailingVehicle; VehicleInfo info = instance2.m_vehicles.m_buffer[(int)num].Info; info.m_vehicleAI.SimulationStep(num, ref instance2.m_vehicles.m_buffer[(int)num], vehicleId, ref vehicleData, lodPhysics); num = trailingVehicle; if (++num2 > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } #if PATHRECALC ushort recalcSegmentId = 0; #endif int privateServiceIndex = ItemClass.GetPrivateServiceIndex(this.m_info.m_class.m_service); int maxBlockCounter = (privateServiceIndex == -1) ? 150 : 100; if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace)) == 0 && vehicleData.m_cargoParent == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if ((int)vehicleData.m_blockCounter >= maxBlockCounter && Options.enableDespawning) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } #if PATHRECALC else if (vehicleData.m_leadingVehicle == 0 && CustomVehicleAI.ShouldRecalculatePath(vehicleId, ref vehicleData, maxBlockCounter, out recalcSegmentId)) { CustomVehicleAI.MarkPathRecalculation(vehicleId, recalcSegmentId); InvalidPath(vehicleId, ref vehicleData, vehicleId, ref vehicleData); } #endif }
/// <summary> /// Lightweight simulation step method. /// This method is occasionally being called for different cars. /// </summary> /// <param name="vehicleId"></param> /// <param name="vehicleData"></param> /// <param name="physicsLodRefPos"></param> public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { #if USEPATHWAITCOUNTER VehicleState state = VehicleStateManager._GetVehicleState(vehicleId); #endif if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) { PathManager instance = Singleton <PathManager> .instance; byte pathFindFlags = instance.m_pathUnits.m_buffer[(int)((UIntPtr)vehicleData.m_path)].m_pathFindFlags; if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { #if USEPATHWAITCOUNTER state.PathWaitCounter = 0; // NON-STOCK CODE #endif vehicleData.m_pathPositionIndex = 255; vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; vehicleData.m_flags &= ~Vehicle.Flags.Arriving; this.PathfindSuccess(vehicleId, ref vehicleData); this.TrySpawn(vehicleId, ref vehicleData); VehicleStateManager.OnPathFindReady(vehicleId, ref vehicleData); // NON-STOCK CODE } else if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0 #if USEPATHWAITCOUNTER || ((pathFindFlags & PathUnit.FLAG_CREATED) != 0 && state.PathWaitCounter == ushort.MaxValue) #endif ) // NON-STOCK CODE { #if USEPATHWAITCOUNTER state.PathWaitCounter = 0; // NON-STOCK CODE #endif vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } #if USEPATHWAITCOUNTER else { state.PathWaitCounter = (ushort)Math.Min(ushort.MaxValue, (int)state.PathWaitCounter + 1); // NON-STOCK CODE } #endif } else { #if USEPATHWAITCOUNTER state.PathWaitCounter = 0; // NON-STOCK CODE #endif if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { this.TrySpawn(vehicleId, ref vehicleData); } } try { VehicleStateManager.LogTraffic(vehicleId, ref vehicleData, true); } catch (Exception e) { Log.Error("CarAI CustomSimulationStep Error: " + e.ToString()); } try { VehicleStateManager.UpdateVehiclePos(vehicleId, ref vehicleData); } catch (Exception e) { Log.Error("CarAI CustomSimulationStep Error: " + e.ToString()); } Vector3 lastFramePosition = vehicleData.GetLastFramePosition(); int lodPhysics; if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1210000f) { lodPhysics = 2; } else if (Vector3.SqrMagnitude(Singleton <SimulationManager> .instance.m_simulationView.m_position - lastFramePosition) >= 250000f) { lodPhysics = 1; } else { lodPhysics = 0; } this.SimulationStep(vehicleId, ref vehicleData, vehicleId, ref vehicleData, lodPhysics); if (vehicleData.m_leadingVehicle == 0 && vehicleData.m_trailingVehicle != 0) { VehicleManager instance2 = Singleton <VehicleManager> .instance; ushort num = vehicleData.m_trailingVehicle; int num2 = 0; while (num != 0) { ushort trailingVehicle = instance2.m_vehicles.m_buffer[(int)num].m_trailingVehicle; VehicleInfo info = instance2.m_vehicles.m_buffer[(int)num].Info; info.m_vehicleAI.SimulationStep(num, ref instance2.m_vehicles.m_buffer[(int)num], vehicleId, ref vehicleData, lodPhysics); num = trailingVehicle; if (++num2 > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } #if PATHRECALC ushort recalcSegmentId = 0; #endif int privateServiceIndex = ItemClass.GetPrivateServiceIndex(this.m_info.m_class.m_service); int maxBlockCounter = (privateServiceIndex == -1) ? 150 : 100; if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace)) == 0 && vehicleData.m_cargoParent == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if ((int)vehicleData.m_blockCounter == maxBlockCounter && Options.enableDespawning) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } #if PATHRECALC else if (vehicleData.m_leadingVehicle == 0 && CustomVehicleAI.ShouldRecalculatePath(vehicleId, ref vehicleData, maxBlockCounter, out recalcSegmentId)) { CustomVehicleAI.MarkPathRecalculation(vehicleId, recalcSegmentId); InvalidPath(vehicleId, ref vehicleData, vehicleId, ref vehicleData); } #endif }
/// <summary> /// Lightweight simulation step method. /// This method is occasionally being called for different cars. /// </summary> /// <param name="vehicleId"></param> /// <param name="vehicleData"></param> /// <param name="physicsLodRefPos"></param> public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { PathManager pathMan = Singleton <PathManager> .instance; #if DEBUG /*if (!GlobalConfig.Instance.DebugSwitches[0]) { * Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}) called. flags: {vehicleData.m_flags} pfFlags: {pathMan.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags}"); * }*/ #endif // NON-STOCK CODE START VehicleState state = null; ExtCitizenInstance driverExtInstance = null; bool prohibitPocketCars = Options.prohibitPocketCars; if (prohibitPocketCars) { // check for valid driver and update return path state state = VehicleStateManager.Instance._GetVehicleState(vehicleData.GetFirstVehicle(vehicleId)); if (state.VehicleType == ExtVehicleType.PassengerCar) { driverExtInstance = state.GetDriverExtInstance(); if (driverExtInstance == null) { prohibitPocketCars = false; } else { driverExtInstance.UpdateReturnPathState(); } } else { prohibitPocketCars = false; } } // NON-STOCK CODE END if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0 && (!prohibitPocketCars || driverExtInstance.ReturnPathState != ExtCitizenInstance.ExtPathState.Calculating)) // NON-STOCK CODE: Parking AI: wait for the return path to be calculated { PathManager pathManager = Singleton <PathManager> .instance; byte pathFindFlags = pathManager.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags; bool pathFindFailed = (pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0; // path == 0: non-stock code! bool pathFindSucceeded = (pathFindFlags & PathUnit.FLAG_READY) != 0; #if USEPATHWAITCOUNTER if ((pathFindFlags & (PathUnit.FLAG_READY | PathUnit.FLAG_FAILED)) != 0) { VehicleState state = VehicleStateManager.Instance._GetVehicleState(vehicleId); state.PathWaitCounter = 0; // NON-STOCK CODE } #endif if (prohibitPocketCars) { if (driverExtInstance.ReturnPathState == ExtPathState.Failed) { // no walking path from parking position to target found. flag main path as 'failed'. #if DEBUG if (GlobalConfig.Instance.DebugSwitches[2]) { Log._Debug($"CustomCarAI.CustomSimulationStep: Return path {driverExtInstance.ReturnPathId} FAILED. Forcing path-finding to fail."); } #endif pathFindSucceeded = false; pathFindFailed = true; } driverExtInstance.ReleaseReturnPath(); if (pathFindSucceeded) { CustomPassengerCarAI.OnPathFindSuccess(vehicleId, ref vehicleData, driverExtInstance); } else if (pathFindFailed) { CustomPassengerCarAI.OnPathFindFailure(driverExtInstance, vehicleId); } } if (pathFindSucceeded) { vehicleData.m_pathPositionIndex = 255; vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; vehicleData.m_flags &= ~Vehicle.Flags.Arriving; this.PathfindSuccess(vehicleId, ref vehicleData); this.TrySpawn(vehicleId, ref vehicleData); } else if (pathFindFailed) { vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } #if USEPATHWAITCOUNTER else { VehicleState state = VehicleStateManager.Instance._GetVehicleState(vehicleId); state.PathWaitCounter = (ushort)Math.Min(ushort.MaxValue, (int)state.PathWaitCounter + 1); // NON-STOCK CODE } #endif } else { if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { this.TrySpawn(vehicleId, ref vehicleData); } } /// NON-STOCK CODE START /// VehicleStateManager vehStateManager = VehicleStateManager.Instance; if (Options.prioritySignsEnabled || Options.timedLightsEnabled) { // update vehicle position for timed traffic lights and priority signs try { vehStateManager.UpdateVehiclePos(vehicleId, ref vehicleData); } catch (Exception e) { Log.Error("CarAI CustomSimulationStep Error: " + e.ToString()); } } if (!Options.isStockLaneChangerUsed()) { // Advanced AI traffic measurement try { vehStateManager.LogTraffic(vehicleId, ref vehicleData, true); } catch (Exception e) { Log.Error("CarAI CustomSimulationStep Error: " + e.ToString()); } } /// NON-STOCK CODE END /// Vector3 lastFramePosition = vehicleData.GetLastFramePosition(); int lodPhysics; if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1210000f) { lodPhysics = 2; } else if (Vector3.SqrMagnitude(Singleton <SimulationManager> .instance.m_simulationView.m_position - lastFramePosition) >= 250000f) { lodPhysics = 1; } else { lodPhysics = 0; } this.SimulationStep(vehicleId, ref vehicleData, vehicleId, ref vehicleData, lodPhysics); if (vehicleData.m_leadingVehicle == 0 && vehicleData.m_trailingVehicle != 0) { VehicleManager vehManager = Singleton <VehicleManager> .instance; ushort num = vehicleData.m_trailingVehicle; int num2 = 0; while (num != 0) { ushort trailingVehicle = vehManager.m_vehicles.m_buffer[(int)num].m_trailingVehicle; VehicleInfo info = vehManager.m_vehicles.m_buffer[(int)num].Info; info.m_vehicleAI.SimulationStep(num, ref vehManager.m_vehicles.m_buffer[(int)num], vehicleId, ref vehicleData, lodPhysics); num = trailingVehicle; if (++num2 > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } #if PATHRECALC ushort recalcSegmentId = 0; #endif int privateServiceIndex = ItemClass.GetPrivateServiceIndex(this.m_info.m_class.m_service); int maxBlockCounter = (privateServiceIndex == -1) ? 150 : 100; if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace)) == 0 && vehicleData.m_cargoParent == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if ((int)vehicleData.m_blockCounter >= maxBlockCounter && Options.enableDespawning) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } #if PATHRECALC else if (vehicleData.m_leadingVehicle == 0 && CustomVehicleAI.ShouldRecalculatePath(vehicleId, ref vehicleData, maxBlockCounter, out recalcSegmentId)) { CustomVehicleAI.MarkPathRecalculation(vehicleId, recalcSegmentId); InvalidPath(vehicleId, ref vehicleData, vehicleId, ref vehicleData); } #endif }
/// <summary> /// Lightweight simulation step method. /// This method is occasionally being called for different cars. /// </summary> /// <param name="vehicleId"></param> /// <param name="vehicleData"></param> /// <param name="physicsLodRefPos"></param> public void TrafficManagerSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != Vehicle.Flags.None) { PathManager instance = Singleton <PathManager> .instance; byte pathFindFlags = instance.m_pathUnits.m_buffer[(int)((UIntPtr)vehicleData.m_path)].m_pathFindFlags; if ((pathFindFlags & 4) != 0) { vehicleData.m_pathPositionIndex = 255; vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; vehicleData.m_flags &= ~Vehicle.Flags.Arriving; this.PathfindSuccess(vehicleId, ref vehicleData); this.TrySpawn(vehicleId, ref vehicleData); } else if ((pathFindFlags & 8) != 0) { vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } } else if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != Vehicle.Flags.None) { this.TrySpawn(vehicleId, ref vehicleData); } try { CustomVehicleAI.HandleVehicle(vehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleId], true, true); } catch (Exception e) { Log.Error("CarAI TrafficManagerSimulationStep Error: " + e.ToString()); } Vector3 lastFramePosition = vehicleData.GetLastFramePosition(); int lodPhysics; if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1210000f) { lodPhysics = 2; } else if (Vector3.SqrMagnitude(Singleton <SimulationManager> .instance.m_simulationView.m_position - lastFramePosition) >= 250000f) { lodPhysics = 1; } else { lodPhysics = 0; } this.SimulationStep(vehicleId, ref vehicleData, vehicleId, ref vehicleData, lodPhysics); if (vehicleData.m_leadingVehicle == 0 && vehicleData.m_trailingVehicle != 0) { VehicleManager instance2 = Singleton <VehicleManager> .instance; ushort num = vehicleData.m_trailingVehicle; int num2 = 0; while (num != 0) { ushort trailingVehicle = instance2.m_vehicles.m_buffer[(int)num].m_trailingVehicle; VehicleInfo info = instance2.m_vehicles.m_buffer[(int)num].Info; info.m_vehicleAI.SimulationStep(num, ref instance2.m_vehicles.m_buffer[(int)num], vehicleId, ref vehicleData, lodPhysics); num = trailingVehicle; if (++num2 > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } int privateServiceIndex = ItemClass.GetPrivateServiceIndex(this.m_info.m_class.m_service); int maxBlockCounter = (privateServiceIndex == -1) ? 150 : 100; if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace)) == Vehicle.Flags.None && vehicleData.m_cargoParent == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if ((int)vehicleData.m_blockCounter == maxBlockCounter && Options.enableDespawning) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if (vehicleData.m_leadingVehicle == 0 && CustomVehicleAI.ShouldRecalculatePath(vehicleId, ref vehicleData, maxBlockCounter)) { CustomVehicleAI.MarkPathRecalculation(vehicleId); InvalidPath(vehicleId, ref vehicleData, vehicleId, ref vehicleData); } }