public new bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, PathUnit.Position vehiclePosition, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, bool isHeavyVehicle, bool ignoreBlocked, bool stablePath, bool skipQueue, ItemClass.Service vehicleService)
        {
            while (!Monitor.TryEnter(this.m_bufferLock, SimulationManager.SYNCHRONIZE_TIMEOUT))
            {
            }
            uint num;
            try
            {
                if (!this.m_pathUnits.CreateItem(out num, ref randomizer))
                {
                    unit = 0u;
                    bool result = false;
                    return result;
                }
                this.m_pathUnitCount = (int)(this.m_pathUnits.ItemCount() - 1u);
            }
            finally
            {
                Monitor.Exit(this.m_bufferLock);
            }
            unit = num;

            byte simulationFlags = createSimulationFlag(isHeavyVehicle, ignoreBlocked, stablePath, vehicleService);
            assignPathProperties(unit, buildIndex, startPosA, startPosB, endPosA, endPosB, vehiclePosition, laneTypes, vehicleTypes, maxLength, simulationFlags);

            return findShortestPath(unit, skipQueue);
        }
示例#2
0
 public static bool FindPathPosition(Vector3 position, ItemClass.Service service, NetInfo.LaneType laneType, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, bool requireConnect, float maxDistance, out PathUnit.Position pathPos, RoadManager.VehicleType vehicleType)
 {
     PathUnit.Position position2;
     float num;
     float num2;
     return CustomPathManager.FindPathPosition(position, service, laneType, vehicleTypes, allowUnderground, requireConnect, maxDistance, out pathPos, out position2, out num, out num2, vehicleType);
 }
 protected new bool StartPathFind(ushort instanceID, ref CitizenInstance citizenData, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo)
 {
     NetInfo.LaneType laneType = NetInfo.LaneType.Pedestrian;
     VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None;
     bool randomParking = false;
     if (vehicleInfo != null)
     {
         if (vehicleInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTaxi)
         {
             if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTaxi) == CitizenInstance.Flags.None && Singleton<DistrictManager>.instance.m_districts.m_buffer[0].m_productionData.m_finalTaxiCapacity != 0u)
             {
                 SimulationManager instance = Singleton<SimulationManager>.instance;
                 if (instance.m_isNightTime || instance.m_randomizer.Int32(2u) == 0)
                 {
                     laneType |= (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
                     vehicleType |= vehicleInfo.m_vehicleType;
                 }
             }
         }
         else
         {
             laneType |= NetInfo.LaneType.Vehicle;
             vehicleType |= vehicleInfo.m_vehicleType;
             if (citizenData.m_targetBuilding != 0 && Singleton<BuildingManager>.instance.m_buildings.m_buffer[(int)citizenData.m_targetBuilding].Info.m_class.m_service > ItemClass.Service.Office)
             {
                 randomParking = true;
             }
         }
     }
     PathUnit.Position vehiclePosition = default(PathUnit.Position);
     ushort parkedVehicle = Singleton<CitizenManager>.instance.m_citizens.m_buffer[(int)((UIntPtr)citizenData.m_citizen)].m_parkedVehicle;
     if (parkedVehicle != 0)
     {
         Vector3 position = Singleton<VehicleManager>.instance.m_parkedVehicles.m_buffer[(int)parkedVehicle].m_position;
         PathManager.FindPathPosition(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, false, false, 32f, out vehiclePosition);
     }
     bool allowUnderground = (citizenData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None;
     PathUnit.Position startPosA;
     PathUnit.Position endPosA;
     if (this.FindPathPosition(instanceID, ref citizenData, startPos, laneType, vehicleType, allowUnderground, out startPosA) && this.FindPathPosition(instanceID, ref citizenData, endPos, laneType, vehicleType, false, out endPosA))
     {
         if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None)
         {
             laneType |= NetInfo.LaneType.PublicTransport;
         }
         PathUnit.Position position2 = default(PathUnit.Position);
         uint path;
         if (Singleton<PathManager>.instance.CreatePath(ExtendedVehicleType.PassengerCar, out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false, randomParking))
         {
             if (citizenData.m_path != 0u)
             {
                 Singleton<PathManager>.instance.ReleasePath(citizenData.m_path);
             }
             citizenData.m_path = path;
             citizenData.m_flags |= CitizenInstance.Flags.WaitingPath;
             return true;
         }
     }
     return false;
 }
 void vhs_GetVehicleInfoByVehicleIDCompleted(object sender, GetVehicleInfoByVehicleIDCompletedEventArgs e)
 {
     if (e.Result != null)
     {
         vinfo = e.Result;
     }
 }
 // from CitizenAI
 public static bool FindPathPosition(ushort instanceID, ref CitizenInstance citizenData, Vector3 pos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, out PathUnit.Position position)
 {
     position = default(PathUnit.Position);
     float num = 1E+10f;
     PathUnit.Position position2;
     PathUnit.Position position3;
     float num2;
     float num3;
     if (CustomPathManager.FindPathPosition(pos, ItemClass.Service.Road, laneTypes, vehicleTypes, allowUnderground, 32f, out position2, out position3, out num2, out num3, RoadManager.VehicleType.PassengerCar) && num2 < num)
     {
         num = num2;
         position = position2;
     }
     PathUnit.Position position4;
     PathUnit.Position position5;
     float num4;
     float num5;
     if (CustomPathManager.FindPathPosition(pos, ItemClass.Service.Beautification, laneTypes, vehicleTypes, allowUnderground, 32f, out position4, out position5, out num4, out num5, RoadManager.VehicleType.PassengerCar) && num4 < num)
     {
         num = num4;
         position = position4;
     }
     PathUnit.Position position6;
     PathUnit.Position position7;
     float num6;
     float num7;
     if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None && CustomPathManager.FindPathPosition(pos, ItemClass.Service.PublicTransport, laneTypes, vehicleTypes, allowUnderground, 32f, out position6, out position7, out num6, out num7, RoadManager.VehicleType.PassengerCar) && num6 < num)
     {
         position = position6;
     }
     return position.m_segment != 0;
 }
示例#6
0
 public SlowVehicleInfo(VehicleInfo i)
 {
     this.i = i;
     BaseMaxSpeed = i.m_maxSpeed;
     BaseLeanMultiplier = i.m_leanMultiplier;
     BaseAcceleration = i.m_acceleration;
     BaseBraking = i.m_braking;
     BaseTurning = i.m_turning;
 }
        public List<HashSet<ushort>> GetMapping(VehicleInfo vehicle)
        {
            int prefabID = vehicle.m_prefabDataIndex;

            if (!_mapping.PrefabMapped(prefabID))
                CategorizePrefab(vehicle);

            return _mapping.GetMapping(prefabID);
        }
        public static float RestrictSpeed(float calculatedSpeed, uint laneId, VehicleInfo info)
        {
            if (calculatedSpeed == 0f || (CSLTraffic.Options & OptionsManager.ModOptions.BetaTestRoadCustomizerTool) == OptionsManager.ModOptions.None)
                return calculatedSpeed;

            float speedLimit = RoadManager.GetLaneSpeed(laneId);
            float curve = NetManager.instance.m_lanes.m_buffer[laneId].m_curve;

            float a = 1000f / (1f + curve * 1000f / info.m_turning) + 2f;
            float b = 8f * speedLimit;
            return Mathf.Min(Mathf.Min(a, b), info.m_maxSpeed);
        }
        private void CategorizePrefab(VehicleInfo vehicle)
        {
            VehicleAI ai = vehicle.m_vehicleAI;
            int prefabID = vehicle.m_prefabDataIndex;

            _mapping.AddMapping(prefabID, _data._Vehicles);

            if (ai is CarTrailerAI)
                return;
            else if (ai is CarAI)
            {
                _mapping.AddMapping(prefabID, _data._Cars);

                if (ai is HearseAI)
                    _mapping.AddMapping(prefabID, _data._Hearses);
                else if (ai is GarbageTruckAI)
                    _mapping.AddMapping(prefabID, _data._GarbageTrucks);
                else if (ai is FireTruckAI)
                    _mapping.AddMapping(prefabID, _data._FireTrucks);
                else if (ai is PoliceCarAI)
                    _mapping.AddMapping(prefabID, _data._PoliceCars);
                else if (ai is AmbulanceAI)
                    _mapping.AddMapping(prefabID, _data._Ambulances);
                else if (ai is BusAI)
                    _mapping.AddMapping(prefabID, _data._Buses);
                else
                    _mapping.AddMapping(prefabID, _data._CarOther);
            }
            else if (ai is TrainAI)
            {
                _mapping.AddMapping(prefabID, _data._Trains);

                if (ai is MetroTrainAI)
                    _mapping.AddMapping(prefabID, _data._MetroTrains);
                else if (ai is PassengerTrainAI)
                    _mapping.AddMapping(prefabID, _data._PassengerTrains);
                else if (ai is CargoTrainAI)
                    _mapping.AddMapping(prefabID, _data._CargoTrains);
                else
                    _mapping.AddMapping(prefabID, _data._TrainOther);
            }
            else if (ai is AircraftAI)
                _mapping.AddMapping(prefabID, _data._Aircraft);
            else if (ai is ShipAI)
                _mapping.AddMapping(prefabID, _data._Ships);
            else
                _mapping.AddMapping(prefabID, _data._VehicleOther);
        }
        private ushort CheckCollisions(ushort instanceID, ref CitizenInstance citizenData, Segment3 segment, Vector3 min, Vector3 max, ushort otherID, ref Vehicle otherData, ref Vector3 pushAmount, ref float pushDivider)
        {
            VehicleInfo info = otherData.Info;

            if (info.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
            {
                return(otherData.m_nextGridVehicle);
            }
            if ((otherData.m_flags & Vehicle.Flags.Transition) == Vehicle.Flags.None && (citizenData.m_flags & CitizenInstance.Flags.Transition) == CitizenInstance.Flags.None && (otherData.m_flags & Vehicle.Flags.Underground) != Vehicle.Flags.None != ((citizenData.m_flags & CitizenInstance.Flags.Underground) != CitizenInstance.Flags.None))
            {
                return(otherData.m_nextGridVehicle);
            }
            Segment3 segment2 = otherData.m_segment;
            Vector3  vector   = Vector3.Min(segment2.Min(), otherData.m_targetPos1);

            vector.x -= 1f;
            vector.z -= 1f;
            Vector3 vector2 = Vector3.Max(segment2.Max(), otherData.m_targetPos1);

            vector2.x += 1f;
            vector2.y += 1f;
            vector2.z += 1f;
            if (min.x < vector2.x && max.x > vector.x && min.z < vector2.z && max.z > vector.z && min.y < vector2.y && max.y > vector.y)
            {
                float num = this.m_info.m_radius + 1f;
                float num3;
                float t;
                float num2 = segment.DistanceSqr(segment2, out num3, out t);
                if (num2 < num * num)
                {
                    float   num4 = num - Mathf.Sqrt(num2);
                    float   num5 = 1f - num2 / (num * num);
                    Vector3 a    = segment.Position(num3 * 0.9f);
                    Vector3 b    = segment2.Position(t);
                    a.y = 0f;
                    b.y = 0f;
                    Vector3 vector3 = Vector3.Normalize(a - b);
                    Vector3 rhs     = Vector3.Normalize(new Vector3(segment.b.x - segment.a.x, 0f, segment.b.z - segment.a.z));
                    Vector3 vector4 = new Vector3(rhs.z, 0f, -rhs.x) * Mathf.Abs(Vector3.Dot(vector3, rhs) * 0.5f);
                    if (Vector3.Dot(vector3, vector4) >= 0f)
                    {
                        vector3 += vector4;
                    }
                    else
                    {
                        vector3 -= vector4;
                    }
                    pushAmount  += vector3 * (num4 * num5);
                    pushDivider += num5;
                }
                float magnitude = otherData.GetLastFrameVelocity().magnitude;
                if (magnitude > 0.1f)
                {
                    float num6 = this.m_info.m_radius + 3f;
                    segment2.a  = segment2.b;
                    segment2.b += Vector3.ClampMagnitude(((Vector3)otherData.m_targetPos1) - segment2.b, magnitude * 4f);
                    num2        = segment.DistanceSqr(segment2, out num3, out t);
                    if (num2 > num * num && num2 < num6 * num6)
                    {
                        float   num7 = num6 - Mathf.Sqrt(num2);
                        float   num8 = 1f - num2 / (num6 * num6);
                        Vector3 a2   = segment.Position(num3 * 0.9f);
                        Vector3 b2   = segment2.Position(t);
                        a2.y = 0f;
                        b2.y = 0f;
                        Vector3 vector5 = a2 - b2;
                        pushAmount  += vector5.normalized * (num7 * num8);
                        pushDivider += num8;
                    }
                }
            }
            return(otherData.m_nextGridVehicle);
        }
示例#11
0
        public HomePage()
        {
            InitializeComponent();

            //Get User data from login
            if (tNetUserLoginData.Contains("UserLoginData"))
            {
                mySelectedVehicle = new VehicleInfo();

                userData = (DriverLogin)tNetUserLoginData["UserLoginData"];
                userId = (string)tNetUserLoginData["UserId"];
                pwmd5 = (string)tNetUserLoginData["PasswordMd5"];
                mySelectedVehicle = (VehicleInfo)tNetUserLoginData["MySelectedVehicle"];
                rawPass = (string)tNetUserLoginData["RawPassword"];
            }

            updateLocationTimer = new DispatcherTimer();
            updateLocationTimer.Tick += new EventHandler(updateLocationTimer_Tick);
            updateLocationTimer.Interval = new TimeSpan(0, 0, 0, 20); //Sau năm dây sẽ chạy cập nhật nếu như lần cập nhật trước không thành công    

            //Tạo kênh Notification
            CreatePushChannel();

            //get First Local Position
            GetCurrentCorrdinate();
            UpdateCurrentLocation(currentLat, currentLng);

            //Open Status Screen
            ShowLoadingScreen();

            LoadDriverProfile();
            UpdateDriverStatus(ConstantVariable.dStatusNotAvailable); //"NA"

            LoadCityNameDataBase();

            TripTrackingOnMap(); //Chuẩn bị cho việc tracking
        }
        public VehicleInfo CustomGetVehicleInfo(ushort instanceID, ref CitizenInstance citizenData, bool forceCar)
        {
            if (citizenData.m_citizen == 0u)
            {
                return(null);
            }

            // NON-STOCK CODE START
            bool forceTaxi = false;

#if BENCHMARK
            using (var bm = new Benchmark(null, "forceTaxi")) {
#endif
            if (Options.prohibitPocketCars)
            {
                if (ExtCitizenInstanceManager.Instance.ExtInstances[instanceID].pathMode == ExtPathMode.TaxiToTarget)
                {
                    forceTaxi = true;
                }
            }
#if BENCHMARK
        }
#endif
            // NON-STOCK CODE END

            int carProb;
            int bikeProb;
            int taxiProb;
            // NON-STOCK CODE START
            if (forceTaxi)
            {
                carProb  = 0;
                bikeProb = 0;
                taxiProb = 100;
            }
            else
            // NON-STOCK CODE END
            if (forceCar || (citizenData.m_flags & CitizenInstance.Flags.BorrowCar) != CitizenInstance.Flags.None)
            {
                carProb  = 100;
                bikeProb = 0;
                taxiProb = 0;
            }
            else
            {
                carProb  = GetCarProbability();
                bikeProb = GetBikeProbability();
                taxiProb = GetTaxiProbability();
            }
            Randomizer randomizer = new Randomizer(citizenData.m_citizen);
            bool useCar           = randomizer.Int32(100u) < carProb;
            bool useBike          = !useCar && randomizer.Int32(100u) < bikeProb;
            bool useTaxi          = !useCar && !useBike && randomizer.Int32(100u) < taxiProb;
            bool useElectricCar   = false;
            if (useCar)
            {
                int electricProb = GetElectricCarProbability(Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].WealthLevel);
                useElectricCar = randomizer.Int32(100u) < electricProb;
            }

            ItemClass.Service service       = ItemClass.Service.Residential;
            ItemClass.SubService subService = useElectricCar ? ItemClass.SubService.ResidentialLowEco : ItemClass.SubService.ResidentialLow;
            if (useTaxi)
            {
                service    = ItemClass.Service.PublicTransport;
                subService = ItemClass.SubService.PublicTransportTaxi;
            }
            // NON-STOCK CODE START
            VehicleInfo carInfo = null;
#if BENCHMARK
            using (var bm = new Benchmark(null, "find-parked-vehicle")) {
#endif
            if (Options.prohibitPocketCars && useCar && !useTaxi)
            {
                ushort parkedVehicleId = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].m_parkedVehicle;
                if (parkedVehicleId != 0)
                {
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomTouristAI.CustomGetVehicleInfo({instanceID}): Citizen instance {instanceID} owns a parked vehicle {parkedVehicleId}. Reusing vehicle info.");
                    }
#endif
                    carInfo = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info;
                }
            }
#if BENCHMARK
        }
#endif

            if (carInfo == null && (useCar || useTaxi))
            {
                // NON-STOCK CODE END
                carInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(ref randomizer, service, subService, ItemClass.Level.Level1);
            }

            if (useBike)
            {
                VehicleInfo bikeInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(ref randomizer, ItemClass.Service.Residential, ItemClass.SubService.ResidentialHigh, ItemClass.Level.Level2);

                if (bikeInfo != null)
                {
                    return(bikeInfo);
                }
            }

            if ((useCar || useTaxi) && carInfo != null)
            {
                return(carInfo);
            }
            return(null);
        }
        /// <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 (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);
                }
                // 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
            VehicleStateManager.Instance.UpdateVehiclePosition(vehicleId, ref vehicleData);
            if (!Options.isStockLaneChangerUsed())
            {
                // Advanced AI traffic measurement
                VehicleStateManager.Instance.LogTraffic(vehicleId);
            }
            // 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 && VehicleBehaviorManager.Instance.MayDespawn(ref vehicleData))                 // NON-STOCK CODE
            {
                Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);
            }
        }
示例#14
0
 public static bool FindPathPosition(Vector3 position, ItemClass.Service service, NetInfo.LaneType laneType, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, bool requireConnect, float maxDistance, out PathUnit.Position pathPosA, out PathUnit.Position pathPosB, out float distanceSqrA, out float distanceSqrB, RoadManager.VehicleType vehicleType)
 {
     Bounds bounds = new Bounds(position, new Vector3(maxDistance * 2f, maxDistance * 2f, maxDistance * 2f));
     int num = Mathf.Max((int)((bounds.min.x - 64f) / 64f + 135f), 0);
     int num2 = Mathf.Max((int)((bounds.min.z - 64f) / 64f + 135f), 0);
     int num3 = Mathf.Min((int)((bounds.max.x + 64f) / 64f + 135f), 269);
     int num4 = Mathf.Min((int)((bounds.max.z + 64f) / 64f + 135f), 269);
     NetManager instance = Singleton<NetManager>.instance;
     pathPosA.m_segment = 0;
     pathPosA.m_lane = 0;
     pathPosA.m_offset = 0;
     distanceSqrA = 1E+10f;
     pathPosB.m_segment = 0;
     pathPosB.m_lane = 0;
     pathPosB.m_offset = 0;
     distanceSqrB = 1E+10f;
     float num5 = maxDistance * maxDistance;
     for (int i = num2; i <= num4; i++)
     {
         for (int j = num; j <= num3; j++)
         {
             ushort num6 = instance.m_segmentGrid[i * 270 + j];
             int num7 = 0;
             while (num6 != 0)
             {
                 NetInfo info = instance.m_segments.m_buffer[(int)num6].Info;
                 if (info.m_class.m_service == service && (instance.m_segments.m_buffer[(int)num6].m_flags & NetSegment.Flags.Flooded) == NetSegment.Flags.None && (allowUnderground || !info.m_netAI.IsUnderground()))
                 {
                     ushort startNode = instance.m_segments.m_buffer[(int)num6].m_startNode;
                     ushort endNode = instance.m_segments.m_buffer[(int)num6].m_endNode;
                     Vector3 position2 = instance.m_nodes.m_buffer[(int)startNode].m_position;
                     Vector3 position3 = instance.m_nodes.m_buffer[(int)endNode].m_position;
                     float num8 = Mathf.Max(Mathf.Max(bounds.min.x - 64f - position2.x, bounds.min.z - 64f - position2.z), Mathf.Max(position2.x - bounds.max.x - 64f, position2.z - bounds.max.z - 64f));
                     float num9 = Mathf.Max(Mathf.Max(bounds.min.x - 64f - position3.x, bounds.min.z - 64f - position3.z), Mathf.Max(position3.x - bounds.max.x - 64f, position3.z - bounds.max.z - 64f));
                     Vector3 b;
                     int num10;
                     float num11;
                     Vector3 b2;
                     int num12;
                     float num13;
                     if ((num8 < 0f || num9 < 0f) && instance.m_segments.m_buffer[(int)num6].m_bounds.Intersects(bounds) && CustomPathManager.GetClosestLanePosition(instance.m_segments.m_buffer[(int)num6], position, laneType, vehicleTypes, requireConnect, out b, out num10, out num11, out b2, out num12, out num13, vehicleType))
                     {
                         float num14 = Vector3.SqrMagnitude(position - b);
                         if (num14 < num5)
                         {
                             num5 = num14;
                             pathPosA.m_segment = num6;
                             pathPosA.m_lane = (byte)num10;
                             pathPosA.m_offset = (byte)Mathf.Clamp(Mathf.RoundToInt(num11 * 255f), 0, 255);
                             distanceSqrA = num14;
                             num14 = Vector3.SqrMagnitude(position - b2);
                             if (num12 == -1 || num14 >= maxDistance * maxDistance)
                             {
                                 pathPosB.m_segment = 0;
                                 pathPosB.m_lane = 0;
                                 pathPosB.m_offset = 0;
                                 distanceSqrB = 1E+10f;
                             }
                             else
                             {
                                 pathPosB.m_segment = num6;
                                 pathPosB.m_lane = (byte)num12;
                                 pathPosB.m_offset = (byte)Mathf.Clamp(Mathf.RoundToInt(num13 * 255f), 0, 255);
                                 distanceSqrB = num14;
                             }
                         }
                     }
                 }
                 num6 = instance.m_segments.m_buffer[(int)num6].m_nextGridSegment;
                 if (++num7 >= 32768)
                 {
                     CODebugBase<LogChannel>.Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
                     break;
                 }
             }
         }
     }
     return pathPosA.m_segment != 0;
 }
