public void CalculateSegmentPosition2(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position position, uint laneId, byte offset, out Vector3 pos, out Vector3 dir, out float maxSpeed)
        {
            var instance = Singleton<NetManager>.instance;
            instance.m_lanes.m_buffer[(int)((UIntPtr)laneId)].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir);
            var info = instance.m_segments.m_buffer[position.m_segment].Info;
            if (info.m_lanes != null && info.m_lanes.Length > position.m_lane)
            {
                var laneSpeedLimit = info.m_lanes[position.m_lane].m_speedLimit;

                if (TrafficRoadRestrictions.IsSegment(position.m_segment))
                {
                    var restrictionSegment = TrafficRoadRestrictions.GetSegment(position.m_segment);

                    if (restrictionSegment.SpeedLimits[position.m_lane] > 0.1f)
                    {
                        laneSpeedLimit = restrictionSegment.SpeedLimits[position.m_lane];
                    }
                }

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

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

            return findShortestPath(unit, skipQueue);
        }
 // from CitizenAI
 public static bool FindPathPosition(ushort instanceID, ref CitizenInstance citizenData, Vector3 pos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, out PathUnit.Position position)
 {
     position = default(PathUnit.Position);
     float num = 1E+10f;
     PathUnit.Position position2;
     PathUnit.Position position3;
     float num2;
     float num3;
     if (CustomPathManager.FindPathPosition(pos, ItemClass.Service.Road, laneTypes, vehicleTypes, allowUnderground, 32f, out position2, out position3, out num2, out num3, RoadManager.VehicleType.PassengerCar) && num2 < num)
     {
         num = num2;
         position = position2;
     }
     PathUnit.Position position4;
     PathUnit.Position position5;
     float num4;
     float num5;
     if (CustomPathManager.FindPathPosition(pos, ItemClass.Service.Beautification, laneTypes, vehicleTypes, allowUnderground, 32f, out position4, out position5, out num4, out num5, RoadManager.VehicleType.PassengerCar) && num4 < num)
     {
         num = num4;
         position = position4;
     }
     PathUnit.Position position6;
     PathUnit.Position position7;
     float num6;
     float num7;
     if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None && CustomPathManager.FindPathPosition(pos, ItemClass.Service.PublicTransport, laneTypes, vehicleTypes, allowUnderground, 32f, out position6, out position7, out num6, out num7, RoadManager.VehicleType.PassengerCar) && num6 < num)
     {
         position = position6;
     }
     return position.m_segment != 0;
 }
 public static bool FindPathPosition(Vector3 position, ItemClass.Service service, NetInfo.LaneType laneType, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, bool requireConnect, float maxDistance, out PathUnit.Position pathPos, RoadManager.VehicleType vehicleType)
 {
     PathUnit.Position position2;
     float num;
     float num2;
     return CustomPathManager.FindPathPosition(position, service, laneType, vehicleTypes, allowUnderground, requireConnect, maxDistance, out pathPos, out position2, out num, out num2, vehicleType);
 }
 public static new uint GetLaneID(PathUnit.Position pathPos)
 {
     var netManager = Singleton<NetManager>.instance;
     var num = netManager.m_segments.m_buffer[pathPos.m_segment].m_lanes;
     var num2 = 0;
     while (num2 < pathPos.m_lane && num != 0u)
     {
         num = netManager.m_lanes.m_buffer[(int)((UIntPtr)num)].m_nextLane;
         num2++;
     }
     return num;
 }
 public static uint GetLaneID(PathUnit.Position pathPos)
 {
     NetManager instance = Singleton<NetManager>.instance;
     uint num = instance.m_segments.m_buffer[(int)pathPos.m_segment].m_lanes;
     int num2 = 0;
     while (num2 < (int)pathPos.m_lane && num != 0u)
     {
         num = instance.m_lanes.m_buffer[(int)((UIntPtr)num)].m_nextLane;
         num2++;
     }
     return num;
 }
		public void CustomCalculateSegmentPosition(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, int index, out Vector3 pos, out Vector3 dir, out float maxSpeed) {
			CalculateSegPos(vehicleID, ref vehicleData, position, laneID, offset, out pos, out dir, out maxSpeed);
		}
Beispiel #8
0
 public new bool ParkVehicle(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position pathPos, uint nextPath, int nextPositionIndex, out byte segmentOffset)
 {
     return base.ParkVehicle(vehicleID, ref vehicleData, pathPos, nextPath, nextPositionIndex, out segmentOffset);
 }
Beispiel #9
0
 public new bool NeedChangeVehicleType(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position pathPos, uint laneID, VehicleInfo.VehicleType laneVehicleType, ref Vector4 target)
 {
     return base.NeedChangeVehicleType(vehicleID, ref vehicleData, pathPos, laneID, laneVehicleType, ref target);
 }
