public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
            ushort driverInstanceId = CustomPassengerCarAI.GetDriverInstanceId(vehicleID, ref vehicleData);

            if (driverInstanceId == 0)
            {
                return(false);
            }

            return(ExtStartPathFind(vehicleID, ref vehicleData, driverInstanceId, ref ExtCitizenInstanceManager.Instance.ExtInstances[driverInstanceId], startPos, endPos, startBothWays, endBothWays, undergroundTarget));
        }
Ejemplo n.º 2
0
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
            ushort driverInstanceId = CustomPassengerCarAI.GetDriverInstanceId(vehicleID, ref vehicleData);

            if (driverInstanceId == 0)
            {
                return(false);
            }

#if BENCHMARK
            using (var bm = new Benchmark(null, "ExtStartPathFind")) {
#endif
            return(ExtStartPathFind(vehicleID, ref vehicleData, driverInstanceId, ref ExtCitizenInstanceManager.Instance.ExtInstances[driverInstanceId], startPos, endPos, startBothWays, endBothWays, undergroundTarget));

#if BENCHMARK
        }
#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 ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0)
            {
                PathManager pathManager   = Singleton <PathManager> .instance;
                byte        pathFindFlags = pathManager.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags;

                // NON-STOCK CODE START
                ExtPathState mainPathState = ExtPathState.Calculating;
                if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0)
                {
                    mainPathState = ExtPathState.Failed;
                }
                else if ((pathFindFlags & PathUnit.FLAG_READY) != 0)
                {
                    mainPathState = ExtPathState.Ready;
                }

#if BENCHMARK
                using (var bm = new Benchmark(null, "UpdateCarPathState")) {
#endif
                if (Options.prohibitPocketCars && VehicleStateManager.Instance.VehicleStates[vehicleId].vehicleType == ExtVehicleType.PassengerCar)
                {
                    mainPathState = AdvancedParkingManager.Instance.UpdateCarPathState(vehicleId, ref vehicleData, ref ExtCitizenInstanceManager.Instance.ExtInstances[CustomPassengerCarAI.GetDriverInstanceId(vehicleId, ref vehicleData)], mainPathState);
                }
#if BENCHMARK
            }
#endif
                // NON-STOCK CODE END

                if (mainPathState == ExtPathState.Ready)
                {
                    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 (mainPathState == ExtPathState.Failed)
                {
                    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) != 0)
                {
                    this.TrySpawn(vehicleId, ref vehicleData);
                }
            }

            // NON-STOCK CODE START
#if BENCHMARK
            using (var bm = new Benchmark(null, "UpdateVehiclePosition")) {
#endif
            VehicleStateManager.Instance.UpdateVehiclePosition(vehicleId, ref vehicleData);
#if BENCHMARK
        }
#endif
            if (!Options.isStockLaneChangerUsed())
            {
#if BENCHMARK
                using (var bm = new Benchmark(null, "LogTraffic")) {
#endif
                // Advanced AI traffic measurement
                VehicleStateManager.Instance.LogTraffic(vehicleId);
#if BENCHMARK
            }
#endif
            }
            // 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         trailerId  = vehicleData.m_trailingVehicle;
                int            numIters   = 0;
                while (trailerId != 0)
                {
                    ushort      trailingVehicle = vehManager.m_vehicles.m_buffer[(int)trailerId].m_trailingVehicle;
                    VehicleInfo info            = vehManager.m_vehicles.m_buffer[(int)trailerId].Info;
                    info.m_vehicleAI.SimulationStep(trailerId, ref vehManager.m_vehicles.m_buffer[(int)trailerId], vehicleId, ref vehicleData, lodPhysics);
                    trailerId = trailingVehicle;
                    if (++numIters > 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)) == 0 && vehicleData.m_cargoParent == 0)
            {
                Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);
            }
            else if ((int)vehicleData.m_blockCounter >= maxBlockCounter)
            {
                // NON-STOCK CODE START
                bool mayDespawn = true;
#if BENCHMARK
                using (var bm = new Benchmark(null, "MayDespawn")) {
#endif
                mayDespawn = VehicleBehaviorManager.Instance.MayDespawn(ref vehicleData);
#if BENCHMARK
            }
#endif

                if (mayDespawn)
                {
                    // NON-STOCK CODE END
                    Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);
                }                 // NON-STOCK CODE
            }
        }
        /// <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 DEBUG
            bool vehDebug  = (GlobalConfig.Instance.Debug.VehicleId == 0 || GlobalConfig.Instance.Debug.VehicleId == vehicleId);
            bool debug     = GlobalConfig.Instance.Debug.Switches[2] && vehDebug;
            bool fineDebug = GlobalConfig.Instance.Debug.Switches[4] && vehDebug;
#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;

                // NON-STOCK CODE START
                ExtPathState mainPathState = ExtPathState.Calculating;
                if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0)
                {
                    mainPathState = ExtPathState.Failed;
                }
                else if ((pathFindFlags & PathUnit.FLAG_READY) != 0)
                {
                    mainPathState = ExtPathState.Ready;
                }