示例#15
0
    public class CustomTrainAI : TrainAI {     // correct would be to inherit from VehicleAI (in order to keep the correct references to `base`)
        public void TrafficManagerSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos)
        {
            try {
                if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0)
                {
                    byte pathFindFlags = Singleton <PathManager> .instance.m_pathUnits.m_buffer[(int)((UIntPtr)vehicleData.m_path)].m_pathFindFlags;
                    if ((pathFindFlags & 4) != 0)
                    {
                        this.PathFindReady(vehicleId, ref vehicleData);
                    }
                    else if ((pathFindFlags & 8) != 0 || vehicleData.m_path == 0u)
                    {
                        vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath;
                        Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);

                        vehicleData.m_path = 0u;
                        vehicleData.Unspawn(vehicleId);
                        return;
                    }
                }
                else if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0)
                {
                    this.TrySpawn(vehicleId, ref vehicleData);
                }

                bool   reversed = (vehicleData.m_flags & Vehicle.Flags.Reversed) != 0;
                ushort frontVehicleId;
                if (reversed)
                {
                    frontVehicleId = vehicleData.GetLastVehicle(vehicleId);
                }
                else
                {
                    frontVehicleId = vehicleId;
                }

                /// NON-STOCK CODE START ///
                try {
                    CustomVehicleAI.HandleVehicle(frontVehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[frontVehicleId], false, false, 5);
                } catch (Exception e) {
                    Log.Error("TrainAI TrafficManagerSimulationStep Error: " + e.ToString());
                }
                /// NON-STOCK CODE END ///

                VehicleManager instance = Singleton <VehicleManager> .instance;
                VehicleInfo    info     = instance.m_vehicles.m_buffer[(int)frontVehicleId].Info;
                info.m_vehicleAI.SimulationStep(frontVehicleId, ref instance.m_vehicles.m_buffer[(int)frontVehicleId], vehicleId, ref vehicleData, 0);
                if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created)
                {
                    return;
                }
                bool flag2 = (vehicleData.m_flags & Vehicle.Flags.Reversed) != 0;
                if (flag2 != reversed)
                {
                    reversed = flag2;
                    if (reversed)
                    {
                        frontVehicleId = vehicleData.GetLastVehicle(vehicleId);
                    }
                    else
                    {
                        frontVehicleId = vehicleId;
                    }
                    info = instance.m_vehicles.m_buffer[(int)frontVehicleId].Info;
                    info.m_vehicleAI.SimulationStep(frontVehicleId, ref instance.m_vehicles.m_buffer[(int)frontVehicleId], vehicleId, ref vehicleData, 0);
                    if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created)
                    {
                        return;
                    }
                    flag2 = ((vehicleData.m_flags & Vehicle.Flags.Reversed) != 0);
                    if (flag2 != reversed)
                    {
                        Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);

                        return;
                    }
                }
                if (reversed)
                {
                    frontVehicleId = instance.m_vehicles.m_buffer[(int)frontVehicleId].m_leadingVehicle;
                    int num2 = 0;
                    while (frontVehicleId != 0)
                    {
                        info = instance.m_vehicles.m_buffer[(int)frontVehicleId].Info;
                        info.m_vehicleAI.SimulationStep(frontVehicleId, ref instance.m_vehicles.m_buffer[(int)frontVehicleId], vehicleId, ref vehicleData, 0);
                        if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created)
                        {
                            return;
                        }
                        frontVehicleId = instance.m_vehicles.m_buffer[(int)frontVehicleId].m_leadingVehicle;
                        if (++num2 > 16384)
                        {
                            CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                            break;
                        }
                    }
                }
                else
                {
                    frontVehicleId = instance.m_vehicles.m_buffer[(int)frontVehicleId].m_trailingVehicle;
                    int num3 = 0;
                    while (frontVehicleId != 0)
                    {
                        info = instance.m_vehicles.m_buffer[(int)frontVehicleId].Info;
                        info.m_vehicleAI.SimulationStep(frontVehicleId, ref instance.m_vehicles.m_buffer[(int)frontVehicleId], vehicleId, ref vehicleData, 0);
                        if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created)
                        {
                            return;
                        }
                        frontVehicleId = instance.m_vehicles.m_buffer[(int)frontVehicleId].m_trailingVehicle;
                        if (++num3 > 16384)
                        {
                            CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                            break;
                        }
                    }
                }
                if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace | Vehicle.Flags.WaitingCargo)) == 0 || (vehicleData.m_blockCounter == 255 && Options.enableDespawning))
                {
                    Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);
                }
            } catch (Exception ex) {
                Log.Error("Error in TrainAI.SimulationStep: " + ex.ToString());
            }
        }
        public void CustomSimulationStep(ushort instanceID, ref CitizenInstance instanceData, Vector3 physicsLodRefPos)
        {
            uint citizenId = instanceData.m_citizen;

            if ((instanceData.m_flags & (CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating)) != CitizenInstance.Flags.None && (instanceData.m_flags & CitizenInstance.Flags.Character) == CitizenInstance.Flags.None)
            {
                Singleton <CitizenManager> .instance.ReleaseCitizenInstance(instanceID);

                if (citizenId != 0u)
                {
                    Singleton <CitizenManager> .instance.ReleaseCitizen(citizenId);
                }
                return;
            }

            if ((instanceData.m_flags & CitizenInstance.Flags.WaitingPath) != CitizenInstance.Flags.None)
            {
                PathManager pathManager   = Singleton <PathManager> .instance;
                byte        pathFindFlags = pathManager.m_pathUnits.m_buffer[instanceData.m_path].m_pathFindFlags;

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

#if DEBUG
                if (GlobalConfig.Instance.Debug.Switches[2])
                {
                    Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Path: {instanceData.m_path}, mainPathState={mainPathState}");
                }
#endif

                ExtSoftPathState finalPathState = ExtCitizenInstance.ConvertPathStateToSoftPathState(mainPathState);
                if (Options.prohibitPocketCars)
                {
                    finalPathState = AdvancedParkingManager.Instance.UpdateCitizenPathState(instanceID, ref instanceData, ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceID], ref Singleton <CitizenManager> .instance.m_citizens.m_buffer[instanceData.m_citizen], mainPathState);
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Applied Parking AI logic. Path: {instanceData.m_path}, mainPathState={mainPathState}, finalPathState={finalPathState}, extCitizenInstance={ExtCitizenInstanceManager.Instance.ExtInstances[instanceID]}");
                    }
#endif
                }

                switch (finalPathState)
                {
                case ExtSoftPathState.Ready:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Path-finding succeeded for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- calling HumanAI.PathfindSuccess");
                    }
#endif
                    this.Spawn(instanceID, ref instanceData);
                    instanceData.m_pathPositionIndex = 255;
                    instanceData.m_flags            &= ~CitizenInstance.Flags.WaitingPath;
                    instanceData.m_flags            &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown);
                    // NON-STOCK CODE START (transferred from ResidentAI.PathfindSuccess)
                    if (citizenId != 0 && (Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenId].m_flags & (Citizen.Flags.Tourist | Citizen.Flags.MovingIn | Citizen.Flags.DummyTraffic)) == Citizen.Flags.MovingIn)
                    {
                        StatisticBase statisticBase = Singleton <StatisticsManager> .instance.Acquire <StatisticInt32>(StatisticType.MoveRate);

                        statisticBase.Add(1);
                    }
                    // NON-STOCK CODE END
                    this.PathfindSuccess(instanceID, ref instanceData);
                    break;

                case ExtSoftPathState.Ignore:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Path-finding result shall be ignored for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- ignoring");
                    }
#endif
                    return;

                case ExtSoftPathState.Calculating:
                default:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Path-finding result undetermined for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- continue");
                    }
#endif
                    break;

                case ExtSoftPathState.FailedHard:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): HARD path-finding failure for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- calling HumanAI.PathfindFailure");
                    }
#endif
                    instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath;
                    instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown);
                    Singleton <PathManager> .instance.ReleasePath(instanceData.m_path);

                    instanceData.m_path = 0u;
                    this.PathfindFailure(instanceID, ref instanceData);
                    return;

                case ExtSoftPathState.FailedSoft:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): SOFT path-finding failure for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- calling HumanAI.InvalidPath");
                    }
#endif
                    // path mode has been updated, repeat path-finding
                    instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath;
                    instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown);
                    this.InvalidPath(instanceID, ref instanceData);
                    return;
                }
                // NON-STOCK CODE END
            }

            // NON-STOCK CODE START
            if (Options.prohibitPocketCars)
            {
                if (ExtSimulationStep(instanceID, ref instanceData, ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceID], physicsLodRefPos))
                {
                    return;
                }
            }
            // NON-STOCK CODE END

            base.SimulationStep(instanceID, ref instanceData, physicsLodRefPos);

            CitizenManager citizenManager = Singleton <CitizenManager> .instance;
            VehicleManager vehicleManager = Singleton <VehicleManager> .instance;
            ushort         vehicleId      = 0;
            if (instanceData.m_citizen != 0u)
            {
                vehicleId = citizenManager.m_citizens.m_buffer[instanceData.m_citizen].m_vehicle;
            }
            if (vehicleId != 0)
            {
                VehicleInfo vehicleInfo = vehicleManager.m_vehicles.m_buffer[(int)vehicleId].Info;
                if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
                {
                    vehicleInfo.m_vehicleAI.SimulationStep(vehicleId, ref vehicleManager.m_vehicles.m_buffer[(int)vehicleId], vehicleId, ref vehicleManager.m_vehicles.m_buffer[(int)vehicleId], 0);
                    vehicleId = 0;
                }
            }
            if (vehicleId == 0 && (instanceData.m_flags & (CitizenInstance.Flags.Character | CitizenInstance.Flags.WaitingPath | CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating)) == CitizenInstance.Flags.None)
            {
                instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown);
                this.ArriveAtDestination(instanceID, ref instanceData, false);
                citizenManager.ReleaseCitizenInstance(instanceID);
            }
        }
示例#17
0
 public bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, RoadManager.VehicleType vehicleType)
 {
     return this.CreatePath(out unit, ref randomizer, buildIndex, startPosA, startPosB, endPosA, endPosB, default(PathUnit.Position), laneTypes, vehicleTypes, maxLength, false, false, false, false, vehicleType);
 }
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
#if DEBUG
            //Log._Debug($"CustomTaxiAI.CustomStartPathFind called for vehicle {vehicleID}");
#endif

#if PATHRECALC
            VehicleState state           = VehicleStateManager._GetVehicleState(vehicleID);
            bool         recalcRequested = state.PathRecalculationRequested;
            state.PathRecalculationRequested = false;
#endif

            CitizenManager instance          = Singleton <CitizenManager> .instance;
            ushort         passengerInstance = CustomTaxiAI.GetPassengerInstance(vehicleID, ref vehicleData);
            if (passengerInstance == 0 || (instance.m_instances.m_buffer[(int)passengerInstance].m_flags & CitizenInstance.Flags.Character) != CitizenInstance.Flags.None)
            {
                return(base.StartPathFind(vehicleID, ref vehicleData, startPos, endPos, startBothWays, endBothWays, undergroundTarget));
            }
            VehicleInfo             info        = this.m_info;
            CitizenInfo             info2       = instance.m_instances.m_buffer[(int)passengerInstance].Info;
            NetInfo.LaneType        laneType    = NetInfo.LaneType.Vehicle | NetInfo.LaneType.Pedestrian | NetInfo.LaneType.TransportVehicle;
            VehicleInfo.VehicleType vehicleType = this.m_info.m_vehicleType;
            bool allowUnderground = (vehicleData.m_flags & Vehicle.Flags.Underground) != 0;
            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(passengerInstance, ref instance.m_instances.m_buffer[(int)passengerInstance], endPos, laneType, vehicleType, undergroundTarget, out endPosA))
            {
                if ((instance.m_instances.m_buffer[(int)passengerInstance].m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None)
                {
                    laneType |= NetInfo.LaneType.PublicTransport;
                }
                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(
#if PATHRECALC
                        recalcRequested,
#endif
                        ExtVehicleType.Taxi, vehicleID, out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, laneType, vehicleType, 20000f))
                {
#if USEPATHWAITCOUNTER
                    VehicleState state = VehicleStateManager.Instance()._GetVehicleState(vehicleID);
                    state.PathWaitCounter = 0;
#endif

                    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);
        }
示例#19
0
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
#if DEBUG
            //Log._Debug($"CustomTaxiAI.CustomStartPathFind called for vehicle {vehicleID}");
#endif

            CitizenManager instance            = Singleton <CitizenManager> .instance;
            ushort         passengerInstanceId = CustomTaxiAI.GetPassengerInstance(vehicleID, ref vehicleData);
            if (passengerInstanceId == 0 || (instance.m_instances.m_buffer[(int)passengerInstanceId].m_flags & CitizenInstance.Flags.Character) != CitizenInstance.Flags.None)
            {
                return(base.StartPathFind(vehicleID, ref vehicleData, startPos, endPos, startBothWays, endBothWays, undergroundTarget));
            }
            VehicleInfo             info         = this.m_info;
            CitizenInfo             info2        = instance.m_instances.m_buffer[(int)passengerInstanceId].Info;
            NetInfo.LaneType        laneTypes    = NetInfo.LaneType.Vehicle | NetInfo.LaneType.Pedestrian | NetInfo.LaneType.TransportVehicle;
            VehicleInfo.VehicleType vehicleTypes = this.m_info.m_vehicleType;
            bool allowUnderground = (vehicleData.m_flags & Vehicle.Flags.Underground) != 0;
            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float             startSqrDistA;
            float             startSqrDistB;
            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 startSqrDistA, out startSqrDistB) &&
                info2.m_citizenAI.FindPathPosition(passengerInstanceId, ref instance.m_instances.m_buffer[(int)passengerInstanceId], endPos, laneTypes, vehicleTypes, undergroundTarget, out endPosA))
            {
                if ((instance.m_instances.m_buffer[(int)passengerInstanceId].m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None)
                {
                    laneTypes |= NetInfo.LaneType.PublicTransport;

                    uint citizenId = instance.m_instances.m_buffer[passengerInstanceId].m_citizen;
                    if (citizenId != 0u && (instance.m_citizens.m_buffer[citizenId].m_flags & Citizen.Flags.Evacuating) != Citizen.Flags.None)
                    {
                        laneTypes |= NetInfo.LaneType.EvacuationTransport;
                    }
                }
                if (!startBothWays || startSqrDistA < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                PathUnit.Position endPosB = default(PathUnit.Position);
                SimulationManager simMan  = Singleton <SimulationManager> .instance;
                uint path;
                // NON-STOCK CODE START
                PathCreationArgs args;
                args.extPathType         = ExtCitizenInstance.ExtPathType.None;
                args.extVehicleType      = ExtVehicleType.Taxi;
                args.vehicleId           = vehicleID;
                args.spawned             = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0;
                args.buildIndex          = simMan.m_currentBuildIndex;
                args.startPosA           = startPosA;
                args.startPosB           = startPosB;
                args.endPosA             = endPosA;
                args.endPosB             = endPosB;
                args.vehiclePosition     = default(PathUnit.Position);
                args.laneTypes           = laneTypes;
                args.vehicleTypes        = vehicleTypes;
                args.maxLength           = 20000f;
                args.isHeavyVehicle      = this.IsHeavyVehicle();
                args.hasCombustionEngine = this.CombustionEngine();
                args.ignoreBlocked       = this.IgnoreBlocked(vehicleID, ref vehicleData);
                args.ignoreFlooded       = false;
                args.ignoreCosts         = false;
                args.randomParking       = false;
                args.stablePath          = false;
                args.skipQueue           = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0;

                if (CustomPathManager._instance.CreatePath(out path, ref simMan.m_randomizer, args))
                {
                    // NON-STOCK CODE END
                    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 ExtStartPathFind(ushort instanceID, ref CitizenInstance citizenData, ref ExtCitizenInstance extInstance, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo)
        {
#if DEBUG
            if (GlobalConfig.Instance.Debug.Switches[2])
            {
                Log.Warning($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID}, citizen {citizenData.m_citizen}, startPos={startPos}, endPos={endPos}, sourceBuilding={citizenData.m_sourceBuilding}, targetBuilding={citizenData.m_targetBuilding}, pathMode={extInstance.pathMode}");
            }
#endif

            // NON-STOCK CODE START
            ExtVehicleType extVehicleType  = ExtVehicleType.None;
            ushort         parkedVehicleId = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].m_parkedVehicle;
            //bool mayUseOwnPassengerCar = true; // allowed to use a passenger car?
            bool           canUseOwnPassengerCar = false;   // allowed to use a passenger car AND given vehicle type is a passenger car?
            CarUsagePolicy carUsageMode          = CarUsagePolicy.Allowed;
            //bool forceUseCar = false;
#if BENCHMARK
            using (var bm = new Benchmark(null, "ParkingAI.Preparation")) {
#endif
            if (Options.prohibitPocketCars)
            {
                switch (extInstance.pathMode)
                {
                case ExtPathMode.RequiresWalkingPathToParkedCar:
                case ExtPathMode.CalculatingWalkingPathToParkedCar:
                case ExtPathMode.WalkingToParkedCar:
                case ExtPathMode.ApproachingParkedCar:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} has CurrentPathMode={extInstance.pathMode}. Change to 'CalculatingWalkingPathToParkedCar'.");
                    }
#endif
                    extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToParkedCar;
                    break;

                case ExtPathMode.RequiresWalkingPathToTarget:
                case ExtPathMode.CalculatingWalkingPathToTarget:
                case ExtPathMode.WalkingToTarget:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} has CurrentPathMode={extInstance.pathMode}. Change to 'CalculatingWalkingPathToTarget'.");
                    }
#endif
                    extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToTarget;
                    break;

                case ExtPathMode.RequiresCarPath:
                case ExtPathMode.DrivingToTarget:
                case ExtPathMode.DrivingToKnownParkPos:
                case ExtPathMode.DrivingToAltParkPos:
                case ExtPathMode.CalculatingCarPathToAltParkPos:
                case ExtPathMode.CalculatingCarPathToKnownParkPos:
                case ExtPathMode.CalculatingCarPathToTarget:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} has CurrentPathMode={extInstance.pathMode}. Change to 'RequiresCarPath'.");
                    }
#endif
                    extInstance.pathMode = ExtPathMode.RequiresCarPath;
                    break;

                default:
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} has CurrentPathMode={extInstance.pathMode}. Change to 'None'.");
                    }
#endif
                    extInstance.Reset();
                    break;
                }

                // pathMode is now either CalculatingWalkingPathToParkedCar, CalculatingWalkingPathToTarget, RequiresCarPath or None.

                if (parkedVehicleId != 0 && extInstance.pathMode != ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToTarget)
                {
                    // Reuse parked vehicle info
                    VehicleParked vehicleParked = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId];
                    vehicleInfo = vehicleParked.Info;

                    // Does citizen need to move their car
                    if (extInstance.pathMode != ExtCitizenInstance.ExtPathMode.RequiresCarPath)
                    {
                        // Citizen may use their car if they want to
                        carUsageMode = CarUsagePolicy.Allowed;

                        // Is citizen going home
                        ushort homeId = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].m_homeBuilding;
                        if (homeId != 0 && citizenData.m_targetBuilding == homeId)
                        {
                            // Check distance between home and parked car. If too far away: force citizen to take their car back home
                            float distHomeToParked = (vehicleParked.m_position - Singleton <BuildingManager> .instance.m_buildings.m_buffer[homeId].m_position).magnitude;
                            if (distHomeToParked > GlobalConfig.Instance.ParkingAI.MaxParkedCarDistanceToHome)
                            {
                                // Force citizen to go to car first, using public transport if required
                                extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToParkedCar;
#if DEBUG
                                if (GlobalConfig.Instance.Debug.Switches[2])
                                {
                                    Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} will try to go to parkedVehicleId={parkedVehicleId}. distHomeToParked={distHomeToParked}");
                                }
#endif
                            }
                            // Don't force citizen to use their car if they are at home
                        }
                        else if (homeId == 0 || citizenData.m_sourceBuilding != homeId)
                        {
                            // Check if citizen parked their car nearby
                            BuildingManager buildingManager    = Singleton <BuildingManager> .instance;
                            float           distSourceToParked = (vehicleParked.m_position - buildingManager.m_buildings.m_buffer[citizenData.m_sourceBuilding].m_position).magnitude;
                            if (distSourceToParked <= GlobalConfig.Instance.ParkingAI.MaxParkedCarDistanceToBuilding)
                            {
                                // Check if target is far enough away to drive to
                                float distTargetToParked = (vehicleParked.m_position - buildingManager.m_buildings.m_buffer[citizenData.m_targetBuilding].m_position).magnitude;
                                if (distTargetToParked > GlobalConfig.Instance.ParkingAI.MaxParkedCarDistanceToBuilding)
                                {
                                    // Make sure car isn't parked near home
                                    float distHomeToParked = 0.0f;
                                    if (homeId != 0)
                                    {
                                        distHomeToParked = (vehicleParked.m_position - buildingManager.m_buildings.m_buffer[homeId].m_position).magnitude;
                                    }

                                    if (homeId == 0 || distHomeToParked > GlobalConfig.Instance.ParkingAI.MaxParkedCarDistanceToHome)
                                    {
                                        // Force citizen to go to car first, using public transport if required
                                        extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToParkedCar;
#if DEBUG
                                        if (GlobalConfig.Instance.Debug.Switches[2])
                                        {
                                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} will try to go to parkedVehicleId={parkedVehicleId}. distSourceToParked={distSourceToParked}, distTargetToParked={distTargetToParked}, distHomeToParked={distHomeToParked}");
                                        }
#endif
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // Citizen has reached their car, force them to drive it
                        carUsageMode = CarUsagePolicy.Forced;
#if DEBUG
                        if (GlobalConfig.Instance.Debug.Switches[2])
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} will try to use parkedVehicleId={parkedVehicleId} to get to target={citizenData.m_targetBuilding}.");
                        }
#endif
                    }
                }

                if (extInstance.pathMode == ExtPathMode.CalculatingWalkingPathToParkedCar || extInstance.pathMode == ExtPathMode.CalculatingWalkingPathToTarget)
                {
                    // vehicle must not be used since we need a walking path
                    vehicleInfo  = null;
                    carUsageMode = CarUsagePolicy.Forbidden;

                    if (extInstance.pathMode == ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToParkedCar)
                    {
                        // check if parked car is present
                        if (parkedVehicleId == 0)
                        {
#if DEBUG
                            if (GlobalConfig.Instance.Debug.Switches[2])
                            {
                                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} should go to parked car (CurrentPathMode={extInstance.pathMode}) but parked vehicle could not be found. Setting CurrentPathMode='CalculatingWalkingPathToTarget'.");
                            }
#endif
                            extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToTarget;
                        }
                        else
                        {
                            endPos = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position;
#if DEBUG
                            if (GlobalConfig.Instance.Debug.Switches[4])
                            {
                                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} shall go to parked vehicle @ {endPos}");
                            }
#endif
                        }
                    }
                }
            }
#if BENCHMARK
        }
#endif

            /*if (Options.parkingRestrictionsEnabled && carUsageMode == CarUsagePolicy.Allowed && parkedVehicleId != 0) {
             *      // force removal of illegaly parked vehicle
             *      PathUnit.Position parkedPathPos;
             *      if (PathManager.FindPathPosition(Singleton<VehicleManager>.instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position, ItemClass.Service.Road, NetInfo.LaneType.Parking, VehicleInfo.VehicleType.Car, false, false, 32f, out parkedPathPos)) {
             *              if (! ParkingRestrictionsManager.Instance.IsParkingAllowed(parkedPathPos.m_segment, Singleton<NetManager>.instance.m_segments.m_buffer[parkedPathPos.m_segment].Info.m_lanes[parkedPathPos.m_lane].m_finalDirection)) {
             *                      carUsageMode = CarUsagePolicy.Forced;
             *                      vehicleInfo = Singleton<VehicleManager>.instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info;
             *              }
             *      }
             * }*/
            // NON-STOCK CODE END

            NetInfo.LaneType laneTypes           = NetInfo.LaneType.Pedestrian;
            VehicleInfo.VehicleType vehicleTypes = VehicleInfo.VehicleType.None;
            bool randomParking    = false;
            bool combustionEngine = false;
            if (vehicleInfo != null)
            {
                if (vehicleInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTaxi)
                {
                    if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTaxi) == CitizenInstance.Flags.None && Singleton <DistrictManager> .instance.m_districts.m_buffer[0].m_productionData.m_finalTaxiCapacity != 0u)
                    {
                        SimulationManager instance = Singleton <SimulationManager> .instance;
                        if (instance.m_isNightTime || instance.m_randomizer.Int32(2u) == 0)
                        {
                            laneTypes     |= (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
                            vehicleTypes  |= vehicleInfo.m_vehicleType;
                            extVehicleType = ExtVehicleType.Taxi;                             // NON-STOCK CODE
                            // NON-STOCK CODE START
                            if (Options.prohibitPocketCars)
                            {
                                extInstance.pathMode = ExtPathMode.TaxiToTarget;
                            }
                            // NON-STOCK CODE END
                        }
                    }
                }
                else
                {
                    // NON-STOCK CODE START
                    if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Car)
                    {
                        if (carUsageMode == CarUsagePolicy.Allowed || carUsageMode == CarUsagePolicy.Forced)
                        {
                            extVehicleType        = ExtVehicleType.PassengerCar;
                            laneTypes            |= NetInfo.LaneType.Vehicle;
                            vehicleTypes         |= vehicleInfo.m_vehicleType;
                            combustionEngine      = vehicleInfo.m_class.m_subService == ItemClass.SubService.ResidentialLow;
                            canUseOwnPassengerCar = true;
                        }
                    }
                    else if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
                    {
                        extVehicleType = ExtVehicleType.Bicycle;
                        laneTypes     |= NetInfo.LaneType.Vehicle;
                        vehicleTypes  |= vehicleInfo.m_vehicleType;
                        if (citizenData.m_targetBuilding != 0 && Singleton <BuildingManager> .instance.m_buildings.m_buffer[citizenData.m_targetBuilding].Info.m_class.m_service > ItemClass.Service.Office)
                        {
                            randomParking = true;
                        }
                    }
                    // NON-STOCK CODE END
                }
            }
            NetInfo.LaneType startLaneType = laneTypes;

            // NON-STOCK CODE START
            if (Options.prohibitPocketCars)
            {
                if (carUsageMode == CarUsagePolicy.Forced && !canUseOwnPassengerCar)
                {
                    carUsageMode = CarUsagePolicy.Forbidden;
                }
            }

            PathUnit.Position endPosA = default(PathUnit.Position);
            bool calculateEndPos      = true;
            bool allowRandomParking   = true;