Beispiel #10
0
 public new bool ChangeVehicleType(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position pathPos, uint laneID)
 {
     return base.ChangeVehicleType(vehicleID, ref vehicleData, pathPos, laneID);
 }
		internal static float CalcMaxSpeed(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position position, Vector3 pos, float maxSpeed, bool isRecklessDriver) {
			var netManager = Singleton<NetManager>.instance;
			NetInfo segmentInfo = netManager.m_segments.m_buffer[(int)position.m_segment].Info;
			bool highwayRules = (segmentInfo.m_netAI is RoadBaseAI && ((RoadBaseAI)segmentInfo.m_netAI).m_highwayRules);

			if (!highwayRules) {
				if (netManager.m_treatWetAsSnow) {
					DistrictManager districtManager = Singleton<DistrictManager>.instance;
					byte district = districtManager.GetDistrict(pos);
					DistrictPolicies.CityPlanning cityPlanningPolicies = districtManager.m_districts.m_buffer[(int)district].m_cityPlanningPolicies;
					if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.StuddedTires) != DistrictPolicies.CityPlanning.None) {
						if (Options.strongerRoadConditionEffects) {
							if (maxSpeed > ICY_ROADS_STUDDED_MIN_SPEED)
								maxSpeed = ICY_ROADS_STUDDED_MIN_SPEED + (float)(255 - netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - ICY_ROADS_STUDDED_MIN_SPEED);
						} else {
							maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.0005882353f; // vanilla: -15% .. �
						}
						districtManager.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= DistrictPolicies.CityPlanning.StuddedTires;
					} else {
						if (Options.strongerRoadConditionEffects) {
							if (maxSpeed > ICY_ROADS_MIN_SPEED)
								maxSpeed = ICY_ROADS_MIN_SPEED + (float)(255 - netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - ICY_ROADS_MIN_SPEED);
						} else {
							maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.00117647066f; // vanilla: -30% .. �
						}
					}
				} else {
					if (Options.strongerRoadConditionEffects) {
						float minSpeed = Math.Min(maxSpeed * WET_ROADS_FACTOR, WET_ROADS_MAX_SPEED);
						if (maxSpeed > minSpeed)
							maxSpeed = minSpeed + (float)(255 - netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - minSpeed);
					} else {
						maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.0005882353f; // vanilla: -15% .. �
					}
				}

				if (Options.strongerRoadConditionEffects) {
					float minSpeed = Math.Min(maxSpeed * BROKEN_ROADS_FACTOR, BROKEN_ROADS_MAX_SPEED);
					if (maxSpeed > minSpeed) {
						maxSpeed = minSpeed + (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_condition * 0.0039215686f * (maxSpeed - minSpeed);
					}
				} else {
					maxSpeed *= 1f + (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_condition * 0.0005882353f; // vanilla: � .. +15 %
				}
			}

			ExtVehicleType? vehicleType = CustomVehicleAI.DetermineVehicleTypeFromVehicle(vehicleId, ref vehicleData);
			float vehicleRand = Math.Min(1f, (float)(vehicleId % 101) * 0.01f); // we choose 101 because it's a prime number
			if (isRecklessDriver)
				maxSpeed *= 1.5f + vehicleRand * 1.5f; // woohooo, 1.5 .. 3
			else if ((vehicleType & ExtVehicleType.PassengerCar) != ExtVehicleType.None)
				maxSpeed *= 0.8f + vehicleRand * 0.3f; // a little variance, 0.8 .. 1.1
			else if ((vehicleType & ExtVehicleType.Taxi) != ExtVehicleType.None)
				maxSpeed *= 0.9f + vehicleRand * 0.4f; // a little variance, 0.9 .. 1.3

			maxSpeed = Math.Max(MIN_SPEED, maxSpeed); // at least 10 km/h

			return maxSpeed;
		}
 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, 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);
 }
 protected virtual void AddBufferItem(BufferItem item, PathUnit.Position target)
 {
     uint num = this.m_laneLocation[(int)((UIntPtr)item.m_laneID)];
     uint num2 = num >> 16;
     int num3 = (int)(num & 65535u);
     int num6;
     if (num2 == this.m_pathFindIndex)
     {
         if (item.m_comparisonValue >= this.m_buffer[num3].m_comparisonValue)
         {
             return;
         }
         int num4 = num3 >> 6;
         int num5 = num3 & -64;
         if (num4 < this.m_bufferMinPos || (num4 == this.m_bufferMinPos && num5 < this.m_bufferMin[num4]))
         {
             return;
         }
         num6 = Mathf.Max(Mathf.RoundToInt(item.m_comparisonValue * 1024f), this.m_bufferMinPos);
         if (num6 == num4)
         {
             this.m_buffer[num3] = item;
             this.m_laneTarget[(int)((UIntPtr)item.m_laneID)] = target;
             return;
         }
         int num7 = num4 << 6 | this.m_bufferMax[num4]--;
         BufferItem bufferItem = this.m_buffer[num7];
         this.m_laneLocation[(int)((UIntPtr)bufferItem.m_laneID)] = num;
         this.m_buffer[num3] = bufferItem;
     }
     else
     {
         num6 = Mathf.Max(Mathf.RoundToInt(item.m_comparisonValue * 1024f), this.m_bufferMinPos);
     }
     if (num6 >= 1024)
     {
         return;
     }
     while (this.m_bufferMax[num6] == 63)
     {
         num6++;
         if (num6 == 1024)
         {
             return;
         }
     }
     if (num6 > this.m_bufferMaxPos)
     {
         this.m_bufferMaxPos = num6;
     }
     num3 = (num6 << 6 | ++this.m_bufferMax[num6]);
     this.m_buffer[num3] = item;
     this.m_laneLocation[(int)((UIntPtr)item.m_laneID)] = (this.m_pathFindIndex << 16 | (uint)num3);
     this.m_laneTarget[(int)((UIntPtr)item.m_laneID)] = target;
 }
 protected override bool SpawnVehicle(ushort instanceID, ref CitizenInstance citizenData, PathUnit.Position pathPos)
 {
     VehicleManager instance = Singleton<VehicleManager>.instance;
     float num = 20f;
     int num2 = Mathf.Max ((int)((citizenData.m_targetPos.x - num) / 32f + 270f), 0);
     int num3 = Mathf.Max ((int)((citizenData.m_targetPos.z - num) / 32f + 270f), 0);
     int num4 = Mathf.Min ((int)((citizenData.m_targetPos.x + num) / 32f + 270f), 539);
     int num5 = Mathf.Min ((int)((citizenData.m_targetPos.z + num) / 32f + 270f), 539);
     for (int i = num3; i <= num5; i++)
     {
         for (int j = num2; j <= num4; j++)
         {
             ushort num6 = instance.m_vehicleGrid [i * 540 + j];
             int num7 = 0;
             while (num6 != 0)
             {
                 if (this.TryJoinVehicle (instanceID, ref citizenData, num6, ref instance.m_vehicles.m_buffer [(int)num6]))
                 {
                     citizenData.m_flags |= CitizenInstance.Flags.EnteringVehicle;
                     citizenData.m_flags &= ~CitizenInstance.Flags.TryingSpawnVehicle;
                     citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting;
                     citizenData.m_waitCounter = 0;
                     return true;
                 }
                 num6 = instance.m_vehicles.m_buffer [(int)num6].m_nextGridVehicle;
                 if (++num7 > 65536)
                 {
                     CODebugBase<LogChannel>.Error (LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
                     break;
                 }
             }
         }
     }
     NetManager instance2 = Singleton<NetManager>.instance;
     CitizenManager instance3 = Singleton<CitizenManager>.instance;
     Vector3 vector = Vector3.zero;
     Quaternion rotation = Quaternion.identity;
     ushort num8 = instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].m_parkedVehicle;
     if (num8 != 0)
     {
         vector = instance.m_parkedVehicles.m_buffer [(int)num8].m_position;
         rotation = instance.m_parkedVehicles.m_buffer [(int)num8].m_rotation;
     }
     VehicleInfo vehicleInfo = this.GetVehicleInfo (instanceID, ref citizenData, false);
     if (vehicleInfo == null || vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
     {
         instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetParkedVehicle (citizenData.m_citizen, 0);
         if ((citizenData.m_flags & CitizenInstance.Flags.TryingSpawnVehicle) == CitizenInstance.Flags.None)
         {
             citizenData.m_flags |= CitizenInstance.Flags.TryingSpawnVehicle;
             citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting;
             citizenData.m_waitCounter = 0;
         }
         return true;
     }
     if (vehicleInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTaxi)
     {
         instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetParkedVehicle (citizenData.m_citizen, 0);
         if ((citizenData.m_flags & CitizenInstance.Flags.WaitingTaxi) == CitizenInstance.Flags.None)
         {
             citizenData.m_flags |= CitizenInstance.Flags.WaitingTaxi;
             citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting;
             citizenData.m_waitCounter = 0;
         }
         return true;
     }
     uint laneID = PathManager.GetLaneID (pathPos);
     Vector3 vector2 = citizenData.m_targetPos;
     if (num8 != 0 && Vector3.SqrMagnitude (vector - vector2) < 1024f)
     {
         vector2 = vector;
     }
     else
     {
         num8 = 0;
     }
     Vector3 a;
     float num9;
     instance2.m_lanes.m_buffer [(int)((UIntPtr)laneID)].GetClosestPosition (vector2, out a, out num9);
     byte lastPathOffset = (byte)Mathf.Clamp (Mathf.RoundToInt (num9 * 255f), 0, 255);
     a = vector2 + Vector3.ClampMagnitude (a - vector2, 5f);
     ushort num10;
     if (instance.CreateVehicle (out num10, ref Singleton<SimulationManager>.instance.m_randomizer, vehicleInfo, vector2, TransferManager.TransferReason.None, false, false))
     {
         Vehicle.Frame frame = instance.m_vehicles.m_buffer [(int)num10].m_frame0;
         if (num8 != 0)
         {
             frame.m_rotation = rotation;
         }
         else
         {
             Vector3 forward = a - citizenData.GetLastFrameData ().m_position;
             if (forward.sqrMagnitude > 0.01f)
             {
                 frame.m_rotation = Quaternion.LookRotation (forward);
             }
         }
         instance.m_vehicles.m_buffer [(int)num10].m_frame0 = frame;
         instance.m_vehicles.m_buffer [(int)num10].m_frame1 = frame;
         instance.m_vehicles.m_buffer [(int)num10].m_frame2 = frame;
         instance.m_vehicles.m_buffer [(int)num10].m_frame3 = frame;
         vehicleInfo.m_vehicleAI.FrameDataUpdated (num10, ref instance.m_vehicles.m_buffer [(int)num10], ref frame);
         instance.m_vehicles.m_buffer [(int)num10].m_targetPos0 = new Vector4 (a.x, a.y, a.z, 2f);
         Vehicle[] expr_4E5_cp_0 = instance.m_vehicles.m_buffer;
         ushort expr_4E5_cp_1 = num10;
         expr_4E5_cp_0 [(int)expr_4E5_cp_1].m_flags = (expr_4E5_cp_0 [(int)expr_4E5_cp_1].m_flags | Vehicle.Flags.Stopped);
         instance.m_vehicles.m_buffer [(int)num10].m_path = citizenData.m_path;
         instance.m_vehicles.m_buffer [(int)num10].m_pathPositionIndex = citizenData.m_pathPositionIndex;
         instance.m_vehicles.m_buffer [(int)num10].m_lastPathOffset = lastPathOffset;
         instance.m_vehicles.m_buffer [(int)num10].m_transferSize = (ushort)(citizenData.m_citizen & 65535u);
         vehicleInfo.m_vehicleAI.TrySpawn (num10, ref instance.m_vehicles.m_buffer [(int)num10]);
         if (num8 != 0)
         {
             InstanceID empty = InstanceID.Empty;
             empty.ParkedVehicle = num8;
             InstanceID empty2 = InstanceID.Empty;
             empty2.Vehicle = num10;
             Singleton<InstanceManager>.instance.ChangeInstance (empty, empty2);
         }
         citizenData.m_path = 0u;
         instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetParkedVehicle (citizenData.m_citizen, 0);
         instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetVehicle (citizenData.m_citizen, num10, 0u);
         citizenData.m_flags |= CitizenInstance.Flags.EnteringVehicle;
         citizenData.m_flags &= ~CitizenInstance.Flags.TryingSpawnVehicle;
         citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting;
         citizenData.m_waitCounter = 0;
         return true;
     }
     instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetParkedVehicle (citizenData.m_citizen, 0);
     if ((citizenData.m_flags & CitizenInstance.Flags.TryingSpawnVehicle) == CitizenInstance.Flags.None)
     {
         citizenData.m_flags |= CitizenInstance.Flags.TryingSpawnVehicle;
         citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting;
         citizenData.m_waitCounter = 0;
     }
     return true;
 }
 //
 // BEGIN STOCK CODE
 //
 public new bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPos, PathUnit.Position endPos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength)
 {
     PathUnit.Position position = default(PathUnit.Position);
     return this.CreatePath(out unit, ref randomizer, buildIndex, startPos, position, endPos, position, position, laneTypes, vehicleTypes, maxLength, false, false, false, false);
 }
        private void assignPathProperties(uint unit, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, PathUnit.Position vehiclePosition, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, byte simulationFlags)
        {
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags = simulationFlags;

            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_pathFindFlags = 0;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_buildIndex = buildIndex;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position00 = startPosA;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position01 = endPosA;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position02 = startPosB;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position03 = endPosB;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position11 = vehiclePosition;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_nextPathUnit = 0u;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_laneTypes = (byte)laneTypes;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_vehicleTypes = (byte)vehicleTypes;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_length = maxLength;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount = 20;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_referenceCount = 1;
        }
		public void CustomCalculateSegmentPositionPathFinder(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position position, uint laneId, byte offset, out Vector3 pos, out Vector3 dir, out float maxSpeed) {
			var netManager = Singleton<NetManager>.instance;
			netManager.m_lanes.m_buffer[(int)((UIntPtr)laneId)].CalculatePositionAndDirection(offset * 0.003921569f,
				out pos, out dir);
			var info = netManager.m_segments.m_buffer[position.m_segment].Info;
			if (info.m_lanes != null && info.m_lanes.Length > position.m_lane) {
				var laneSpeedLimit = SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneId, info.m_lanes[position.m_lane]); //info.m_lanes[position.m_lane].m_speedLimit;
				maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit,	netManager.m_lanes.m_buffer[(int)((UIntPtr)laneId)].m_curve);
			} else {
				maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
			}

			maxSpeed = CalcMaxSpeed(vehicleId, ref vehicleData, position, pos, maxSpeed, IsRecklessDriver(vehicleId, ref vehicleData));
		}
		public void CustomCalculateSegmentPositionPathFinder(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position position, uint laneID, byte offset, out Vector3 pos, out Vector3 dir, out float maxSpeed) {
			CalculateSegPos(vehicleID, ref vehicleData, position, laneID, offset, out pos, out dir, out maxSpeed);
		}
 public static bool FindPathPosition(Vector3 position, ItemClass.Service service, NetInfo.LaneType laneType, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, bool requireConnect, float maxDistance, out PathUnit.Position pathPosA, out PathUnit.Position pathPosB, out float distanceSqrA, out float distanceSqrB, RoadManager.VehicleType vehicleType)
 {
     Bounds bounds = new Bounds(position, new Vector3(maxDistance * 2f, maxDistance * 2f, maxDistance * 2f));
     int num = Mathf.Max((int)((bounds.min.x - 64f) / 64f + 135f), 0);
     int num2 = Mathf.Max((int)((bounds.min.z - 64f) / 64f + 135f), 0);
     int num3 = Mathf.Min((int)((bounds.max.x + 64f) / 64f + 135f), 269);
     int num4 = Mathf.Min((int)((bounds.max.z + 64f) / 64f + 135f), 269);
     NetManager instance = Singleton<NetManager>.instance;
     pathPosA.m_segment = 0;
     pathPosA.m_lane = 0;
     pathPosA.m_offset = 0;
     distanceSqrA = 1E+10f;
     pathPosB.m_segment = 0;
     pathPosB.m_lane = 0;
     pathPosB.m_offset = 0;
     distanceSqrB = 1E+10f;
     float num5 = maxDistance * maxDistance;
     for (int i = num2; i <= num4; i++)
     {
         for (int j = num; j <= num3; j++)
         {
             ushort num6 = instance.m_segmentGrid[i * 270 + j];
             int num7 = 0;
             while (num6 != 0)
             {
                 NetInfo info = instance.m_segments.m_buffer[(int)num6].Info;
                 if (info.m_class.m_service == service && (instance.m_segments.m_buffer[(int)num6].m_flags & NetSegment.Flags.Flooded) == NetSegment.Flags.None && (allowUnderground || !info.m_netAI.IsUnderground()))
                 {
                     ushort startNode = instance.m_segments.m_buffer[(int)num6].m_startNode;
                     ushort endNode = instance.m_segments.m_buffer[(int)num6].m_endNode;
                     Vector3 position2 = instance.m_nodes.m_buffer[(int)startNode].m_position;
                     Vector3 position3 = instance.m_nodes.m_buffer[(int)endNode].m_position;
                     float num8 = Mathf.Max(Mathf.Max(bounds.min.x - 64f - position2.x, bounds.min.z - 64f - position2.z), Mathf.Max(position2.x - bounds.max.x - 64f, position2.z - bounds.max.z - 64f));
                     float num9 = Mathf.Max(Mathf.Max(bounds.min.x - 64f - position3.x, bounds.min.z - 64f - position3.z), Mathf.Max(position3.x - bounds.max.x - 64f, position3.z - bounds.max.z - 64f));
                     Vector3 b;
                     int num10;
                     float num11;
                     Vector3 b2;
                     int num12;
                     float num13;
                     if ((num8 < 0f || num9 < 0f) && instance.m_segments.m_buffer[(int)num6].m_bounds.Intersects(bounds) && CustomPathManager.GetClosestLanePosition(instance.m_segments.m_buffer[(int)num6], position, laneType, vehicleTypes, requireConnect, out b, out num10, out num11, out b2, out num12, out num13, vehicleType))
                     {
                         float num14 = Vector3.SqrMagnitude(position - b);
                         if (num14 < num5)
                         {
                             num5 = num14;
                             pathPosA.m_segment = num6;
                             pathPosA.m_lane = (byte)num10;
                             pathPosA.m_offset = (byte)Mathf.Clamp(Mathf.RoundToInt(num11 * 255f), 0, 255);
                             distanceSqrA = num14;
                             num14 = Vector3.SqrMagnitude(position - b2);
                             if (num12 == -1 || num14 >= maxDistance * maxDistance)
                             {
                                 pathPosB.m_segment = 0;
                                 pathPosB.m_lane = 0;
                                 pathPosB.m_offset = 0;
                                 distanceSqrB = 1E+10f;
                             }
                             else
                             {
                                 pathPosB.m_segment = num6;
                                 pathPosB.m_lane = (byte)num12;
                                 pathPosB.m_offset = (byte)Mathf.Clamp(Mathf.RoundToInt(num13 * 255f), 0, 255);
                                 distanceSqrB = num14;
                             }
                         }
                     }
                 }
                 num6 = instance.m_segments.m_buffer[(int)num6].m_nextGridSegment;
                 if (++num7 >= 32768)
                 {
                     CODebugBase<LogChannel>.Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
                     break;
                 }
             }
         }
     }
     return pathPosA.m_segment != 0;
 }
		protected virtual void CalculateSegPos(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position position, uint laneID, byte offset, out Vector3 pos, out Vector3 dir, out float maxSpeed) {
			NetManager instance = Singleton<NetManager>.instance;
			instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection((float)offset * 0.003921569f, out pos, out dir);
			NetInfo info = instance.m_segments.m_buffer[(int)position.m_segment].Info;
			if (info.m_lanes != null && info.m_lanes.Length > (int)position.m_lane) {
				var laneSpeedLimit = SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info.m_lanes[position.m_lane]);
				maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, laneSpeedLimit, instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve);
			} else {
				maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1f, 0f);
			}
		}
 private void GetLaneDirection(PathUnit.Position pathPos, out NetInfo.Direction direction, out NetInfo.LaneType type)
 {
     NetManager instance = Singleton<NetManager>.instance;
     //if (instance == null)
     //	Logger.LogInfo("GetLaneDirection -> instance is null!\n");
     NetInfo info = instance.m_segments.m_buffer[(int)pathPos.m_segment].Info;
     //if (info == null)
     //	Logger.LogInfo("GetLaneDirection -> info is null!\n");
     //else if (info.m_lanes == null)
     //	Logger.LogInfo("GetLaneDirection -> info.m_lanes is null!\n");
     if (info.m_lanes.Length > (int)pathPos.m_lane)
     {
         direction = info.m_lanes[(int)pathPos.m_lane].m_finalDirection;
         type = info.m_lanes[(int)pathPos.m_lane].m_laneType;
         if ((instance.m_segments.m_buffer[(int)pathPos.m_segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
         {
             direction = NetInfo.InvertDirection(direction);
         }
     }
     else
     {
         direction = NetInfo.Direction.None;
         type = NetInfo.LaneType.None;
     }
 }
 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);
 }
		private void AddBufferItem(BufferItem item, PathUnit.Position target) {
			//bCurrentState = 0;
#if DEBUGPF
			/*if (m_queuedPathFindCount > 100 && Options.disableSomething1)
				Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: AddBufferItem item {item.m_position.m_segment} {item.m_position.m_lane}");*/
#endif

			uint num = _laneLocation[(int)((UIntPtr)item.m_laneID)];
			uint num2 = num >> 16;
			int num3 = (int)(num & 65535u);
			int comparisonBufferPos;
			if (num2 == _pathFindIndex) {
				//bCurrentState = 1;
				if (item.m_comparisonValue >= _buffer[num3].m_comparisonValue) {
					return;
				}
				//bCurrentState = 2;
				int num4 = num3 >> 6;
				int num5 = num3 & -64;
				if (num4 < _bufferMinPos || (num4 == _bufferMinPos && num5 < _bufferMin[num4])) {
					return;
				}
				//bCurrentState = 3;
				comparisonBufferPos = Mathf.Max(Mathf.RoundToInt(item.m_comparisonValue * 1024f), _bufferMinPos);
				if (comparisonBufferPos == num4) {
					_buffer[num3] = item;
					_laneTarget[(int)((UIntPtr)item.m_laneID)] = target;
					return;
				}
				//bCurrentState = 4;
				int num7 = num4 << 6 | _bufferMax[num4]--;
				BufferItem bufferItem = _buffer[num7];
				_laneLocation[(int)((UIntPtr)bufferItem.m_laneID)] = num;
				_buffer[num3] = bufferItem;
				//bCurrentState = 5;
			} else {
				//bCurrentState = 6;
				comparisonBufferPos = Mathf.Max(Mathf.RoundToInt(item.m_comparisonValue * 1024f), _bufferMinPos);
			}
			//bCurrentState = 7;
			if (comparisonBufferPos >= 1024) {
				return;
			}
			//bCurrentState = 8;
			if (comparisonBufferPos < 0) {
#if DEBUG
				Log.Error("comparisonBufferPos < 0!");
#endif
				return;
			}
			//bCurrentState = 9;
			while (_bufferMax[comparisonBufferPos] == 63) {
				//bCurrentState = 10;
				comparisonBufferPos++;
				if (comparisonBufferPos == 1024) {
					//bCurrentState = 11;
					return;
				}
			}
			//bCurrentState = 12;
			if (comparisonBufferPos > _bufferMaxPos) {
				_bufferMaxPos = comparisonBufferPos;
			}
			//bCurrentState = 13;
			num3 = (comparisonBufferPos << 6 | ++_bufferMax[comparisonBufferPos]);
			_buffer[num3] = item;
			_laneLocation[(int)((UIntPtr)item.m_laneID)] = (_pathFindIndex << 16 | (uint)num3);
			_laneTarget[(int)((UIntPtr)item.m_laneID)] = target;
			//bCurrentState = 14;
		}
 protected virtual void GetLaneDirection(PathUnit.Position pathPos, out NetInfo.Direction direction, out NetInfo.LaneType type)
 {
     NetManager instance = Singleton<NetManager>.instance;
     NetInfo info = instance.m_segments.m_buffer[(int)pathPos.m_segment].Info;
     if (info.m_lanes.Length > (int)pathPos.m_lane)
     {
         direction = info.m_lanes[(int)pathPos.m_lane].m_finalDirection;
         type = info.m_lanes[(int)pathPos.m_lane].m_laneType;
         if ((instance.m_segments.m_buffer[(int)pathPos.m_segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
         {
             direction = NetInfo.InvertDirection(direction);
         }
     }
     else
     {
         direction = NetInfo.Direction.None;
         type = NetInfo.LaneType.None;
     }
 }
		public void CustomCalculateSegmentPosition(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position nextPosition,
			PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID,
			byte prevOffset, int index, out Vector3 pos, out Vector3 dir, out float maxSpeed) {
			var netManager = Singleton<NetManager>.instance;
			//var vehicleManager = Singleton<VehicleManager>.instance;
			netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir);
			bool isRecklessDriver = IsRecklessDriver(vehicleId, ref vehicleData);

			var lastFrameData = vehicleData.GetLastFrameData();
			var lastFrameVehiclePos = lastFrameData.m_position;

			var camPos = Camera.main.transform.position;
			bool simulatePrioritySigns = (lastFrameVehiclePos - camPos).sqrMagnitude < FarLod && !isRecklessDriver;

			if (Options.simAccuracy <= 0) {
				if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car) {
					VehiclePosition vehiclePos = TrafficPriority.GetVehiclePosition(vehicleId);
					if (vehiclePos.Valid && simulatePrioritySigns) { // TODO check if this should be !vehiclePos.Valid
						try {
							CustomVehicleAI.HandleVehicle(vehicleId, ref Singleton<VehicleManager>.instance.m_vehicles.m_buffer[vehicleId], false, false);
						} catch (Exception e) {
							Log.Error("CarAI TmCalculateSegmentPosition Error: " + e.ToString());
						}
					}
				} else {
					//Log._Debug($"TmCalculateSegmentPosition does not handle vehicles of type {vehicleData.Info.m_vehicleType}");
				}
			}

			// I think this is supposed to be the lane position?
			// [VN, 12/23/2015] It's the 3D car position on the Bezier curve of the lane.
			// This crazy 0.003921569f equals to 1f/255 and prevOffset is the byte value (0..255) of the car position.
			var vehiclePosOnBezier = netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].CalculatePosition(prevOffset * 0.003921569f);
			//ushort currentSegmentId = netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_segment;

			ushort destinationNodeId;
			ushort sourceNodeId;
			if (offset < position.m_offset) {
				destinationNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode;
				sourceNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode;
			} else {
				destinationNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode;
				sourceNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode;
			}
			var previousDestinationNode = prevOffset == 0 ? netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode : netManager.m_segments.m_buffer[prevPos.m_segment].m_endNode;

			// this seems to be like the required braking force in order to stop the vehicle within its half length.
			var crazyValue = 0.5f * lastFrameData.m_velocity.sqrMagnitude / m_info.m_braking + m_info.m_generatedInfo.m_size.z * 0.5f;

			// Essentially, this is true if the car has enough time and space to brake (e.g. for a red traffic light)
			if (destinationNodeId == previousDestinationNode) {
				if (Vector3.Distance(lastFrameVehiclePos, vehiclePosOnBezier) >= crazyValue - 1f) {
					var currentFrameIndex = Singleton<SimulationManager>.instance.m_currentFrameIndex;
					var num5 = (uint)((previousDestinationNode << 8) / 32768);
					var num6 = currentFrameIndex - num5 & 255u;

					var nodeFlags = netManager.m_nodes.m_buffer[destinationNodeId].m_flags;
					var prevLaneFlags = (NetLane.Flags)netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_flags;
					var hasTrafficLight = (nodeFlags & NetNode.Flags.TrafficLights) != NetNode.Flags.None;
					var hasCrossing = (nodeFlags & NetNode.Flags.LevelCrossing) != NetNode.Flags.None;
					var isJoinedJunction = (prevLaneFlags & NetLane.Flags.JoinedJunction) != NetLane.Flags.None;
					bool checkSpace = !Flags.getEnterWhenBlockedAllowed(prevPos.m_segment, netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode == destinationNodeId) && !isRecklessDriver;
					//TrafficLightSimulation nodeSim = TrafficLightSimulation.GetNodeSimulation(destinationNodeId);
					/*if (timedNode != null && timedNode.vehiclesMayEnterBlockedJunctions) {
						checkSpace = false;
					}*/

					if (checkSpace) {
						// check if there is enough space
						if ((nodeFlags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) == NetNode.Flags.Junction &&
							netManager.m_nodes.m_buffer[destinationNodeId].CountSegments() != 2) {
							var len = vehicleData.CalculateTotalLength(vehicleId) + 2f;
							if (!netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(len)) {
								var sufficientSpace = false;
								if (nextPosition.m_segment != 0 &&
									netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_length < 30f) {
									var flags3 = netManager.m_nodes.m_buffer[sourceNodeId].m_flags;
									if ((flags3 &
										 (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) !=
										NetNode.Flags.Junction || netManager.m_nodes.m_buffer[sourceNodeId].CountSegments() == 2) {
										var laneId2 = PathManager.GetLaneID(nextPosition);
										if (laneId2 != 0u) {
											sufficientSpace = netManager.m_lanes.m_buffer[(int)((UIntPtr)laneId2)].CheckSpace(len);
										}
									}
								}
								if (!sufficientSpace) {
									maxSpeed = 0f;
									return;
								}
							}
						}
					}

					try {
						VehiclePosition globalTargetPos = TrafficPriority.GetVehiclePosition(vehicleId);

						if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == 0) {
							if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car) {
								if (hasTrafficLight && (!isJoinedJunction || hasCrossing)) {
									var destinationInfo = netManager.m_nodes.m_buffer[destinationNodeId].Info;

									if (globalTargetPos.CarState == VehicleJunctionTransitState.None) {
										globalTargetPos.CarState = VehicleJunctionTransitState.Enter;
									}

									RoadBaseAI.TrafficLightState vehicleLightState;
									RoadBaseAI.TrafficLightState pedestrianLightState;
									bool vehicles;
									bool pedestrians;
									CustomRoadAI.GetTrafficLightState(vehicleId, ref vehicleData, destinationNodeId, prevPos.m_segment, position.m_segment, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - num5, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians);

									if (isRecklessDriver && (destinationInfo.GetConnectionClass().m_service & ItemClass.Service.PublicTransport) == ItemClass.Service.None) { // no reckless driving at railroad crossings
										vehicleLightState = RoadBaseAI.TrafficLightState.Green;
									}

									if (!vehicles && num6 >= 196u) {
										vehicles = true;
										RoadBaseAI.SetTrafficLightState(destinationNodeId, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - num5, vehicleLightState, pedestrianLightState, vehicles, pedestrians);
									}

									var stopCar = false;
									switch (vehicleLightState) {
										case RoadBaseAI.TrafficLightState.RedToGreen:
											if (num6 < 60u) {
												stopCar = true;
											} else {
												globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
											}
											break;
										case RoadBaseAI.TrafficLightState.Red:
											stopCar = true;
											break;
										case RoadBaseAI.TrafficLightState.GreenToRed:
											if (num6 >= 30u) {
												stopCar = true;
											} else {
												globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
											}
											break;
									}

									if ((vehicleLightState == RoadBaseAI.TrafficLightState.Green || vehicleLightState == RoadBaseAI.TrafficLightState.RedToGreen) && !Flags.getEnterWhenBlockedAllowed(prevPos.m_segment, netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode == destinationNodeId)) {
										var hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId);

										if (hasIncomingCars) {
											// green light but other cars are incoming and they have priority: stop
											stopCar = true;
										}
									}

									if (stopCar) {
										globalTargetPos.CarState = VehicleJunctionTransitState.Stop;
										maxSpeed = 0f;
										return;
									}
								} else if (simulatePrioritySigns) {
#if DEBUG
									//bool debug = destinationNodeId == 10864;
									//bool debug = destinationNodeId == 13531;
									bool debug = false;
#endif
									//bool debug = false;
#if DEBUG
									if (debug)
										Log._Debug($"Vehicle {vehicleId} is arriving @ seg. {prevPos.m_segment} ({position.m_segment}, {nextPosition.m_segment}), node {destinationNodeId} which is not a traffic light.");
#endif

									var prioritySegment = TrafficPriority.GetPrioritySegment(destinationNodeId, prevPos.m_segment);
									if (prioritySegment != null) {
#if DEBUG
										if (debug)
											Log._Debug($"Vehicle {vehicleId} is arriving @ seg. {prevPos.m_segment} ({position.m_segment}, {nextPosition.m_segment}), node {destinationNodeId} which is not a traffic light and is a priority segment.");
#endif
										if (prioritySegment.HasVehicle(vehicleId)) {
#if DEBUG
											if (debug)
												Log._Debug($"Vehicle {vehicleId}: segment target position found");
#endif
											if (globalTargetPos.Valid) {
#if DEBUG
												if (debug)
													Log._Debug($"Vehicle {vehicleId}: global target position found. carState = {globalTargetPos.CarState.ToString()}");
#endif
												var currentFrameIndex2 = Singleton<SimulationManager>.instance.m_currentFrameIndex;
												var frame = currentFrameIndex2 >> 4;

												if (globalTargetPos.CarState == VehicleJunctionTransitState.None) {
													globalTargetPos.CarState = VehicleJunctionTransitState.Enter;
												}

												if (globalTargetPos.CarState != VehicleJunctionTransitState.Leave) {
													bool hasIncomingCars;
													switch (prioritySegment.Type) {
														case SegmentEnd.PriorityType.Stop:
#if DEBUG
															if (debug)
																Log._Debug($"Vehicle {vehicleId}: STOP sign. waittime={globalTargetPos.WaitTime}, vel={lastFrameData.m_velocity.magnitude}");
#endif
															if (globalTargetPos.WaitTime < MaxPriorityWaitTime) {
																globalTargetPos.CarState = VehicleJunctionTransitState.Stop;

																if (lastFrameData.m_velocity.magnitude < 0.5f ||
																	globalTargetPos.Stopped) {
																	globalTargetPos.Stopped = true;
																	globalTargetPos.WaitTime++;

																	float minStopWaitTime = Random.Range(0f, 3f);
																	if (globalTargetPos.WaitTime >= minStopWaitTime) {
																		hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId);
#if DEBUG
																		if (debug)
																			Log._Debug($"hasIncomingCars: {hasIncomingCars}");
#endif

																		if (hasIncomingCars) {
																			maxSpeed = 0f;
																			return;
																		}
																		globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
																	} else {
																		maxSpeed = 0;
																		return;
																	}
																} else {
																	maxSpeed = 0f;
																	return;
																}
															} else {
																globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
															}
															break;
														case SegmentEnd.PriorityType.Yield:
#if DEBUG
															if (debug)
																Log._Debug($"Vehicle {vehicleId}: YIELD sign. waittime={globalTargetPos.WaitTime}");
#endif
															if (globalTargetPos.WaitTime < MaxPriorityWaitTime) {
																globalTargetPos.WaitTime++;
																globalTargetPos.CarState = VehicleJunctionTransitState.Stop;
																hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId);
#if DEBUG
																if (debug)
																	Log._Debug($"hasIncomingCars: {hasIncomingCars}");
#endif
																if (hasIncomingCars) {
																	if (lastFrameData.m_velocity.magnitude > 0) {
																		maxSpeed = Math.Max(0f, lastFrameData.m_velocity.magnitude - globalTargetPos.ReduceSpeedByValueToYield);
																	} else {
																		maxSpeed = 0;
																	}
#if DEBUG
																	/*if (TrafficPriority.Vehicles[vehicleId].ToNode == 8621)
																		Log.Message($"Vehicle {vehicleId} is yielding at node {destinationNodeId}. Speed: {maxSpeed}, Waiting time: {TrafficPriority.Vehicles[vehicleId].WaitTime}");*/
#endif
																	return;
																} else {
#if DEBUG
																	/*if (TrafficPriority.Vehicles[vehicleId].ToNode == 8621)
																		Log.Message($"Vehicle {vehicleId} is NOT yielding at node {destinationNodeId}.");*/
#endif
																	if (lastFrameData.m_velocity.magnitude > 0) {
																		maxSpeed = Math.Max(1f, lastFrameData.m_velocity.magnitude - globalTargetPos.ReduceSpeedByValueToYield * 0.5f);
																	}
																}
																globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
															} else {
																globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
															}
															break;
														case SegmentEnd.PriorityType.Main:
#if DEBUG
															if (debug)
																Log._Debug($"Vehicle {vehicleId}: MAIN sign. waittime={globalTargetPos.WaitTime}");
#endif
															if (globalTargetPos.WaitTime < MaxPriorityWaitTime) {
																globalTargetPos.WaitTime++;
																globalTargetPos.CarState = VehicleJunctionTransitState.Stop;
																maxSpeed = 0f;

																hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId);
#if DEBUG
																if (debug)
																	Log._Debug($"hasIncomingCars: {hasIncomingCars}");
#endif

																if (hasIncomingCars) {
																	globalTargetPos.Stopped = true;
																	return;
																}
																globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
																globalTargetPos.Stopped = false;
															}

															var info3 = netManager.m_segments.m_buffer[position.m_segment].Info;
															if (info3.m_lanes != null && info3.m_lanes.Length > position.m_lane) {
																//maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, info3.m_lanes[position.m_lane].m_speedLimit, netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve) * 0.8f;
																maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info3.m_lanes[position.m_lane]), netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve);
															} else {
																maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
															}
															return;
													}
												} else {
													globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
												}
											} else {
#if DEBUG
												if (debug)
													Log._Debug($"globalTargetPos is null! {vehicleId} @ seg. {prevPos.m_segment} @ node {destinationNodeId}");
#endif
											}
										} else {
#if DEBUG
											if (debug)
												Log._Debug($"targetPos is null! {vehicleId} @ seg. {prevPos.m_segment} @ node {destinationNodeId}");
#endif
										}
									}
								}
							}
						}
					} catch (Exception e) {
						Log.Error($"Error occured in TmCalculateSegmentPosition: {e.ToString()}");
					}
				}
			}

			var info2 = netManager.m_segments.m_buffer[position.m_segment].Info;
			if (info2.m_lanes != null && info2.m_lanes.Length > position.m_lane) {
				var laneSpeedLimit = SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info2.m_lanes[position.m_lane]); // info2.m_lanes[position.m_lane].m_speedLimit;

