public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
#if PATHRECALC
            VehicleState state           = VehicleStateManager._GetVehicleState(vehicleID);
            bool         recalcRequested = state.PathRecalculationRequested;
            state.PathRecalculationRequested = false;
#endif

            VehicleInfo info           = this.m_info;
            ushort      driverInstance = CustomPassengerCarAI.GetDriverInstance(vehicleID, ref vehicleData);
            if (driverInstance == 0)
            {
                return(false);
            }
            CitizenManager          instance    = Singleton <CitizenManager> .instance;
            CitizenInfo             info2       = instance.m_instances.m_buffer[(int)driverInstance].Info;
            NetInfo.LaneType        laneTypes   = NetInfo.LaneType.Vehicle | NetInfo.LaneType.Pedestrian;
            VehicleInfo.VehicleType vehicleType = this.m_info.m_vehicleType;
            bool   allowUnderground             = (vehicleData.m_flags & Vehicle.Flags.Underground) != 0;
            bool   randomParking  = false;
            ushort targetBuilding = instance.m_instances.m_buffer[(int)driverInstance].m_targetBuilding;
            if (targetBuilding != 0 && Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)targetBuilding].Info.m_class.m_service > ItemClass.Service.Office)
            {
                randomParking = true;
            }
            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float             num;
            float             num2;
            PathUnit.Position endPosA;
            if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out num, out num2) &&
                info2.m_citizenAI.FindPathPosition(driverInstance, ref instance.m_instances.m_buffer[(int)driverInstance], endPos, laneTypes, vehicleType, undergroundTarget, out endPosA))
            {
                if (!startBothWays || num < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                PathUnit.Position endPosB   = default(PathUnit.Position);
                SimulationManager instance2 = Singleton <SimulationManager> .instance;
                uint path;
                PathUnit.Position def = default(PathUnit.Position);
                if (Singleton <CustomPathManager> .instance.CreatePath(
#if PATHRECALC
                        recalcRequested
#else
                        false
#endif
                        , ExtVehicleType.PassengerCar, out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, ref startPosA, ref startPosB, ref endPosA, ref endPosB, ref def, laneTypes, vehicleType, 20000f, false, false, false, false, randomParking))
                {
                    if (vehicleData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);
                    }
                    vehicleData.m_path   = path;
                    vehicleData.m_flags |= Vehicle.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
        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));
        }