#if BENCHMARK
            using (var bm = new Benchmark(null, "ParkingAI.Main")) {
#endif
            if (Options.prohibitPocketCars)
            {
                // Parking AI

                if (extInstance.pathMode == ExtCitizenInstance.ExtPathMode.RequiresCarPath)
                {
                    if (canUseOwnPassengerCar)
                    {
                        ushort homeId = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].m_homeBuilding;

                        startLaneType &= ~NetInfo.LaneType.Pedestrian;                                                               // force to use the car from the beginning
                        startPos       = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position; // force to start from the parked car

#if DEBUG
                        if (GlobalConfig.Instance.Debug.Switches[2])
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Setting startLaneType={startLaneType}, startPos={startPos} for citizen instance {instanceID}. CurrentDepartureMode={extInstance.pathMode}");
                        }
#endif

                        if (citizenData.m_targetBuilding == 0 || (Singleton <BuildingManager> .instance.m_buildings.m_buffer[citizenData.m_targetBuilding].m_flags & Building.Flags.IncomingOutgoing) == Building.Flags.None)
                        {
                            // the citizen is starting their journey and the target is not an outside connection: find a suitable parking space near the target

#if DEBUG
                            if (GlobalConfig.Instance.Debug.Switches[2])
                            {
                                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Finding parking space at target for citizen instance {instanceID}. CurrentDepartureMode={extInstance.pathMode} parkedVehicleId={parkedVehicleId}");
                            }
#endif

                            // find a parking space in the vicinity of the target
                            bool    calcEndPos;
                            Vector3 parkPos;
                            if (AdvancedParkingManager.Instance.FindParkingSpaceForCitizen(endPos, vehicleInfo, ref extInstance, homeId, citizenData.m_targetBuilding == homeId, 0, false, out parkPos, ref endPosA, out calcEndPos) && extInstance.CalculateReturnPath(parkPos, endPos))
                            {
                                // success
                                extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingCarPathToKnownParkPos;
                                calculateEndPos      = calcEndPos;                                  // if true, the end path position still needs to be calculated
                                allowRandomParking   = false;                                       // find a direct path to the calculated parking position
#if DEBUG
                                if (GlobalConfig.Instance.Debug.Switches[2])
                                {
                                    Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Finding known parking space for citizen instance {instanceID}, parked vehicle {parkedVehicleId} succeeded and return path {extInstance.returnPathId} ({extInstance.returnPathState}) is calculating. PathMode={extInstance.pathMode}");
                                }
#endif

                                /*if (! extInstance.CalculateReturnPath(parkPos, endPos)) {
                                 *      // TODO retry?
                                 *      if (GlobalConfig.Instance.Debug.Switches[2])
                                 *              Log._Debug($"CustomCitizenAI.CustomStartPathFind: [PFFAIL] Could not calculate return path for citizen instance {instanceID}, parked vehicle {parkedVehicleId}. Calling OnPathFindFailed.");
                                 *      CustomHumanAI.OnPathFindFailure(extInstance);
                                 *      return false;
                                 * }*/
                            }
                        }

                        if (extInstance.pathMode == ExtPathMode.RequiresCarPath)
                        {
                            // no known parking space found. calculate direct path to target
#if DEBUG
                            if (GlobalConfig.Instance.Debug.Switches[2])
                            {
                                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} is still at CurrentPathMode={extInstance.pathMode} (no parking space found?). Setting it to CalculatingCarPath. parkedVehicleId={parkedVehicleId}");
                            }
#endif
                            extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingCarPathToTarget;
                        }
                    }
                    else if (extInstance.pathMode == ExtPathMode.RequiresCarPath)
                    {
#if DEBUG
                        if (GlobalConfig.Instance.Debug.Switches[2])
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} requires car path but no parked car present. Citizen will need to walk to target.");
                        }
#endif
                        extInstance.Reset();
                    }
                }
            }
#if BENCHMARK
        }
#endif

            if (canUseOwnPassengerCar)
            {
                if (allowRandomParking && citizenData.m_targetBuilding != 0 && Singleton <BuildingManager> .instance.m_buildings.m_buffer[citizenData.m_targetBuilding].Info.m_class.m_service > ItemClass.Service.Office)
                {
                    randomParking = true;
                }
            }

            // determine path type
            ExtPathType extPathType = ExtPathType.None;
            if (Options.prohibitPocketCars)
            {
                extPathType = extInstance.GetPathType();
            }

            // NON-STOCK CODE END
            PathUnit.Position vehiclePosition = default(PathUnit.Position);

            if (parkedVehicleId != 0 && canUseOwnPassengerCar)
            {
                Vector3 position = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position;
                CustomPathManager.FindPathPosition(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, false, false, GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance, out vehiclePosition);
            }
            bool allowUnderground = (citizenData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None;

#if DEBUG
            if (GlobalConfig.Instance.Debug.Switches[2])
            {
                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Requesting path-finding for citizen instance {instanceID}, citizen {citizenData.m_citizen}, extVehicleType={extVehicleType}, extPathType={extPathType}, startPos={startPos}, endPos={endPos}, sourceBuilding={citizenData.m_sourceBuilding}, targetBuilding={citizenData.m_targetBuilding} pathMode={extInstance.pathMode}");
            }
#endif

            bool foundEndPos   = !calculateEndPos || FindPathPosition(instanceID, ref citizenData, endPos, Options.prohibitPocketCars && (citizenData.m_targetBuilding == 0 || (Singleton <BuildingManager> .instance.m_buildings.m_buffer[citizenData.m_targetBuilding].m_flags & Building.Flags.IncomingOutgoing) == Building.Flags.None) ? NetInfo.LaneType.Pedestrian : (laneTypes | NetInfo.LaneType.Pedestrian), vehicleTypes, false, out endPosA);         // NON-STOCK CODE: with Parking AI enabled, the end position must be a pedestrian position
            bool foundStartPos = false;
            PathUnit.Position startPosA;

            if (Options.prohibitPocketCars && (extInstance.pathMode == ExtPathMode.CalculatingCarPathToTarget || extInstance.pathMode == ExtPathMode.CalculatingCarPathToKnownParkPos))
            {
                foundStartPos = CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, laneTypes & ~NetInfo.LaneType.Pedestrian, vehicleTypes, allowUnderground, false, GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance, out startPosA);
            }
            else
            {
                foundStartPos = FindPathPosition(instanceID, ref citizenData, startPos, startLaneType, vehicleTypes, allowUnderground, out startPosA);
            }

            if (foundStartPos &&            // TODO probably fails if vehicle is parked too far away from road
                foundEndPos                 // NON-STOCK CODE
                )
            {
                bool canUseTransport = (citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None;
                if (canUseTransport)
                {
                    if (carUsageMode != CarUsagePolicy.Forced)                       // NON-STOCK CODE
                    {
                        laneTypes |= NetInfo.LaneType.PublicTransport;

                        CitizenManager citizenManager = Singleton <CitizenManager> .instance;
                        uint           citizenId      = citizenManager.m_instances.m_buffer[instanceID].m_citizen;
                        if (citizenId != 0u && (citizenManager.m_citizens.m_buffer[citizenId].m_flags & Citizen.Flags.Evacuating) != Citizen.Flags.None)
                        {
                            laneTypes |= NetInfo.LaneType.EvacuationTransport;
                        }
                    }
                }
                else if (Options.prohibitPocketCars)                     // TODO check for incoming connection
                // cim tried to use public transport but waiting time was too long
                {
                    if (citizenData.m_sourceBuilding != 0)
                    {
#if DEBUG
                        if (GlobalConfig.Instance.Debug.Switches[2])
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} cannot uses public transport from building {citizenData.m_sourceBuilding} to {citizenData.m_targetBuilding}. Incrementing public transport demand.");
                        }
#endif
                        ExtBuildingManager.Instance.ExtBuildings[citizenData.m_sourceBuilding].AddPublicTransportDemand((uint)GlobalConfig.Instance.ParkingAI.PublicTransportDemandWaitingIncrement, true);
                    }
                }

                PathUnit.Position dummyPathPos = default(PathUnit.Position);
                uint path;
                // NON-STOCK CODE START
                PathCreationArgs args;
                args.extPathType         = extPathType;
                args.extVehicleType      = extVehicleType;
                args.vehicleId           = 0;
                args.buildIndex          = Singleton <SimulationManager> .instance.m_currentBuildIndex;
                args.startPosA           = startPosA;
                args.startPosB           = dummyPathPos;
                args.endPosA             = endPosA;
                args.endPosB             = dummyPathPos;
                args.vehiclePosition     = vehiclePosition;
                args.laneTypes           = laneTypes;
                args.vehicleTypes        = vehicleTypes;
                args.maxLength           = 20000f;
                args.isHeavyVehicle      = false;
                args.hasCombustionEngine = combustionEngine;
                args.ignoreBlocked       = false;
                args.ignoreFlooded       = false;
                args.randomParking       = randomParking;
                args.stablePath          = false;
                args.skipQueue           = false;

                bool res = CustomPathManager._instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, args);
                // NON-STOCK CODE END

                if (res)
                {
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Path-finding starts for citizen instance {instanceID}, path={path}, extVehicleType={extVehicleType}, startPosA.segment={startPosA.m_segment}, startPosA.lane={startPosA.m_lane}, laneType={laneTypes}, vehicleType={vehicleTypes}, endPosA.segment={endPosA.m_segment}, endPosA.lane={endPosA.m_lane}, vehiclePos.m_segment={vehiclePosition.m_segment}, vehiclePos.m_lane={vehiclePosition.m_lane}, vehiclePos.m_offset={vehiclePosition.m_offset}");
                    }
#endif

                    if (citizenData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(citizenData.m_path);
                    }
                    citizenData.m_path   = path;
                    citizenData.m_flags |= CitizenInstance.Flags.WaitingPath;
                    return(true);
                }
            }

#if DEBUG
            if (Options.prohibitPocketCars)
            {
                if (GlobalConfig.Instance.Debug.Switches[2])
                {
                    Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): CustomCitizenAI.CustomStartPathFind: [PFFAIL] failed for citizen instance {instanceID} (CurrentPathMode={extInstance.pathMode}). startPosA.segment={startPosA.m_segment}, startPosA.lane={startPosA.m_lane}, startPosA.offset={startPosA.m_offset}, endPosA.segment={endPosA.m_segment}, endPosA.lane={endPosA.m_lane}, endPosA.offset={endPosA.m_offset}, foundStartPos={foundStartPos}, foundEndPos={foundEndPos}");
                }
            }
#endif
            return(false);
        }
 public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenData, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo)
 {
     return(ExtStartPathFind(instanceID, ref citizenData, ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceID], startPos, endPos, vehicleInfo));
 }
        private static bool CustomFindParkingSpace(VehicleInfo vehicleInfo, ushort homeID, Vector3 refPos, Vector3 searchDir, ushort segmentId, out Vector3 parkPos, out Quaternion parkRot, out float parkOffset)
        {
            float searchRadius           = Options.prohibitPocketCars ? 32f : 16f;
            uint  chanceOfParkingOffRoad = 3u;

            Vector3 searchMagnitude = refPos + searchDir * 16f;

            if (GlobalConfig.RushHourParkingSearchRadius != null)
            {
                searchRadius = (int)GlobalConfig.RushHourParkingSearchRadius;
#if DEBUG
                if (GlobalConfig.Instance.Debug.Switches[2])
                {
                    Log._Debug($"RushHour's Improved Parking AI is active. searchRadius={searchRadius}");
                }
#endif
                chanceOfParkingOffRoad = 80u;
            }
            else
            {
#if DEBUG
                if (GlobalConfig.Instance.Debug.Switches[2])
                {
                    Log._Debug("RushHour's Improved Parking AI is NOT active.");
                }
#endif
            }

            /*if (Options.prohibitPocketCars) {
             *      //searchRadius = Mathf.Max(32f, searchRadius);
             * }*/

            Vector3 refPos2 = refPos + searchDir * 16f;
            if (Singleton <SimulationManager> .instance.m_randomizer.Int32(chanceOfParkingOffRoad) == 0)
            {
                float width  = vehicleInfo.m_generatedInfo.m_size.x;
                float length = vehicleInfo.m_generatedInfo.m_size.z;

                if (FindParkingSpaceRoadSide(0, segmentId, refPos, width - 0.2f, length, out parkPos, out parkRot, out parkOffset))
                {
                    if (Options.parkingRestrictionsEnabled)
                    {
                        Vector3 innerParkPos;
                        uint    laneId;
                        int     laneIndex;
                        float   laneOffset;
                        if (Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].GetClosestLanePosition(refPos, NetInfo.LaneType.Parking, VehicleInfo.VehicleType.Car, out innerParkPos, out laneId, out laneIndex, out laneOffset))
                        {
                            if (ParkingRestrictionsManager.Instance.IsParkingAllowed(segmentId, Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info.m_lanes[laneIndex].m_finalDirection))
                            {
                                return(true);
                            }
                        }
                    }
                    else
                    {
                        return(true);
                    }
                }

                if (AdvancedParkingManager.Instance.FindParkingSpaceBuilding(vehicleInfo, homeID, 0, segmentId, refPos2, GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance, searchRadius, out parkPos, out parkRot, out parkOffset))
                {
                    return(true);
                }
            }
            else
            {
                if (AdvancedParkingManager.Instance.FindParkingSpaceBuilding(vehicleInfo, homeID, 0, segmentId, refPos2, GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance, searchRadius, out parkPos, out parkRot, out parkOffset))
                {
                    return(true);
                }

                float width  = vehicleInfo.m_generatedInfo.m_size.x;
                float length = vehicleInfo.m_generatedInfo.m_size.z;

                if (FindParkingSpaceRoadSide(0, segmentId, refPos, width - 0.2f, length, out parkPos, out parkRot, out parkOffset))
                {
                    if (Options.parkingRestrictionsEnabled)
                    {
                        Vector3 innerParkPos;
                        uint    laneId;
                        int     laneIndex;
                        float   laneOffset;
                        if (Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].GetClosestLanePosition(refPos, NetInfo.LaneType.Parking, VehicleInfo.VehicleType.Car, out innerParkPos, out laneId, out laneIndex, out laneOffset))
                        {
                            if (ParkingRestrictionsManager.Instance.IsParkingAllowed(segmentId, Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info.m_lanes[laneIndex].m_finalDirection))
                            {
                                return(true);
                            }
                        }
                    }
                    else
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
 //
 // BEGIN STOCK CODE
 //
 public new bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPos, PathUnit.Position endPos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength)
 {
     PathUnit.Position position = default(PathUnit.Position);
     return this.CreatePath(out unit, ref randomizer, buildIndex, startPos, position, endPos, position, position, laneTypes, vehicleTypes, maxLength, false, false, false, false);
 }
        /// <summary>
        /// Makes the given citizen instance enter their parked car.
        /// </summary>
        /// <param name="instanceID">Citizen instance id</param>
        /// <param name="instanceData">Citizen instance data</param>
        /// <param name="parkedVehicleId">Parked vehicle id</param>
        /// <param name="vehicleId">Vehicle id</param>
        /// <returns>true if entering the car succeeded, false otherwise</returns>
        public static bool EnterParkedCar(ushort instanceID, ref CitizenInstance instanceData, ushort parkedVehicleId, out ushort vehicleId)
        {
#if DEBUG
            if (GlobalConfig.Instance.Debug.Switches[2])
            {
                Log._Debug($"CustomHumanAI.EnterParkedCar({instanceID}, ..., {parkedVehicleId}) called.");
            }
#endif
            VehicleManager vehManager = Singleton <VehicleManager> .instance;
            NetManager     netManager = Singleton <NetManager> .instance;
            CitizenManager citManager = Singleton <CitizenManager> .instance;

            Vector3     parkedVehPos = vehManager.m_parkedVehicles.m_buffer[parkedVehicleId].m_position;
            Quaternion  parkedVehRot = vehManager.m_parkedVehicles.m_buffer[parkedVehicleId].m_rotation;
            VehicleInfo vehicleInfo  = vehManager.m_parkedVehicles.m_buffer[parkedVehicleId].Info;

            PathUnit.Position vehLanePathPos;
            if (!CustomPathManager._instance.m_pathUnits.m_buffer[instanceData.m_path].GetPosition(0, out vehLanePathPos))
            {
#if DEBUG
                if (GlobalConfig.Instance.Debug.Switches[2])
                {
                    Log._Debug($"CustomHumanAI.EnterParkedCar: Could not get first car path position of citizen instance {instanceID}!");
                }
#endif

                vehicleId = 0;
                return(false);
            }
            uint vehLaneId = PathManager.GetLaneID(vehLanePathPos);
#if DEBUG
            if (GlobalConfig.Instance.Debug.Switches[4])
            {
                Log._Debug($"CustomHumanAI.EnterParkedCar: Determined vehicle position for citizen instance {instanceID}: seg. {vehLanePathPos.m_segment}, lane {vehLanePathPos.m_lane}, off {vehLanePathPos.m_offset} (lane id {vehLaneId})");
            }
#endif

            Vector3 vehLanePos;
            float   vehLaneOff;
            netManager.m_lanes.m_buffer[vehLaneId].GetClosestPosition(parkedVehPos, out vehLanePos, out vehLaneOff);
            byte vehLaneOffset = (byte)Mathf.Clamp(Mathf.RoundToInt(vehLaneOff * 255f), 0, 255);

            // movement vector from parked vehicle position to road position
            Vector3 forwardVector = parkedVehPos + Vector3.ClampMagnitude(vehLanePos - parkedVehPos, 5f);
            if (vehManager.CreateVehicle(out vehicleId, ref Singleton <SimulationManager> .instance.m_randomizer, vehicleInfo, parkedVehPos, TransferManager.TransferReason.None, false, false))
            {
                // update frame data
                Vehicle.Frame frame = vehManager.m_vehicles.m_buffer[(int)vehicleId].m_frame0;
                frame.m_rotation = parkedVehRot;

                vehManager.m_vehicles.m_buffer[vehicleId].m_frame0 = frame;
                vehManager.m_vehicles.m_buffer[vehicleId].m_frame1 = frame;
                vehManager.m_vehicles.m_buffer[vehicleId].m_frame2 = frame;
                vehManager.m_vehicles.m_buffer[vehicleId].m_frame3 = frame;
                vehicleInfo.m_vehicleAI.FrameDataUpdated(vehicleId, ref vehManager.m_vehicles.m_buffer[vehicleId], ref frame);

                // update vehicle target position
                vehManager.m_vehicles.m_buffer[vehicleId].m_targetPos0 = new Vector4(vehLanePos.x, vehLanePos.y, vehLanePos.z, 2f);

                // update other fields
                vehManager.m_vehicles.m_buffer[vehicleId].m_flags             = (vehManager.m_vehicles.m_buffer[vehicleId].m_flags | Vehicle.Flags.Stopped);
                vehManager.m_vehicles.m_buffer[vehicleId].m_path              = instanceData.m_path;
                vehManager.m_vehicles.m_buffer[vehicleId].m_pathPositionIndex = 0;
                vehManager.m_vehicles.m_buffer[vehicleId].m_lastPathOffset    = vehLaneOffset;
                vehManager.m_vehicles.m_buffer[vehicleId].m_transferSize      = (ushort)(instanceData.m_citizen & 65535u);

                if (!vehicleInfo.m_vehicleAI.TrySpawn(vehicleId, ref vehManager.m_vehicles.m_buffer[vehicleId]))
                {
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomHumanAI.EnterParkedCar: Could not spawn a {vehicleInfo.m_vehicleType} for citizen instance {instanceID}!");
                    }
#endif
                    return(false);
                }

                // change instances
                InstanceID parkedVehInstance = InstanceID.Empty;
                parkedVehInstance.ParkedVehicle = parkedVehicleId;
                InstanceID vehInstance = InstanceID.Empty;
                vehInstance.Vehicle = vehicleId;
                Singleton <InstanceManager> .instance.ChangeInstance(parkedVehInstance, vehInstance);

                // set vehicle id for citizen instance
                instanceData.m_path = 0u;
                citManager.m_citizens.m_buffer[instanceData.m_citizen].SetParkedVehicle(instanceData.m_citizen, 0);
                citManager.m_citizens.m_buffer[instanceData.m_citizen].SetVehicle(instanceData.m_citizen, vehicleId, 0u);

                // update citizen instance flags
                instanceData.m_flags      &= ~CitizenInstance.Flags.WaitingPath;
                instanceData.m_flags      &= ~CitizenInstance.Flags.EnteringVehicle;
                instanceData.m_flags      &= ~CitizenInstance.Flags.TryingSpawnVehicle;
                instanceData.m_flags      &= ~CitizenInstance.Flags.BoredOfWaiting;
                instanceData.m_waitCounter = 0;

                // unspawn citizen instance
                instanceData.Unspawn(instanceID);

#if DEBUG
                if (GlobalConfig.Instance.Debug.Switches[4])
                {
                    Log._Debug($"CustomHumanAI.EnterParkedCar: Citizen instance {instanceID} is now entering vehicle {vehicleId}. Set vehicle target position to {vehLanePos} (segment={vehLanePathPos.m_segment}, lane={vehLanePathPos.m_lane}, offset={vehLanePathPos.m_offset})");
                }
#endif

                return(true);
            }
            else
            {
                // failed to find a road position
#if DEBUG
                if (GlobalConfig.Instance.Debug.Switches[2])
                {
                    Log._Debug($"CustomHumanAI.EnterParkedCar: Could not find a road position for citizen instance {instanceID} near parked vehicle {parkedVehicleId}!");
                }
#endif
                return(false);
            }
        }
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
#if DEBUG
            if (GlobalConfig.Instance.Debug.Switches[2])
            {
                Log.Warning($"CustomCarAI.CustomStartPathFind({vehicleID}): called for vehicle {vehicleID}, startPos={startPos}, endPos={endPos}, startBothWays={startBothWays}, endBothWays={endBothWays}, undergroundTarget={undergroundTarget}");
            }
