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);
            }
        }
示例#2
0
        /// <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
        }
示例#3
0
        /// <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);
            }
        }