Exemple #3
0
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
            VehicleInfo info           = this.m_info;
            ushort      driverInstance = CustomPassengerCarAI.GetDriverInstance(vehicleID, ref vehicleData);

            if (driverInstance == 0)
            {
                return(false);
            }
            CitizenManager instance = Singleton <CitizenManager> .instance;
            CitizenInfo    info2    = instance.m_instances.m_buffer[(int)driverInstance].Info;

            NetInfo.LaneType        laneTypes   = NetInfo.LaneType.Vehicle | NetInfo.LaneType.Pedestrian;
            VehicleInfo.VehicleType vehicleType = this.m_info.m_vehicleType;
            bool allowUnderground = (vehicleData.m_flags & Vehicle.Flags.Underground) != Vehicle.Flags.None;

            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float             num;
            float             num2;

            PathUnit.Position endPosA;
            if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out num, out num2) &&
                info2.m_citizenAI.FindPathPosition(driverInstance, ref instance.m_instances.m_buffer[(int)driverInstance], endPos, laneTypes, vehicleType, undergroundTarget, out endPosA))
            {
                if (!startBothWays || num < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                PathUnit.Position endPosB   = default(PathUnit.Position);
                SimulationManager instance2 = Singleton <SimulationManager> .instance;
                uint path;
                if (Singleton <CustomPathManager> .instance.CreatePath(ExtVehicleType.PassengerCar, out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, laneTypes, vehicleType, 20000f))
                {
                    if (vehicleData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);
                    }
                    vehicleData.m_path   = path;
                    vehicleData.m_flags |= Vehicle.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
Exemple #4
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
        }
Exemple #5
0
        /// <summary>
        /// Tries to spawn a parked passenger car for the given citizen <paramref name="citizenId"/> at a building in the vicinity of the given position <paramref name="refPos"/>
        /// </summary>
        /// <param name="citizenId">Citizen that requires a parked car</param>
        /// <param name="homeId">Home building id of the citizen (For residential buildings, parked cars may only spawn at the home building)</param>
        /// <param name="refPos">Reference position</param>
        /// <param name="vehicleInfo">Vehicle type to spawn</param>
        /// <param name="parkPos">Parked vehicle position (output)</param>
        /// <returns>true if a passenger car could be spawned, false otherwise</returns>
        protected static bool TrySpawnParkedPassengerCarBuilding(uint citizenId, ushort homeId, Vector3 refPos, VehicleInfo vehicleInfo, out Vector3 parkPos)
        {
#if DEBUG
            if (GlobalConfig.Instance.DebugSwitches[4] && homeId != 0)
            {
                Log._Debug($"Trying to spawn parked passenger car next to building for citizen {citizenId} @ {refPos}");
            }
#endif
            parkPos = Vector3.zero;
            Quaternion parkRot = Quaternion.identity;
            float      parkOffset;

            if (CustomPassengerCarAI.FindParkingSpaceBuilding(vehicleInfo, homeId, 0, 0, refPos, GlobalConfig.Instance.VicinityParkingSpaceSearchRadius, GlobalConfig.Instance.VicinityParkingSpaceSearchRadius, out parkPos, out parkRot, out parkOffset))
            {
                // position found, spawn a parked vehicle
                ushort parkedVehicleId;
                if (Singleton <VehicleManager> .instance.CreateParkedVehicle(out parkedVehicleId, ref Singleton <SimulationManager> .instance.m_randomizer, vehicleInfo, parkPos, parkRot, citizenId))
                {
                    Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenId].SetParkedVehicle(citizenId, parkedVehicleId);
                    Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_flags &= (ushort)(VehicleParked.Flags.All & ~VehicleParked.Flags.Parking);
#if DEBUG
                    if (GlobalConfig.Instance.DebugSwitches[4] && homeId != 0)
                    {
                        Log._Debug($"[SUCCESS] Spawned parked passenger car next to building for citizen {citizenId}: {parkedVehicleId}");
                    }
#endif
                    return(true);
                }
            }
#if DEBUG
            if (GlobalConfig.Instance.DebugSwitches[2] && homeId != 0)
            {
                Log._Debug($"[FAIL] Failed to spawn parked passenger car next to building for citizen {citizenId}");
            }
#endif
            return(false);
        }
        /// <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
            }
        }
        /// <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
        }
Exemple #9
0
        /// <summary>
        /// Finds a free parking space in the vicinity of the given target position <paramref name="endPos"/> for the given citizen instance <paramref name="extDriverInstance"/>.
        /// </summary>
        /// <param name="endPos">target position</param>
        /// <param name="vehicleInfo">vehicle type that is being used</param>
        /// <param name="extDriverInstance">cititzen instance that is driving the car</param>
        /// <param name="homeId">Home building of the citizen (may be 0 for tourists/homeless cims)</param>
        /// <param name="vehicleId">Vehicle that is being used (used for logging)</param>
        /// <param name="allowTourists">If true, method fails if given citizen is a tourist (TODO remove this parameter)</param>
        /// <param name="parkPos">parking position (output)</param>
        /// <param name="endPathPos">sidewalk path position near parking space (output). only valid if <paramref name="calculateEndPos"/> yields false.</param>
        /// <param name="calculateEndPos">if false, a parking space path position could be calculated (TODO negate & rename parameter)</param>
        /// <returns>true if a parking space could be found, false otherwise</returns>
        public static bool FindParkingSpaceForExtInstance(Vector3 endPos, VehicleInfo vehicleInfo, ExtCitizenInstance extDriverInstance, ushort homeId, ushort vehicleId, bool allowTourists, out Vector3 parkPos, ref PathUnit.Position endPathPos, out bool calculateEndPos)
        {
            calculateEndPos = true;
            parkPos         = default(Vector3);

            if (!allowTourists)
            {
                // TODO remove this from this method
                uint citizenId = extDriverInstance.GetCitizenId();
                if (citizenId == 0 ||
                    (Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenId].m_flags & Citizen.Flags.Tourist) != Citizen.Flags.None)
                {
                    return(false);
                }
            }

#if DEBUG
            if (GlobalConfig.Instance.DebugSwitches[4])
            {
                Log._Debug($"Citizen instance {extDriverInstance.InstanceId} (CurrentPathMode={extDriverInstance.PathMode}) can still use their passenger car and is either not a tourist or wants to find an alternative parking spot. Finding a parking space before starting path-finding.");
            }