#endif

            ExtVehicleType vehicleType = VehicleStateManager.Instance.OnStartPathFind(vehicleID, ref vehicleData, null);
            if (vehicleType == ExtVehicleType.None)
            {
#if DEBUG
                Log.Warning($"CustomCarAI.CustomStartPathFind({vehicleID}): Vehicle {vehicleID} does not have a valid vehicle type!");
#endif
                vehicleType = ExtVehicleType.RoadVehicle;
            }

            VehicleInfo       info             = this.m_info;
            bool              allowUnderground = (vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0;
            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float             startDistSqrA;
            float             startDistSqrB;
            PathUnit.Position endPosA;
            PathUnit.Position endPosB;
            float             endDistSqrA;
            float             endDistSqrB;
            if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out startDistSqrA, out startDistSqrB) &&
                CustomPathManager.FindPathPosition(endPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, undergroundTarget, false, 32f, out endPosA, out endPosB, out endDistSqrA, out endDistSqrB))
            {
                if (!startBothWays || startDistSqrA < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                if (!endBothWays || endDistSqrA < 10f)
                {
                    endPosB = default(PathUnit.Position);
                }
                uint path;

                // NON-STOCK CODE START
                if (CustomPathManager._instance.CreatePath((ExtVehicleType)vehicleType, vehicleID, ExtCitizenInstance.ExtPathType.None, out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle, info.m_vehicleType, 20000f, this.IsHeavyVehicle(), this.IgnoreBlocked(vehicleID, ref vehicleData), false, (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0))
                {
#if DEBUG
                    if (GlobalConfig.Instance.Debug.Switches[2])
                    {
                        Log._Debug($"CustomCarAI.CustomStartPathFind({vehicleID}): Path-finding starts for vehicle {vehicleID}, path={path}, extVehicleType={vehicleType}, startPosA.segment={startPosA.m_segment}, startPosA.lane={startPosA.m_lane}, info.m_vehicleType={info.m_vehicleType}, endPosA.segment={endPosA.m_segment}, endPosA.lane={endPosA.m_lane}");
                    }
#endif

                    // NON-STOCK CODE END
                    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);
        }
示例#26
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
        }
示例#27
0
 public bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, PathUnit.Position vehiclePosition, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, bool isHeavyVehicle, bool ignoreBlocked, bool stablePath, bool skipQueue, RoadManager.VehicleType vehicleType)
 {
     while (!Monitor.TryEnter(this.m_bufferLock, SimulationManager.SYNCHRONIZE_TIMEOUT))
     {
     }
     uint num;
     try
     {
         if (!this.m_pathUnits.CreateItem(out num, ref randomizer))
         {
             unit = 0u;
             bool result = false;
             return result;
         }
         this.m_pathUnitCount = (int)(this.m_pathUnits.ItemCount() - 1u);
     }
     finally
     {
         Monitor.Exit(this.m_bufferLock);
     }
     unit = num;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags = 1;
     if (isHeavyVehicle)
     {
         PathUnit[] expr_92_cp_0 = this.m_pathUnits.m_buffer;
         UIntPtr expr_92_cp_1 = (UIntPtr)unit;
         expr_92_cp_0[(int)expr_92_cp_1].m_simulationFlags = (byte)(expr_92_cp_0[(int)expr_92_cp_1].m_simulationFlags | 16);
     }
     if (ignoreBlocked)
     {
         PathUnit[] expr_BB_cp_0 = this.m_pathUnits.m_buffer;
         UIntPtr expr_BB_cp_1 = (UIntPtr)unit;
         expr_BB_cp_0[(int)expr_BB_cp_1].m_simulationFlags = (byte)(expr_BB_cp_0[(int)expr_BB_cp_1].m_simulationFlags | 32);
     }
     if (stablePath)
     {
         PathUnit[] expr_E4_cp_0 = this.m_pathUnits.m_buffer;
         UIntPtr expr_E4_cp_1 = (UIntPtr)unit;
         expr_E4_cp_0[(int)expr_E4_cp_1].m_simulationFlags = (byte)(expr_E4_cp_0[(int)expr_E4_cp_1].m_simulationFlags | 64);
     }
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_pathFindFlags = 0;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_buildIndex = buildIndex;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position00 = startPosA;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position01 = endPosA;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position02 = startPosB;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position03 = endPosB;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position11 = vehiclePosition;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_nextPathUnit = 0u;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_laneTypes = (byte)laneTypes;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_vehicleTypes = (byte)vehicleTypes;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_length = maxLength;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount = 20;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_referenceCount = 1;
     int num2 = 10000000;
     CustomPathFind pathFind = null;
     for (int i = 0; i < this.m_pathFinds.Length; i++)
     {
         CustomPathFind pathFind2 = this.m_pathFinds[i];
         if (pathFind2.IsAvailable && pathFind2.m_queuedPathFindCount < num2)
         {
             num2 = pathFind2.m_queuedPathFindCount;
             pathFind = pathFind2;
         }
     }
     if (pathFind != null && pathFind.CalculatePath(unit, skipQueue, vehicleType))
     {
         return true;
     }
     this.ReleasePath(unit);
     return false;
 }
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
#if DEBUG
            //Log._Debug($"CustomBusAI.CustomStartPathFind called for vehicle {vehicleID}");
#endif

            VehicleInfo       info             = this.m_info;
            bool              allowUnderground = (vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0;
            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float             startDistSqrA;
            float             startDistSqrB;
            PathUnit.Position endPosA;
            PathUnit.Position endPosB;
            float             endDistSqrA;
            float             endDistSqrB;
            if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out startDistSqrA, out startDistSqrB) &&
                CustomPathManager.FindPathPosition(endPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, undergroundTarget, false, 32f, out endPosA, out endPosB, out endDistSqrA, out endDistSqrB))
            {
                if (!startBothWays || startDistSqrA < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                if (!endBothWays || endDistSqrA < 10f)
                {
                    endPosB = default(PathUnit.Position);
                }
                uint path;
                // NON-STOCK CODE START
                PathCreationArgs args;
                args.extPathType         = ExtCitizenInstance.ExtPathType.None;
                args.extVehicleType      = ExtVehicleType.Bus;
                args.vehicleId           = vehicleID;
                args.spawned             = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0;
                args.buildIndex          = Singleton <SimulationManager> .instance.m_currentBuildIndex;
                args.startPosA           = startPosA;
                args.startPosB           = startPosB;
                args.endPosA             = endPosA;
                args.endPosB             = endPosB;
                args.vehiclePosition     = default(PathUnit.Position);
                args.laneTypes           = NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle;
                args.vehicleTypes        = info.m_vehicleType;
                args.maxLength           = 20000f;
                args.isHeavyVehicle      = this.IsHeavyVehicle();
                args.hasCombustionEngine = this.CombustionEngine();
                args.ignoreBlocked       = this.IgnoreBlocked(vehicleID, ref vehicleData);
                args.ignoreFlooded       = false;
                args.randomParking       = false;
                args.ignoreCosts         = false;
                args.stablePath          = true;
                args.skipQueue           = true;

                if (CustomPathManager._instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, args))
                {
                    // NON-STOCK CODE END

                    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 static bool GetStopLane(ref PathUnit.Position pos, VehicleInfo.VehicleType vehicleType) {
			if (pos.m_segment != 0) {
				NetManager instance = Singleton<NetManager>.instance;
				int num;
				uint num2;
				if (instance.m_segments.m_buffer[(int)pos.m_segment].GetClosestLane((int)pos.m_lane, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, vehicleType, out num, out num2)) {
					pos.m_lane = (byte)num;
					return true;
				}
			}
			pos = default(PathUnit.Position);
			return false;
		}
示例#30
0
 public static new bool UpdatePath(ushort segmentID, ref NetSegment data, ItemClass.Service netService, VehicleInfo.VehicleType vehicleType, bool skipQueue)
 {
     if (data.m_path == 0u)
     {
         return BusTransportLineAI.StartPathFind(segmentID, ref data, netService, vehicleType, skipQueue);
     }
     if ((data.m_flags & NetSegment.Flags.WaitingPath) == NetSegment.Flags.None)
     {
         return true;
     }
     PathManager instance = Singleton<PathManager>.instance;
     NetManager instance2 = Singleton<NetManager>.instance;
     byte pathFindFlags = instance.m_pathUnits.m_buffer[(int)((UIntPtr)data.m_path)].m_pathFindFlags;
     if ((pathFindFlags & 4) != 0)
     {
         bool flag = false;
         PathUnit.Position pathPos;
         if (instance.m_pathUnits.m_buffer[(int)((UIntPtr)data.m_path)].GetPosition(0, out pathPos))
         {
             flag = TransportLineAI.CheckNodePosition(data.m_startNode, pathPos);
         }
         if (instance.m_pathUnits.m_buffer[(int)((UIntPtr)data.m_path)].GetLastPosition(out pathPos))
         {
             TransportLineAI.CheckNodePosition(data.m_endNode, pathPos);
         }
         float length = instance.m_pathUnits.m_buffer[(int)((UIntPtr)data.m_path)].m_length;
         if (length != data.m_averageLength)
         {
             data.m_averageLength = length;
             ushort transportLine = instance2.m_nodes.m_buffer[(int)data.m_startNode].m_transportLine;
             if (transportLine != 0)
             {
                 Singleton<TransportManager>.instance.UpdateLine(transportLine);
             }
         }
         if (data.m_lanes != 0u)
         {
             instance2.m_lanes.m_buffer[(int)((UIntPtr)data.m_lanes)].m_length = data.m_averageLength * ((!flag) ? 1f : 0.75f);
         }
         data.m_flags &= ~NetSegment.Flags.WaitingPath;
         data.m_flags &= ~NetSegment.Flags.PathFailed;
         return true;
     }
     if ((pathFindFlags & 8) != 0)
     {
         if (data.m_averageLength == 0f)
         {
             Vector3 position = instance2.m_nodes.m_buffer[(int)data.m_startNode].m_position;
             Vector3 position2 = instance2.m_nodes.m_buffer[(int)data.m_endNode].m_position;
             data.m_averageLength = Vector3.Distance(position, position2);
         }
         data.m_flags &= ~NetSegment.Flags.WaitingPath;
         data.m_flags |= NetSegment.Flags.PathFailed;
         return true;
     }
     return false;
 }
        public string CustomGetLocalizedStatus(ushort instanceID, ref CitizenInstance data, out InstanceID target)
        {
            if ((data.m_flags & (CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating)) != CitizenInstance.Flags.None)
            {
                target = InstanceID.Empty;
                return(Locale.Get("CITIZEN_STATUS_CONFUSED"));
            }
            CitizenManager instance  = Singleton <CitizenManager> .instance;
            uint           citizenId = data.m_citizen;
            ushort         vehicleId = 0;

            if (citizenId != 0u)
            {
                vehicleId = instance.m_citizens.m_buffer[citizenId].m_vehicle;
            }
            ushort targetBuilding = data.m_targetBuilding;

            if (targetBuilding == 0)
            {
                target = InstanceID.Empty;
                return(Locale.Get("CITIZEN_STATUS_CONFUSED"));
            }
            bool   flag  = (Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)targetBuilding].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None;
            bool   flag2 = data.m_path == 0u && (data.m_flags & CitizenInstance.Flags.HangAround) != CitizenInstance.Flags.None;
            String ret   = "";

            if (vehicleId != 0)
            {
                VehicleManager instance2 = Singleton <VehicleManager> .instance;
                VehicleInfo    info      = instance2.m_vehicles.m_buffer[(int)vehicleId].Info;
                if (info.m_class.m_service == ItemClass.Service.Residential && info.m_vehicleType != VehicleInfo.VehicleType.Bicycle)
                {
                    if (info.m_vehicleAI.GetOwnerID(vehicleId, ref instance2.m_vehicles.m_buffer[(int)vehicleId]).Citizen == citizenId)
                    {
                        if (flag)
                        {
                            target = InstanceID.Empty;
                            return(Locale.Get("CITIZEN_STATUS_DRIVINGTO_OUTSIDE"));
                        }

                        target          = InstanceID.Empty;
                        target.Building = targetBuilding;
                        return(Locale.Get("CITIZEN_STATUS_DRIVINGTO"));
                    }
                }
                else if (info.m_class.m_service == ItemClass.Service.PublicTransport || info.m_class.m_service == ItemClass.Service.Disaster)
                {
                    if (flag)
                    {
                        target = InstanceID.Empty;
                        return(Locale.Get("CITIZEN_STATUS_TRAVELLINGTO_OUTSIDE"));
                    }
                    target          = InstanceID.Empty;
                    target.Building = targetBuilding;
                    return(Locale.Get("CITIZEN_STATUS_TRAVELLINGTO"));
                }
            }
            if (flag)
            {
                target = InstanceID.Empty;
                return(Locale.Get("CITIZEN_STATUS_GOINGTO_OUTSIDE"));
            }
            if (flag2)
            {
                target          = InstanceID.Empty;
                target.Building = targetBuilding;
                return(Locale.Get("CITIZEN_STATUS_VISITING"));
            }
            target          = InstanceID.Empty;
            target.Building = targetBuilding;
            ret             = Locale.Get("CITIZEN_STATUS_GOINGTO");

            // NON-STOCK CODE START
#if BENCHMARK
            using (var bm = new Benchmark(null, "EnrichLocalizedCitizenStatus")) {
#endif
            if (Options.prohibitPocketCars)
            {
                ret = AdvancedParkingManager.Instance.EnrichLocalizedCitizenStatus(ret, ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceID]);
            }
#if BENCHMARK
        }
#endif
            // NON-STOCK CODE END
            return(ret);
        }
示例#32
0
 public void ApplySpeedMultiplier(VehicleInfo vehicle)
 {
     vehicle.m_acceleration *= speedMultiplier;
     //vehicle.m_braking *= speedMultiplier;
     //vehicle.m_turning *= speedMultiplier;
     vehicle.m_maxSpeed *= speedMultiplier;
 }
        public VehicleInfo CustomGetVehicleInfo(ushort instanceId,
                                                ref CitizenInstance citizenData,
                                                bool forceCar,
                                                out VehicleInfo trailer)
        {
#if DEBUG
            bool citizenDebug = (DebugSettings.CitizenInstanceId == 0 ||
                                 DebugSettings.CitizenInstanceId == instanceId) &&
                                (DebugSettings.CitizenId == 0 ||
                                 DebugSettings.CitizenId == citizenData.m_citizen) &&
                                (DebugSettings.SourceBuildingId == 0 ||
                                 DebugSettings.SourceBuildingId == citizenData.m_sourceBuilding) &&
                                (DebugSettings.TargetBuildingId == 0 ||
                                 DebugSettings.TargetBuildingId == citizenData.m_targetBuilding);
            bool logParkingAi = DebugSwitch.BasicParkingAILog.Get() && citizenDebug;
#else
            var logParkingAi = false;
#endif
            trailer = null;

            if (citizenData.m_citizen == 0u)
            {
                return(null);
            }

            // NON-STOCK CODE START
            bool forceTaxi = false;
            if (Options.parkingAI)
            {
                if (ExtCitizenInstanceManager.Instance.ExtInstances[instanceId]
                    .pathMode == ExtPathMode.TaxiToTarget)
                {
                    forceTaxi = true;
                }
            }

            // NON-STOCK CODE END
            Citizen.AgeGroup ageGroup =
                Constants.ManagerFactory.ExtCitizenManager.GetAgeGroup(citizenData.Info.m_agePhase);

            int carProb;
            int bikeProb;
            int taxiProb;

            // NON-STOCK CODE START
            if (forceTaxi)
            {
                carProb  = 0;
                bikeProb = 0;
                taxiProb = 100;
            }
            else   // NON-STOCK CODE END
            if (forceCar ||
                (citizenData.m_flags & CitizenInstance.Flags.BorrowCar) !=
                CitizenInstance.Flags.None)
            {
                carProb  = 100;
                bikeProb = 0;
                taxiProb = 0;
            }
            else
            {
                carProb  = GetCarProbability(instanceId, ref citizenData, ageGroup);
                bikeProb = GetBikeProbability(instanceId, ref citizenData, ageGroup);
                taxiProb = GetTaxiProbability(instanceId, ref citizenData, ageGroup);
            }

            Randomizer randomizer     = new Randomizer(citizenData.m_citizen);
            bool       useCar         = randomizer.Int32(100u) < carProb;
            bool       useBike        = !useCar && randomizer.Int32(100u) < bikeProb;
            bool       useTaxi        = !useCar && !useBike && randomizer.Int32(100u) < taxiProb;
            bool       useElectricCar = false;

            if (useCar)
            {
                int electricProb = GetElectricCarProbability(
                    instanceId,
                    ref citizenData,
                    m_info.m_agePhase);
                useElectricCar = randomizer.Int32(100u) < electricProb;
            }

            ItemClass.Service    service    = ItemClass.Service.Residential;
            ItemClass.SubService subService = useElectricCar
                                 ? ItemClass.SubService.ResidentialLowEco
                                 : ItemClass.SubService.ResidentialLow;
            if (useTaxi)
            {
                service    = ItemClass.Service.PublicTransport;
                subService = ItemClass.SubService.PublicTransportTaxi;
            }

            // NON-STOCK CODE START
            VehicleInfo carInfo = null;
            if (Options.parkingAI && useCar)
            {
                ushort parkedVehicleId = Singleton <CitizenManager>
                                         .instance.m_citizens.m_buffer[citizenData.m_citizen]
                                         .m_parkedVehicle;

                if (parkedVehicleId != 0)
                {
                    Log._DebugIf(
                        logParkingAi,
                        () => $"CustomResidentAI.CustomGetVehicleInfo({instanceId}): " +
                        $"Citizen instance {instanceId} owns a parked vehicle {parkedVehicleId}. " +
                        $"Reusing vehicle info.");
                    carInfo = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info;
                }
            }

            if (carInfo == null && (useCar || useTaxi))
            {
                // NON-STOCK CODE END
                carInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(
                    ref randomizer,
                    service,
                    subService,
                    ItemClass.Level.Level1);
            }

            if (useBike)
            {
                ItemClass.Level ageGroupLvl = ageGroup != Citizen.AgeGroup.Child
                                      ? ItemClass.Level.Level2
                                      : ItemClass.Level.Level1;
                VehicleInfo bikeInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(
                    ref randomizer,
                    ItemClass.Service.Residential,
                    ItemClass.SubService.ResidentialHigh,
                    ageGroupLvl);

                if (bikeInfo != null)
                {
                    return(bikeInfo);
                }
            }

            if ((useCar || useTaxi) && carInfo != null)
            {
                return(carInfo);
            }

            return(null);
        }
        private IEnumerable<Vehicle> GetValidVehicles(VehicleInfo.VehicleType vType, int? districId)
        {
            Vehicle[] vehicles = Singleton<VehicleManager>.instance.m_vehicles.m_buffer;
            if (vehicles == null)
                yield break;

            var districtManager = Singleton<DistrictManager>.instance;
            foreach (var vehicle in vehicles)
            {
                if (!((vehicle.Info.m_vehicleType & vType) == vType))
                {
                    continue;
                }

                if (!((vehicle.m_flags & Vehicle.Flags.Created) == Vehicle.Flags.Created))
                {
                    continue;
                }

                if (!((vehicle.m_flags & Vehicle.Flags.Spawned) == Vehicle.Flags.Spawned))
                {
                    continue;
                }

                if (vehicle.m_leadingVehicle != 0)
                {
                    continue;
                }

                if (districId.HasValue)
                {
                    var vehicleDistrictID = (int)districtManager.GetDistrict(vehicle.GetLastFramePosition());
                    if (vehicleDistrictID != districId.Value)
                        continue;
                }

                yield return vehicle;
            }
        }
示例#35
0
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
            ExtVehicleType?vehicleType = VehicleStateManager.DetermineVehicleType(vehicleID, ref vehicleData);

#if PATHRECALC
            VehicleState state           = VehicleStateManager._GetVehicleState(vehicleID);
            bool         recalcRequested = state.PathRecalculationRequested;
            state.PathRecalculationRequested = false;
#endif

            /*if (vehicleType == null) {
             *      Log._Debug($"CustomCarAI.CustomStartPathFind: Could not determine ExtVehicleType from class type. typeof this={this.GetType().ToString()}");
             * } else {
             *      Log._Debug($"CustomCarAI.CustomStartPathFind: vehicleType={vehicleType}. typeof this={this.GetType().ToString()}");
             * }*/

            VehicleInfo       info             = this.m_info;
            bool              allowUnderground = (vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0;
            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float             num;
            float             num2;
            PathUnit.Position endPosA;
            PathUnit.Position endPosB;
            float             num3;
            float             num4;
            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) &&
                CustomPathManager.FindPathPosition(endPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, undergroundTarget, false, 32f, out endPosA, out endPosB, out num3, out num4))
            {
                if (!startBothWays || num < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                if (!endBothWays || num3 < 10f)
                {
                    endPosB = default(PathUnit.Position);
                }
                uint path;
                bool res = false;
                if (vehicleType == null)
                {
                    res = Singleton <CustomPathManager> .instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle, info.m_vehicleType, 20000f, this.IsHeavyVehicle(), this.IgnoreBlocked(vehicleID, ref vehicleData), false, false);
                }
                else
                {
                    res = Singleton <CustomPathManager> .instance.CreatePath(
#if PATHRECALC
                        recalcRequested,
#endif
                        (ExtVehicleType)vehicleType, out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, ref startPosA, ref startPosB, ref endPosA, ref endPosB, NetInfo.LaneType.Vehicle, info.m_vehicleType, 20000f, this.IsHeavyVehicle(), this.IgnoreBlocked(vehicleID, ref vehicleData), false, false);
                }
                if (res)
                {
                    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 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)
            {
                byte pathFindFlags = Singleton <PathManager> .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
                    try {
                        this.PathfindSuccess(vehicleId, ref vehicleData);
                        this.PathFindReady(vehicleId, ref vehicleData);
                        VehicleStateManager.OnPathFindReady(vehicleId, ref vehicleData);                         // NON-STOCK CODE
                    } catch (Exception e) {
                        Log.Warning($"TramBaseAI.PathFindSuccess/PathFindReady({vehicleId}) threw an exception: {e.ToString()}");
                        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 ((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);
                }
            }

            /// NON-STOCK CODE START ///
            bool   reversed = (vehicleData.m_flags & Vehicle.Flags.Reversed) != 0;
            ushort frontVehicleId;
            if (reversed)
            {
                frontVehicleId = vehicleData.GetLastVehicle(vehicleId);
            }
            else
            {
                frontVehicleId = vehicleId;
            }

            try {
                //Log._Debug($"HandleVehicle for trams. vehicleId={vehicleId} frontVehicleId={frontVehicleId}");
                VehicleStateManager.LogTraffic(frontVehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[frontVehicleId], true);
            } catch (Exception e) {
                Log.Error("TramAI CustomSimulationStep (1) Error: " + e.ToString());
            }

            try {
                VehicleStateManager.UpdateVehiclePos(frontVehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[frontVehicleId]);
            } catch (Exception e) {
                Log.Error("TramAI CustomSimulationStep (2) Error: " + e.ToString());
            }
            /// NON-STOCK CODE END ///

            VehicleManager instance = Singleton <VehicleManager> .instance;
            VehicleInfo    info     = instance.m_vehicles.m_buffer[(int)vehicleId].Info;
            info.m_vehicleAI.SimulationStep(vehicleId, ref instance.m_vehicles.m_buffer[(int)vehicleId], vehicleId, ref vehicleData, 0);
            if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created)
            {
                return;
            }
            ushort trailingVehicle = instance.m_vehicles.m_buffer[(int)vehicleId].m_trailingVehicle;
            int    num             = 0;
            while (trailingVehicle != 0)
            {
                info = instance.m_vehicles.m_buffer[(int)trailingVehicle].Info;
                info.m_vehicleAI.SimulationStep(trailingVehicle, ref instance.m_vehicles.m_buffer[(int)trailingVehicle], vehicleId, ref vehicleData, 0);
                if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created)
                {
                    return;
                }
                trailingVehicle = instance.m_vehicles.m_buffer[(int)trailingVehicle].m_trailingVehicle;
                if (++num > 16384)
                {
                    CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                    break;
                }
            }
            if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace | Vehicle.Flags.WaitingCargo)) == 0 || (vehicleData.m_blockCounter == 255 && Options.enableDespawning))
            {
                Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);
            }
        }
