示例#1
0
        public static bool Prefix(ref bool __result, ref 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, bool randomParking, bool ignoreFlooded, bool combustionEngine, bool ignoreCost)
        {
            PathCreationArgs args = default;
            VehicleInfo      info = null;

            if (VehicleID != 0)
            {
                // CreatePath called for customized AI
                Vehicle[]   vehicleBuffer = VehicleManager.instance.m_vehicles.m_buffer;
                ref Vehicle vehicleData   = ref vehicleBuffer[VehicleID];

                args.vehicleId      = VehicleID;
                args.extPathType    = ExtPathType;
                args.extVehicleType = ExtVehicleType;
                args.spawned        = vehicleData.m_flags.IsFlagSet(Vehicle.Flags.Spawned);
                args.skipQueue      = skipQueue;

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

            VehicleInfo info           = this.m_info;
            ushort      driverInstance = CustomPassengerCarAI.GetDriverInstance(vehicleID, ref vehicleData);
            if (driverInstance == 0)
            {
                return(false);
            }
            CitizenManager          instance    = Singleton <CitizenManager> .instance;
            CitizenInfo             info2       = instance.m_instances.m_buffer[(int)driverInstance].Info;
            NetInfo.LaneType        laneTypes   = NetInfo.LaneType.Vehicle | NetInfo.LaneType.Pedestrian;
            VehicleInfo.VehicleType vehicleType = this.m_info.m_vehicleType;
            bool   allowUnderground             = (vehicleData.m_flags & Vehicle.Flags.Underground) != 0;
            bool   randomParking  = false;
            ushort targetBuilding = instance.m_instances.m_buffer[(int)driverInstance].m_targetBuilding;
            if (targetBuilding != 0 && Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)targetBuilding].Info.m_class.m_service > ItemClass.Service.Office)
            {
                randomParking = true;
            }
            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float             num;
            float             num2;
            PathUnit.Position endPosA;
            if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out num, out num2) &&
                info2.m_citizenAI.FindPathPosition(driverInstance, ref instance.m_instances.m_buffer[(int)driverInstance], endPos, laneTypes, vehicleType, undergroundTarget, out endPosA))
            {
                if (!startBothWays || num < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                PathUnit.Position endPosB   = default(PathUnit.Position);
                SimulationManager instance2 = Singleton <SimulationManager> .instance;
                uint path;
                PathUnit.Position def = default(PathUnit.Position);
                if (Singleton <CustomPathManager> .instance.CreatePath(
#if PATHRECALC
                        recalcRequested
#else
                        false
#endif
                        , ExtVehicleType.PassengerCar, out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, ref startPosA, ref startPosB, ref endPosA, ref endPosB, ref def, laneTypes, vehicleType, 20000f, false, false, false, false, randomParking))
                {
                    if (vehicleData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);
                    }
                    vehicleData.m_path   = path;
                    vehicleData.m_flags |= Vehicle.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
 public bool FindPathPositionWithSpiralLoop(Vector3 position,
                                            ItemClass.Service service,
                                            NetInfo.LaneType laneType,
                                            VehicleInfo.VehicleType vehicleType,
                                            NetInfo.LaneType otherLaneType,
                                            VehicleInfo.VehicleType otherVehicleType,
                                            bool allowUnderground,
                                            bool requireConnect,
                                            float maxDistance,
                                            out PathUnit.Position pathPosA,
                                            out PathUnit.Position pathPosB,
                                            out float distanceSqrA,
                                            out float distanceSqrB)
 {
     return(FindPathPositionWithSpiralLoop(
                position,
                null,
                service,
                laneType,
                vehicleType,
                otherLaneType,
                otherVehicleType,
                allowUnderground,
                requireConnect,
                maxDistance,
                out pathPosA,
                out pathPosB,
                out distanceSqrA,
                out distanceSqrB));
 }
        /// <summary>
        /// Finds a suitable path position for a walking citizen with the given world position.
        /// If secondary lane constraints are given also checks whether there exists another lane that matches those constraints.
        /// </summary>
        /// <param name="pos">world position</param>
        /// <param name="laneTypes">allowed lane types</param>
        /// <param name="vehicleTypes">allowed vehicle types</param>
        /// <param name="otherLaneTypes">allowed lane types for secondary lane</param>
        /// <param name="otherVehicleTypes">other vehicle types for secondary lane</param>
        /// <param name="allowTransport">public transport allowed?</param>
        /// <param name="allowUnderground">underground position allowed?</param>
        /// <param name="position">resulting path position</param>
        /// <returns><code>true</code> if a position could be found, <code>false</code> otherwise</returns>
        public static bool FindCitizenPathPosition(Vector3 pos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, NetInfo.LaneType otherLaneTypes, VehicleInfo.VehicleType otherVehicleTypes, bool allowTransport, bool allowUnderground, out PathUnit.Position position)
        {
            // TODO move to ExtPathManager after harmony upgrade
            position = default(PathUnit.Position);
            float minDist = 1E+10f;

            PathUnit.Position posA;
            PathUnit.Position posB;
            float             distA;
            float             distB;

            if (FindPathPositionWithSpiralLoop(pos, ItemClass.Service.Road, laneTypes, vehicleTypes, otherLaneTypes, otherVehicleTypes, allowUnderground, false, Options.prohibitPocketCars ? GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance : 32f, out posA, out posB, out distA, out distB) && distA < minDist)
            {
                minDist  = distA;
                position = posA;
            }
            if (FindPathPositionWithSpiralLoop(pos, ItemClass.Service.Beautification, laneTypes, vehicleTypes, otherLaneTypes, otherVehicleTypes, allowUnderground, false, Options.prohibitPocketCars ? GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance : 32f, out posA, out posB, out distA, out distB) && distA < minDist)
            {
                minDist  = distA;
                position = posA;
            }
            if (allowTransport && FindPathPositionWithSpiralLoop(pos, ItemClass.Service.PublicTransport, laneTypes, vehicleTypes, otherLaneTypes, otherVehicleTypes, allowUnderground, false, Options.prohibitPocketCars ? GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance : 32f, out posA, out posB, out distA, out distB) && distA < minDist)
            {
                minDist  = distA;
                position = posA;
            }
            return(position.m_segment != 0);
        }
 public bool FindPathPositionWithSpiralLoop(Vector3 position,
                                            Vector3?secondaryPosition,
                                            ItemClass.Service service,
                                            NetInfo.LaneType laneType,
                                            VehicleInfo.VehicleType vehicleType,
                                            NetInfo.LaneType otherLaneType,
                                            VehicleInfo.VehicleType otherVehicleType,
                                            bool allowUnderground,
                                            bool requireConnect,
                                            float maxDistance,
                                            out PathUnit.Position pathPos)
 {
     return(FindPathPositionWithSpiralLoop(
                position,
                secondaryPosition,
                service,
                laneType,
                vehicleType,
                otherLaneType,
                otherVehicleType,
                VehicleInfo.VehicleType.None,
                allowUnderground,
                requireConnect,
                maxDistance,
                out pathPos,
                out PathUnit.Position _,
                out float _,
                out float _));
 }
 public LanePos(uint laneId, byte laneIndex, float position, VehicleInfo.VehicleType vehicleType, NetInfo.LaneType laneType)
 {
     this.laneId      = laneId;
     this.laneIndex   = laneIndex;
     this.position    = position;
     this.vehicleType = vehicleType;
     this.laneType    = laneType;
 }
 static bool Prefix(ref bool __result, NetSegment __instance, Vector3 point, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, ref bool requireConnect)
 {
     if (requireConnect && __instance.Info.m_netAI is RoadBridgeAI)
     {
         requireConnect = false;
     }
     return(true);
 }
示例#8
0
        public static void Postfix(ushort nodeID, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, ref NetSegment __instance, ref int leftIndex, ref int rightIndex, ref uint leftLane, ref uint rightLane)
        {
            if (OptionUI.noJunction)
            {
                if (CSURUtil.IsCSURNoJunction(__instance.Info))
                {
                    if (leftIndex == -1 && rightIndex == -1 && leftLane == 0 && rightLane == 0)
                    {
                        int        debugPedestrianCount = 0;
                        NetManager instance             = Singleton <NetManager> .instance;
                        NetInfo    info  = __instance.Info;
                        int        num   = info.m_lanes.Length;
                        uint       num2  = __instance.m_lanes;
                        int        num10 = 0;
                        while (num10 < num && num2 != 0u)
                        {
                            NetInfo.Lane lane2 = info.m_lanes[num10];
                            if (info.m_lanes[num10].m_laneType.IsFlagSet(NetInfo.LaneType.Pedestrian))
                            {
                                debugPedestrianCount++;
                                if (lane2.m_position > 0)
                                {
                                    //DebugLog.LogToFileOnly($"Fix this case for XR, only one Pedestrian lane {__instance.Info.name}");
                                    //XR case
                                    leftIndex = num10;
                                    leftLane  = num2;
                                }
                                else
                                {
                                    //DebugLog.LogToFileOnly($"Fix this case for XL, only one Pedestrian lane {__instance.Info.name}");
                                    //XL case??
                                    rightIndex = num10;
                                    rightLane  = num2;
                                }
                                break;
                            }
                            num2 = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_nextLane;
                            num10++;
                        }

                        if (debugPedestrianCount == 1)
                        {
                            //DebugLog.LogToFileOnly($"Fix this case, only one Pedestrian lane {__instance.Info.name}");
                        }

                        if (nodeID == __instance.m_startNode != ((__instance.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None))
                        {
                            int num12 = leftIndex;
                            leftIndex  = rightIndex;
                            rightIndex = num12;
                            uint num13 = leftLane;
                            leftLane  = rightLane;
                            rightLane = num13;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Checks if any lanes from source segment can go to target segment.
        /// Precondition: assuming that the segments can have connected lanes.
        /// </summary>
        /// <param name="sourceSegmentId"></param>
        /// <param name="targetSegmentId"></param>
        /// <param name="nodeId"></param>
        /// <param name="laneType"></param>
        /// <param name="vehicleType"></param>
        /// <returns></returns>
        internal static bool HasDirectConnect(
            ushort sourceSegmentId,
            ushort targetSegmentId,
            ushort nodeId,
            NetInfo.LaneType laneType,
            VehicleInfo.VehicleType vehicleType)
        {
            try {
                bool sourceStartNode = IsStartNode(sourceSegmentId, nodeId);
                var  sourceLaneInfos = sourceSegmentId.ToSegment().Info.m_lanes;
                int  nSource         = sourceLaneInfos.Length;

                var targetLaneInfos = targetSegmentId.ToSegment().Info.m_lanes;
                int nTarget         = targetLaneInfos.Length;

                uint sourceLaneId, targetLaneId;
                int  sourceLaneIndex, targetLaneIndex;
                for (sourceLaneIndex = 0, sourceLaneId = sourceSegmentId.ToSegment().m_lanes;
                     sourceLaneIndex < nSource;
                     ++sourceLaneIndex, sourceLaneId = sourceLaneId.ToLane().m_nextLane)
                {
                    //Log.Debug($"sourceLaneId={sourceLaneId} {sourceLaneInfos[sourceLaneIndex].m_laneType} & {laneType} = {sourceLaneInfos[sourceLaneIndex].m_laneType & laneType}\n" +
                    //    $"{sourceLaneInfos[sourceLaneIndex].m_vehicleType} & {vehicleType} = {sourceLaneInfos[sourceLaneIndex].m_vehicleType & vehicleType}");

                    if ((sourceLaneInfos[sourceLaneIndex].m_laneType & laneType) == 0 ||
                        (sourceLaneInfos[sourceLaneIndex].m_vehicleType & vehicleType) == 0)
                    {
                        continue;
                    }
                    //Log.Debug($"POINT A> ");
                    for (targetLaneIndex = 0, targetLaneId = targetSegmentId.ToSegment().m_lanes;
                         targetLaneIndex < nTarget;
                         ++targetLaneIndex, targetLaneId = targetLaneId.ToLane().m_nextLane)
                    {
                        //Log.Debug($"targetLaneId={targetLaneId} {targetLaneInfos[targetLaneIndex].m_laneType} & {laneType} = {targetLaneInfos[targetLaneIndex].m_laneType & laneType}\n" +
                        //    $"{targetLaneInfos[targetLaneIndex].m_vehicleType} & {vehicleType} = {targetLaneInfos[targetLaneIndex].m_vehicleType & vehicleType}");
                        if ((targetLaneInfos[targetLaneIndex].m_laneType & laneType) == 0 ||
                            (targetLaneInfos[targetLaneIndex].m_vehicleType & vehicleType) == 0)
                        {
                            continue;
                        }

                        bool connected = AreLanesConnected(
                            sourceSegmentId, sourceLaneId, (byte)sourceLaneIndex,
                            targetSegmentId, targetLaneId, (byte)targetLaneIndex,
                            nodeId);

                        //Log($"sourceLaneId={sourceLaneId} targetLaneId={targetLaneId} sourceStartNode={sourceStartNode} connected={connected}");
                        if (connected)
                        {
                            return(true);
                        }
                    }
                }
            } catch (Exception ex) { ex.Log(); }
            return(false);
        }
        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 vehicleType = 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, vehicleType, 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 instance2 = Singleton <SimulationManager> .instance;
                uint path;
                if (CustomPathManager._instance.CreatePath(
                        ExtVehicleType.Taxi, vehicleID, 0, out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, laneTypes, vehicleType, 20000f, IsHeavyVehicle(), IgnoreBlocked(vehicleID, ref vehicleData), false, (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0))
                {
                    if (vehicleData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);
                    }
                    vehicleData.m_path   = path;
                    vehicleData.m_flags |= Vehicle.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
#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, out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, ref startPosA, ref startPosB, ref endPosA, ref endPosB, laneType, vehicleType, 20000f))
                {
                    if (vehicleData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);
                    }
                    vehicleData.m_path   = path;
                    vehicleData.m_flags |= Vehicle.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
        protected override bool StartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays)
        {
            VehicleInfo info           = this.m_info;
            ushort      driverInstance = this.GetDriverInstance(vehicleID, ref vehicleData);

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

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

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

            PathUnit.Position endPosA;
            //    if (PathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out num, out num2)                     && info2.m_citizenAI.FindPathPosition(driverInstance, ref instance.m_instances.m_buffer[(int)driverInstance], endPos, laneTypes, vehicleType, false, out 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, RoadManager.VehicleType.PassengerCar) && FindPathPosition(driverInstance, ref instance.m_instances.m_buffer[(int)driverInstance], endPos, laneTypes, vehicleType, false, out endPosA))
            {
                if (!startBothWays || num < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                PathUnit.Position endPosB   = default(PathUnit.Position);
                SimulationManager instance2 = Singleton <SimulationManager> .instance;
                uint path;
                bool createPathResult;
                CustomPathManager customPathManager = Singleton <PathManager> .instance as CustomPathManager;
                if (customPathManager != null)
                {
                    createPathResult = customPathManager.CreatePath(out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, laneTypes, vehicleType, 20000f, RoadManager.VehicleType.PassengerCar);
                }
                else
                {
                    createPathResult = Singleton <PathManager> .instance.CreatePath(out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, laneTypes, vehicleType, 20000f);
                }
                if (createPathResult)
                {
                    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);
        }
        // assuming that the segments can have connected lanes.
        public static bool ShouldConnectTracks(
            ushort sourceSegmentId,
            ushort targetSegmentId,
            ushort nodeId,
            NetInfo.LaneType laneType,
            VehicleInfo.VehicleType vehicleType)
        {
            bool sourceStartNode = (bool)netService.IsStartNode(sourceSegmentId, nodeId);
            var  sourceLaneInfos = sourceSegmentId.ToSegment().Info.m_lanes;
            int  nSource         = sourceLaneInfos.Length;

            var targetLaneInfos = targetSegmentId.ToSegment().Info.m_lanes;
            int nTarget         = targetLaneInfos.Length;

            uint sourceLaneId, targetLaneId;
            int  sourceLaneIndex, targetLaneIndex;

            for (sourceLaneIndex = 0, sourceLaneId = sourceSegmentId.ToSegment().m_lanes;
                 sourceLaneIndex < nSource;
                 ++sourceLaneIndex, sourceLaneId = laneBuffer[sourceLaneId].m_nextLane)
            {
                //Extensions.Log($"sourceLaneId={sourceLaneId} {sourceLaneInfos[sourceLaneIndex].m_laneType} & {laneType} = {sourceLaneInfos[sourceLaneIndex].m_laneType & laneType}\n" +
                //    $"{sourceLaneInfos[sourceLaneIndex].m_vehicleType} & {vehicleType} = {sourceLaneInfos[sourceLaneIndex].m_vehicleType & vehicleType}");

                if ((sourceLaneInfos[sourceLaneIndex].m_laneType & laneType) == 0 ||
                    (sourceLaneInfos[sourceLaneIndex].m_vehicleType & vehicleType) == 0)
                {
                    continue;
                }
                //Extensions.Log($"POINT A> ");
                for (targetLaneIndex = 0, targetLaneId = targetSegmentId.ToSegment().m_lanes;
                     targetLaneIndex < nTarget;
                     ++targetLaneIndex, targetLaneId = laneBuffer[targetLaneId].m_nextLane)
                {
                    //Extensions.Log($"targetLaneId={targetLaneId} {targetLaneInfos[targetLaneIndex].m_laneType} & {laneType} = {targetLaneInfos[targetLaneIndex].m_laneType & laneType}\n" +
                    //    $"{targetLaneInfos[targetLaneIndex].m_vehicleType} & {vehicleType} = {targetLaneInfos[targetLaneIndex].m_vehicleType & vehicleType}");
                    if ((targetLaneInfos[targetLaneIndex].m_laneType & laneType) == 0 ||
                        (targetLaneInfos[targetLaneIndex].m_vehicleType & vehicleType) == 0)
                    {
                        continue;
                    }
                    bool b1 = LCMan.HasConnections(sourceLaneId, sourceStartNode);
                    bool b2 = LCMan.AreLanesConnected(sourceLaneId, targetLaneId, sourceStartNode);
                    Extensions.Log($"sourceLaneId={sourceLaneId} targetLaneId={targetLaneId} sourceStartNode={sourceStartNode} b1={b1} b2={b2}");

                    if (!b1 || b2)
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
 /// <summary>
 /// Precondition: assuming that the segments can have connected lanes.
 /// </summary>
 internal static NetInfo.Node DetermineDirectConnect(
     NetInfo.Node nodeInfo,
     ushort sourceSegmentId,
     ushort targetSegmentId,
     ushort nodeId,
     NetInfo.LaneType laneType,
     VehicleInfo.VehicleType vehicleType,
     out bool flipMesh)
 {
     flipMesh = false;
     try {
         ref NetSegment sourceSegment = ref sourceSegmentId.ToSegment();
         ref NetSegment targetSegment = ref targetSegmentId.ToSegment();
        protected override bool StartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
            VehicleInfo info           = this.m_info;
            ushort      driverInstance = this.GetDriverInstance(vehicleID, ref vehicleData);

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

            NetInfo.LaneType        laneTypes   = NetInfo.LaneType.Vehicle | NetInfo.LaneType.Pedestrian;
            VehicleInfo.VehicleType vehicleType = this.m_info.m_vehicleType;
            bool   allowUnderground             = (vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != (Vehicle.Flags) 0;
            bool   randomParking  = false;
            ushort targetBuilding = instance.m_instances.m_buffer[(int)driverInstance].m_targetBuilding;

            if (targetBuilding != 0 && Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)targetBuilding].Info.m_class.m_service > ItemClass.Service.Office)
            {
                randomParking = true;
            }
            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float             num;
            float             num2;

            PathUnit.Position endPosA;
            if (PathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out num, out num2) && info2.m_citizenAI.FindPathPosition(driverInstance, ref instance.m_instances.m_buffer[(int)driverInstance], endPos, laneTypes, vehicleType, undergroundTarget, out endPosA))
            {
                if (!startBothWays || num < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                PathUnit.Position endPosB   = default(PathUnit.Position);
                SimulationManager instance2 = Singleton <SimulationManager> .instance;
                uint path;
                if (Singleton <PathManager> .instance.CreatePath(ExtendedVehicleType.PassengerCar, out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, default(PathUnit.Position), laneTypes, vehicleType, 20000f, false, false, false, false, randomParking))
                {
                    if (vehicleData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);
                    }
                    vehicleData.m_path   = path;
                    vehicleData.m_flags |= Vehicle.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
示例#16
0
        private static void SeparateSegmentLanes(
            ushort segmentId,
            ushort nodeId,
            out SetLaneArrow_Result res,
            NetInfo.LaneType laneType,
            VehicleInfo.VehicleType vehicleType,
            bool alt2 = false,
            bool alt3 = false) {
            res = CanChangeLanes(segmentId, nodeId);
            if (res != SetLaneArrow_Result.Success) {
                return;
            }
            res = SetLaneArrow_Result.Success;

            ref NetSegment seg = ref segmentId.ToSegment();
示例#17
0
        public static NetInfo.Lane FindLane(this NetInfo info, NetInfo.LaneType predicate, bool crashOnNotFound = true)
        {
            var lane = info
                       .m_lanes
                       .FirstOrDefault(l => l.m_laneType == NetInfo.LaneType.Vehicle);

            if (lane == null)
            {
                if (crashOnNotFound)
                {
                    throw new Exception("TFW: Lane not found");
                }
            }

            return(lane);
        }
        // Adapted from NetNode.CountLanes
        private static JunctionInfo AnalyseNode(NetNode node,
                                                ushort nodeID,
                                                ushort ignoreSegmentID,
                                                NetInfo.LaneType laneTypes,
                                                VehicleInfo.VehicleType vehicleTypes,
                                                Vector3 directionVector)
        {
            var nodeInfo = new JunctionInfo();

            if (node.m_flags == NetNode.Flags.None)
            {
                return(nodeInfo);
            }

            NetManager netManager = Singleton <NetManager> .instance;

            for (int i = 0; i < 8; i++)
            {
                ushort segmentID = node.GetSegment(i);
                if (segmentID == 0 || segmentID == ignoreSegmentID)
                {
                    continue;
                }

                var segment = netManager.m_segments.m_buffer[segmentID];

                if (segment.Info == null)
                {
                    continue; // may happen if loading a map with a missing road asset
                }

                bool isInverted  = (segment.m_flags & NetSegment.Flags.Invert) != 0;
                bool isStartNode = segment.m_startNode == nodeID;

                SegmentLanes lanes = SegmentAnalyser.IdentifyLanes(netManager, segment.Info, segmentID);

                Vector3 vector = isStartNode ? segment.m_startDirection : segment.m_endDirection;

                float angleDeg = GetAngleDeg(vector, directionVector);

                nodeInfo.AddLanes(isStartNode ^ isInverted ? lanes.forward : lanes.backward, angleDeg);
            }

            return(nodeInfo);
        }
示例#19
0
 protected override bool StartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays)
 {
     if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == Vehicle.Flags.None)
     {
         return(CustomCarAI.StartPathFind(this, vehicleID, ref vehicleData, startPos, endPos, startBothWays, endBothWays, true));
     }
     else
     {
         VehicleInfo       info      = this.m_info;
         NetInfo.LaneType  laneTypes = NetInfo.LaneType.Vehicle | ((NetInfo.LaneType)((byte)32)) | ((NetInfo.LaneType)((byte)64));
         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, laneTypes, info.m_vehicleType, 32f, out startPosA, out startPosB, out num, out num2) && CustomPathManager.FindPathPosition(endPos, ItemClass.Service.Road, laneTypes, info.m_vehicleType, 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;
             if ((Singleton <PathManager> .instance as CustomPathManager).CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, laneTypes, info.m_vehicleType, 20000f, this.IsHeavyVehicle(), this.IgnoreBlocked(vehicleID, ref vehicleData), false, false, true))
             {
                 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);
     }
 }
示例#20
0
        public static void SetDirectionImpl(bool lht = true)
        {
            if (lht == NetUtil.LHT)
            {
                return;                        // no need for change.
            }
            SimulationManager.instance.m_metaData.m_invertTraffic =
                lht ? SimulationMetaData.MetaBool.True: SimulationMetaData.MetaBool.False;

            for (ushort i = 0; i < PrefabCollection <NetInfo> .LoadedCount(); ++i)
            {
                var info = PrefabCollection <NetInfo> .GetLoaded(i);

                if (!info)
                {
                    continue;
                }
                foreach (var lane in info.m_lanes)
                {
                    const NetInfo.LaneType flags = NetInfo.LaneType.Vehicle | NetInfo.LaneType.Parking | NetInfo.LaneType.CargoVehicle | NetInfo.LaneType.TransportVehicle;
                    if (lht && lane.m_laneType.IsFlagSet(flags))
                    {
                        lane.m_finalDirection = NetInfo.InvertDirection(lane.m_direction);
                    }
                    else
                    {
                        lane.m_finalDirection = lane.m_direction;
                    }
                }
                Swap(ref info.m_hasForwardVehicleLanes, ref info.m_hasBackwardVehicleLanes);
                Swap(ref info.m_forwardVehicleLaneCount, ref info.m_backwardVehicleLaneCount);
            }

            SimulationManager.instance.m_ThreadingWrapper.QueueMainThread(RoadEditorUtils.RefreshRoadEditor);

            for (ushort segmentID = 1; segmentID < NetManager.MAX_SEGMENT_COUNT; ++segmentID)
            {
                if (NetUtil.IsSegmentValid(segmentID))
                {
                    NetManager.instance.UpdateSegment(segmentID);
                }
            }
        }
示例#21
0
        public static bool StartPathFind(CarAI carAI, ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool usePedestrianRoads)
        {
            VehicleInfo info = carAI.m_info;

            NetInfo.LaneType laneTypes = NetInfo.LaneType.Vehicle;
            if (usePedestrianRoads)
            {
                laneTypes |= ((NetInfo.LaneType)((byte)32));
            }
            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, laneTypes, info.m_vehicleType, 32f, out startPosA, out startPosB, out num, out num2) && CustomPathManager.FindPathPosition(endPos, ItemClass.Service.Road, laneTypes, info.m_vehicleType, 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;
                if ((Singleton <PathManager> .instance as CustomPathManager).CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, laneTypes, info.m_vehicleType, 20000f, (carAI as IVehicle).IsHeavyVehicle(), (carAI as IVehicle).IgnoreBlocked(vehicleID, ref vehicleData), false, false, true))
                {
                    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 StartPathFind2(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays)
        {
            VehicleInfo info           = this.m_info;
            ushort      driverInstance = CustomPassengerCarAI.GetDriverInstance2(vehicleID, ref vehicleData);

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

            NetInfo.LaneType        laneTypes   = NetInfo.LaneType.Vehicle | NetInfo.LaneType.Pedestrian;
            VehicleInfo.VehicleType vehicleType = this.m_info.m_vehicleType;
            PathUnit.Position       startPosA;
            PathUnit.Position       startPosB;
            float num;
            float num2;

            PathUnit.Position endPosA;
            if (PathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle, info.m_vehicleType, 32f, out startPosA, out startPosB, out num, out num2) && info2.m_citizenAI.FindPathPosition(driverInstance, ref instance.m_instances.m_buffer[(int)driverInstance], endPos, laneTypes, vehicleType, out endPosA))
            {
                if (!startBothWays || num < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                PathUnit.Position endPosB   = default(PathUnit.Position);
                SimulationManager instance2 = Singleton <SimulationManager> .instance;
                uint path;
                if (Singleton <CustomPathManager> .instance.CreatePath(out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, laneTypes, vehicleType, 20000f, false, false, false, false, ItemClass.Service.None))
                {
                    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 IEnumerable <uint> segmentLanes(
            ushort segmentId,
            NetInfo.LaneType laneType,
            VehicleInfo.VehicleType vehicleType)
        {
            var laneInfos = segmentId.ToSegment().Info.m_lanes;
            int n         = laneInfos.Length;

            uint laneId;
            int  laneIndex;

            for (laneIndex = 0, laneId = segmentId.ToSegment().m_lanes;
                 laneIndex < n;
                 ++laneIndex, laneId = laneBuffer[laneId].m_nextLane)
            {
                if ((laneInfos[laneIndex].m_laneType & laneType) == 0 ||
                    (laneInfos[laneIndex].m_vehicleType & vehicleType) == 0)
                {
                    continue;
                }
                yield return(laneId);
            }
        }
        protected override bool StartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays)
        {
            if ((vehicleData.m_flags & (Vehicle.Flags.TransferToSource | Vehicle.Flags.GoingBack)) != Vehicle.Flags.None)
            {
                return(CustomCarAI.StartPathFind(this, vehicleID, ref vehicleData, startPos, endPos, startBothWays, endBothWays, RoadManager.VehicleType.CargoTruck));
            }
            bool allowUnderground = (vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != Vehicle.Flags.None;

            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float             num;
            float             num2;
            bool flag = CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle, VehicleInfo.VehicleType.Car, allowUnderground, 32f, out startPosA, out startPosB, out num, out num2, RoadManager.VehicleType.CargoTruck);

            PathUnit.Position position;
            PathUnit.Position position2;
            float             num3;
            float             num4;

            if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.PublicTransport, NetInfo.LaneType.Vehicle, VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Ship, allowUnderground, 32f, out position, out position2, out num3, out num4, RoadManager.VehicleType.CargoTruck))
            {
                if (!flag || num3 < num)
                {
                    startPosA = position;
                    startPosB = position2;
                    num       = num3;
                    num2      = num4;
                }
                flag = true;
            }
            PathUnit.Position endPosA;
            PathUnit.Position endPosB;
            float             num5;
            float             num6;
            bool flag2 = CustomPathManager.FindPathPosition(endPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle, VehicleInfo.VehicleType.Car, false, 32f, out endPosA, out endPosB, out num5, out num6, RoadManager.VehicleType.CargoTruck);

            PathUnit.Position position3;
            PathUnit.Position position4;
            float             num7;
            float             num8;

            if (CustomPathManager.FindPathPosition(endPos, ItemClass.Service.PublicTransport, NetInfo.LaneType.Vehicle, VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Ship, false, 32f, out position3, out position4, out num7, out num8, RoadManager.VehicleType.CargoTruck))
            {
                if (!flag2 || num7 < num5)
                {
                    endPosA = position3;
                    endPosB = position4;
                    num5    = num7;
                    num6    = num8;
                }
                flag2 = true;
            }
            if (flag && flag2)
            {
                if (!startBothWays || num < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                if (!endBothWays || num5 < 10f)
                {
                    endPosB = default(PathUnit.Position);
                }
                NetInfo.LaneType        laneTypes    = NetInfo.LaneType.Vehicle | NetInfo.LaneType.CargoVehicle;
                VehicleInfo.VehicleType vehicleTypes = VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Ship;
                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, laneTypes, vehicleTypes, 20000f, this.IsHeavyVehicle(), this.IgnoreBlocked(vehicleID, ref vehicleData), false, false, RoadManager.VehicleType.CargoTruck);
                }
                else
                {
                    createPathResult = Singleton <PathManager> .instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, laneTypes, vehicleTypes, 20000f, this.IsHeavyVehicle(), this.IgnoreBlocked(vehicleID, ref vehicleData), false, false);
                }
                if (createPathResult)
                {
                    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);
        }
示例#25
0
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
#if DEBUG
            //Log._Debug($"CustomCargoTruckAI.CustomStartPathFind called for vehicle {vehicleID}");
#endif

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

            if ((vehicleData.m_flags & (Vehicle.Flags.TransferToSource | Vehicle.Flags.GoingBack)) != 0)
            {
                return(base.StartPathFind(vehicleID, ref vehicleData, startPos, endPos, startBothWays, endBothWays, undergroundTarget));
            }

            bool allowUnderground = (vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0;
            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float startDistSqrA;
            float startDistSqrB;
            bool startPosFound = CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, allowUnderground, false, 32f, out startPosA, out startPosB, out startDistSqrA, out startDistSqrB);
            PathUnit.Position startAltPosA;
            PathUnit.Position startAltPosB;
            float startAltDistSqrA;
            float startAltDistSqrB;
            if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.PublicTransport, NetInfo.LaneType.Vehicle, VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Ship, allowUnderground, false, 32f, out startAltPosA, out startAltPosB, out startAltDistSqrA, out startAltDistSqrB))
            {
                if (!startPosFound || startAltDistSqrA < startDistSqrA)
                {
                    startPosA     = startAltPosA;
                    startPosB     = startAltPosB;
                    startDistSqrA = startAltDistSqrA;
                    startDistSqrB = startAltDistSqrB;
                }
                startPosFound = true;
            }
            PathUnit.Position endPosA;
            PathUnit.Position endPosB;
            float endDistSqrA;
            float endDistSqrB;
            bool endPosFound = CustomPathManager.FindPathPosition(endPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, undergroundTarget, false, 32f, out endPosA, out endPosB, out endDistSqrA, out endDistSqrB);
            PathUnit.Position endAltPosA;
            PathUnit.Position endAltPosB;
            float endAltDistSqrA;
            float endAltDistSqrB;
            if (CustomPathManager.FindPathPosition(endPos, ItemClass.Service.PublicTransport, NetInfo.LaneType.Vehicle, VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Ship, undergroundTarget, false, 32f, out endAltPosA, out endAltPosB, out endAltDistSqrA, out endAltDistSqrB))
            {
                if (!endPosFound || endAltDistSqrA < endDistSqrA)
                {
                    endPosA     = endAltPosA;
                    endPosB     = endAltPosB;
                    endDistSqrA = endAltDistSqrA;
                    endDistSqrB = endAltDistSqrB;
                }
                endPosFound = true;
            }
            if (startPosFound && endPosFound)
            {
                CustomPathManager pathMan = CustomPathManager._instance;
                if (!startBothWays || startDistSqrA < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                if (!endBothWays || endDistSqrA < 10f)
                {
                    endPosB = default(PathUnit.Position);
                }
                NetInfo.LaneType        laneTypes    = NetInfo.LaneType.Vehicle | NetInfo.LaneType.CargoVehicle;
                VehicleInfo.VehicleType vehicleTypes = VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Ship;
                uint path;
                // NON-STOCK CODE START
                PathCreationArgs args;
                args.extPathType         = ExtCitizenInstance.ExtPathType.None;
                args.extVehicleType      = ExtVehicleType.CargoVehicle;
                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           = 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.randomParking       = false;
                args.stablePath          = false;
                args.skipQueue           = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0;

                if (pathMan.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, args))
                {
                    // NON-STOCK CODE END
                    if (vehicleData.m_path != 0u)
                    {
                        pathMan.ReleasePath(vehicleData.m_path);
                    }
                    vehicleData.m_path   = path;
                    vehicleData.m_flags |= Vehicle.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
示例#26
0
        public bool CustomStartPathFind(ushort vehicleId,
                                        ref Vehicle vehicleData,
                                        Vector3 startPos,
                                        Vector3 endPos,
                                        bool startBothWays,
                                        bool endBothWays,
                                        bool undergroundTarget)
        {
            ExtVehicleType vehicleType =
                ExtVehicleManager.Instance.OnStartPathFind(vehicleId, ref vehicleData, null);

            if (vehicleType == ExtVehicleType.None)
            {
                Log._DebugOnlyWarning(
                    $"CustomCargoTruck.CustomStartPathFind: Vehicle {vehicleId} " +
                    $"does not have a valid vehicle type!");
            }

            if ((vehicleData.m_flags & (Vehicle.Flags.TransferToSource
                                        | Vehicle.Flags.GoingBack)) != 0)
            {
                return(base.StartPathFind(
                           vehicleId,
                           ref vehicleData,
                           startPos,
                           endPos,
                           startBothWays,
                           endBothWays,
                           undergroundTarget));
            }

            bool allowUnderground = (vehicleData.m_flags & (Vehicle.Flags.Underground
                                                            | Vehicle.Flags.Transition)) != 0;
            bool startPosFound = PathManager.FindPathPosition(
                startPos,
                ItemClass.Service.Road,
                NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle,
                VehicleInfo.VehicleType.Car,
                allowUnderground,
                false,
                32f,
                out PathUnit.Position startPosA,
                out PathUnit.Position startPosB,
                out float startDistSqrA,
                out _);

            if (PathManager.FindPathPosition(
                    startPos,
                    ItemClass.Service.PublicTransport,
                    NetInfo.LaneType.Vehicle,
                    VehicleInfo.VehicleType.Train
                    | VehicleInfo.VehicleType.Ship
                    | VehicleInfo.VehicleType.Plane,
                    allowUnderground,
                    false,
                    32f,
                    out PathUnit.Position startAltPosA,
                    out PathUnit.Position startAltPosB,
                    out float startAltDistSqrA,
                    out _))
            {
                if (!startPosFound ||
                    (startAltDistSqrA < startDistSqrA &&
                     (Mathf.Abs(endPos.x) > 8000f ||
                      Mathf.Abs(endPos.z) > 8000f)))
                {
                    startPosA     = startAltPosA;
                    startPosB     = startAltPosB;
                    startDistSqrA = startAltDistSqrA;
                }

                startPosFound = true;
            }

            bool endPosFound = PathManager.FindPathPosition(
                endPos,
                ItemClass.Service.Road,
                NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle,
                VehicleInfo.VehicleType.Car,
                undergroundTarget,
                false,
                32f,
                out PathUnit.Position endPosA,
                out PathUnit.Position endPosB,
                out float endDistSqrA,
                out _);

            if (PathManager.FindPathPosition(
                    endPos,
                    ItemClass.Service.PublicTransport,
                    NetInfo.LaneType.Vehicle,
                    VehicleInfo.VehicleType.Train
                    | VehicleInfo.VehicleType.Ship
                    | VehicleInfo.VehicleType.Plane,
                    undergroundTarget,
                    false,
                    32f,
                    out PathUnit.Position endAltPosA,
                    out PathUnit.Position endAltPosB,
                    out float endAltDistSqrA,
                    out _))
            {
                if (!endPosFound ||
                    (endAltDistSqrA < endDistSqrA &&
                     (Mathf.Abs(endPos.x) > 8000f ||
                      Mathf.Abs(endPos.z) > 8000f)))
                {
                    endPosA     = endAltPosA;
                    endPosB     = endAltPosB;
                    endDistSqrA = endAltDistSqrA;
                }

                endPosFound = true;
            }

            if (!startPosFound || !endPosFound)
            {
                return(false);
            }

            CustomPathManager pathMan = CustomPathManager._instance;

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

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

            const NetInfo.LaneType LANE_TYPES = NetInfo.LaneType.Vehicle
                                                | NetInfo.LaneType.CargoVehicle;
            const VehicleInfo.VehicleType VEHICLE_TYPES = VehicleInfo.VehicleType.Car
                                                          | VehicleInfo.VehicleType.Train
                                                          | VehicleInfo.VehicleType.Ship
                                                          | VehicleInfo.VehicleType.Plane;

            // NON-STOCK CODE START
            PathCreationArgs args;

            args.extPathType         = ExtPathType.None;
            args.extVehicleType      = ExtVehicleType.CargoVehicle;
            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           = LANE_TYPES;
            args.vehicleTypes        = VEHICLE_TYPES;
            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 (!pathMan.CustomCreatePath(
                    out uint path,
                    ref Singleton <SimulationManager> .instance.m_randomizer,
                    args))
            {
                return(false);
            }

            // NON-STOCK CODE END
            if (vehicleData.m_path != 0u)
            {
                pathMan.ReleasePath(vehicleData.m_path);
            }

            vehicleData.m_path   = path;
            vehicleData.m_flags |= Vehicle.Flags.WaitingPath;
            return(true);
        }
        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 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));
 }
 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));
 }
 // NetSegment.GetClosestLane -- it's only called by the PathManager
 public static bool GetClosestLanePosition(NetSegment seg, Vector3 point, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, 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) && 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);
 }
        protected virtual void PathFindImplementation(uint unit, ref PathUnit data)
        {
            NetManager instance = Singleton<NetManager>.instance;
            this.m_laneTypes = (NetInfo.LaneType)this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_laneTypes;
            this.m_vehicleTypes = (VehicleInfo.VehicleType)this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_vehicleTypes;
            this.m_maxLength = this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_length;
            this.m_pathFindIndex = (this.m_pathFindIndex + 1u & 32767u);
            this.m_pathRandomizer = new Randomizer(unit);
            this.m_isHeavyVehicle = ((this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags & 16) != 0);
            this.m_ignoreBlocked = ((this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags & 32) != 0);
            this.m_stablePath = ((this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags & 64) != 0);
            this.m_transportVehicle = ((byte)(this.m_laneTypes & NetInfo.LaneType.TransportVehicle) != 0);
            if ((byte)(this.m_laneTypes & NetInfo.LaneType.Vehicle) != 0)
            {
                this.m_laneTypes |= NetInfo.LaneType.TransportVehicle;
            }

            int num = (int)(this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount & 15);
            int num2 = this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount >> 4;
            BufferItem bufferItem;
            if (data.m_position00.m_segment != 0 && num >= 1)
            {
                this.m_startLaneA = PathManager.GetLaneID(data.m_position00);
                this.m_startOffsetA = data.m_position00.m_offset;
                bufferItem.m_laneID = this.m_startLaneA;
                bufferItem.m_position = data.m_position00;
                this.GetLaneDirection(data.m_position00, out bufferItem.m_direction, out bufferItem.m_lanesUsed);
                bufferItem.m_comparisonValue = 0f;
            }
            else
            {
                this.m_startLaneA = 0u;
                this.m_startOffsetA = 0;
                bufferItem = default(BufferItem);
            }
            BufferItem bufferItem2;
            if (data.m_position02.m_segment != 0 && num >= 3)
            {
                this.m_startLaneB = PathManager.GetLaneID(data.m_position02);
                this.m_startOffsetB = data.m_position02.m_offset;
                bufferItem2.m_laneID = this.m_startLaneB;
                bufferItem2.m_position = data.m_position02;
                this.GetLaneDirection(data.m_position02, out bufferItem2.m_direction, out bufferItem2.m_lanesUsed);
                bufferItem2.m_comparisonValue = 0f;
            }
            else
            {
                this.m_startLaneB = 0u;
                this.m_startOffsetB = 0;
                bufferItem2 = default(BufferItem);
            }
            BufferItem bufferItem3;
            if (data.m_position01.m_segment != 0 && num >= 2)
            {
                this.m_endLaneA = PathManager.GetLaneID(data.m_position01);
                bufferItem3.m_laneID = this.m_endLaneA;
                bufferItem3.m_position = data.m_position01;
                this.GetLaneDirection(data.m_position01, out bufferItem3.m_direction, out bufferItem3.m_lanesUsed);
                bufferItem3.m_methodDistance = 0f;
                bufferItem3.m_comparisonValue = 0f;
            }
            else
            {
                this.m_endLaneA = 0u;
                bufferItem3 = default(BufferItem);
            }
            BufferItem bufferItem4;
            if (data.m_position03.m_segment != 0 && num >= 4)
            {
                this.m_endLaneB = PathManager.GetLaneID(data.m_position03);
                bufferItem4.m_laneID = this.m_endLaneB;
                bufferItem4.m_position = data.m_position03;
                this.GetLaneDirection(data.m_position03, out bufferItem4.m_direction, out bufferItem4.m_lanesUsed);
                bufferItem4.m_methodDistance = 0f;
                bufferItem4.m_comparisonValue = 0f;
            }
            else
            {
                this.m_endLaneB = 0u;
                bufferItem4 = default(BufferItem);
            }
            if (data.m_position11.m_segment != 0 && num2 >= 1)
            {
                this.m_vehicleLane = PathManager.GetLaneID(data.m_position11);
                this.m_vehicleOffset = data.m_position11.m_offset;
            }
            else
            {
                this.m_vehicleLane = 0u;
                this.m_vehicleOffset = 0;
            }
            BufferItem bufferItem5 = default(BufferItem);
            byte b = 0;
            this.m_bufferMinPos = 0;
            this.m_bufferMaxPos = -1;
            if (this.m_pathFindIndex == 0u)
            {
                uint num3 = 4294901760u;
                for (int i = 0; i < 262144; i++)
                {
                    this.m_laneLocation[i] = num3;
                }
            }
            for (int j = 0; j < 1024; j++)
            {
                this.m_bufferMin[j] = 0;
                this.m_bufferMax[j] = -1;
            }
            if (bufferItem3.m_position.m_segment != 0)
            {
                this.m_bufferMax[0]++;
                this.m_buffer[++this.m_bufferMaxPos] = bufferItem3;
            }
            if (bufferItem4.m_position.m_segment != 0)
            {
                this.m_bufferMax[0]++;
                this.m_buffer[++this.m_bufferMaxPos] = bufferItem4;
            }
            bool flag = false;
            while (this.m_bufferMinPos <= this.m_bufferMaxPos)
            {
                int num4 = this.m_bufferMin[this.m_bufferMinPos];
                int num5 = this.m_bufferMax[this.m_bufferMinPos];
                if (num4 > num5)
                {
                    this.m_bufferMinPos++;
                }
                else
                {
                    this.m_bufferMin[this.m_bufferMinPos] = num4 + 1;
                    BufferItem bufferItem6 = this.m_buffer[(this.m_bufferMinPos << 6) + num4];
                    if (bufferItem6.m_position.m_segment == bufferItem.m_position.m_segment && bufferItem6.m_position.m_lane == bufferItem.m_position.m_lane)
                    {
                        if ((byte)(bufferItem6.m_direction & NetInfo.Direction.Forward) != 0 && bufferItem6.m_position.m_offset >= this.m_startOffsetA)
                        {
                            bufferItem5 = bufferItem6;
                            b = this.m_startOffsetA;
                            flag = true;
                            break;
                        }
                        if ((byte)(bufferItem6.m_direction & NetInfo.Direction.Backward) != 0 && bufferItem6.m_position.m_offset <= this.m_startOffsetA)
                        {
                            bufferItem5 = bufferItem6;
                            b = this.m_startOffsetA;
                            flag = true;
                            break;
                        }
                    }
                    if (bufferItem6.m_position.m_segment == bufferItem2.m_position.m_segment && bufferItem6.m_position.m_lane == bufferItem2.m_position.m_lane)
                    {
                        if ((byte)(bufferItem6.m_direction & NetInfo.Direction.Forward) != 0 && bufferItem6.m_position.m_offset >= this.m_startOffsetB)
                        {
                            bufferItem5 = bufferItem6;
                            b = this.m_startOffsetB;
                            flag = true;
                            break;
                        }
                        if ((byte)(bufferItem6.m_direction & NetInfo.Direction.Backward) != 0 && bufferItem6.m_position.m_offset <= this.m_startOffsetB)
                        {
                            bufferItem5 = bufferItem6;
                            b = this.m_startOffsetB;
                            flag = true;
                            break;
                        }
                    }
                    if ((byte)(bufferItem6.m_direction & NetInfo.Direction.Forward) != 0)
                    {
                        ushort startNode = instance.m_segments.m_buffer[(int)bufferItem6.m_position.m_segment].m_startNode;
                        this.ProcessItem(bufferItem6, startNode, ref instance.m_nodes.m_buffer[(int)startNode], 0, false);
                    }
                    if ((byte)(bufferItem6.m_direction & NetInfo.Direction.Backward) != 0)
                    {
                        ushort endNode = instance.m_segments.m_buffer[(int)bufferItem6.m_position.m_segment].m_endNode;
                        this.ProcessItem(bufferItem6, endNode, ref instance.m_nodes.m_buffer[(int)endNode], 255, false);
                    }
                    int num6 = 0;
                    ushort num7 = instance.m_lanes.m_buffer[(int)((UIntPtr)bufferItem6.m_laneID)].m_nodes;
                    if (num7 != 0)
                    {
                        ushort startNode2 = instance.m_segments.m_buffer[(int)bufferItem6.m_position.m_segment].m_startNode;
                        ushort endNode2 = instance.m_segments.m_buffer[(int)bufferItem6.m_position.m_segment].m_endNode;
                        bool flag2 = ((instance.m_nodes.m_buffer[(int)startNode2].m_flags | instance.m_nodes.m_buffer[(int)endNode2].m_flags) & NetNode.Flags.Disabled) != NetNode.Flags.None;
                        while (num7 != 0)
                        {
                            NetInfo.Direction direction = NetInfo.Direction.None;
                            byte laneOffset = instance.m_nodes.m_buffer[(int)num7].m_laneOffset;
                            if (laneOffset <= bufferItem6.m_position.m_offset)
                            {
                                direction |= NetInfo.Direction.Forward;
                            }
                            if (laneOffset >= bufferItem6.m_position.m_offset)
                            {
                                direction |= NetInfo.Direction.Backward;
                            }
                            if ((byte)(bufferItem6.m_direction & direction) != 0 && (!flag2 || (instance.m_nodes.m_buffer[(int)num7].m_flags & NetNode.Flags.Disabled) != NetNode.Flags.None))
                            {
                                this.ProcessItem(bufferItem6, num7, ref instance.m_nodes.m_buffer[(int)num7], laneOffset, true);
                            }
                            num7 = instance.m_nodes.m_buffer[(int)num7].m_nextLaneNode;
                            if (++num6 == 32768)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            if (!flag)
            {
                PathUnit[] expr_909_cp_0 = this.m_pathUnits.m_buffer;
                UIntPtr expr_909_cp_1 = (UIntPtr)unit;
                expr_909_cp_0[(int)expr_909_cp_1].m_pathFindFlags = (byte)(expr_909_cp_0[(int)expr_909_cp_1].m_pathFindFlags | 8);
                return;
            }
            float num8 = bufferItem5.m_comparisonValue * this.m_maxLength;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_length = num8;
            uint num9 = unit;
            int num10 = 0;
            int num11 = 0;
            PathUnit.Position position = bufferItem5.m_position;
            if ((position.m_segment != bufferItem3.m_position.m_segment || position.m_lane != bufferItem3.m_position.m_lane || position.m_offset != bufferItem3.m_position.m_offset) && (position.m_segment != bufferItem4.m_position.m_segment || position.m_lane != bufferItem4.m_position.m_lane || position.m_offset != bufferItem4.m_position.m_offset))
            {
                if (b != position.m_offset)
                {
                    PathUnit.Position position2 = position;
                    position2.m_offset = b;
                    this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].SetPosition(num10++, position2);
                }
                this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].SetPosition(num10++, position);
                position = this.m_laneTarget[(int)((UIntPtr)bufferItem5.m_laneID)];
            }
            for (int k = 0; k < 262144; k++)
            {
                this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].SetPosition(num10++, position);
                if ((position.m_segment == bufferItem3.m_position.m_segment && position.m_lane == bufferItem3.m_position.m_lane && position.m_offset == bufferItem3.m_position.m_offset) || (position.m_segment == bufferItem4.m_position.m_segment && position.m_lane == bufferItem4.m_position.m_lane && position.m_offset == bufferItem4.m_position.m_offset))
                {
                    this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].m_positionCount = (byte)num10;
                    num11 += num10;
                    if (num11 != 0)
                    {
                        num9 = this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_nextPathUnit;
                        num10 = (int)this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount;
                        int num12 = 0;
                        while (num9 != 0u)
                        {
                            this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].m_length = num8 * (float)(num11 - num10) / (float)num11;
                            num10 += (int)this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].m_positionCount;
                            num9 = this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].m_nextPathUnit;
                            if (++num12 >= 262144)
                            {
                                CODebugBase<LogChannel>.Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
                                break;
                            }
                        }
                    }
                    PathUnit[] expr_C16_cp_0 = this.m_pathUnits.m_buffer;
                    UIntPtr expr_C16_cp_1 = (UIntPtr)unit;
                    expr_C16_cp_0[(int)expr_C16_cp_1].m_pathFindFlags = (byte)(expr_C16_cp_0[(int)expr_C16_cp_1].m_pathFindFlags | 4);
                    return;
                }
                if (num10 == 12)
                {
                    while (!Monitor.TryEnter(this.m_bufferLock, SimulationManager.SYNCHRONIZE_TIMEOUT))
                    {
                    }
                    uint num13;
                    try
                    {
                        if (!this.m_pathUnits.CreateItem(out num13, ref this.m_pathRandomizer))
                        {
                            PathUnit[] expr_D15_cp_0 = this.m_pathUnits.m_buffer;
                            UIntPtr expr_D15_cp_1 = (UIntPtr)unit;
                            expr_D15_cp_0[(int)expr_D15_cp_1].m_pathFindFlags = (byte)(expr_D15_cp_0[(int)expr_D15_cp_1].m_pathFindFlags | 8);
                            return;
                        }
                        this.m_pathUnits.m_buffer[(int)((UIntPtr)num13)] = this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)];
                        this.m_pathUnits.m_buffer[(int)((UIntPtr)num13)].m_referenceCount = 1;
                        this.m_pathUnits.m_buffer[(int)((UIntPtr)num13)].m_pathFindFlags = 4;
                        this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].m_nextPathUnit = num13;
                        this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].m_positionCount = (byte)num10;
                        num11 += num10;
                        Singleton<PathManager>.instance.m_pathUnitCount = (int)(this.m_pathUnits.ItemCount() - 1u);
                    }
                    finally
                    {
                        Monitor.Exit(this.m_bufferLock);
                    }
                    num9 = num13;
                    num10 = 0;
                }
                uint laneID = PathManager.GetLaneID(position);
                position = this.m_laneTarget[(int)((UIntPtr)laneID)];
            }
            PathUnit[] expr_D99_cp_0 = this.m_pathUnits.m_buffer;
            UIntPtr expr_D99_cp_1 = (UIntPtr)unit;
            expr_D99_cp_0[(int)expr_D99_cp_1].m_pathFindFlags = (byte)(expr_D99_cp_0[(int)expr_D99_cp_1].m_pathFindFlags | 8);
        }
        private void PathFindImplementation(uint unit, ref PathUnit data)
        {
            var instance = Singleton<NetManager>.instance;
            _laneTypes = (NetInfo.LaneType)PathUnits.m_buffer[(int)((UIntPtr)unit)].m_laneTypes;
            _vehicleTypes = (VehicleInfo.VehicleType)PathUnits.m_buffer[(int)((UIntPtr)unit)].m_vehicleTypes;
            _maxLength = PathUnits.m_buffer[(int)((UIntPtr)unit)].m_length;
            _pathFindIndex = (_pathFindIndex + 1u & 32767u);
            _pathRandomizer = new Randomizer(unit);
            _isHeavyVehicle = ((PathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags & 16) != 0);
            _ignoreBlocked = ((PathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags & 32) != 0);
            _stablePath = ((PathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags & 64) != 0);
            //this._vehicleType =
            //    TrafficRoadRestrictions.vehicleType(this._pathUnits._buffer[(int) ((UIntPtr) unit)].m_simulationFlags);

            var num = PathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount & 15;
            var num2 = PathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount >> 4;
            BufferItem startPosA;
            if (data.m_position00.m_segment != 0 && num >= 1)
            {
                _startLaneA = PathManager.GetLaneID(data.m_position00);
                _startOffsetA = data.m_position00.m_offset;
                startPosA.LaneId = _startLaneA;
                startPosA.Position = data.m_position00;
                GetLaneDirection(data.m_position00, out startPosA.Direction, out startPosA.LanesUsed);
                startPosA.ComparisonValue = 0f;
            }
            else
            {
                _startLaneA = 0u;
                _startOffsetA = 0;
                startPosA = default(BufferItem);
            }
            BufferItem startPosB;
            if (data.m_position02.m_segment != 0 && num >= 3)
            {
                _startLaneB = PathManager.GetLaneID(data.m_position02);
                _startOffsetB = data.m_position02.m_offset;
                startPosB.LaneId = _startLaneB;
                startPosB.Position = data.m_position02;
                GetLaneDirection(data.m_position02, out startPosB.Direction, out startPosB.LanesUsed);
                startPosB.ComparisonValue = 0f;
            }
            else
            {
                _startLaneB = 0u;
                _startOffsetB = 0;
                startPosB = default(BufferItem);
            }
            BufferItem endPosA;
            if (data.m_position01.m_segment != 0 && num >= 2)
            {
                _endLaneA = PathManager.GetLaneID(data.m_position01);
                endPosA.LaneId = _endLaneA;
                endPosA.Position = data.m_position01;
                GetLaneDirection(data.m_position01, out endPosA.Direction, out endPosA.LanesUsed);
                endPosA.MethodDistance = 0f;
                endPosA.ComparisonValue = 0f;
            }
            else
            {
                _endLaneA = 0u;
                endPosA = default(BufferItem);
            }
            BufferItem endPosB;
            if (data.m_position03.m_segment != 0 && num >= 4)
            {
                _endLaneB = PathManager.GetLaneID(data.m_position03);
                endPosB.LaneId = _endLaneB;
                endPosB.Position = data.m_position03;
                GetLaneDirection(data.m_position03, out endPosB.Direction, out endPosB.LanesUsed);
                endPosB.MethodDistance = 0f;
                endPosB.ComparisonValue = 0f;
            }
            else
            {
                _endLaneB = 0u;
                endPosB = default(BufferItem);
            }
            if (data.m_position11.m_segment != 0 && num2 >= 1)
            {
                _vehicleLane = PathManager.GetLaneID(data.m_position11);
                _vehicleOffset = data.m_position11.m_offset;
            }
            else
            {
                _vehicleLane = 0u;
                _vehicleOffset = 0;
            }
            BufferItem goalItem = default(BufferItem);
            byte b = 0;
            _bufferMinPos = 0;
            _bufferMaxPos = -1;
            if (_pathFindIndex == 0u)
            {
                uint num3 = 4294901760u;
                for (int i = 0; i < 262144; i++)
                {
                    _laneLocation[i] = num3;
                }
            }
            for (int j = 0; j < 1024; j++)
            {
                _bufferMin[j] = 0;
                _bufferMax[j] = -1;
            }
            if (endPosA.Position.m_segment != 0)
            {
                _bufferMax[0]++;
                _buffer[++_bufferMaxPos] = endPosA;
            }
            if (endPosB.Position.m_segment != 0)
            {
                _bufferMax[0]++;
                _buffer[++_bufferMaxPos] = endPosB;
            }
            bool flag = false;
            while (_bufferMinPos <= _bufferMaxPos)
            {
                int num4 = _bufferMin[_bufferMinPos];
                int num5 = _bufferMax[_bufferMinPos];
                if (num4 > num5)
                {
                    _bufferMinPos++;
                }
                else
                {
                    _bufferMin[_bufferMinPos] = num4 + 1;
                    BufferItem currentItem = _buffer[(_bufferMinPos << 6) + num4];
                    if (currentItem.Position.m_segment == startPosA.Position.m_segment && currentItem.Position.m_lane == startPosA.Position.m_lane)
                    {
                        if ((byte)(currentItem.Direction & NetInfo.Direction.Forward) != 0 && currentItem.Position.m_offset >= _startOffsetA)
                        {
                            goalItem = currentItem;
                            b = _startOffsetA;
                            flag = true;
                            break;
                        }
                        if ((byte)(currentItem.Direction & NetInfo.Direction.Backward) != 0 && currentItem.Position.m_offset <= _startOffsetA)
                        {
                            goalItem = currentItem;
                            b = _startOffsetA;
                            flag = true;
                            break;
                        }
                    }
                    if (currentItem.Position.m_segment == startPosB.Position.m_segment && currentItem.Position.m_lane == startPosB.Position.m_lane)
                    {
                        if ((byte)(currentItem.Direction & NetInfo.Direction.Forward) != 0 && currentItem.Position.m_offset >= _startOffsetB)
                        {
                            goalItem = currentItem;
                            b = _startOffsetB;
                            flag = true;
                            break;
                        }
                        if ((byte)(currentItem.Direction & NetInfo.Direction.Backward) != 0 && currentItem.Position.m_offset <= _startOffsetB)
                        {
                            goalItem = currentItem;
                            b = _startOffsetB;
                            flag = true;
                            break;
                        }
                    }
                    if ((byte)(currentItem.Direction & NetInfo.Direction.Forward) != 0)
                    {
                        ushort startNode = instance.m_segments.m_buffer[currentItem.Position.m_segment].m_startNode;
                        ProcessItem1(currentItem, startNode, ref instance.m_nodes.m_buffer[startNode], 0, false, ref data);
                    }
                    if ((byte)(currentItem.Direction & NetInfo.Direction.Backward) != 0)
                    {
                        ushort endNode = instance.m_segments.m_buffer[currentItem.Position.m_segment].m_endNode;
                        ProcessItem1(currentItem, endNode, ref instance.m_nodes.m_buffer[endNode], 255, false, ref data);
                    }
                    int num6 = 0;
                    ushort num7 = instance.m_lanes.m_buffer[(int)((UIntPtr)currentItem.LaneId)].m_nodes;
                    if (num7 != 0)
                    {
                        ushort startNode2 = instance.m_segments.m_buffer[currentItem.Position.m_segment].m_startNode;
                        ushort endNode2 = instance.m_segments.m_buffer[currentItem.Position.m_segment].m_endNode;
                        bool flag2 = ((instance.m_nodes.m_buffer[startNode2].m_flags | instance.m_nodes.m_buffer[endNode2].m_flags) & NetNode.Flags.Disabled) != NetNode.Flags.None;
                        while (num7 != 0)
                        {
                            NetInfo.Direction direction = NetInfo.Direction.None;
                            byte laneOffset = instance.m_nodes.m_buffer[num7].m_laneOffset;
                            if (laneOffset <= currentItem.Position.m_offset)
                            {
                                direction |= NetInfo.Direction.Forward;
                            }
                            if (laneOffset >= currentItem.Position.m_offset)
                            {
                                direction |= NetInfo.Direction.Backward;
                            }
                            if ((byte)(currentItem.Direction & direction) != 0 && (!flag2 || (instance.m_nodes.m_buffer[num7].m_flags & NetNode.Flags.Disabled) != NetNode.Flags.None))
                            {
                                ProcessItem1(currentItem, num7, ref instance.m_nodes.m_buffer[num7], laneOffset, true, ref data);
                            }
                            num7 = instance.m_nodes.m_buffer[num7].m_nextLaneNode;
                            if (++num6 == 32768)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            if (!flag)
            {
                var expr_8D5Cp0 = PathUnits.m_buffer;
                var expr_8D5Cp1 = (UIntPtr)unit;
                expr_8D5Cp0[(int)expr_8D5Cp1].m_pathFindFlags = (byte)(expr_8D5Cp0[(int)expr_8D5Cp1].m_pathFindFlags | 8);
                return;
            }
            var num8 = goalItem.ComparisonValue * _maxLength;
            PathUnits.m_buffer[(int)((UIntPtr)unit)].m_length = num8;
            var num9 = unit;
            var num10 = 0;
            var num11 = 0;
            var position = goalItem.Position;
            if ((position.m_segment != endPosA.Position.m_segment || position.m_lane != endPosA.Position.m_lane || position.m_offset != endPosA.Position.m_offset) && (position.m_segment != endPosB.Position.m_segment || position.m_lane != endPosB.Position.m_lane || position.m_offset != endPosB.Position.m_offset))
            {
                if (b != position.m_offset)
                {
                    var position2 = position;
                    position2.m_offset = b;
                    PathUnits.m_buffer[(int)((UIntPtr)num9)].SetPosition(num10++, position2);
                }
                PathUnits.m_buffer[(int)((UIntPtr)num9)].SetPosition(num10++, position);
                position = _laneTarget[(int)((UIntPtr)goalItem.LaneId)];
            }
            for (var k = 0; k < 262144; k++)
            {
                PathUnits.m_buffer[(int)((UIntPtr)num9)].SetPosition(num10++, position);
                if ((position.m_segment == endPosA.Position.m_segment && position.m_lane == endPosA.Position.m_lane && position.m_offset == endPosA.Position.m_offset) || (position.m_segment == endPosB.Position.m_segment && position.m_lane == endPosB.Position.m_lane && position.m_offset == endPosB.Position.m_offset))
                {
                    PathUnits.m_buffer[(int)((UIntPtr)num9)].m_positionCount = (byte)num10;
                    num11 += num10;
                    if (num11 != 0)
                    {
                        num9 = PathUnits.m_buffer[(int)((UIntPtr)unit)].m_nextPathUnit;
                        num10 = PathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount;
                        var num12 = 0;
                        while (num9 != 0u)
                        {
                            PathUnits.m_buffer[(int)((UIntPtr)num9)].m_length = num8 * (num11 - num10) / num11;
                            num10 += PathUnits.m_buffer[(int)((UIntPtr)num9)].m_positionCount;
                            num9 = PathUnits.m_buffer[(int)((UIntPtr)num9)].m_nextPathUnit;
                            if (++num12 >= 262144)
                            {
                                CODebugBase<LogChannel>.Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
                                break;
                            }
                        }
                    }
                    var exprBe2Cp0 = PathUnits.m_buffer;
                    var exprBe2Cp1 = (UIntPtr)unit;
                    exprBe2Cp0[(int)exprBe2Cp1].m_pathFindFlags = (byte)(exprBe2Cp0[(int)exprBe2Cp1].m_pathFindFlags | 4);
                    return;
                }
                if (num10 == 12)
                {
                    while (!Monitor.TryEnter(_bufferLock, SimulationManager.SYNCHRONIZE_TIMEOUT))
                    {
                    }
                    uint num13;
                    try
                    {
                        var localRandom = _pathRandomizer;
                        if (!PathUnits.CreateItem(out num13, ref localRandom))
                        {
                            var exprCe1Cp0 = PathUnits.m_buffer;
                            var exprCe1Cp1 = (UIntPtr)unit;
                            exprCe1Cp0[(int)exprCe1Cp1].m_pathFindFlags = (byte)(exprCe1Cp0[(int)exprCe1Cp1].m_pathFindFlags | 8);
                            return;
                        }
                        _pathRandomizer = localRandom;
                        PathUnits.m_buffer[(int)((UIntPtr)num13)] = PathUnits.m_buffer[(int)((UIntPtr)num9)];
                        PathUnits.m_buffer[(int)((UIntPtr)num13)].m_referenceCount = 1;
                        PathUnits.m_buffer[(int)((UIntPtr)num13)].m_pathFindFlags = 4;
                        PathUnits.m_buffer[(int)((UIntPtr)num9)].m_nextPathUnit = num13;
                        PathUnits.m_buffer[(int)((UIntPtr)num9)].m_positionCount = (byte)num10;
                        num11 += num10;
                        Singleton<PathManager>.instance.m_pathUnitCount = (int)(PathUnits.ItemCount() - 1u);
                    }
                    finally
                    {
                        Monitor.Exit(_bufferLock);
                    }
                    num9 = num13;
                    num10 = 0;
                }
                var laneId = PathManager.GetLaneID(position);
                position = _laneTarget[(int)((UIntPtr)laneId)];
            }
            var exprD65Cp0 = PathUnits.m_buffer;
            var exprD65Cp1 = (UIntPtr)unit;
            exprD65Cp0[(int)exprD65Cp1].m_pathFindFlags = (byte)(exprD65Cp0[(int)exprD65Cp1].m_pathFindFlags | 8);
        }
		// PathFind
		protected void PathFindImplementation(uint unit, ref PathUnit data) {
			//pfCurrentState = 0;

			NetManager instance = Singleton<NetManager>.instance;
			this._laneTypes = (NetInfo.LaneType)this.PathUnits.m_buffer[(int)((UIntPtr)unit)].m_laneTypes;
			this._vehicleTypes = (VehicleInfo.VehicleType)this.PathUnits.m_buffer[(int)((UIntPtr)unit)].m_vehicleTypes;
			this._maxLength = this.PathUnits.m_buffer[(int)((UIntPtr)unit)].m_length;
			this._pathFindIndex = (this._pathFindIndex + 1u & 32767u);
			this._pathRandomizer = new Randomizer(unit);
			this._isHeavyVehicle = ((this.PathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags & 16) != 0);
			this._ignoreBlocked = ((this.PathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags & 32) != 0);
			this._stablePath = ((this.PathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags & 64) != 0);
			this._transportVehicle = ((byte)(this._laneTypes & NetInfo.LaneType.TransportVehicle) != 0);
			this._extVehicleType = pathUnitExtVehicleType[unit];
			if ((byte)(this._laneTypes & NetInfo.LaneType.Vehicle) != 0) {
				this._laneTypes |= NetInfo.LaneType.TransportVehicle;
			}
			int num = (int)(this.PathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount & 15);
			int num2 = this.PathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount >> 4;
			BufferItem bufferItemStartA;
			if (data.m_position00.m_segment != 0 && num >= 1) {
				this._startLaneA = PathManager.GetLaneID(data.m_position00);
				this._startOffsetA = data.m_position00.m_offset;
				bufferItemStartA.m_laneID = this._startLaneA;
				bufferItemStartA.m_position = data.m_position00;
				this.GetLaneDirection(data.m_position00, out bufferItemStartA.m_direction, out bufferItemStartA.m_lanesUsed);
				bufferItemStartA.m_comparisonValue = 0f;
			} else {
				this._startLaneA = 0u;
				this._startOffsetA = 0;
				bufferItemStartA = default(BufferItem);
			}
			BufferItem bufferItemStartB;
			if (data.m_position02.m_segment != 0 && num >= 3) {
				this._startLaneB = PathManager.GetLaneID(data.m_position02);
				this._startOffsetB = data.m_position02.m_offset;
				bufferItemStartB.m_laneID = this._startLaneB;
				bufferItemStartB.m_position = data.m_position02;
				this.GetLaneDirection(data.m_position02, out bufferItemStartB.m_direction, out bufferItemStartB.m_lanesUsed);
				bufferItemStartB.m_comparisonValue = 0f;
			} else {
				this._startLaneB = 0u;
				this._startOffsetB = 0;
				bufferItemStartB = default(BufferItem);
			}
			BufferItem bufferItemEndA;
			if (data.m_position01.m_segment != 0 && num >= 2) {
				this._endLaneA = PathManager.GetLaneID(data.m_position01);
				bufferItemEndA.m_laneID = this._endLaneA;
				bufferItemEndA.m_position = data.m_position01;
				this.GetLaneDirection(data.m_position01, out bufferItemEndA.m_direction, out bufferItemEndA.m_lanesUsed);
				bufferItemEndA.m_methodDistance = 0f;
				bufferItemEndA.m_comparisonValue = 0f;
			} else {
				this._endLaneA = 0u;
				bufferItemEndA = default(BufferItem);
			}
			BufferItem bufferItemEndB;
			if (data.m_position03.m_segment != 0 && num >= 4) {
				this._endLaneB = PathManager.GetLaneID(data.m_position03);
				bufferItemEndB.m_laneID = this._endLaneB;
				bufferItemEndB.m_position = data.m_position03;
				this.GetLaneDirection(data.m_position03, out bufferItemEndB.m_direction, out bufferItemEndB.m_lanesUsed);
				bufferItemEndB.m_methodDistance = 0f;
				bufferItemEndB.m_comparisonValue = 0f;
			} else {
				this._endLaneB = 0u;
				bufferItemEndB = default(BufferItem);
			}
			if (data.m_position11.m_segment != 0 && num2 >= 1) {
				this._vehicleLane = PathManager.GetLaneID(data.m_position11);
				this._vehicleOffset = data.m_position11.m_offset;
			} else {
				this._vehicleLane = 0u;
				this._vehicleOffset = 0;
			}
			BufferItem finalBufferItem = default(BufferItem);
			byte startOffset = 0;
			this._bufferMinPos = 0;
			this._bufferMaxPos = -1;
			if (this._pathFindIndex == 0u) {
				uint num3 = 4294901760u;
				for (int i = 0; i < 262144; i++) {
					this._laneLocation[i] = num3;
				}
			}
			for (int j = 0; j < 1024; j++) {
				this._bufferMin[j] = 0;
				this._bufferMax[j] = -1;
			}
			if (bufferItemEndA.m_position.m_segment != 0) {
				this._bufferMax[0]++;
				this._buffer[++this._bufferMaxPos] = bufferItemEndA;
			}
			if (bufferItemEndB.m_position.m_segment != 0) {
				this._bufferMax[0]++;
				this._buffer[++this._bufferMaxPos] = bufferItemEndB;
			}
			bool canFindPath = false;
#if DEBUGPF
			uint wIter = 0;
#endif
			//Log.Message($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: STARTING MAIN LOOP! bufferMinPos: {this._bufferMinPos}, bufferMaxPos: {this._bufferMaxPos}, startA: {bufferItemStartA.m_position.m_segment}, startB: {bufferItemStartB.m_position.m_segment}, endA: {bufferItemEndA.m_position.m_segment}, endB: {bufferItemEndB.m_position.m_segment}");
			while (this._bufferMinPos <= this._bufferMaxPos) {
				//pfCurrentState = 1;
#if DEBUGPF
				/*if (m_queuedPathFindCount > 100 && Options.disableSomething1)
					Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: MAIN LOOP RUNNING! bufferMinPos: {this._bufferMinPos}, bufferMaxPos: {this._bufferMaxPos}, startA: {bufferItemStartA.m_position.m_segment}, startB: {bufferItemStartB.m_position.m_segment}, endA: {bufferItemEndA.m_position.m_segment}, endB: {bufferItemEndB.m_position.m_segment}");*/
#endif
				int num4 = this._bufferMin[this._bufferMinPos];
				int num5 = this._bufferMax[this._bufferMinPos];
				if (num4 > num5) {
					this._bufferMinPos++;
				} else {
					this._bufferMin[this._bufferMinPos] = num4 + 1;
					BufferItem candidateItem = this._buffer[(this._bufferMinPos << 6) + num4];
					if (candidateItem.m_position.m_segment == bufferItemStartA.m_position.m_segment && candidateItem.m_position.m_lane == bufferItemStartA.m_position.m_lane) {
						// we reached startA
						if ((byte)(candidateItem.m_direction & NetInfo.Direction.Forward) != 0 && candidateItem.m_position.m_offset >= this._startOffsetA) {
							finalBufferItem = candidateItem;
							startOffset = this._startOffsetA;
							canFindPath = true;
							break;
						}
						if ((byte)(candidateItem.m_direction & NetInfo.Direction.Backward) != 0 && candidateItem.m_position.m_offset <= this._startOffsetA) {
							finalBufferItem = candidateItem;
							startOffset = this._startOffsetA;
							canFindPath = true;
							break;
						}
					}
					if (candidateItem.m_position.m_segment == bufferItemStartB.m_position.m_segment && candidateItem.m_position.m_lane == bufferItemStartB.m_position.m_lane) {
						// we reached startB
						if ((byte)(candidateItem.m_direction & NetInfo.Direction.Forward) != 0 && candidateItem.m_position.m_offset >= this._startOffsetB) {
							finalBufferItem = candidateItem;
							startOffset = this._startOffsetB;
							canFindPath = true;
							break;
						}
						if ((byte)(candidateItem.m_direction & NetInfo.Direction.Backward) != 0 && candidateItem.m_position.m_offset <= this._startOffsetB) {
							finalBufferItem = candidateItem;
							startOffset = this._startOffsetB;
							canFindPath = true;
							break;
						}
					}

					// explore the path
					if ((byte)(candidateItem.m_direction & NetInfo.Direction.Forward) != 0) {
						ushort startNode = instance.m_segments.m_buffer[(int)candidateItem.m_position.m_segment].m_startNode;
						this.ProcessItemMain(unit, candidateItem, startNode, ref instance.m_nodes.m_buffer[(int)startNode], 0, false);
					}

					if ((byte)(candidateItem.m_direction & NetInfo.Direction.Backward) != 0) {
						ushort endNode = instance.m_segments.m_buffer[(int)candidateItem.m_position.m_segment].m_endNode;
						this.ProcessItemMain(unit, candidateItem, endNode, ref instance.m_nodes.m_buffer[(int)endNode], 255, false);
					}

					// handle special nodes (e.g. bus stops)
					int num6 = 0;
					ushort specialNodeId = instance.m_lanes.m_buffer[(int)((UIntPtr)candidateItem.m_laneID)].m_nodes;
					if (specialNodeId != 0) {
						ushort startNode2 = instance.m_segments.m_buffer[(int)candidateItem.m_position.m_segment].m_startNode;
						ushort endNode2 = instance.m_segments.m_buffer[(int)candidateItem.m_position.m_segment].m_endNode;
						bool flag2 = ((instance.m_nodes.m_buffer[(int)startNode2].m_flags | instance.m_nodes.m_buffer[(int)endNode2].m_flags) & NetNode.Flags.Disabled) != NetNode.Flags.None;
						while (specialNodeId != 0) {
							NetInfo.Direction direction = NetInfo.Direction.None;
							byte laneOffset = instance.m_nodes.m_buffer[(int)specialNodeId].m_laneOffset;
							if (laneOffset <= candidateItem.m_position.m_offset) {
								direction |= NetInfo.Direction.Forward;
							}
							if (laneOffset >= candidateItem.m_position.m_offset) {
								direction |= NetInfo.Direction.Backward;
							}
							if ((byte)(candidateItem.m_direction & direction) != 0 && (!flag2 || (instance.m_nodes.m_buffer[(int)specialNodeId].m_flags & NetNode.Flags.Disabled) != NetNode.Flags.None)) {
								this.ProcessItemMain(unit, candidateItem, specialNodeId, ref instance.m_nodes.m_buffer[(int)specialNodeId], laneOffset, true);
							}
							specialNodeId = instance.m_nodes.m_buffer[(int)specialNodeId].m_nextLaneNode;
							if (++num6 == 32768) {
								Log.Warning("Special loop: Too many iterations");
								break;
							}
						}
					}
				}
#if DEBUGPF
				++wIter;
				if (wIter > 1000000) {
					Log.Error("Too many iterations in PathFindImpl.");
					break;
				}
#endif
			}
			//pfCurrentState = 2;
			/*if (m_queuedPathFindCount > 100 && Options.disableSomething0)
				Log.Message($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: MAIN LOOP FINISHED! bufferMinPos: {this._bufferMinPos}, bufferMaxPos: {this._bufferMaxPos}, startA: {bufferItemStartA.m_position.m_segment}, startB: {bufferItemStartB.m_position.m_segment}, endA: {bufferItemEndA.m_position.m_segment}, endB: {bufferItemEndB.m_position.m_segment}");*/
			if (!canFindPath) {
				// we could not find a path
				//pfCurrentState = 3;
				PathUnits.m_buffer[(int)unit].m_pathFindFlags = (byte)(PathUnits.m_buffer[(int)((UIntPtr)unit)].m_pathFindFlags | 8);
#if DEBUG
				++_failedPathFinds;
				//Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: Cannot find path (pfCurrentState={pfCurrentState}) for unit {unit}");
#endif
				pathUnitExtVehicleType[unit] = null;

				/*PathUnit[] expr_909_cp_0 = this._pathUnits.m_buffer;
				UIntPtr expr_909_cp_1 = (UIntPtr)unit;
				expr_909_cp_0[(int)expr_909_cp_1].m_pathFindFlags = (byte)(expr_909_cp_0[(int)expr_909_cp_1].m_pathFindFlags | 8);*/
				return;
			}
			// we could calculate a valid path

			//pfCurrentState = 4;
			float totalPathLength = finalBufferItem.m_comparisonValue * this._maxLength;
			this.PathUnits.m_buffer[(int)((UIntPtr)unit)].m_length = totalPathLength;
			uint currentPathUnitId = unit;
			int currentItemPositionCount = 0;
			int sumOfPositionCounts = 0;
			PathUnit.Position currentPosition = finalBufferItem.m_position;
			if ((currentPosition.m_segment != bufferItemEndA.m_position.m_segment || currentPosition.m_lane != bufferItemEndA.m_position.m_lane || currentPosition.m_offset != bufferItemEndA.m_position.m_offset) &&
				(currentPosition.m_segment != bufferItemEndB.m_position.m_segment || currentPosition.m_lane != bufferItemEndB.m_position.m_lane || currentPosition.m_offset != bufferItemEndB.m_position.m_offset)) {
				// the found starting position differs from the desired end position
				if (startOffset != currentPosition.m_offset) {
					// the offsets differ: copy the found starting position and modify the offset to fit the desired offset
					PathUnit.Position position2 = currentPosition;
					position2.m_offset = startOffset;
					this.PathUnits.m_buffer[(int)((UIntPtr)currentPathUnitId)].SetPosition(currentItemPositionCount++, position2);
					// now we have: [desired starting position]
				}
				// add the found starting position to the path unit
				this.PathUnits.m_buffer[(int)((UIntPtr)currentPathUnitId)].SetPosition(currentItemPositionCount++, currentPosition);
				currentPosition = this._laneTarget[(int)((UIntPtr)finalBufferItem.m_laneID)]; // go to the next path position

				// now we have either [desired starting position, found starting position] or [found starting position], depending on if the found starting position matched the desired
			}
			//pfCurrentState = 5;

			// beginning with the starting position, going to the target position: assemble the path units
			for (int k = 0; k < 262144; k++) {
				//pfCurrentState = 6;
				this.PathUnits.m_buffer[(int)((UIntPtr)currentPathUnitId)].SetPosition(currentItemPositionCount++, currentPosition); // add the next path position to the current unit

				if ((currentPosition.m_segment == bufferItemEndA.m_position.m_segment && currentPosition.m_lane == bufferItemEndA.m_position.m_lane && currentPosition.m_offset == bufferItemEndA.m_position.m_offset) ||
					(currentPosition.m_segment == bufferItemEndB.m_position.m_segment && currentPosition.m_lane == bufferItemEndB.m_position.m_lane && currentPosition.m_offset == bufferItemEndB.m_position.m_offset)) {
					// we have reached the end position

					this.PathUnits.m_buffer[(int)((UIntPtr)currentPathUnitId)].m_positionCount = (byte)currentItemPositionCount;
					sumOfPositionCounts += currentItemPositionCount; // add position count of last unit to sum
					if (sumOfPositionCounts != 0) {
						// for each path unit from start to target: calculate length (distance) to target
						currentPathUnitId = this.PathUnits.m_buffer[(int)((UIntPtr)unit)].m_nextPathUnit; // (we do not need to calculate the length for the starting unit since this is done before; it's the total path length)
						currentItemPositionCount = (int)this.PathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount;
						int totalIter = 0;
						while (currentPathUnitId != 0u) {
							//pfCurrentState = 7;
							this.PathUnits.m_buffer[(int)((UIntPtr)currentPathUnitId)].m_length = totalPathLength * (float)(sumOfPositionCounts - currentItemPositionCount) / (float)sumOfPositionCounts;
							currentItemPositionCount += (int)this.PathUnits.m_buffer[(int)((UIntPtr)currentPathUnitId)].m_positionCount;
							currentPathUnitId = this.PathUnits.m_buffer[(int)((UIntPtr)currentPathUnitId)].m_nextPathUnit;
							if (++totalIter >= 262144) {
#if DEBUG
								Log.Error("THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: PathFindImplementation: Invalid list detected.");
#endif
								CODebugBase<LogChannel>.Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
								break;
							}
						}
					}
#if DEBUG
					//Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: Path found (pfCurrentState={pfCurrentState}) for unit {unit}");
#endif
					PathUnits.m_buffer[(int)unit].m_pathFindFlags = (byte)(PathUnits.m_buffer[(int)((UIntPtr)unit)].m_pathFindFlags | 4); // Path found
#if DEBUG
					++_succeededPathFinds;
					pathUnitExtVehicleType[unit] = null;
#endif
					return;
				}

				// We have not reached the target position yet 
				if (currentItemPositionCount == 12) {
					// the current path unit is full, we need a new one
					//pfCurrentState = 8;
					uint createdPathUnitId;
					try {
						Monitor.Enter(this._bufferLock);
						//pfCurrentState = 10;
						if (!this.PathUnits.CreateItem(out createdPathUnitId, ref this._pathRandomizer)) {
							// we failed to create a new path unit, thus the path-finding also failed
							PathUnits.m_buffer[(int)((UIntPtr)unit)].m_pathFindFlags = (byte)(PathUnits.m_buffer[(int)unit].m_pathFindFlags | 8);
#if DEBUG
							++_failedPathFinds;
							//Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: Cannot find path (pfCurrentState={pfCurrentState}) for unit {unit}");
#endif
							pathUnitExtVehicleType[unit] = null;
							return;
						}
						this.PathUnits.m_buffer[(int)((UIntPtr)createdPathUnitId)] = this.PathUnits.m_buffer[(int)currentPathUnitId];
						this.PathUnits.m_buffer[(int)((UIntPtr)createdPathUnitId)].m_referenceCount = 1;
						this.PathUnits.m_buffer[(int)((UIntPtr)createdPathUnitId)].m_pathFindFlags = 4;
						this.PathUnits.m_buffer[(int)((UIntPtr)currentPathUnitId)].m_nextPathUnit = createdPathUnitId;
						this.PathUnits.m_buffer[(int)((UIntPtr)currentPathUnitId)].m_positionCount = (byte)currentItemPositionCount;
						sumOfPositionCounts += currentItemPositionCount;
						Singleton<PathManager>.instance.m_pathUnitCount = (int)(this.PathUnits.ItemCount() - 1u);
					} catch (Exception e) {
						Log.Error("CustomPathFind.PathFindImplementation Error: " + e.ToString());
						break;
					} finally {
						Monitor.Exit(this._bufferLock);
					}
					currentPathUnitId = createdPathUnitId;
					currentItemPositionCount = 0;
				}
				uint laneID = PathManager.GetLaneID(currentPosition);
				// NON-STOCK CODE START
				CustomRoadAI.AddTraffic(laneID, (ushort)(this._isHeavyVehicle || _extVehicleType == ExtVehicleType.Bus ? 50 : 25), (ushort)GetLaneSpeedLimit(currentPosition.m_segment, currentPosition.m_lane, laneID, Singleton<NetManager>.instance.m_segments.m_buffer[currentPosition.m_segment].Info.m_lanes[currentPosition.m_lane]), false); //SpeedLimitManager.GetLockFreeGameSpeedLimit(currentPosition.m_segment, currentPosition.m_lane, laneID, ref Singleton<NetManager>.instance.m_segments.m_buffer[currentPosition.m_segment].Info.m_lanes[currentPosition.m_lane])
				// NON-STOCK CODE END
				currentPosition = this._laneTarget[(int)((UIntPtr)laneID)];
			}
			PathUnits.m_buffer[(int)((UIntPtr)unit)].m_pathFindFlags = (byte)(PathUnits.m_buffer[(int)unit].m_pathFindFlags | 8);
#if DEBUG
			++_failedPathFinds;
#endif
			pathUnitExtVehicleType[unit] = null;
#if DEBUG
			//Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: Cannot find path (pfCurrentState={pfCurrentState}) for unit {unit}");
#endif
		}