#if DEBUG
                if (debug)
                {
                    Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): Path: {vehicleData.m_path}, mainPathState={mainPathState}");
                }
#endif
                ExtSoftPathState finalPathState = ExtSoftPathState.None;
#if BENCHMARK
                using (var bm = new Benchmark(null, "UpdateCarPathState")) {
#endif
                finalPathState = ExtCitizenInstance.ConvertPathStateToSoftPathState(mainPathState);
                if (Options.prohibitPocketCars && VehicleStateManager.Instance.VehicleStates[vehicleId].vehicleType == ExtVehicleType.PassengerCar)
                {
                    ushort driverInstanceId = CustomPassengerCarAI.GetDriverInstanceId(vehicleId, ref vehicleData);
                    finalPathState = AdvancedParkingManager.Instance.UpdateCarPathState(vehicleId, ref vehicleData, ref Singleton <CitizenManager> .instance.m_instances.m_buffer[driverInstanceId], ref ExtCitizenInstanceManager.Instance.ExtInstances[driverInstanceId], mainPathState);

#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): Applied Parking AI logic. Path: {vehicleData.m_path}, mainPathState={mainPathState}, finalPathState={finalPathState}");
                    }
#endif
                }
#if BENCHMARK
            }
#endif

                switch (finalPathState)
                {
                case ExtSoftPathState.Ready:
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): Path-finding succeeded for vehicle {vehicleId} (finalPathState={finalPathState}). Path: {vehicleData.m_path} -- calling CarAI.PathfindSuccess");
                    }
#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);
                    break;

                case ExtSoftPathState.Ignore:
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): Path-finding result shall be ignored for vehicle {vehicleId} (finalPathState={finalPathState}). Path: {vehicleData.m_path} -- ignoring");
                    }
#endif
                    return;

                case ExtSoftPathState.Calculating:
                default:
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): Path-finding result undetermined for vehicle {vehicleId} (finalPathState={finalPathState}). Path: {vehicleData.m_path} -- continue");
                    }
#endif
                    break;

                case ExtSoftPathState.FailedHard:
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): HARD path-finding failure for vehicle {vehicleId} (finalPathState={finalPathState}). Path: {vehicleData.m_path} -- calling CarAI.PathfindFailure");
                    }
#endif
                    vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath;
                    Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);

                    vehicleData.m_path = 0u;
                    this.PathfindFailure(vehicleId, ref vehicleData);
                    return;

                case ExtSoftPathState.FailedSoft:
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): SOFT path-finding failure for vehicle {vehicleId} (finalPathState={finalPathState}). Path: {vehicleData.m_path} -- calling CarAI.InvalidPath");
                    }
#endif
                    // path mode has been updated, repeat path-finding
                    vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath;
                    this.InvalidPath(vehicleId, ref vehicleData, vehicleId, ref vehicleData);
                    break;
                }
                // NON-STOCK CODE END
            }
            else
            {
                if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0)
                {
                    this.TrySpawn(vehicleId, ref vehicleData);
                }
            }

            // NON-STOCK CODE START
#if BENCHMARK
            using (var bm = new Benchmark(null, "UpdateVehiclePosition")) {
#endif
            VehicleStateManager.Instance.UpdateVehiclePosition(vehicleId, ref vehicleData);
#if BENCHMARK
        }
#endif
            if (!Options.isStockLaneChangerUsed() && (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0)
            {
#if BENCHMARK
                using (var bm = new Benchmark(null, "LogTraffic")) {
#endif
                // Advanced AI traffic measurement
                VehicleStateManager.Instance.LogTraffic(vehicleId);
#if BENCHMARK
            }
#endif
            }
            // 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         trailerId  = vehicleData.m_trailingVehicle;
                int            numIters   = 0;
                while (trailerId != 0)
                {
                    ushort      trailingVehicle = vehManager.m_vehicles.m_buffer[(int)trailerId].m_trailingVehicle;
                    VehicleInfo info            = vehManager.m_vehicles.m_buffer[(int)trailerId].Info;
                    info.m_vehicleAI.SimulationStep(trailerId, ref vehManager.m_vehicles.m_buffer[(int)trailerId], vehicleId, ref vehicleData, lodPhysics);
                    trailerId = trailingVehicle;
                    if (++numIters > 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)) == 0 && vehicleData.m_cargoParent == 0)
            {
                Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);
            }
            else if ((int)vehicleData.m_blockCounter >= maxBlockCounter)
            {
                // NON-STOCK CODE START
                bool mayDespawn = true;
#if BENCHMARK
                using (var bm = new Benchmark(null, "MayDespawn")) {
#endif
                mayDespawn = VehicleBehaviorManager.Instance.MayDespawn(ref vehicleData);
#if BENCHMARK
            }
#endif

                if (mayDespawn)
                {
                    // NON-STOCK CODE END
                    Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);
                }                 // NON-STOCK CODE
            }
        }