示例#37
0
 public static new bool StartPathFind(ushort segmentID, ref NetSegment data, ItemClass.Service netService, VehicleInfo.VehicleType vehicleType, bool skipQueue)
 {
     if (data.m_path != 0u)
     {
         Singleton<PathManager>.instance.ReleasePath(data.m_path);
         data.m_path = 0u;
     }
     NetManager instance = Singleton<NetManager>.instance;
     if ((instance.m_nodes.m_buffer[(int)data.m_startNode].m_flags & NetNode.Flags.Ambiguous) != NetNode.Flags.None)
     {
         for (int i = 0; i < 8; i++)
         {
             ushort segment = instance.m_nodes.m_buffer[(int)data.m_startNode].GetSegment(i);
             if (segment != 0 && segment != segmentID && instance.m_segments.m_buffer[(int)segment].m_path != 0u)
             {
                 return true;
             }
         }
     }
     if ((instance.m_nodes.m_buffer[(int)data.m_endNode].m_flags & NetNode.Flags.Ambiguous) != NetNode.Flags.None)
     {
         for (int j = 0; j < 8; j++)
         {
             ushort segment2 = instance.m_nodes.m_buffer[(int)data.m_endNode].GetSegment(j);
             if (segment2 != 0 && segment2 != segmentID && instance.m_segments.m_buffer[(int)segment2].m_path != 0u)
             {
                 return true;
             }
         }
     }
     Vector3 position = instance.m_nodes.m_buffer[(int)data.m_startNode].m_position;
     Vector3 position2 = instance.m_nodes.m_buffer[(int)data.m_endNode].m_position;
     PathUnit.Position startPosA;
     PathUnit.Position startPosB;
     float num;
     float num2;
     if (!PathManager.FindPathPosition(position, netService, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, true, false, 32f, out startPosA, out startPosB, out num, out num2))
     {
         return true;
     }
     PathUnit.Position endPosA;
     PathUnit.Position endPosB;
     float num3;
     float num4;
     if (!PathManager.FindPathPosition(position2, netService, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, true, false, 32f, out endPosA, out endPosB, out num3, out num4))
     {
         return true;
     }
     if ((instance.m_nodes.m_buffer[(int)data.m_startNode].m_flags & NetNode.Flags.Fixed) != NetNode.Flags.None)
     {
         startPosB = default(PathUnit.Position);
     }
     if ((instance.m_nodes.m_buffer[(int)data.m_endNode].m_flags & NetNode.Flags.Fixed) != NetNode.Flags.None)
     {
         endPosB = default(PathUnit.Position);
     }
     startPosA.m_offset = 128;
     startPosB.m_offset = 128;
     endPosA.m_offset = 128;
     endPosB.m_offset = 128;
     bool stopLane = BusTransportLineAI.GetStopLane(ref startPosA, vehicleType);
     bool stopLane2 = BusTransportLineAI.GetStopLane(ref startPosB, vehicleType);
     bool stopLane3 = BusTransportLineAI.GetStopLane(ref endPosA, vehicleType);
     bool stopLane4 = BusTransportLineAI.GetStopLane(ref endPosB, vehicleType);
     if ((!stopLane && !stopLane2) || (!stopLane3 && !stopLane4))
     {
         return true;
     }
     uint path;
     bool createPathResult;
     CustomPathManager customPathManager = Singleton<PathManager>.instance as CustomPathManager;
     if (customPathManager != null)
         createPathResult = customPathManager.CreatePath(out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, vehicleType, 20000f, false, true, true, skipQueue, RoadManager.VehicleType.Bus);
     else
         createPathResult = Singleton<PathManager>.instance.CreatePath(out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, vehicleType, 20000f, false, true, true, skipQueue);
     if (createPathResult)
     {
         if (startPosA.m_segment != 0 && startPosB.m_segment != 0)
         {
             NetNode[] expr_2D9_cp_0 = instance.m_nodes.m_buffer;
             ushort expr_2D9_cp_1 = data.m_startNode;
             expr_2D9_cp_0[(int)expr_2D9_cp_1].m_flags = (expr_2D9_cp_0[(int)expr_2D9_cp_1].m_flags | NetNode.Flags.Ambiguous);
         }
         else
         {
             NetNode[] expr_305_cp_0 = instance.m_nodes.m_buffer;
             ushort expr_305_cp_1 = data.m_startNode;
             expr_305_cp_0[(int)expr_305_cp_1].m_flags = (expr_305_cp_0[(int)expr_305_cp_1].m_flags & ~NetNode.Flags.Ambiguous);
         }
         if (endPosA.m_segment != 0 && endPosB.m_segment != 0)
         {
             NetNode[] expr_344_cp_0 = instance.m_nodes.m_buffer;
             ushort expr_344_cp_1 = data.m_endNode;
             expr_344_cp_0[(int)expr_344_cp_1].m_flags = (expr_344_cp_0[(int)expr_344_cp_1].m_flags | NetNode.Flags.Ambiguous);
         }
         else
         {
             NetNode[] expr_370_cp_0 = instance.m_nodes.m_buffer;
             ushort expr_370_cp_1 = data.m_endNode;
             expr_370_cp_0[(int)expr_370_cp_1].m_flags = (expr_370_cp_0[(int)expr_370_cp_1].m_flags & ~NetNode.Flags.Ambiguous);
         }
         data.m_path = path;
         data.m_flags |= NetSegment.Flags.WaitingPath;
         return false;
     }
     return true;
 }
        public void CustomSimulationStep(ushort instanceId,
                                         ref CitizenInstance instanceData,
                                         Vector3 physicsLodRefPos)
        {
#if DEBUG
            bool citizenDebug = (DebugSettings.CitizenInstanceId == 0 ||
                                 DebugSettings.CitizenInstanceId == instanceId) &&
                                (DebugSettings.CitizenId == 0 ||
                                 DebugSettings.CitizenId == instanceData.m_citizen) &&
                                (DebugSettings.SourceBuildingId == 0 ||
                                 DebugSettings.SourceBuildingId == instanceData.m_sourceBuilding) &&
                                (DebugSettings.TargetBuildingId == 0 ||
                                 DebugSettings.TargetBuildingId == instanceData.m_targetBuilding);
            bool logParkingAi = DebugSwitch.BasicParkingAILog.Get() && citizenDebug;
#else
            var logParkingAi = false;
#endif
            CitizenManager citizenManager = Singleton <CitizenManager> .instance;
            uint           citizenId      = instanceData.m_citizen;

            if ((instanceData.m_flags & (CitizenInstance.Flags.Blown
                                         | CitizenInstance.Flags.Floating)) != CitizenInstance.Flags.None &&
                (instanceData.m_flags & CitizenInstance.Flags.Character) == CitizenInstance.Flags.None)
            {
                citizenManager.ReleaseCitizenInstance(instanceId);
                if (citizenId != 0u)
                {
                    citizenManager.ReleaseCitizen(citizenId);
                }

                return;
            }

            Citizen[] citizensBuffer = citizenManager.m_citizens.m_buffer;
            if ((instanceData.m_flags & CitizenInstance.Flags.WaitingPath) != CitizenInstance.Flags.None)
            {
                PathManager pathManager   = Singleton <PathManager> .instance;
                byte        pathFindFlags = pathManager.m_pathUnits.m_buffer[instanceData.m_path].m_pathFindFlags;

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

                if (logParkingAi)
                {
                    Log._Debug(
                        $"CustomHumanAI.CustomSimulationStep({instanceId}): " +
                        $"Path: {instanceData.m_path}, mainPathState={mainPathState}");
                }

                ExtSoftPathState finalPathState;
                using (var bm = Benchmark.MaybeCreateBenchmark(
                           null,
                           "ConvertPathStateToSoftPathState+UpdateCitizenPathState"))
                {
                    finalPathState = ExtCitizenInstance.ConvertPathStateToSoftPathState(mainPathState);

                    if (Options.parkingAI)
                    {
                        finalPathState = AdvancedParkingManager.Instance.UpdateCitizenPathState(
                            instanceId,
                            ref instanceData,
                            ref ExtCitizenInstanceManager
                            .Instance.ExtInstances[
                                instanceId],
                            ref ExtCitizenManager
                            .Instance.ExtCitizens[
                                citizenId],
                            ref citizensBuffer[
                                instanceData.m_citizen],
                            mainPathState);
                        if (logParkingAi)
                        {
                            Log._Debug(
                                $"CustomHumanAI.CustomSimulationStep({instanceId}): " +
                                $"Applied Parking AI logic. Path: {instanceData.m_path}, " +
                                $"mainPathState={mainPathState}, finalPathState={finalPathState}, " +
                                $"extCitizenInstance={ExtCitizenInstanceManager.Instance.ExtInstances[instanceId]}");
                        }
                    } // if Options.parkingAi
                }

                switch (finalPathState)
                {
                case ExtSoftPathState.Ready: {
                    if (logParkingAi)
                    {
                        Log._Debug(
                            $"CustomHumanAI.CustomSimulationStep({instanceId}): Path-finding " +
                            $"succeeded for citizen instance {instanceId} " +
                            $"(finalPathState={finalPathState}). Path: {instanceData.m_path} " +
                            "-- calling HumanAI.PathfindSuccess");
                    }

                    if (citizenId == 0 ||
                        citizensBuffer[instanceData.m_citizen].m_vehicle == 0)
                    {
                        Spawn(instanceId, ref instanceData);
                    }

                    instanceData.m_pathPositionIndex = 255;
                    instanceData.m_flags            &= ~CitizenInstance.Flags.WaitingPath;
                    instanceData.m_flags            &= ~(CitizenInstance.Flags.HangAround
                                                         | CitizenInstance.Flags.Panicking
                                                         | CitizenInstance.Flags.SittingDown
                                                         | CitizenInstance.Flags.Cheering);

                    // NON-STOCK CODE START (transferred from ResidentAI.PathfindSuccess)
                    const Citizen.Flags CTZ_MASK = Citizen.Flags.Tourist
                                                   | Citizen.Flags.MovingIn
                                                   | Citizen.Flags.DummyTraffic;
                    if (citizenId != 0 &&
                        (citizensBuffer[citizenId].m_flags & CTZ_MASK) == Citizen.Flags.MovingIn)
                    {
                        StatisticBase statisticBase = Singleton <StatisticsManager>
                                                      .instance.Acquire <StatisticInt32>(StatisticType.MoveRate);

                        statisticBase.Add(1);
                    }

                    // NON-STOCK CODE END
                    PathfindSuccess(instanceId, ref instanceData);
                    break;
                }

                case ExtSoftPathState.Ignore: {
                    if (logParkingAi)
                    {
                        Log._Debug(
                            $"CustomHumanAI.CustomSimulationStep({instanceId}): " +
                            "Path-finding result shall be ignored for citizen instance " +
                            $"{instanceId} (finalPathState={finalPathState}). " +
                            $"Path: {instanceData.m_path} -- ignoring");
                    }

                    return;
                }

                case ExtSoftPathState.Calculating:
                default: {
                    if (logParkingAi)
                    {
                        Log._Debug(
                            $"CustomHumanAI.CustomSimulationStep({instanceId}): " +
                            $"Path-finding result undetermined for citizen instance {instanceId} " +
                            $"(finalPathState={finalPathState}). " +
                            $"Path: {instanceData.m_path} -- continue");
                    }

                    break;
                }

                case ExtSoftPathState.FailedHard: {
                    if (logParkingAi)
                    {
                        Log._Debug(
                            $"CustomHumanAI.CustomSimulationStep({instanceId}): " +
                            $"HARD path-finding failure for citizen instance {instanceId} " +
                            $"(finalPathState={finalPathState}). Path: {instanceData.m_path} " +
                            "-- calling HumanAI.PathfindFailure");
                    }

                    instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath;
                    instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround
                                              | CitizenInstance.Flags.Panicking
                                              | CitizenInstance.Flags.SittingDown
                                              | CitizenInstance.Flags.Cheering);
                    Singleton <PathManager> .instance.ReleasePath(instanceData.m_path);

                    instanceData.m_path = 0u;
                    PathfindFailure(instanceId, ref instanceData);
                    return;
                }

                case ExtSoftPathState.FailedSoft: {
                    if (logParkingAi)
                    {
                        Log._Debug(
                            $"CustomHumanAI.CustomSimulationStep({instanceId}): " +
                            $"SOFT path-finding failure for citizen instance {instanceId} " +
                            $"(finalPathState={finalPathState}). Path: {instanceData.m_path} " +
                            "-- calling HumanAI.InvalidPath");
                    }

                    // path mode has been updated, repeat path-finding
                    instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath;
                    instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround
                                              | CitizenInstance.Flags.Panicking
                                              | CitizenInstance.Flags.SittingDown
                                              | CitizenInstance.Flags.Cheering);
                    InvalidPath(instanceId, ref instanceData);
                    break;
                }
                }

                // NON-STOCK CODE END
            }

            // NON-STOCK CODE START
            using (var bm = Benchmark.MaybeCreateBenchmark(null, "ExtSimulationStep")) {
                if (Options.parkingAI)
                {
                    if (ExtSimulationStep(
                            instanceId,
                            ref instanceData,
                            ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceId],
                            physicsLodRefPos))
                    {
                        return;
                    }
                }
            }

            // NON-STOCK CODE END
            base.SimulationStep(instanceId, ref instanceData, physicsLodRefPos);

            VehicleManager vehicleManager = Singleton <VehicleManager> .instance;
            ushort         vehicleId      = 0;
            if (instanceData.m_citizen != 0u)
            {
                vehicleId = citizensBuffer[instanceData.m_citizen].m_vehicle;
            }

            if (vehicleId != 0)
            {
                Vehicle[]   vehiclesBuffer = vehicleManager.m_vehicles.m_buffer;
                VehicleInfo vehicleInfo    = vehiclesBuffer[vehicleId].Info;

                if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
                {
                    vehicleInfo.m_vehicleAI.SimulationStep(
                        vehicleId,
                        ref vehiclesBuffer[vehicleId],
                        vehicleId,
                        ref vehiclesBuffer[vehicleId],
                        0);
                    vehicleId = 0;
                }
            }

            if (vehicleId != 0 ||
                (instanceData.m_flags & (CitizenInstance.Flags.Character
                                         | CitizenInstance.Flags.WaitingPath
                                         | CitizenInstance.Flags.Blown
                                         | CitizenInstance.Flags.Floating)) !=
                CitizenInstance.Flags.None)
            {
                return;
            }

            instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround
                                      | CitizenInstance.Flags.Panicking
                                      | CitizenInstance.Flags.SittingDown);
            ArriveAtDestination(instanceId, ref instanceData, false);
            citizenManager.ReleaseCitizenInstance(instanceId);
        }
示例#39
0
        //Fare Cal
        public static Double FareCalculate(VehicleInfo taxiInput, double kmInput)
        {

            double price;
            double oKm = taxiInput.oKm;
            double oPrice = taxiInput.oPrice;
            double f1Km = 0;
            if (taxiInput.f1Km != null)
            {
                f1Km = (double)taxiInput.f1Km;
            }
            double f2Km = 0;
            if (taxiInput.f2Km != null)
            {
                f2Km = (double)taxiInput.f2Km;
            }
            double f3Km = 0;
            if (taxiInput.f3Km != null)
            {
                f3Km = (double)taxiInput.f3Km;
            }
            double f4Km = 0;
            if (taxiInput.f4Km != null)
            {
                f4Km = (double)taxiInput.f4Km;
            }
            double f1Price = 0;
            if (taxiInput.f1Price != null)
            {
                f1Price = (double)taxiInput.f1Price;
            }
            double f2Price = 0;
            if (taxiInput.f2Price != null)
            {
                f2Price = (double)taxiInput.f2Price;
            }
            double f3Price = 0;
            if (taxiInput.f3Price != null)
            {
                f3Price = (double)taxiInput.f3Price;
            }
            double f4Price = 0;
            if (taxiInput.f4Price != null)
            {
                f4Price = (double)taxiInput.f4Price;
            }

            price = oPrice;

            if (kmInput > 0 && kmInput < oKm)
            {
                price = oPrice; // Nếu như mới lên xe hoặc đi quãng đường nhỏ hơn open km (0.6) thì bằng giá mở cửa
            }
            else if (kmInput > oKm && kmInput < (f1Km + oKm)) //Nếu đi trong khoảng từ 0.6 đến 15.6 (+ thêm 15km) thì
            {
                price = oPrice + ((kmInput - oKm) * f1Price);
            }
            else if (kmInput > (f1Km + oKm) && kmInput < (f2Km + f1Km + oKm))
            {
                price = oPrice + (f1Km * f1Price) + (kmInput - (f1Km + oKm)) * f2Price;
            }
            else if (f4Km == 0 && f3Km == 0)
            {
                price = oPrice + (f1Km * f1Price) + (kmInput - (f1Km + oKm)) * f2Price;
            }
            else if (f4Km == 0 && f3Km != 0)
            {
                price = oPrice + (f1Km * f1Price) + (f2Km * f2Price) + (kmInput - (f1Km + oKm + f2Km)) * f3Price;
            }
            else if (f4Km != 0 && f3Km != 0)
            {
                if (kmInput > (oKm + f1Km + f2Km + f3Km) && kmInput < (oKm + f1Km + f2Km + f3Km + f4Km))
                {
                    price = oPrice + (f1Km * f1Price) + (f2Km * f2Price) + (f3Km * f3Price) + (kmInput - (f1Km + oKm + f2Km + f3Km)) * f4Price;
                }
                else
                {
                    price = oPrice + (f1Km * f1Price) + (f2Km * f2Price) + (kmInput - (f1Km + oKm + f2Km)) * f3Price;
                }
            }
            return price;
        }
示例#40
0
        public void CustomSimulationStep(ushort vehicleId,
                                         ref Vehicle vehicleData,
                                         Vector3 physicsLodRefPos)
        {
#if DEBUG
            bool vehDebug = DebugSettings.VehicleId == 0 ||
                            DebugSettings.VehicleId == vehicleId;
            bool logParkingAi = DebugSwitch.BasicParkingAILog.Get() && vehDebug;
#else
            var logParkingAi = false;
#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
                uint logVehiclePath = vehicleData.m_path;
                Log._DebugIf(
                    logParkingAi,
                    () => $"CustomCarAI.CustomSimulationStep({vehicleId}): " +
                    $"Path: {logVehiclePath}, mainPathState={mainPathState}");
#endif

                IExtVehicleManager extVehicleManager = Constants.ManagerFactory.ExtVehicleManager;
                ExtSoftPathState   finalPathState    = ExtCitizenInstance.ConvertPathStateToSoftPathState(mainPathState);
                if (Options.parkingAI &&
                    extVehicleManager.ExtVehicles[vehicleId].vehicleType == ExtVehicleType.PassengerCar)
                {
                    ushort driverInstanceId = extVehicleManager.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 (logParkingAi)
                    {
                        Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): " +
                                   $"Applied Parking AI logic. Path: {vehicleData.m_path}, " +
                                   $"mainPathState={mainPathState}, finalPathState={finalPathState}");
                    }