#if DEBUG
				/*if (position.m_segment == 275) {
					Log._Debug($"Applying lane speed limit of {laneSpeedLimit} to lane {laneID} @ seg. {position.m_segment}");
                }*/
#endif

				/*if (TrafficRoadRestrictions.IsSegment(position.m_segment)) {
					var restrictionSegment = TrafficRoadRestrictions.GetSegment(position.m_segment);

					if (restrictionSegment.SpeedLimits[position.m_lane] > 0.1f) {
						laneSpeedLimit = restrictionSegment.SpeedLimits[position.m_lane];
					}
				}*/

				maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve);
			} else {
				maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
			}

			maxSpeed = CalcMaxSpeed(vehicleId, ref vehicleData, position, pos, maxSpeed, isRecklessDriver);
		}
        protected override void CalculateSegmentPosition(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position nextPosition,
            PathUnit.Position position, uint laneId, byte offset, PathUnit.Position prevPos, uint prevLaneId,
            byte prevOffset, out Vector3 pos, out Vector3 dir, out float maxSpeed)
        {
            NetManager instance = Singleton<NetManager>.instance;
            instance.m_lanes.m_buffer[(int)((UIntPtr)laneId)].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir);
            Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData();
            Vector3 position2 = lastFrameData.m_position;
            Vector3 b = instance.m_lanes.m_buffer[(int)((UIntPtr)prevLaneId)].CalculatePosition(prevOffset * 0.003921569f);
            float num = 0.5f * lastFrameData.m_velocity.sqrMagnitude / m_info.m_braking + m_info.m_generatedInfo.m_size.z * 0.5f;

            if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car)
            {
                if (!TrafficPriority.VehicleList.ContainsKey(vehicleId))
                {
                    TrafficPriority.VehicleList.Add(vehicleId, new PriorityCar());
                }
            }

            if (Vector3.Distance(position2, b) >= num - 1f)
            {
                Segment3 segment;
                segment.a = pos;
                ushort num2;
                ushort num3;
                if (offset < position.m_offset)
                {
                    segment.b = pos + dir.normalized*m_info.m_generatedInfo.m_size.z;
                    num2 = instance.m_segments.m_buffer[position.m_segment].m_startNode;
                    num3 = instance.m_segments.m_buffer[position.m_segment].m_endNode;
                }
                else
                {
                    segment.b = pos - dir.normalized*m_info.m_generatedInfo.m_size.z;
                    num2 = instance.m_segments.m_buffer[position.m_segment].m_endNode;
                    num3 = instance.m_segments.m_buffer[position.m_segment].m_startNode;
                }
                ushort num4;
                if (prevOffset == 0)
                {
                    num4 = instance.m_segments.m_buffer[prevPos.m_segment].m_startNode;
                }
                else
                {
                    num4 = instance.m_segments.m_buffer[prevPos.m_segment].m_endNode;
                }

                if (num2 == num4)
                {
                    uint currentFrameIndex = Singleton<SimulationManager>.instance.m_currentFrameIndex;
                    uint num5 = (uint)((num4 << 8) / 32768);
                    uint num6 = currentFrameIndex - num5 & 255u;

                    NetNode.Flags flags = instance.m_nodes.m_buffer[num2].m_flags;
                    NetLane.Flags flags2 =
                        (NetLane.Flags) instance.m_lanes.m_buffer[(int) ((UIntPtr) prevLaneId)].m_flags;
                    bool flag = (flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None;
                    bool flag2 = (flags & NetNode.Flags.LevelCrossing) != NetNode.Flags.None;
                    bool flag3 = (flags2 & NetLane.Flags.JoinedJunction) != NetLane.Flags.None;
                    if ((flags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) ==
                        NetNode.Flags.Junction && instance.m_nodes.m_buffer[num2].CountSegments() != 2)
                    {
                        float len = vehicleData.CalculateTotalLength(vehicleId) + 2f;
                        if (!instance.m_lanes.m_buffer[(int) ((UIntPtr) laneId)].CheckSpace(len))
                        {
                            bool flag4 = false;
                            if (nextPosition.m_segment != 0 &&
                                instance.m_lanes.m_buffer[(int) ((UIntPtr) laneId)].m_length < 30f)
                            {
                                NetNode.Flags flags3 = instance.m_nodes.m_buffer[num3].m_flags;
                                if ((flags3 &
                                     (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) !=
                                    NetNode.Flags.Junction || instance.m_nodes.m_buffer[num3].CountSegments() == 2)
                                {
                                    uint laneId2 = PathManager.GetLaneID(nextPosition);
                                    if (laneId2 != 0u)
                                    {
                                        flag4 = instance.m_lanes.m_buffer[(int) ((UIntPtr) laneId2)].CheckSpace(len);
                                    }
                                }
                            }
                            if (!flag4)
                            {
                                maxSpeed = 0f;
                                return;
                            }
                        }
                    }

                    if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car &&
                        TrafficPriority.VehicleList.ContainsKey(vehicleId) &&
                        TrafficPriority.IsPrioritySegment(num2, prevPos.m_segment))
                    {
                        uint currentFrameIndex2 = Singleton<SimulationManager>.instance.m_currentFrameIndex;
                        uint frame = currentFrameIndex2 >> 4;

                        var prioritySegment = TrafficPriority.GetPrioritySegment(num2, prevPos.m_segment);
                        if (TrafficPriority.VehicleList[vehicleId].toNode != num2 ||
                            TrafficPriority.VehicleList[vehicleId].fromSegment != prevPos.m_segment)
                        {
                            if (TrafficPriority.VehicleList[vehicleId].toNode != 0 &&
                                TrafficPriority.VehicleList[vehicleId].fromSegment != 0)
                            {
                                var oldNode = TrafficPriority.VehicleList[vehicleId].toNode;
                                var oldSegment = TrafficPriority.VehicleList[vehicleId].fromSegment;

                                if (TrafficPriority.IsPrioritySegment(oldNode, oldSegment))
                                {
                                    var oldPrioritySegment = TrafficPriority.GetPrioritySegment(oldNode, oldSegment);
                                    TrafficPriority.VehicleList[vehicleId].waitTime = 0;
                                    TrafficPriority.VehicleList[vehicleId].stopped = false;
                                    oldPrioritySegment.RemoveCar(vehicleId);
                                }
                            }

                            // prevPos - current segment
                            // position - next segment
                            TrafficPriority.VehicleList[vehicleId].toNode = num2;
                            TrafficPriority.VehicleList[vehicleId].fromSegment = prevPos.m_segment;
                            TrafficPriority.VehicleList[vehicleId].toSegment = position.m_segment;
                            TrafficPriority.VehicleList[vehicleId].toLaneID = PathManager.GetLaneID(position);
                            TrafficPriority.VehicleList[vehicleId].fromLaneID = PathManager.GetLaneID(prevPos);
                            TrafficPriority.VehicleList[vehicleId].fromLaneFlags =
                                instance.m_lanes.m_buffer[PathManager.GetLaneID(prevPos)].m_flags;
                            TrafficPriority.VehicleList[vehicleId].yieldSpeedReduce = Random.Range(13f,
                                18f);

                            prioritySegment.AddCar(vehicleId);
                        }

                        TrafficPriority.VehicleList[vehicleId].lastFrame = frame;
                        TrafficPriority.VehicleList[vehicleId].lastSpeed =
                            vehicleData.GetLastFrameData().m_velocity.sqrMagnitude;
                    }

                    if (flag && (!flag3 || flag2))
                    {
                        var nodeSimulation = CustomRoadAI.GetNodeSimulation(num4);

                        NetInfo info = instance.m_nodes.m_buffer[num2].Info;
                        RoadBaseAI.TrafficLightState vehicleLightState;

                        if (nodeSimulation == null || (nodeSimulation.FlagTimedTrafficLights && !nodeSimulation.TimedTrafficLightsActive))
                        {
                            RoadBaseAI.TrafficLightState pedestrianLightState;
                            bool flag5;
                            bool pedestrians;
                            RoadBaseAI.GetTrafficLightState(num4,
                                ref instance.m_segments.m_buffer[prevPos.m_segment],
                                currentFrameIndex - num5, out vehicleLightState, out pedestrianLightState, out flag5,
                                out pedestrians);
                            if (!flag5 && num6 >= 196u)
                            {
                                flag5 = true;
                                RoadBaseAI.SetTrafficLightState(num4,
                                    ref instance.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - num5,
                                    vehicleLightState, pedestrianLightState, flag5, pedestrians);
                            }

                            if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == Vehicle.Flags.None ||
                                info.m_class.m_service != ItemClass.Service.Road)
                            {
                                switch (vehicleLightState)
                                {
                                    case RoadBaseAI.TrafficLightState.RedToGreen:
                                        if (num6 < 60u)
                                        {
                                            maxSpeed = 0f;
                                            return;
                                        }
                                        break;
                                    case RoadBaseAI.TrafficLightState.Red:
                                        maxSpeed = 0f;
                                        return;
                                    case RoadBaseAI.TrafficLightState.GreenToRed:
                                        if (num6 >= 30u)
                                        {
                                            maxSpeed = 0f;
                                            return;
                                        }
                                        break;
                                }
                            }
                        }
                        else
                        {
                            var stopCar = false;

                            if (TrafficPriority.IsLeftSegment(prevPos.m_segment, position.m_segment, num2))
                            {
                                vehicleLightState =
                                    TrafficLightsManual.GetSegmentLight(num4, prevPos.m_segment).GetLightLeft();
                            }
                            else if (TrafficPriority.IsRightSegment(prevPos.m_segment, position.m_segment, num2))
                            {
                                vehicleLightState =
                                    TrafficLightsManual.GetSegmentLight(num4, prevPos.m_segment).GetLightRight();
                            }
                            else
                            {
                                vehicleLightState =
                                    TrafficLightsManual.GetSegmentLight(num4, prevPos.m_segment).GetLightMain();
                            }

                            if (vehicleLightState == RoadBaseAI.TrafficLightState.Green)
                            {
                                var hasIncomingCars = TrafficPriority.IncomingVehicles(vehicleId, num2);

                                if (hasIncomingCars)
                                {
                                    stopCar = true;
                                }
                            }

                            if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == Vehicle.Flags.None ||
                                info.m_class.m_service != ItemClass.Service.Road)
                            {
                                switch (vehicleLightState)
                                {
                                    case RoadBaseAI.TrafficLightState.RedToGreen:
                                        if (num6 < 60u)
                                        {
                                            stopCar = true;
                                        }
                                        break;
                                    case RoadBaseAI.TrafficLightState.Red:
                                        stopCar = true;
                                        break;
                                    case RoadBaseAI.TrafficLightState.GreenToRed:
                                        if (num6 >= 30u)
                                        {
                                            stopCar = true;
                                        }
                                        break;
                                }
                            }

                            if (stopCar)
                            {
                                maxSpeed = 0f;
                                return;
                            }
                        }
                    }
                    else
                    {
                        if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car &&
                            TrafficPriority.VehicleList.ContainsKey(vehicleId) &&
                            TrafficPriority.IsPrioritySegment(num2, prevPos.m_segment))
                        {
                            var currentFrameIndex2 = Singleton<SimulationManager>.instance.m_currentFrameIndex;
                            var frame = currentFrameIndex2 >> 4;

                            var prioritySegment = TrafficPriority.GetPrioritySegment(num2, prevPos.m_segment);

                            if (TrafficPriority.VehicleList[vehicleId].carState == PriorityCar.CarState.None)
                            {
                                TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Enter;
                            }

                            if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == Vehicle.Flags.None &&
                                TrafficPriority.VehicleList[vehicleId].carState != PriorityCar.CarState.Leave)
                            {
                                if (prioritySegment.Type == PrioritySegment.PriorityType.Stop)
                                {
                                    if (TrafficPriority.VehicleList[vehicleId].waitTime < 75)
                                    {
                                        TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Stop;

                                        if (vehicleData.GetLastFrameData().m_velocity.sqrMagnitude < 0.1f ||
                                            TrafficPriority.VehicleList[vehicleId].stopped)
                                        {
                                            TrafficPriority.VehicleList[vehicleId].stopped = true;
                                            TrafficPriority.VehicleList[vehicleId].waitTime++;

                                            if (TrafficPriority.VehicleList[vehicleId].waitTime > 2)
                                            {
                                                var hasIncomingCars = TrafficPriority.IncomingVehicles(vehicleId, num2);

                                                if (hasIncomingCars)
                                                {
                                                    maxSpeed = 0f;
                                                    return;
                                                }
                                            }
                                            else
                                            {
                                                maxSpeed = 0f;
                                                return;
                                            }
                                        }
                                        else
                                        {
                                            maxSpeed = 0f;
                                            return;
                                        }
                                    }
                                    else
                                    {
                                        TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Leave;
                                    }
                                }
                                else if (prioritySegment.Type == PrioritySegment.PriorityType.Yield)
                                {
                                    if (TrafficPriority.VehicleList[vehicleId].waitTime < 75)
                                    {
                                        TrafficPriority.VehicleList[vehicleId].waitTime++;
                                        TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Stop;
                                        maxSpeed = 0f;

                                        if (vehicleData.GetLastFrameData().m_velocity.sqrMagnitude <
                                            TrafficPriority.VehicleList[vehicleId].yieldSpeedReduce)
                                        {
                                            var hasIncomingCars = TrafficPriority.IncomingVehicles(vehicleId, num2);

                                            if (hasIncomingCars)
                                            {
                                                return;
                                            }
                                        }
                                        else
                                        {
                                            return;
                                        }
                                    }
                                    else
                                    {
                                        TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Leave;
                                    }
                                }
                                else if (prioritySegment.Type == PrioritySegment.PriorityType.Main)
                                {
                                    TrafficPriority.VehicleList[vehicleId].waitTime++;
                                    TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Stop;
                                    maxSpeed = 0f;

                                    var hasIncomingCars = TrafficPriority.IncomingVehicles(vehicleId, num2);

                                    if (hasIncomingCars)
                                    {
                                        TrafficPriority.VehicleList[vehicleId].stopped = true;
                                        return;
                                    }
                                    TrafficPriority.VehicleList[vehicleId].stopped = false;

                                    NetInfo info3 = instance.m_segments.m_buffer[position.m_segment].Info;
                                    if (info3.m_lanes != null && info3.m_lanes.Length > position.m_lane)
                                    {
                                        maxSpeed =
                                            CalculateTargetSpeed(vehicleId, ref vehicleData,
                                                info3.m_lanes[position.m_lane].m_speedLimit,
                                                instance.m_lanes.m_buffer[(int) ((UIntPtr) laneId)].m_curve)*0.8f;
                                    }
                                    else
                                    {
                                        maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f)*
                                                   0.8f;
                                    }
                                    return;
                                }
                            }
                            else
                            {
                                TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Transit;
                            }
                        }
                    }
                }
            }

            NetInfo info2 = instance.m_segments.m_buffer[position.m_segment].Info;
            if (info2.m_lanes != null && info2.m_lanes.Length > position.m_lane)
            {
                var laneSpeedLimit = info2.m_lanes[position.m_lane].m_speedLimit;

                if (TrafficRoadRestrictions.IsSegment(position.m_segment))
                {
                    var restrictionSegment = TrafficRoadRestrictions.GetSegment(position.m_segment);

                    if (restrictionSegment.SpeedLimits[position.m_lane] > 0.1f)
                    {
                        laneSpeedLimit = restrictionSegment.SpeedLimits[position.m_lane];
                    }
                }

                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, instance.m_lanes.m_buffer[(int)((UIntPtr)laneId)].m_curve);
            }
            else
            {
                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
            }
        }
        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);
        }
		public static bool GetStopLane(ref PathUnit.Position pos, VehicleInfo.VehicleType vehicleType) {
			if (pos.m_segment != 0) {
				NetManager instance = Singleton<NetManager>.instance;
				int num;
				uint num2;
				if (instance.m_segments.m_buffer[(int)pos.m_segment].GetClosestLane((int)pos.m_lane, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, vehicleType, out num, out num2)) {
					pos.m_lane = (byte)num;
					return true;
				}
			}
			pos = default(PathUnit.Position);
			return false;
		}
Beispiel #30
0
 public new void CalculateSegmentPosition(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, out Vector3 pos, out Vector3 dir, out float maxSpeed)
 {
     base.CalculateSegmentPosition(vehicleID, ref vehicleData, nextPosition, position, laneID, offset, prevPos, prevLaneID, prevOffset, out pos, out dir, out maxSpeed);
 }