#endif

            ExtParkingSpaceLocation knownParkingSpaceLocation;
            ushort     knownParkingSpaceLocationId;
            Quaternion parkRot;
            float      parkOffset;

            // find a free parking space
            bool success = CustomPassengerCarAI.FindParkingSpaceInVicinity(endPos, vehicleInfo, homeId, vehicleId, out knownParkingSpaceLocation, out knownParkingSpaceLocationId, out parkPos, out parkRot, out parkOffset);

            extDriverInstance.ParkingSpaceLocation   = knownParkingSpaceLocation;
            extDriverInstance.ParkingSpaceLocationId = knownParkingSpaceLocationId;

            if (success)
            {
#if DEBUG
                if (GlobalConfig.Instance.DebugSwitches[4])
                {
                    Log._Debug($"Found a parking spot for citizen instance {extDriverInstance.InstanceId} (CurrentPathMode={extDriverInstance.PathMode}) before starting car path: {knownParkingSpaceLocation} @ {knownParkingSpaceLocationId}");
                }
#endif

                if (knownParkingSpaceLocation == ExtParkingSpaceLocation.RoadSide)
                {
                    // found segment with parking space
                    Vector3 pedPos;
                    uint    laneId;
                    int     laneIndex;
                    float   laneOffset;

#if DEBUG
                    if (GlobalConfig.Instance.DebugSwitches[2])
                    {
                        Log._Debug($"Found segment {knownParkingSpaceLocationId} for road-side parking position for citizen instance {extDriverInstance.InstanceId}!");
                    }
#endif

                    // determine nearest sidewalk position for parking position at segment
                    if (Singleton <NetManager> .instance.m_segments.m_buffer[knownParkingSpaceLocationId].GetClosestLanePosition(parkPos, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, out pedPos, out laneId, out laneIndex, out laneOffset))
                    {
                        endPathPos.m_segment = knownParkingSpaceLocationId;
                        endPathPos.m_lane    = (byte)laneIndex;
                        endPathPos.m_offset  = (byte)(parkOffset * 255f);
                        calculateEndPos      = false;

                        //extDriverInstance.CurrentPathMode = successMode;// ExtCitizenInstance.PathMode.CalculatingKnownCarPath;
#if DEBUG
                        if (GlobalConfig.Instance.DebugSwitches[2])
                        {
                            Log._Debug($"Found an parking spot sidewalk position for citizen instance {extDriverInstance.InstanceId} @ segment {knownParkingSpaceLocationId}, laneId {laneId}, laneIndex {laneIndex}, offset={endPathPos.m_offset}! CurrentPathMode={extDriverInstance.PathMode}");
                        }
#endif
                        return(true);
                    }
                    else
                    {
#if DEBUG
                        if (GlobalConfig.Instance.DebugSwitches[2])
                        {
                            Log._Debug($"Could not find an alternative parking spot sidewalk position for citizen instance {extDriverInstance.InstanceId}! CurrentPathMode={extDriverInstance.PathMode}");
                        }
#endif
                        return(false);
                    }
                }
                else if (knownParkingSpaceLocation == ExtParkingSpaceLocation.Building)
                {
                    // found a building with parking space
                    if (CustomPathManager.FindPathPositionWithSpiralLoop(parkPos, endPos, ItemClass.Service.Road, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, false, false, GlobalConfig.Instance.MaxBuildingToPedestrianLaneDistance, out endPathPos))
                    {
                        calculateEndPos = false;
                    }

                    //endPos = parkPos;

                    //extDriverInstance.CurrentPathMode = successMode;// ExtCitizenInstance.PathMode.CalculatingKnownCarPath;
#if DEBUG
                    if (GlobalConfig.Instance.DebugSwitches[2])
                    {
                        Log._Debug($"Navigating citizen instance {extDriverInstance.InstanceId} to parking building {knownParkingSpaceLocationId}! segment={endPathPos.m_segment}, laneIndex={endPathPos.m_lane}, offset={endPathPos.m_offset}. CurrentPathMode={extDriverInstance.PathMode} calculateEndPos={calculateEndPos}");
                    }
#endif
                    return(true);
                }
            }
            return(false);
        }