#endif
                }

                switch (finalPathState)
                {
                case ExtSoftPathState.Ready: {
#if DEBUG
                    if (logParkingAi)
                    {
                        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;
                    PathfindSuccess(vehicleId, ref vehicleData);
                    TrySpawn(vehicleId, ref vehicleData);
                    break;
                }

                case ExtSoftPathState.Ignore: {
#if DEBUG
                    if (logParkingAi)
                    {
                        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 (logParkingAi)
                    {
                        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 (logParkingAi)
                    {
                        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;
                    PathfindFailure(vehicleId, ref vehicleData);
                    return;
                }

                case ExtSoftPathState.FailedSoft: {
#if DEBUG
                    if (logParkingAi)
                    {
                        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;
                    InvalidPath(vehicleId, ref vehicleData, vehicleId, ref vehicleData);
                    break;
                }
                }

                // NON-STOCK CODE END
            }
            else
            {
                if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0)
                {
                    TrySpawn(vehicleId, ref vehicleData);
                }
            }

            // NON-STOCK CODE START
            IExtVehicleManager extVehicleMan = Constants.ManagerFactory.ExtVehicleManager;
            extVehicleMan.UpdateVehiclePosition(vehicleId, ref vehicleData);

            if (Options.advancedAI &&
                (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0)
            {
                extVehicleMan.LogTraffic(vehicleId, ref vehicleData);
            }

            // NON-STOCK CODE END
            Vector3 lastFramePosition = vehicleData.GetLastFramePosition();
            int     lodPhysics;
            if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1100f * 1100f)
            {
                lodPhysics = 2;
            }
            else if (Vector3.SqrMagnitude(
                         Singleton <SimulationManager> .instance.m_simulationView.m_position -
                         lastFramePosition) >= 500f * 500f)
            {
                lodPhysics = 1;
            }
            else
            {
                lodPhysics = 0;
            }

            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[trailerId].m_trailingVehicle;
                    VehicleInfo info            = vehManager.m_vehicles.m_buffer[trailerId].Info;

                    info.m_vehicleAI.SimulationStep(
                        trailerId,
                        ref vehManager.m_vehicles.m_buffer[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(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 (vehicleData.m_blockCounter >= maxBlockCounter)
            {
                // NON-STOCK CODE START
                if (VehicleBehaviorManager.Instance.MayDespawn(ref vehicleData))
                {
                    // NON-STOCK CODE END
                    Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);
                } // NON-STOCK CODE
            }
        }
示例#41
0
 public void RestoreVehicleSpeed(VehicleInfo vehicle)
 {
     vehicle.m_acceleration /= speedMultiplier;
     //vehicle.m_braking /= speedMultiplier;
     //vehicle.m_turning /= speedMultiplier;
     vehicle.m_maxSpeed /= speedMultiplier;
 }
示例#42
0
        public bool CustomStartPathFind(ushort vehicleId,
                                        ref Vehicle vehicleData,
                                        Vector3 startPos,
                                        Vector3 endPos,
                                        bool startBothWays,
                                        bool endBothWays,
                                        bool undergroundTarget)
        {
#if DEBUG
            bool vehDebug = DebugSettings.VehicleId == 0 ||
                            DebugSettings.VehicleId == vehicleId;
            bool logParkingAi = DebugSwitch.BasicParkingAILog.Get() && vehDebug;
#else
            var logParkingAi = false;
#endif
            Log._DebugOnlyWarningIf(
                logParkingAi,
                () => $"CustomCarAI.CustomStartPathFind({vehicleId}): called for vehicle " +
                $"{vehicleId}, startPos={startPos}, endPos={endPos}, " +
                $"startBothWays={startBothWays}, endBothWays={endBothWays}, " +
                $"undergroundTarget={undergroundTarget}");

            ExtVehicleType vehicleType;

            using (var bm = Benchmark.MaybeCreateBenchmark(null, "OnStartPathFind")) {
                vehicleType =
                    ExtVehicleManager.Instance.OnStartPathFind(vehicleId, ref vehicleData, null);
                if (vehicleType == ExtVehicleType.None)
                {
                    Log._DebugOnlyWarning(
                        $"CustomCarAI.CustomStartPathFind({vehicleId}): Vehicle {vehicleId} " +
                        "does not have a valid vehicle type!");
                    vehicleType = ExtVehicleType.RoadVehicle;
                }
            }

            VehicleInfo info             = m_info;
            bool        allowUnderground = (vehicleData.m_flags & (Vehicle.Flags.Underground
                                                                   | Vehicle.Flags.Transition)) != 0;

            if (!PathManager.FindPathPosition(
                    startPos,
                    ItemClass.Service.Road,
                    NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle,
                    info.m_vehicleType,
                    allowUnderground,
                    false,
                    32f,
                    out PathUnit.Position startPosA,
                    out PathUnit.Position startPosB,
                    out float startDistSqrA,
                    out _) || !PathManager.FindPathPosition(
                    endPos,
                    ItemClass.Service.Road,
                    NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle,
                    info.m_vehicleType,
                    undergroundTarget,
                    false,
                    32f,
                    out PathUnit.Position endPosA,
                    out PathUnit.Position endPosB,
                    out float endDistSqrA,
                    out _))
            {
                return(false);
            }

            if (!startBothWays || startDistSqrA < 10f)
            {
                startPosB = default;
            }

            if (!endBothWays || endDistSqrA < 10f)
            {
                endPosB = default;
            }

            // NON-STOCK CODE START
            PathCreationArgs args;
            args.extPathType         = ExtPathType.None;
            args.extVehicleType      = vehicleType;
            args.vehicleId           = vehicleId;
            args.spawned             = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0;
            args.buildIndex          = Singleton <SimulationManager> .instance.m_currentBuildIndex;
            args.startPosA           = startPosA;
            args.startPosB           = startPosB;
            args.endPosA             = endPosA;
            args.endPosB             = endPosB;
            args.vehiclePosition     = default;
            args.laneTypes           = NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle;
            args.vehicleTypes        = info.m_vehicleType;
            args.maxLength           = 20000f;
            args.isHeavyVehicle      = IsHeavyVehicle();
            args.hasCombustionEngine = CombustionEngine();
            args.ignoreBlocked       = IgnoreBlocked(vehicleId, ref vehicleData);
            args.ignoreFlooded       = false;
            args.ignoreCosts         = false;
            args.randomParking       = false;
            args.stablePath          = false;
            args.skipQueue           = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0;

            if (!CustomPathManager._instance.CustomCreatePath(
                    out uint path,
                    ref Singleton <SimulationManager> .instance.m_randomizer,
                    args))
            {
                return(false);
            }

            Log._DebugIf(
                logParkingAi,
                () => $"CustomCarAI.CustomStartPathFind({vehicleId}): " +
                $"Path-finding starts for vehicle {vehicleId}, path={path}, " +
                $"extVehicleType={vehicleType}, startPosA.segment={startPosA.m_segment}, " +
                $"startPosA.lane={startPosA.m_lane}, info.m_vehicleType={info.m_vehicleType}, " +
                $"endPosA.segment={endPosA.m_segment}, endPosA.lane={endPosA.m_lane}");

            // NON-STOCK CODE END
            if (vehicleData.m_path != 0u)
            {
                Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);
            }

            vehicleData.m_path   = path;
            vehicleData.m_flags |= Vehicle.Flags.WaitingPath;
            return(true);
        }
示例#43
0
        private async void SelectVehicle(int myVehicleId)
        {
            var did = userData.content.driverInfo.did.ToString();
            var uid = userId;
            var mid = pushChannelURI;
            var mType = ConstantVariable.mTypeWIN; //Chuyển did thành id
            var input = string.Format("{{\"id\":\"{0}\",\"uid\":\"{1}\",\"vehicleId\":\"{2}\",\"mid\":\"{3}\",\"mType\":\"{4}\"}}", did, uid, myVehicleId, mid, mType);     
       
            try
            {
                //Thử xem có lấy được thông tin về ko, nếu không thì do lỗi máy chủ
                var output = await GetJsonFromPOSTMethod.GetJsonString(ConstantVariable.tNetDriverSelectVehicle, input);                
                var selectVehicle = JsonConvert.DeserializeObject<DriverLogin>(output);
                if (selectVehicle.status.Equals("0000")) //0000
                {
                    //Lấy thông tin  giá xe                        
                    foreach (var car in userData.content.vehicleInfos)
                    {
                        if (car.vehicleId == myVehicleId)
                        {
                            myVehicle = new VehicleInfo
                            {
                                status = car.status,
                                lmd = car.lmd,
                                content = car.content,
                                oPrice = car.oPrice,
                                oKm = car.oKm,
                                f1Price = car.f1Price,
                                f1Km = car.f1Km,
                                f2Price = car.f2Price,
                                f2Km = car.f2Km,
                                f3Price = car.f3Price,
                                f3Km = car.f3Km,
                                f4Price = car.f4Price,
                                f4Km = car.f4Km,
                                vehicleId = car.vehicleId,
                                plate = car.plate,
                                carTitle = car.carTitle,
                                carLevel = car.carLevel,
                                vRegDate = car.vRegDate,
                                manuYear = car.manuYear,
                                cap = car.cap
                            };

                            //
                            tNetUserLoginData["MySelectedVehicle"] = myVehicle;
                            tNetUserLoginData["UserLmd"] = selectVehicle.lmd; //Cái này là để cập nhật lmd cho việc update thông tin
                        }
                    }

                    NavigationService.Navigate(new Uri("/Pages/HomePage.xaml", UriKind.Relative));
                    Thread.Sleep(1000);
                    grv_ProcessScreen.Visibility = Visibility.Collapsed;//Disable Process bar
                }
                else
                {
                    MessageBox.Show("(Mã lỗi 1802) " + ConstantVariable.errServerError);
                    grv_ProcessScreen.Visibility = Visibility.Collapsed; //Disable Process bar
                    Debug.WriteLine("Mã lối ght67 ở SelectVehicle");
                }

            }
            catch (Exception)
            {

                //máy chủ lỗi
                MessageBox.Show("(Mã lỗi 1801) " + ConstantVariable.errServerError);
                grv_ProcessScreen.Visibility = Visibility.Collapsed; //Disable Process bar
                Debug.WriteLine("Mã lối 7hgtr3 ở SelectVehicle");
            }


        }
        /// <summary>
        /// Gets the spawn position.
        /// </summary>
        /// <param name="vehicleId">The vehicle identifier.</param>
        /// <param name="vehicleInfo">The vehicle information.</param>
        /// <param name="buildingId">The building identifier.</param>
        /// <returns>The spawn position.</returns>
        public static Vector3 GetSpawnPosition(ushort vehicleId, VehicleInfo vehicleInfo, ushort buildingId)
        {
            try
            {
                Building building = BuildingHelper.GetBuilding(buildingId);
                Randomizer randomizer = new Randomizer((int)buildingId);
                Vector3 position;
                Vector3 target;
                building.Info.m_buildingAI.CalculateSpawnPosition(buildingId, ref building, ref randomizer, vehicleInfo, out position, out target);

                return position;
            }
            catch (Exception)
            {
                return Vector3.zero;
            }
        }
        private void assignPathProperties(uint unit, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, PathUnit.Position vehiclePosition, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, byte simulationFlags)
        {
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags = simulationFlags;

            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_pathFindFlags = 0;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_buildIndex = buildIndex;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position00 = startPosA;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position01 = endPosA;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position02 = startPosB;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position03 = endPosB;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position11 = vehiclePosition;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_nextPathUnit = 0u;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_laneTypes = (byte)laneTypes;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_vehicleTypes = (byte)vehicleTypes;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_length = maxLength;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount = 20;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_referenceCount = 1;
        }
		internal static ExtVehicleType? DetermineVehicleTypeFromVehicleInfo(VehicleInfo vehicleInfo) {
			VehicleAI ai = vehicleInfo.m_vehicleAI;
			return DetermineVehicleTypeFromAIType(ai, false);
		}
示例#47
0
        public static ushort CustomCheckOtherVehicle(ushort vehicleId,
                                                     ref Vehicle vehicleData,
                                                     ref Vehicle.Frame frameData,
                                                     ref float maxSpeed,
                                                     ref bool blocked,
                                                     ref Vector3 collisionPush,
                                                     float maxBraking,
                                                     ushort otherID,
                                                     ref Vehicle otherData,
                                                     Vector3 min,
                                                     Vector3 max,
                                                     int lodPhysics)
        {
            if (otherID == vehicleId ||
                vehicleData.m_leadingVehicle == otherID ||
                vehicleData.m_trailingVehicle == otherID)
            {
                return(otherData.m_nextGridVehicle);
            }

            VehicleInfo info = otherData.Info;

            if (info.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
            {
                return(otherData.m_nextGridVehicle);
            }

            if (((vehicleData.m_flags | otherData.m_flags) & Vehicle.Flags.Transition) == 0 &&
                (vehicleData.m_flags & Vehicle.Flags.Underground) !=
                (otherData.m_flags & Vehicle.Flags.Underground))
            {
                return(otherData.m_nextGridVehicle);
            }

#if DEBUG
            bool logLogic = DebugSwitch.ResourceLoading.Get() &&
                            (GlobalConfig.Instance.Debug.ApiExtVehicleType == ExtVehicleType.None ||
                             GlobalConfig.Instance.Debug.ApiExtVehicleType == ExtVehicleType.RoadVehicle) &&
                            (DebugSettings.VehicleId == 0 ||
                             DebugSettings.VehicleId == vehicleId);
#else
            const bool logLogic = false;
#endif
            Log._DebugIf(
                logLogic,
                () => $"CustomCarAI.CustomCheckOtherVehicle({vehicleId}, {otherID}) called.");

            Vector3 otherSegMin;
            Vector3 otherSegMax;
            if (lodPhysics >= 2)
            {
                otherSegMin = otherData.m_segment.Min();
                otherSegMax = otherData.m_segment.Max();
            }
            else
            {
                otherSegMin = Vector3.Min(otherData.m_segment.Min(), otherData.m_targetPos3);
                otherSegMax = Vector3.Max(otherData.m_segment.Max(), otherData.m_targetPos3);
            }

            if (min.x >= otherSegMax.x + 2f &&
                min.y >= otherSegMax.y + 2f &&
                min.z >= otherSegMax.z + 2f &&
                otherSegMin.x >= max.x + 2f &&
                otherSegMin.y >= max.y + 2f &&
                otherSegMin.z >= max.z + 2f)
            {
                return(otherData.m_nextGridVehicle);
            }

            Vehicle.Frame otherFrameData = otherData.GetLastFrameData();
            if (lodPhysics < 2)
            {
                float segSqrDist = vehicleData.m_segment.DistanceSqr(otherData.m_segment, out _, out _);

                if (segSqrDist < 4f)
                {
                    Vector3 vehPos    = vehicleData.m_segment.Position(0.5f);
                    Vector3 otherPos  = otherData.m_segment.Position(0.5f);
                    Vector3 vehBounds = vehicleData.m_segment.b - vehicleData.m_segment.a;
                    if (Vector3.Dot(vehBounds, vehPos - otherPos) < 0f)
                    {
                        collisionPush -= vehBounds.normalized * (0.1f - (segSqrDist * 0.025f));
                    }
                    else
                    {
                        collisionPush += vehBounds.normalized * (0.1f - (segSqrDist * 0.025f));
                    }

                    blocked = true;
                }
            }

            float vehVelocity       = frameData.m_velocity.magnitude + 0.01f;
            float otherVehVelocity  = otherFrameData.m_velocity.magnitude;
            float otherBreakingDist =
                (otherVehVelocity * (0.5f + (0.5f * otherVehVelocity / info.m_braking)))
                + Mathf.Min(1f, otherVehVelocity);
            otherVehVelocity += 0.01f;

            float   prevLength    = 0f;
            Vector3 prevTargetPos = vehicleData.m_segment.b;
            Vector3 prevBounds    = vehicleData.m_segment.b - vehicleData.m_segment.a;
            int     startI        = (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Tram) ? 1 : 0;

            for (int i = startI; i < 4; i++)
            {
                Vector3 targetPos     = vehicleData.GetTargetPos(i);
                Vector3 targetPosDiff = targetPos - prevTargetPos;
                if (Vector3.Dot(prevBounds, targetPosDiff) <= 0f)
                {
                    continue;
                }

                float    targetPosDiffLen = targetPosDiff.magnitude;
                Segment3 curSegment       = new Segment3(prevTargetPos, targetPos);
                min             = curSegment.Min();
                max             = curSegment.Max();
                curSegment.a.y *= 0.5f;
                curSegment.b.y *= 0.5f;

                if (targetPosDiffLen > 0.01f &&
                    min.x < otherSegMax.x + 2f &&
                    min.y < otherSegMax.y + 2f &&
                    min.z < otherSegMax.z + 2f &&
                    otherSegMin.x < max.x + 2f &&
                    otherSegMin.y < max.y + 2f &&
                    otherSegMin.z < max.z + 2f)
                {
                    Vector3 otherVehFrontPos = otherData.m_segment.a;
                    otherVehFrontPos.y *= 0.5f;

                    if (curSegment.DistanceSqr(otherVehFrontPos, out float u) < 4f)
                    {
                        float otherCosAngleToTargetPosDiff =
                            Vector3.Dot(otherFrameData.m_velocity, targetPosDiff) / targetPosDiffLen;
                        float uDist = prevLength + (targetPosDiffLen * u);

                        if (uDist >= 0.01f)
                        {
                            uDist -= otherCosAngleToTargetPosDiff + 3f;
                            float speed = Mathf.Max(
                                0f,
                                CalculateMaxSpeed(uDist,
                                                  otherCosAngleToTargetPosDiff,
                                                  maxBraking));
                            if (speed < 0.01f)
                            {
                                blocked = true;
                            }

                            Vector3 normOtherDir =
                                Vector3.Normalize((Vector3)otherData.m_targetPos0 - otherData.m_segment.a);

                            float blockFactor = 1.2f - (1f / ((vehicleData.m_blockCounter * 0.02f) + 0.5f));

                            if (Vector3.Dot(targetPosDiff, normOtherDir) > blockFactor * targetPosDiffLen)
                            {
                                maxSpeed = Mathf.Min(maxSpeed, speed);
                            }
                        }

                        break;
                    }

                    if (lodPhysics < 2)
                    {
                        float   totalDist                = 0f;
                        float   otherBreakDist           = otherBreakingDist;
                        Vector3 otherFrontPos            = otherData.m_segment.b;
                        Vector3 otherBounds              = otherData.m_segment.b - otherData.m_segment.a;
                        int     startOtherTargetPosIndex = (info.m_vehicleType == VehicleInfo.VehicleType.Tram) ? 1 : 0;
                        bool    exitTargetPosLoop        = false;
                        int     otherTargetPosIndex      = startOtherTargetPosIndex;

                        while (otherTargetPosIndex < 4 && otherBreakDist > 0.1f)
                        {
                            Vector3 otherTargetPos;
                            if (otherData.m_leadingVehicle == 0)
                            {
                                otherTargetPos = otherData.GetTargetPos(otherTargetPosIndex);
                            }
                            else
                            {
                                if (otherTargetPosIndex != startOtherTargetPosIndex)
                                {
                                    break;
                                }

                                Vehicle[] vehiclesBuffer = Singleton <VehicleManager> .instance.m_vehicles.m_buffer;
                                otherTargetPos = vehiclesBuffer[otherData.m_leadingVehicle].m_segment.b;
                            }

                            Vector3 minBreakPos = Vector3.ClampMagnitude(otherTargetPos - otherFrontPos,
                                                                         otherBreakDist);

                            if (Vector3.Dot(otherBounds, minBreakPos) > 0f)
                            {
                                otherTargetPos = otherFrontPos + minBreakPos;

                                float breakPosDist = minBreakPos.magnitude;
                                otherBreakDist -= breakPosDist;

                                Segment3 otherVehNextSegment = new Segment3(otherFrontPos, otherTargetPos);
                                otherVehNextSegment.a.y *= 0.5f;
                                otherVehNextSegment.b.y *= 0.5f;

                                if (breakPosDist > 0.01f)
                                {
                                    float otherVehNextSegmentDistToCurSegment
                                        = otherID >= vehicleId
                                              ? curSegment.DistanceSqr(
                                              otherVehNextSegment,
                                              out float otherVehNextSegU,
                                              out float otherVehNextSegV)
                                              : otherVehNextSegment.DistanceSqr(
                                              curSegment,
                                              out otherVehNextSegV,
                                              out otherVehNextSegU);

                                    if (otherVehNextSegmentDistToCurSegment < 4f)
                                    {
                                        float uDist = prevLength + (targetPosDiffLen * otherVehNextSegU);
                                        float vDist = totalDist + (breakPosDist * otherVehNextSegV) + 0.1f;

                                        if (uDist >= 0.01f && uDist * otherVehVelocity > vDist * vehVelocity)
                                        {
                                            float otherCosAngleToTargetPosDiff =
                                                Vector3.Dot(
                                                    otherFrameData.m_velocity,
                                                    targetPosDiff) / targetPosDiffLen;
                                            if (uDist >= 0.01f)
                                            {
                                                uDist -= otherCosAngleToTargetPosDiff
                                                         + 1f
                                                         + otherData.Info.m_generatedInfo.m_size.z;
                                                float speed = Mathf.Max(
                                                    0f,
                                                    CalculateMaxSpeed(uDist,
                                                                      otherCosAngleToTargetPosDiff,
                                                                      maxBraking));

                                                if (speed < 0.01f)
                                                {
                                                    blocked = true;
                                                }

                                                maxSpeed = Mathf.Min(maxSpeed, speed);
                                            }
                                        }

                                        exitTargetPosLoop = true;
                                        break;
                                    }
                                }

                                otherBounds   = minBreakPos;
                                totalDist    += breakPosDist;
                                otherFrontPos = otherTargetPos;
                            }

                            otherTargetPosIndex++;
                        }

                        if (exitTargetPosLoop)
                        {
                            break;
                        }
                    }
                }

                prevBounds    = targetPosDiff;
                prevLength   += targetPosDiffLen;
                prevTargetPos = targetPos;
            }

            return(otherData.m_nextGridVehicle);
        }
示例#48
0
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays)
        {
            /// NON-STOCK CODE START ///
            ExtVehicleType?vehicleType = CustomVehicleAI.DetermineVehicleTypeFromVehicle(vehicleID, ref vehicleData);
            //Log._Debug($"CustomTrainAI.CustomStartPathFind. vehicleID={vehicleID}. type={this.GetType().ToString()} vehicleType={vehicleType}");
            /// NON-STOCK CODE END ///

            VehicleInfo info = this.m_info;

            if ((vehicleData.m_flags & Vehicle.Flags.Spawned) == 0 && Vector3.Distance(startPos, endPos) < 100f)
            {
                startPos = endPos;
            }
            bool allowUnderground;
            bool allowUnderground2;

            if (info.m_vehicleType == VehicleInfo.VehicleType.Metro)
            {
                allowUnderground  = true;
                allowUnderground2 = true;
            }
            else
            {
                allowUnderground  = ((vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0);
                allowUnderground2 = false;
            }
            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float             num;
            float             num2;

            PathUnit.Position endPosA;
            PathUnit.Position endPosB;
            float             num3;
            float             num4;

            if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.PublicTransport, NetInfo.LaneType.Vehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out num, out num2) &&
                CustomPathManager.FindPathPosition(endPos, ItemClass.Service.PublicTransport, NetInfo.LaneType.Vehicle, info.m_vehicleType, allowUnderground2, false, 32f, out endPosA, out endPosB, out num3, out num4))
            {
                if (!startBothWays || num2 > num * 1.2f)
                {
                    startPosB = default(PathUnit.Position);
                }
                if (!endBothWays || num4 > num3 * 1.2f)
                {
                    endPosB = default(PathUnit.Position);
                }
                uint path;
                bool res = false;
                if (vehicleType == null)
                {
                    res = Singleton <PathManager> .instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle, info.m_vehicleType, 20000f, false, false, true, false);
                }
                else
                {
                    res = Singleton <CustomPathManager> .instance.CreatePath((ExtVehicleType)vehicleType, out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle, info.m_vehicleType, 20000f, false, false, true, false);
                }
                if (res)
                {
                    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);
        }
示例#49
0
 public new bool NeedChangeVehicleType(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position pathPos, uint laneID, VehicleInfo.VehicleType laneVehicleType, ref Vector4 target)
 {
     return base.NeedChangeVehicleType(vehicleID, ref vehicleData, pathPos, laneID, laneVehicleType, ref target);
 }
示例#50
0
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays)
        {
#if DEBUG
            //Log._Debug($"CustomTramBaseAI.CustomStartPathFind called for vehicle {vehicleID}");
#endif

#if BENCHMARK
            using (var bm = new Benchmark(null, "OnStartPathFind")) {
#endif
            VehicleStateManager.Instance.OnStartPathFind(vehicleID, ref vehicleData, null);
#if BENCHMARK
        }
#endif

            VehicleInfo info = this.m_info;
            bool allowUnderground;
            bool allowUnderground2;
            if (info.m_vehicleType == VehicleInfo.VehicleType.Metro)
            {
                allowUnderground  = true;
                allowUnderground2 = true;
            }
            else
            {
                allowUnderground  = ((vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0);
                allowUnderground2 = false;
            }
            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float startSqrDistA;
            float startSqrDistB;
            PathUnit.Position endPosA;
            PathUnit.Position endPosB;
            float endSqrDistA;
            float endSqrDistB;
            if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out startSqrDistA, out startSqrDistB) &&
                CustomPathManager.FindPathPosition(endPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle, info.m_vehicleType, allowUnderground2, false, 32f, out endPosA, out endPosB, out endSqrDistA, out endSqrDistB))
            {
                if (!startBothWays || startSqrDistB > startSqrDistA * 1.2f)
                {
                    startPosB = default(PathUnit.Position);
                }
                if (!endBothWays || endSqrDistB > endSqrDistA * 1.2f)
                {
                    endPosB = default(PathUnit.Position);
                }
                uint path;
                // NON-STOCK CODE START
                PathCreationArgs args;
                args.extPathType         = ExtCitizenInstance.ExtPathType.None;
                args.extVehicleType      = ExtVehicleType.Tram;
                args.vehicleId           = vehicleID;
                args.buildIndex          = Singleton <SimulationManager> .instance.m_currentBuildIndex;
                args.startPosA           = startPosA;
                args.startPosB           = startPosB;
                args.endPosA             = endPosA;
                args.endPosB             = endPosB;
                args.vehiclePosition     = default(PathUnit.Position);
                args.laneTypes           = NetInfo.LaneType.Vehicle;
                args.vehicleTypes        = info.m_vehicleType;
                args.maxLength           = 20000f;
                args.isHeavyVehicle      = false;
                args.hasCombustionEngine = false;
                args.ignoreBlocked       = this.IgnoreBlocked(vehicleID, ref vehicleData);
                args.ignoreFlooded       = false;
                args.randomParking       = false;
                args.stablePath          = true;
                args.skipQueue           = true;

                if (CustomPathManager._instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, args))
                {
                    // NON-STOCK CODE END
                    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);
        }
示例#51
0
 // NetSegment.GetClosestLane -- it's only called by the PathManager
 public static bool GetClosestLanePosition(NetSegment seg, Vector3 point, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, bool requireConnect, out Vector3 positionA, out int laneIndexA, out float laneOffsetA, out Vector3 positionB, out int laneIndexB, out float laneOffsetB, RoadManager.VehicleType vehicleType)
 {
     positionA = point;
     laneIndexA = -1;
     laneOffsetA = 0f;
     positionB = point;
     laneIndexB = -1;
     laneOffsetB = 0f;
     if (seg.m_flags != NetSegment.Flags.None && seg.m_lanes != 0u)
     {
         NetInfo info = seg.Info;
         if (info.m_lanes != null)
         {
             float num = 1E+09f;
             float num2 = 1E+09f;
             uint num3 = seg.m_lanes;
             int num4 = 0;
             while (num4 < info.m_lanes.Length && num3 != 0u)
             {
                 NetInfo.Lane lane = info.m_lanes[num4];
                 if (lane.CheckType(laneTypes, vehicleTypes) && (lane.m_allowConnect || !requireConnect) && RoadManager.CanUseLane(vehicleType, num3))
                 {
                     Vector3 vector;
                     float num5;
                     Singleton<NetManager>.instance.m_lanes.m_buffer[(int)((UIntPtr)num3)].GetClosestPosition(point, out vector, out num5);
                     float num6 = Vector3.SqrMagnitude(point - vector);
                     if (lane.m_finalDirection == NetInfo.Direction.Backward || lane.m_finalDirection == NetInfo.Direction.AvoidForward)
                     {
                         if (num6 < num2)
                         {
                             num2 = num6;
                             positionB = vector;
                             laneIndexB = num4;
                             laneOffsetB = num5;
                         }
                     }
                     else if (num6 < num)
                     {
                         num = num6;
                         positionA = vector;
                         laneIndexA = num4;
                         laneOffsetA = num5;
                     }
                 }
                 num3 = Singleton<NetManager>.instance.m_lanes.m_buffer[(int)((UIntPtr)num3)].m_nextLane;
                 num4++;
             }
             if (num2 < num)
             {
                 Vector3 vector2 = positionA;
                 int num7 = laneIndexA;
                 float num8 = laneOffsetA;
                 positionA = positionB;
                 laneIndexA = laneIndexB;
                 laneOffsetA = laneOffsetB;
                 positionB = vector2;
                 laneIndexB = num7;
                 laneOffsetB = num8;
             }
             if (!info.m_canCrossLanes)
             {
                 positionB = point;
                 laneIndexB = -1;
                 laneOffsetB = 0f;
             }
         }
     }
     return laneIndexA != -1;
 }
示例#52
0
    class CustomTramBaseAI : TramBaseAI {     // TODO inherit from VehicleAI (in order to keep the correct references to `base`)
        public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos)
        {
            if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0)
            {
                byte pathFindFlags = Singleton <PathManager> .instance.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags;

                if ((pathFindFlags & PathUnit.FLAG_READY) != 0)
                {
                    try {
                        this.PathfindSuccess(vehicleId, ref vehicleData);
                        this.PathFindReady(vehicleId, ref vehicleData);
                    } catch (Exception e) {
                        Log.Warning($"TramBaseAI.PathFindSuccess/PathFindReady({vehicleId}) threw an exception: {e.ToString()}");
                        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 ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 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) != 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

            VehicleManager instance = Singleton <VehicleManager> .instance;
            VehicleInfo info        = instance.m_vehicles.m_buffer[(int)vehicleId].Info;
            info.m_vehicleAI.SimulationStep(vehicleId, ref instance.m_vehicles.m_buffer[(int)vehicleId], vehicleId, ref vehicleData, 0);
            if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created)
            {
                return;
            }
            ushort trailingVehicle = instance.m_vehicles.m_buffer[(int)vehicleId].m_trailingVehicle;
            int num = 0;
            while (trailingVehicle != 0)
            {
                info = instance.m_vehicles.m_buffer[(int)trailingVehicle].Info;
                info.m_vehicleAI.SimulationStep(trailingVehicle, ref instance.m_vehicles.m_buffer[(int)trailingVehicle], vehicleId, ref vehicleData, 0);
                if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created)
                {
                    return;
                }
                trailingVehicle = instance.m_vehicles.m_buffer[(int)trailingVehicle].m_trailingVehicle;
                if (++num > 16384)
                {
                    CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                    break;
                }
            }
            if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace | Vehicle.Flags.WaitingCargo)) == 0)
            {
                Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId);
            }
            else if (vehicleData.m_blockCounter == 255)
            {
                // 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
            }
        }
示例#53
0
 public bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, bool isHeavyVehicle, bool ignoreBlocked, bool stablePath, bool skipQueue, RoadManager.VehicleType vehicleType)
 {
     return this.CreatePath(out unit, ref randomizer, buildIndex, startPosA, startPosB, endPosA, endPosB, default(PathUnit.Position), laneTypes, vehicleTypes, maxLength, isHeavyVehicle, ignoreBlocked, stablePath, skipQueue, vehicleType);
 }
示例#54
0
        public void CustomSimulationStep(ushort vehicleID, ref Vehicle vehicleData, ref Vehicle.Frame frameData, ushort leaderID, ref Vehicle leaderData, int lodPhysics)
        {
#if DEBUG
            bool debug = GlobalConfig.Instance.Debug.Switches[16] && GlobalConfig.Instance.Debug.NodeId == vehicleID;
#endif

            ushort leadingVehicle  = vehicleData.m_leadingVehicle;
            uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
            VehicleInfo leaderInfo;
            if (leaderID != vehicleID)
            {
                leaderInfo = leaderData.Info;
            }
            else
            {
                leaderInfo = this.m_info;
            }
            TramBaseAI tramBaseAI = leaderInfo.m_vehicleAI as TramBaseAI;

            if (leadingVehicle != 0)
            {
                frameData.m_position += frameData.m_velocity * 0.4f;
            }
            else
            {
                frameData.m_position += frameData.m_velocity * 0.5f;
            }

            frameData.m_swayPosition += frameData.m_swayVelocity * 0.5f;
            Vector3 wheelBaseRot      = frameData.m_rotation * new Vector3(0f, 0f, this.m_info.m_generatedInfo.m_wheelBase * 0.5f);
            Vector3 posAfterWheelRot  = frameData.m_position + wheelBaseRot;
            Vector3 posBeforeWheelRot = frameData.m_position - wheelBaseRot;

            float acceleration = this.m_info.m_acceleration;
            float braking      = this.m_info.m_braking;
            float curSpeed     = frameData.m_velocity.magnitude;

            Vector3 afterRotToTargetPos1Diff     = (Vector3)vehicleData.m_targetPos1 - posAfterWheelRot;
            float afterRotToTargetPos1DiffSqrMag = afterRotToTargetPos1Diff.sqrMagnitude;

            Quaternion curInvRot = Quaternion.Inverse(frameData.m_rotation);
            Vector3 curveTangent = curInvRot * frameData.m_velocity;

#if DEBUG
            if (debug)
            {
                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): ================================================");
                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): leadingVehicle={leadingVehicle} frameData.m_position={frameData.m_position} frameData.m_swayPosition={frameData.m_swayPosition} wheelBaseRot={wheelBaseRot} posAfterWheelRot={posAfterWheelRot} posBeforeWheelRot={posBeforeWheelRot} acceleration={acceleration} braking={braking} curSpeed={curSpeed} afterRotToTargetPos1Diff={afterRotToTargetPos1Diff} afterRotToTargetPos1DiffSqrMag={afterRotToTargetPos1DiffSqrMag} curInvRot={curInvRot} curveTangent={curveTangent} this.m_info.m_generatedInfo.m_wheelBase={this.m_info.m_generatedInfo.m_wheelBase}");
            }
#endif

            Vector3 forward      = Vector3.forward;
            Vector3 targetMotion = Vector3.zero;
            float targetSpeed    = 0f;
            float motionFactor   = 0.5f;
            float turnAngle      = 0f;
            if (leadingVehicle != 0)
            {
                VehicleManager vehMan = Singleton <VehicleManager> .instance;
                Vehicle.Frame leadingVehLastFrameData = vehMan.m_vehicles.m_buffer[(int)leadingVehicle].GetLastFrameData();
                VehicleInfo leadingVehInfo            = vehMan.m_vehicles.m_buffer[(int)leadingVehicle].Info;

                float attachOffset;
                if ((vehicleData.m_flags & Vehicle.Flags.Inverted) != (Vehicle.Flags) 0)
                {
                    attachOffset = this.m_info.m_attachOffsetBack - this.m_info.m_generatedInfo.m_size.z * 0.5f;
                }
                else
                {
                    attachOffset = this.m_info.m_attachOffsetFront - this.m_info.m_generatedInfo.m_size.z * 0.5f;
                }

                float leadingAttachOffset;
                if ((vehMan.m_vehicles.m_buffer[(int)leadingVehicle].m_flags & Vehicle.Flags.Inverted) != (Vehicle.Flags) 0)
                {
                    leadingAttachOffset = leadingVehInfo.m_attachOffsetFront - leadingVehInfo.m_generatedInfo.m_size.z * 0.5f;
                }
                else
                {
                    leadingAttachOffset = leadingVehInfo.m_attachOffsetBack - leadingVehInfo.m_generatedInfo.m_size.z * 0.5f;
                }

                Vector3 curPosMinusRotAttachOffset    = frameData.m_position - frameData.m_rotation * new Vector3(0f, 0f, attachOffset);
                Vector3 leadingPosPlusRotAttachOffset = leadingVehLastFrameData.m_position + leadingVehLastFrameData.m_rotation * new Vector3(0f, 0f, leadingAttachOffset);

                wheelBaseRot = leadingVehLastFrameData.m_rotation * new Vector3(0f, 0f, leadingVehInfo.m_generatedInfo.m_wheelBase * 0.5f);
                Vector3 leadingPosBeforeWheelRot = leadingVehLastFrameData.m_position - wheelBaseRot;

                if (Vector3.Dot(vehicleData.m_targetPos1 - vehicleData.m_targetPos0, (Vector3)vehicleData.m_targetPos0 - posBeforeWheelRot) < 0f && vehicleData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0)
                {
                    int someIndex = -1;
                    InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, vehicleData.m_targetPos0, posBeforeWheelRot, 0, ref leaderData, ref someIndex, 0, 0, Vector3.SqrMagnitude(posBeforeWheelRot - (Vector3)vehicleData.m_targetPos0) + 1f, 1f);
                    afterRotToTargetPos1DiffSqrMag = 0f;
                }

                float attachRotDist = Mathf.Max(Vector3.Distance(curPosMinusRotAttachOffset, leadingPosPlusRotAttachOffset), 2f);

                float one = 1f;
                float attachRotSqrDist = attachRotDist * attachRotDist;
                float oneSqr           = one * one;
                int i = 0;
                if (afterRotToTargetPos1DiffSqrMag < attachRotSqrDist)
                {
                    if (vehicleData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0)
                    {
                        InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, posBeforeWheelRot, posAfterWheelRot, 0, ref leaderData, ref i, 1, 2, attachRotSqrDist, oneSqr);
                    }
                    while (i < 4)
                    {
                        vehicleData.SetTargetPos(i, vehicleData.GetTargetPos(i - 1));
                        i++;
                    }
                    afterRotToTargetPos1Diff       = (Vector3)vehicleData.m_targetPos1 - posAfterWheelRot;
                    afterRotToTargetPos1DiffSqrMag = afterRotToTargetPos1Diff.sqrMagnitude;
                }
                afterRotToTargetPos1Diff = curInvRot * afterRotToTargetPos1Diff;

                float negTotalAttachLen = -((this.m_info.m_generatedInfo.m_wheelBase + leadingVehInfo.m_generatedInfo.m_wheelBase) * 0.5f + attachOffset + leadingAttachOffset);
                bool hasPath            = false;
                if (vehicleData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0)
                {
                    float u1;
                    float u2;
                    if (Line3.Intersect(posAfterWheelRot, vehicleData.m_targetPos1, leadingPosBeforeWheelRot, negTotalAttachLen, out u1, out u2))
                    {
                        targetMotion = afterRotToTargetPos1Diff * Mathf.Clamp(Mathf.Min(u1, u2) / 0.6f, 0f, 2f);
                    }
                    else
                    {
                        Line3.DistanceSqr(posAfterWheelRot, vehicleData.m_targetPos1, leadingPosBeforeWheelRot, out u1);
                        targetMotion = afterRotToTargetPos1Diff * Mathf.Clamp(u1 / 0.6f, 0f, 2f);
                    }
                    hasPath = true;
                }

                if (hasPath)
                {
                    if (Vector3.Dot(leadingPosBeforeWheelRot - posAfterWheelRot, posAfterWheelRot - posBeforeWheelRot) < 0f)
                    {
                        motionFactor = 0f;
                    }
                }
                else
                {
                    float leadingPosBeforeToAfterWheelRotDist = Vector3.Distance(leadingPosBeforeWheelRot, posAfterWheelRot);
                    motionFactor = 0f;
                    targetMotion = curInvRot * ((leadingPosBeforeWheelRot - posAfterWheelRot) * (Mathf.Max(0f, leadingPosBeforeToAfterWheelRotDist - negTotalAttachLen) / Mathf.Max(1f, leadingPosBeforeToAfterWheelRotDist * 0.6f)));
                }
            }
            else
            {
                float estimatedFrameDist = (curSpeed + acceleration) * (0.5f + 0.5f * (curSpeed + acceleration) / braking) + (this.m_info.m_generatedInfo.m_size.z - this.m_info.m_generatedInfo.m_wheelBase) * 0.5f;
                float maxSpeedAdd        = Mathf.Max(curSpeed + acceleration, 2f);
                float meanSpeedAdd       = Mathf.Max((estimatedFrameDist - maxSpeedAdd) / 2f, 2f);
                float maxSpeedAddSqr     = maxSpeedAdd * maxSpeedAdd;
                float meanSpeedAddSqr    = meanSpeedAdd * meanSpeedAdd;
                if (Vector3.Dot(vehicleData.m_targetPos1 - vehicleData.m_targetPos0, (Vector3)vehicleData.m_targetPos0 - posBeforeWheelRot) < 0f && vehicleData.m_path != 0u && (leaderData.m_flags & (Vehicle.Flags.WaitingPath | Vehicle.Flags.Stopped)) == (Vehicle.Flags) 0)
                {
                    int someIndex = -1;
                    InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, vehicleData.m_targetPos0, posBeforeWheelRot, leaderID, ref leaderData, ref someIndex, 0, 0, Vector3.SqrMagnitude(posBeforeWheelRot - (Vector3)vehicleData.m_targetPos0) + 1f, 1f);
                    afterRotToTargetPos1DiffSqrMag = 0f;
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): dot < 0");
                    }
#endif
                }

#if DEBUG
                if (debug)
                {
                    Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Leading vehicle is 0. vehicleData.m_targetPos0={vehicleData.m_targetPos0} vehicleData.m_targetPos1={vehicleData.m_targetPos1} posBeforeWheelRot={posBeforeWheelRot} posBeforeWheelRot={posAfterWheelRot} estimatedFrameDist={estimatedFrameDist} maxSpeedAdd={maxSpeedAdd} meanSpeedAdd={meanSpeedAdd} maxSpeedAddSqr={maxSpeedAddSqr} meanSpeedAddSqr={meanSpeedAddSqr} afterRotToTargetPos1DiffSqrMag={afterRotToTargetPos1DiffSqrMag}");
                }
#endif

                int posIndex = 0;
                bool hasValidPathTargetPos = false;
                if ((afterRotToTargetPos1DiffSqrMag < maxSpeedAddSqr || vehicleData.m_targetPos3.w < 0.01f) && (leaderData.m_flags & (Vehicle.Flags.WaitingPath | Vehicle.Flags.Stopped)) == (Vehicle.Flags) 0)
                {
                    if (vehicleData.m_path != 0u)
                    {
                        InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, posBeforeWheelRot, posAfterWheelRot, leaderID, ref leaderData, ref posIndex, 1, 4, maxSpeedAddSqr, meanSpeedAddSqr);
                    }
                    if (posIndex < 4)
                    {
                        hasValidPathTargetPos = true;
                        while (posIndex < 4)
                        {
                            vehicleData.SetTargetPos(posIndex, vehicleData.GetTargetPos(posIndex - 1));
                            posIndex++;
                        }
                    }
                    afterRotToTargetPos1Diff       = (Vector3)vehicleData.m_targetPos1 - posAfterWheelRot;
                    afterRotToTargetPos1DiffSqrMag = afterRotToTargetPos1Diff.sqrMagnitude;
                }

#if DEBUG
                if (debug)
                {
                    Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): posIndex={posIndex} hasValidPathTargetPos={hasValidPathTargetPos}");
                }
#endif

                if (leaderData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0)
                {
                    NetManager netMan         = Singleton <NetManager> .instance;
                    byte leaderPathPosIndex   = leaderData.m_pathPositionIndex;
                    byte leaderLastPathOffset = leaderData.m_lastPathOffset;
                    if (leaderPathPosIndex == 255)
                    {
                        leaderPathPosIndex = 0;
                    }
                    int noise;
                    float leaderLen = 1f + leaderData.CalculateTotalLength(leaderID, out noise);

#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): leaderPathPosIndex={leaderPathPosIndex} leaderLastPathOffset={leaderLastPathOffset} leaderPathPosIndex={leaderPathPosIndex} leaderLen={leaderLen}");
                    }
#endif

                    // reserve space / add traffic
                    PathManager pathMan = Singleton <PathManager> .instance;
                    PathUnit.Position pathPos;
                    if (pathMan.m_pathUnits.m_buffer[leaderData.m_path].GetPosition(leaderPathPosIndex >> 1, out pathPos))
                    {
                        netMan.m_segments.m_buffer[(int)pathPos.m_segment].AddTraffic(Mathf.RoundToInt(leaderLen * 2.5f), noise);
                        bool reservedSpaceOnCurrentLane = false;
                        if ((leaderPathPosIndex & 1) == 0 || leaderLastPathOffset == 0)
                        {
                            uint laneId = PathManager.GetLaneID(pathPos);
                            if (laneId != 0u)
                            {
                                Vector3 curPathOffsetPos              = netMan.m_lanes.m_buffer[laneId].CalculatePosition((float)pathPos.m_offset * 0.003921569f);
                                float speedAdd                        = 0.5f * curSpeed * curSpeed / this.m_info.m_braking;
                                float afterWheelRotCurPathOffsetDist  = Vector3.Distance(posAfterWheelRot, curPathOffsetPos);
                                float beforeWheelRotCurPathOffsetDist = Vector3.Distance(posBeforeWheelRot, curPathOffsetPos);
                                if (Mathf.Min(afterWheelRotCurPathOffsetDist, beforeWheelRotCurPathOffsetDist) >= speedAdd - 1f)
                                {
                                    netMan.m_lanes.m_buffer[laneId].ReserveSpace(leaderLen);
                                    reservedSpaceOnCurrentLane = true;
                                }
                            }
                        }

                        if (!reservedSpaceOnCurrentLane && pathMan.m_pathUnits.m_buffer[leaderData.m_path].GetNextPosition(leaderPathPosIndex >> 1, out pathPos))
                        {
                            uint nextLaneId = PathManager.GetLaneID(pathPos);
                            if (nextLaneId != 0u)
                            {
                                netMan.m_lanes.m_buffer[nextLaneId].ReserveSpace(leaderLen);
                            }
                        }
                    }

                    if ((ulong)(currentFrameIndex >> 4 & 15u) == (ulong)((long)(leaderID & 15)))
                    {
                        // check if vehicle can proceed to next path position

                        bool canProceeed          = false;
                        uint curLeaderPathId      = leaderData.m_path;
                        int curLeaderPathPosIndex = leaderPathPosIndex >> 1;
                        int k = 0;
                        while (k < 5)
                        {
                            bool invalidPos;
                            if (PathUnit.GetNextPosition(ref curLeaderPathId, ref curLeaderPathPosIndex, out pathPos, out invalidPos))
                            {
                                uint laneId = PathManager.GetLaneID(pathPos);
                                if (laneId != 0u && !netMan.m_lanes.m_buffer[laneId].CheckSpace(leaderLen))
                                {
                                    k++;
                                    continue;
                                }
                            }
                            if (invalidPos)
                            {
                                this.InvalidPath(vehicleID, ref vehicleData, leaderID, ref leaderData);
                            }
                            canProceeed = true;
                            break;
                        }
                        if (!canProceeed)
                        {
                            leaderData.m_flags |= Vehicle.Flags.Congestion;
                        }
                    }
                }

                float maxSpeed;
                if ((leaderData.m_flags & Vehicle.Flags.Stopped) != (Vehicle.Flags) 0)
                {
                    maxSpeed = 0f;
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Vehicle is stopped. maxSpeed={maxSpeed}");
                    }
#endif
                }
                else
                {
                    maxSpeed = Mathf.Min(vehicleData.m_targetPos1.w, GetMaxSpeed(leaderID, ref leaderData));
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Vehicle is not stopped. maxSpeed={maxSpeed}");
                    }
#endif
                }

#if DEBUG
                if (debug)
                {
                    Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Start of second part. curSpeed={curSpeed} curInvRot={curInvRot}");
                }
#endif

                afterRotToTargetPos1Diff = curInvRot * afterRotToTargetPos1Diff;
#if DEBUG
                if (debug)
                {
                    Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1Diff={afterRotToTargetPos1Diff} (old afterRotToTargetPos1DiffSqrMag={afterRotToTargetPos1DiffSqrMag})");
                }
#endif
                Vector3 zero     = Vector3.zero;
                bool blocked     = false;
                float forwardLen = 0f;
                if (afterRotToTargetPos1DiffSqrMag > 1f)                   // TODO why is this not recalculated?
                {
                    forward = VectorUtils.NormalizeXZ(afterRotToTargetPos1Diff, out forwardLen);
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1DiffSqrMag > 1f. forward={forward} forwardLen={forwardLen}");
                    }
#endif
                    if (forwardLen > 1f)
                    {
                        Vector3 fwd = afterRotToTargetPos1Diff;
                        maxSpeedAdd    = Mathf.Max(curSpeed, 2f);
                        maxSpeedAddSqr = maxSpeedAdd * maxSpeedAdd;
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): forwardLen > 1f. fwd={fwd} maxSpeedAdd={maxSpeedAdd} maxSpeedAddSqr={maxSpeedAddSqr}");
                        }
#endif
                        if (afterRotToTargetPos1DiffSqrMag > maxSpeedAddSqr)
                        {
                            float fwdLimiter = maxSpeedAdd / Mathf.Sqrt(afterRotToTargetPos1DiffSqrMag);
                            fwd.x *= fwdLimiter;
                            fwd.y *= fwdLimiter;

#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1DiffSqrMag > maxSpeedAddSqr. afterRotToTargetPos1DiffSqrMag={afterRotToTargetPos1DiffSqrMag} maxSpeedAddSqr={maxSpeedAddSqr} fwdLimiter={fwdLimiter} fwd={fwd}");
                            }
#endif
                        }

                        if (fwd.z < -1f)                           // !!!
                        {
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): fwd.z < -1f. fwd={fwd}");
                            }
#endif

                            if (vehicleData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0)
                            {
                                Vector3 targetPos0TargetPos1Diff = vehicleData.m_targetPos1 - vehicleData.m_targetPos0;
                                if ((curInvRot * targetPos0TargetPos1Diff).z < -0.01f)                                   // !!!
                                {
#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): (curInvRot * targetPos0TargetPos1Diff).z < -0.01f. curInvRot={curInvRot} targetPos0TargetPos1Diff={targetPos0TargetPos1Diff}");
                                    }
#endif
                                    if (afterRotToTargetPos1Diff.z < Mathf.Abs(afterRotToTargetPos1Diff.x) * -10f)                                       // !!!
                                    {
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1Diff.z < Mathf.Abs(afterRotToTargetPos1Diff.x) * -10f. fwd={fwd} targetPos0TargetPos1Diff={targetPos0TargetPos1Diff} afterRotToTargetPos1Diff={afterRotToTargetPos1Diff}");
                                        }
#endif

                                        /*fwd.z = 0f;
                                         * afterRotToTargetPos1Diff = Vector3.zero;*/
                                        maxSpeed = 0.5f;                                         // NON-STOCK CODE

#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): (1) set maxSpeed={maxSpeed}");
                                        }
#endif
                                    }
                                    else
                                    {
                                        posAfterWheelRot = posBeforeWheelRot + Vector3.Normalize(vehicleData.m_targetPos1 - vehicleData.m_targetPos0) * this.m_info.m_generatedInfo.m_wheelBase;
                                        posIndex         = -1;
                                        InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, vehicleData.m_targetPos0, vehicleData.m_targetPos1, leaderID, ref leaderData, ref posIndex, 0, 0, Vector3.SqrMagnitude(vehicleData.m_targetPos1 - vehicleData.m_targetPos0) + 1f, 1f);

#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1Diff.z >= Mathf.Abs(afterRotToTargetPos1Diff.x) * -10f. Invoked UpdatePathTargetPositions. posAfterWheelRot={posAfterWheelRot} posBeforeWheelRot={posBeforeWheelRot} this.m_info.m_generatedInfo.m_wheelBase={this.m_info.m_generatedInfo.m_wheelBase}");
                                        }
#endif
                                    }
                                }
                                else
                                {
                                    posIndex = -1;
                                    InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, vehicleData.m_targetPos0, posBeforeWheelRot, leaderID, ref leaderData, ref posIndex, 0, 0, Vector3.SqrMagnitude(posBeforeWheelRot - (Vector3)vehicleData.m_targetPos0) + 1f, 1f);
                                    vehicleData.m_targetPos1 = posAfterWheelRot;
                                    fwd.z = 0f;
                                    afterRotToTargetPos1Diff = Vector3.zero;
                                    maxSpeed = 0f;

#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Vehicle is waiting for a path. posIndex={posIndex} vehicleData.m_targetPos1={vehicleData.m_targetPos1} fwd={fwd} afterRotToTargetPos1Diff={afterRotToTargetPos1Diff} maxSpeed={maxSpeed}");
                                    }
#endif
                                }
                            }
                            motionFactor = 0f;
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Reset motion factor. motionFactor={motionFactor}");
                            }
#endif
                        }

                        forward = VectorUtils.NormalizeXZ(fwd, out forwardLen);
                        float curve = Mathf.PI / 2f /* 1.57079637f*/ * (1f - forward.z);                       // <- constant: a bit inaccurate PI/2
                        if (forwardLen > 1f)
                        {
                            curve /= forwardLen;
                        }
                        float targetDist = forwardLen;
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): targetDist={targetDist} fwd={fwd} curve={curve} maxSpeed={maxSpeed}");
                        }
#endif

                        if (vehicleData.m_targetPos1.w < 0.1f)
                        {
                            maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, curve);
                            maxSpeed = Mathf.Min(maxSpeed, CalculateMaxSpeed(targetDist, vehicleData.m_targetPos1.w, braking * 0.9f));
                        }
                        else
                        {
                            maxSpeed = Mathf.Min(maxSpeed, this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, curve));
                        }
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): [1] maxSpeed={maxSpeed}");
                        }
#endif
                        maxSpeed = Mathf.Min(maxSpeed, CalculateMaxSpeed(targetDist, vehicleData.m_targetPos2.w, braking * 0.9f));
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): [2] maxSpeed={maxSpeed}");
                        }
#endif
                        targetDist += VectorUtils.LengthXZ(vehicleData.m_targetPos2 - vehicleData.m_targetPos1);
                        maxSpeed    = Mathf.Min(maxSpeed, CalculateMaxSpeed(targetDist, vehicleData.m_targetPos3.w, braking * 0.9f));
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): [3] maxSpeed={maxSpeed}");
                        }
#endif
                        targetDist += VectorUtils.LengthXZ(vehicleData.m_targetPos3 - vehicleData.m_targetPos2);
                        if (vehicleData.m_targetPos3.w < 0.01f)
                        {
                            targetDist = Mathf.Max(0f, targetDist + (this.m_info.m_generatedInfo.m_wheelBase - this.m_info.m_generatedInfo.m_size.z) * 0.5f);
                        }
                        maxSpeed = Mathf.Min(maxSpeed, CalculateMaxSpeed(targetDist, 0f, braking * 0.9f));
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): [4] maxSpeed={maxSpeed}");
                        }
#endif
                        CarAI.CheckOtherVehicles(vehicleID, ref vehicleData, ref frameData, ref maxSpeed, ref blocked, ref zero, estimatedFrameDist, braking * 0.9f, lodPhysics);
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): CheckOtherVehicles finished. blocked={blocked}");
                        }
#endif
                        if (maxSpeed < curSpeed)
                        {
                            float brake = Mathf.Max(acceleration, Mathf.Min(braking, curSpeed));
                            targetSpeed = Mathf.Max(maxSpeed, curSpeed - brake);
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): maxSpeed < curSpeed. maxSpeed={maxSpeed} curSpeed={curSpeed} brake={brake} targetSpeed={targetSpeed}");
                            }
#endif
                        }
                        else
                        {
                            float accel = Mathf.Max(acceleration, Mathf.Min(braking, -curSpeed));
                            targetSpeed = Mathf.Min(maxSpeed, curSpeed + accel);
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): maxSpeed >= curSpeed. maxSpeed={maxSpeed} curSpeed={curSpeed} accel={accel} targetSpeed={targetSpeed}");
                            }
#endif
                        }
                    }
                }
                else if (curSpeed < 0.1f && hasValidPathTargetPos && leaderInfo.m_vehicleAI.ArriveAtDestination(leaderID, ref leaderData))
                {
                    leaderData.Unspawn(leaderID);
                    return;
                }
                if ((leaderData.m_flags & Vehicle.Flags.Stopped) == (Vehicle.Flags) 0 && maxSpeed < 0.1f)
                {
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Vehicle is not stopped but maxSpeed < 0.1. maxSpeed={maxSpeed}");
                    }
#endif
                    blocked = true;
                }
                if (blocked)
                {
                    leaderData.m_blockCounter = (byte)Mathf.Min((int)(leaderData.m_blockCounter + 1), 255);
                }
                else
                {
                    leaderData.m_blockCounter = 0;
                }
                if (forwardLen > 1f)
                {
                    turnAngle    = Mathf.Asin(forward.x) * Mathf.Sign(targetSpeed);
                    targetMotion = forward * targetSpeed;
                }
                else
                {
                    Vector3 vel = Vector3.ClampMagnitude(afterRotToTargetPos1Diff * 0.5f - curveTangent, braking);
                    targetMotion = curveTangent + vel;
                }
            }
            bool mayBlink   = (currentFrameIndex + (uint)leaderID & 16u) != 0u;
            Vector3 springs = targetMotion - curveTangent;
            Vector3 targetAfterWheelRotMotion  = frameData.m_rotation * targetMotion;
            Vector3 targetBeforeWheelRotMotion = Vector3.Normalize((Vector3)vehicleData.m_targetPos0 - posBeforeWheelRot) * (targetMotion.magnitude * motionFactor);
            targetBeforeWheelRotMotion -= targetAfterWheelRotMotion * (Vector3.Dot(targetAfterWheelRotMotion, targetBeforeWheelRotMotion) / Mathf.Max(1f, targetAfterWheelRotMotion.sqrMagnitude));
            posAfterWheelRot           += targetAfterWheelRotMotion;
            posBeforeWheelRot          += targetBeforeWheelRotMotion;
            frameData.m_rotation        = Quaternion.LookRotation(posAfterWheelRot - posBeforeWheelRot);
            Vector3 targetPos = posAfterWheelRot - frameData.m_rotation * new Vector3(0f, 0f, this.m_info.m_generatedInfo.m_wheelBase * 0.5f);
            frameData.m_velocity = targetPos - frameData.m_position;
            if (leadingVehicle != 0)
            {
                frameData.m_position += frameData.m_velocity * 0.6f;
            }
            else
            {
                frameData.m_position += frameData.m_velocity * 0.5f;
            }
            frameData.m_swayVelocity    = frameData.m_swayVelocity * (1f - this.m_info.m_dampers) - springs * (1f - this.m_info.m_springs) - frameData.m_swayPosition * this.m_info.m_springs;
            frameData.m_swayPosition   += frameData.m_swayVelocity * 0.5f;
            frameData.m_steerAngle      = 0f;
            frameData.m_travelDistance += targetMotion.z;
            if (leadingVehicle != 0)
            {
                frameData.m_lightIntensity = Singleton <VehicleManager> .instance.m_vehicles.m_buffer[(int)leaderID].GetLastFrameData().m_lightIntensity;
            }
            else
            {
                frameData.m_lightIntensity.x = 5f;
                frameData.m_lightIntensity.y = ((springs.z >= -0.1f) ? 0.5f : 5f);
                frameData.m_lightIntensity.z = ((turnAngle >= -0.1f || !mayBlink) ? 0f : 5f);
                frameData.m_lightIntensity.w = ((turnAngle <= 0.1f || !mayBlink) ? 0f : 5f);
            }
            frameData.m_underground = ((vehicleData.m_flags & Vehicle.Flags.Underground) != (Vehicle.Flags) 0);
            frameData.m_transition  = ((vehicleData.m_flags & Vehicle.Flags.Transition) != (Vehicle.Flags) 0);
            //base.SimulationStep(vehicleID, ref vehicleData, ref frameData, leaderID, ref leaderData, lodPhysics);
        }
        protected virtual bool ProcessOffer(ushort buildingID, ref Building data, TransferManager.TransferReason material, TransferManager.TransferOffer offer, TransferManager.TransferReason trTarget, StartTransferCallStructure tup, U instance)
        {
            if (material == trTarget)
            {
                ServiceSystemDefinition def = ServiceSystemDefinition.from(instance.m_info, tup.vehicleType);
                if (def == null)
                {
                    SVMUtils.doLog("SSD Não definido para: {0} {1} {2} {3}", instance.m_info.m_class.m_service, instance.m_info.m_class.m_subService, tup.vehicleLevel ?? instance.m_info.m_class.m_level, tup.vehicleType);
                    return(false);
                }

                #region District Check
                var ext = def.GetTransportExtension();

                if (ext.GetAllowDistrictServiceRestrictions())
                {
                    var buildingDistrict = DistrictManager.instance.GetDistrict(data.m_position);
                    var offerDistrict    = DistrictManager.instance.GetDistrict(offer.Position);
                    if (buildingDistrict != offerDistrict)
                    {
                        if (ServiceVehiclesManagerMod.debugMode)
                        {
                            SVMUtils.doLog($"Building serving different district: building {data.Info} ({buildingID} - districtId {buildingDistrict} {DistrictManager.instance.GetDistrictName(buildingDistrict)}) => offerDistrict: {offerDistrict} {DistrictManager.instance.GetDistrictName(offerDistrict)}");
                        }
                        if (!ext.GetAllowOutsidersEffective(offerDistrict))
                        {
                            var districtBuildings = SVMBuildingUtils.getAllBuildingsFromCity(def, offerDistrict, true, true);

                            if (ServiceVehiclesManagerMod.debugMode)
                            {
                                SVMUtils.doLog($"Offer doesn't allow outsiders. Available buildings found: {districtBuildings}");
                            }
                            if (districtBuildings.Count > 0)
                            {
                                var newBuildingId = districtBuildings[Singleton <SimulationManager> .instance.m_randomizer.Int32((uint)districtBuildings.Count)];
                                return(ProcessOffer(newBuildingId, ref BuildingManager.instance.m_buildings.m_buffer[newBuildingId], material, offer, trTarget, tup, instance));
                            }
                            if (ServiceVehiclesManagerMod.debugMode)
                            {
                                SVMUtils.doLog($"Ignoring because no buildings can handle it");
                            }
                        }
                        if (!ext.GetAllowGoOutsideEffective(buildingDistrict))
                        {
                            var districtBuildings = SVMBuildingUtils.getAllBuildingsFromCity(def, offerDistrict, false, true);
                            if (ServiceVehiclesManagerMod.debugMode)
                            {
                                SVMUtils.doLog($"Building district doesn't allow go out. Available buildings found: {districtBuildings}");
                            }
                            if (districtBuildings.Count > 0)
                            {
                                var newBuildingId = districtBuildings[Singleton <SimulationManager> .instance.m_randomizer.Int32((uint)districtBuildings.Count)];
                                return(ProcessOffer(newBuildingId, ref BuildingManager.instance.m_buildings.m_buffer[newBuildingId], material, offer, trTarget, tup, instance));
                            }
                            if (ServiceVehiclesManagerMod.debugMode)
                            {
                                SVMUtils.doLog($"Ignoring because no buildings can handle it (2)");
                            }
                        }
                    }
                }
                #endregion

                SVMUtils.doLog("[{1}] SSD = {0}", def, material);
                VehicleInfo randomVehicleInfo = ServiceSystemDefinition.availableDefinitions[def].GetAModel(buildingID);
                SVMUtils.doLog("[{1}] Veh = {0}", randomVehicleInfo?.ToString() ?? "<NULL>", material);
                if (randomVehicleInfo != null)
                {
                    Array16 <Vehicle> vehicles = Singleton <VehicleManager> .instance.m_vehicles;
                    instance.CalculateSpawnPosition(buildingID, ref data, ref Singleton <SimulationManager> .instance.m_randomizer, randomVehicleInfo, out Vector3 position, out Vector3 vector2);
                    if (Singleton <VehicleManager> .instance.CreateVehicle(out ushort num, ref Singleton <SimulationManager> .instance.m_randomizer, randomVehicleInfo, position, material, tup.tramsferToSource, tup.transferToTarget))
                    {
                        randomVehicleInfo.m_vehicleAI.SetSource(num, ref vehicles.m_buffer[(int)num], buildingID);
                        randomVehicleInfo.m_vehicleAI.StartTransfer(num, ref vehicles.m_buffer[(int)num], material, offer);
                        return(true);
                    }
                }
            }
            return(false);
        }
示例#56
0
        public static int spawn_vehicle(Vehicle veh, Vector3 pos)
        {
            var returnCode = veh.Spawn(pos);

            if (returnCode == 1)
            {
                API.Shared.SetEntityData(veh.NetHandle, "Vehicle", veh);
            }

            API.Shared.SetVehicleEngineStatus(veh.NetHandle, false);
            if (veh.OwnerId != 0)
            {
                API.Shared.SetVehicleLocked(veh.NetHandle, true);
            }

            if (veh.Group.CommandType == Group.CommandTypeLspd)
            {
                API.Shared.SetVehicleEnginePowerMultiplier(veh.NetHandle, 4);
            }

            //Install modifications.
            ModdingManager.ApplyVehicleMods(veh);

            //Set wheel type.
            GrandTheftMultiplayer.Server.API.Shared.Red.setVehicleWheelType(veh.NetHandle, VehicleInfo.Get(veh.VehModel).wheelType);
            return(returnCode);
        }
 protected static bool StartPathFind(ushort segmentId, ref NetSegment data, ItemClass.Service netService, VehicleInfo.VehicleType vehicleType, bool skipQueue)
 {
     if (data.m_path != 0u)
     {
         Singleton<PathManager>.instance.ReleasePath(data.m_path);
         data.m_path = 0u;
     }
     NetManager instance = Singleton<NetManager>.instance;
     if ((instance.m_nodes.m_buffer[data.m_startNode].m_flags & NetNode.Flags.Ambiguous) != NetNode.Flags.None)
     {
         for (int i = 0; i < 8; i++)
         {
             ushort segment = instance.m_nodes.m_buffer[data.m_startNode].GetSegment(i);
             if (segment != 0 && segment != segmentId && instance.m_segments.m_buffer[segment].m_path != 0u)
             {
                 return true;
             }
         }
     }
     if ((instance.m_nodes.m_buffer[data.m_endNode].m_flags & NetNode.Flags.Ambiguous) != NetNode.Flags.None)
     {
         for (int j = 0; j < 8; j++)
         {
             ushort segment2 = instance.m_nodes.m_buffer[data.m_endNode].GetSegment(j);
             if (segment2 != 0 && segment2 != segmentId && instance.m_segments.m_buffer[segment2].m_path != 0u)
             {
                 return true;
             }
         }
     }
     var position = instance.m_nodes.m_buffer[data.m_startNode].m_position;
     var position2 = instance.m_nodes.m_buffer[data.m_endNode].m_position;
     PathUnit.Position startPosA;
     PathUnit.Position startPosB;
     float num;
     float num2;
     if (!PathManager.FindPathPosition(position, netService, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, true, true, 32f, out startPosA, out startPosB, out num, out num2))
     {
         return true;
     }
     PathUnit.Position endPosA;
     PathUnit.Position endPosB;
     float num3;
     float num4;
     if (!PathManager.FindPathPosition(position2, netService, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, true, true, 32f, out endPosA, out endPosB, out num3, out num4))
     {
         return true;
     }
     if ((instance.m_nodes.m_buffer[data.m_startNode].m_flags & NetNode.Flags.Fixed) != NetNode.Flags.None)
     {
         startPosB = default(PathUnit.Position);
     }
     if ((instance.m_nodes.m_buffer[data.m_endNode].m_flags & NetNode.Flags.Fixed) != NetNode.Flags.None)
     {
         endPosB = default(PathUnit.Position);
     }
     startPosA.m_offset = 128;
     startPosB.m_offset = 128;
     endPosA.m_offset = 128;
     endPosB.m_offset = 128;
     bool stopLane = GetStopLane(ref startPosA, vehicleType);
     bool stopLane2 = GetStopLane(ref startPosB, vehicleType);
     bool stopLane3 = GetStopLane(ref endPosA, vehicleType);
     bool stopLane4 = GetStopLane(ref endPosB, vehicleType);
     if ((!stopLane && !stopLane2) || (!stopLane3 && !stopLane4))
     {
         return true;
     }
     uint path;
     if (Singleton<CustomPathManager>.instance.CreatePath(out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle, vehicleType, 20000f, false, true, true, skipQueue, ItemClass.Service.PublicTransport))
     {
         if (startPosA.m_segment != 0 && startPosB.m_segment != 0)
         {
             var expr_2D9Cp0 = instance.m_nodes.m_buffer;
             var expr_2D9Cp1 = data.m_startNode;
             expr_2D9Cp0[expr_2D9Cp1].m_flags = (expr_2D9Cp0[expr_2D9Cp1].m_flags | NetNode.Flags.Ambiguous);
         }
         else
         {
             var expr305Cp0 = instance.m_nodes.m_buffer;
             var expr305Cp1 = data.m_startNode;
             expr305Cp0[expr305Cp1].m_flags = (expr305Cp0[expr305Cp1].m_flags & ~NetNode.Flags.Ambiguous);
         }
         if (endPosA.m_segment != 0 && endPosB.m_segment != 0)
         {
             var expr344Cp0 = instance.m_nodes.m_buffer;
             var expr344Cp1 = data.m_endNode;
             expr344Cp0[expr344Cp1].m_flags = (expr344Cp0[expr344Cp1].m_flags | NetNode.Flags.Ambiguous);
         }
         else
         {
             var expr370Cp0 = instance.m_nodes.m_buffer;
             var expr370Cp1 = data.m_endNode;
             expr370Cp0[expr370Cp1].m_flags = (expr370Cp0[expr370Cp1].m_flags & ~NetNode.Flags.Ambiguous);
         }
         data.m_path = path;
         data.m_flags |= NetSegment.Flags.WaitingPath;
         return false;
     }
     return true;
 }
示例#58
0
        public bool CustomStartPathFind(ushort vehicleId,
                                        ref Vehicle vehicleData,
                                        Vector3 startPos,
                                        Vector3 endPos,
                                        bool startBothWays,
                                        bool endBothWays)
        {
            VehicleInfo info             = m_info;
            bool        allowUnderground =
                (vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0;

            if (!PathManager.FindPathPosition(
                    startPos,
                    ItemClass.Service.Road,
                    NetInfo.LaneType.Vehicle,
                    info.m_vehicleType,
                    allowUnderground,
                    false,
                    32f,
                    out PathUnit.Position startPosA,
                    out PathUnit.Position startPosB,
                    out float startDistSqrA,
                    out float startDistSqrB) ||
                !PathManager.FindPathPosition(
                    endPos,
                    ItemClass.Service.Road,
                    NetInfo.LaneType.Vehicle,
                    info.m_vehicleType,
                    false,
                    false,
                    32f,
                    out PathUnit.Position endPosA,
                    out PathUnit.Position endPosB,
                    out float endDistSqrA,
                    out float endDistSqrB))
            {
                return(false);
            }

            if (!startBothWays || startDistSqrB > startDistSqrA * 1.2f)
            {
                startPosB = default(PathUnit.Position);
            }

            if (!endBothWays || endDistSqrB > endDistSqrA * 1.2f)
            {
                endPosB = default(PathUnit.Position);
            }

            // NON-STOCK CODE START
            PathCreationArgs args;

            args.extPathType         = ExtPathType.None;
            args.extVehicleType      = ExtVehicleType.Trolleybus;
            args.vehicleId           = vehicleId;
            args.spawned             = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0;
            args.buildIndex          = Singleton <SimulationManager> .instance.m_currentBuildIndex;
            args.startPosA           = startPosA;
            args.startPosB           = startPosB;
            args.endPosA             = endPosA;
            args.endPosB             = endPosB;
            args.vehiclePosition     = default;
            args.laneTypes           = NetInfo.LaneType.Vehicle;
            args.vehicleTypes        = info.m_vehicleType;
            args.maxLength           = 20000f;
            args.isHeavyVehicle      = IsHeavyVehicle();
            args.hasCombustionEngine = CombustionEngine();
            args.ignoreBlocked       = IgnoreBlocked(vehicleId, ref vehicleData);
            args.ignoreFlooded       = false;
            args.randomParking       = false;
            args.ignoreCosts         = false;
            args.stablePath          = true;
            args.skipQueue           = true;

            if (CustomPathManager._instance.CustomCreatePath(
                    out uint path,
                    ref Singleton <SimulationManager> .instance.m_randomizer,
                    args))
            {
                // NON-STOCK CODE END
                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 static bool CustomStartPathFind(ushort segmentID, ref NetSegment data, ItemClass.Service netService, VehicleInfo.VehicleType vehicleType, bool skipQueue) {
			if (data.m_path != 0u) {
				Singleton<PathManager>.instance.ReleasePath(data.m_path);
				data.m_path = 0u;
			}
			NetManager instance = Singleton<NetManager>.instance;
			if ((instance.m_nodes.m_buffer[(int)data.m_startNode].m_flags & NetNode.Flags.Ambiguous) != NetNode.Flags.None) {
				for (int i = 0; i < 8; i++) {
					ushort segment = instance.m_nodes.m_buffer[(int)data.m_startNode].GetSegment(i);
					if (segment != 0 && segment != segmentID && instance.m_segments.m_buffer[(int)segment].m_path != 0u) {
						return true;
					}
				}
			}
			if ((instance.m_nodes.m_buffer[(int)data.m_endNode].m_flags & NetNode.Flags.Ambiguous) != NetNode.Flags.None) {
				for (int j = 0; j < 8; j++) {
					ushort segment2 = instance.m_nodes.m_buffer[(int)data.m_endNode].GetSegment(j);
					if (segment2 != 0 && segment2 != segmentID && instance.m_segments.m_buffer[(int)segment2].m_path != 0u) {
						return true;
					}
				}
			}
			Vector3 position = instance.m_nodes.m_buffer[(int)data.m_startNode].m_position;
			Vector3 position2 = instance.m_nodes.m_buffer[(int)data.m_endNode].m_position;
			PathUnit.Position startPosA;
			PathUnit.Position startPosB;
			float num;
			float num2;
			if (!PathManager.FindPathPosition(position, netService, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, vehicleType, true, false, 32f, out startPosA, out startPosB, out num, out num2)) {
				CustomTransportLineAI.CheckSegmentProblems(segmentID, ref data);
				return true;
			}
			PathUnit.Position endPosA;
			PathUnit.Position endPosB;
			float num3;
			float num4;
			if (!PathManager.FindPathPosition(position2, netService, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, vehicleType, true, false, 32f, out endPosA, out endPosB, out num3, out num4)) {
				CustomTransportLineAI.CheckSegmentProblems(segmentID, ref data);
				return true;
			}
			if ((instance.m_nodes.m_buffer[(int)data.m_startNode].m_flags & NetNode.Flags.Fixed) != NetNode.Flags.None) {
				startPosB = default(PathUnit.Position);
			}
			if ((instance.m_nodes.m_buffer[(int)data.m_endNode].m_flags & NetNode.Flags.Fixed) != NetNode.Flags.None) {
				endPosB = default(PathUnit.Position);
			}
			startPosA.m_offset = 128;
			startPosB.m_offset = 128;
			endPosA.m_offset = 128;
			endPosB.m_offset = 128;
			bool stopLane = CustomTransportLineAI.GetStopLane(ref startPosA, vehicleType);
			bool stopLane2 = CustomTransportLineAI.GetStopLane(ref startPosB, vehicleType);
			bool stopLane3 = CustomTransportLineAI.GetStopLane(ref endPosA, vehicleType);
			bool stopLane4 = CustomTransportLineAI.GetStopLane(ref endPosB, vehicleType);
			if ((!stopLane && !stopLane2) || (!stopLane3 && !stopLane4)) {
				CustomTransportLineAI.CheckSegmentProblems(segmentID, ref data);
				return true;
			}
			uint path;
			ExtVehicleType extVehicleType = ExtVehicleType.Bus;
			if ((vehicleType & (VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Metro)) != VehicleInfo.VehicleType.None)
				extVehicleType = ExtVehicleType.PassengerTrain;
			if ((vehicleType & VehicleInfo.VehicleType.Tram) != VehicleInfo.VehicleType.None)
				extVehicleType = ExtVehicleType.Tram;
			if ((vehicleType & VehicleInfo.VehicleType.Ship) != VehicleInfo.VehicleType.None)
				extVehicleType = ExtVehicleType.PassengerShip;
			if ((vehicleType & VehicleInfo.VehicleType.Plane) != VehicleInfo.VehicleType.None)
				extVehicleType = ExtVehicleType.PassengerPlane;
			//Log._Debug($"Transport line. extVehicleType={extVehicleType}");

			if (Singleton<CustomPathManager>.instance.CreatePath(extVehicleType, out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, vehicleType, 20000f, false, true, true, skipQueue)) {
				if (startPosA.m_segment != 0 && startPosB.m_segment != 0) {
					NetNode[] expr_2F5_cp_0 = instance.m_nodes.m_buffer;
					ushort expr_2F5_cp_1 = data.m_startNode;
					expr_2F5_cp_0[(int)expr_2F5_cp_1].m_flags = (expr_2F5_cp_0[(int)expr_2F5_cp_1].m_flags | NetNode.Flags.Ambiguous);
				} else {
					NetNode[] expr_321_cp_0 = instance.m_nodes.m_buffer;
					ushort expr_321_cp_1 = data.m_startNode;
					expr_321_cp_0[(int)expr_321_cp_1].m_flags = (expr_321_cp_0[(int)expr_321_cp_1].m_flags & ~NetNode.Flags.Ambiguous);
				}
				if (endPosA.m_segment != 0 && endPosB.m_segment != 0) {
					NetNode[] expr_360_cp_0 = instance.m_nodes.m_buffer;
					ushort expr_360_cp_1 = data.m_endNode;
					expr_360_cp_0[(int)expr_360_cp_1].m_flags = (expr_360_cp_0[(int)expr_360_cp_1].m_flags | NetNode.Flags.Ambiguous);
				} else {
					NetNode[] expr_38C_cp_0 = instance.m_nodes.m_buffer;
					ushort expr_38C_cp_1 = data.m_endNode;
					expr_38C_cp_0[(int)expr_38C_cp_1].m_flags = (expr_38C_cp_0[(int)expr_38C_cp_1].m_flags & ~NetNode.Flags.Ambiguous);
				}
				data.m_path = path;
				data.m_flags |= NetSegment.Flags.WaitingPath;
				return false;
			}
			CustomTransportLineAI.CheckSegmentProblems(segmentID, ref data);
			return true;
		}
示例#60
0
        public Task SetVehicleTrackingInfo(VehicleInfo info)
        {
            _vehicleInfo = info;

            return(TaskDone.Done);
        }