コード例 #1
0
        internal static void AddLiveSegmentLights(ushort nodeId, ushort segmentId)
        {
#if TRACE
            Singleton <CodeProfiler> .instance.Start("CustomTrafficLights.AddLiveSegmentLights");
#endif
            if (IsSegmentLight(nodeId, segmentId))
            {
#if TRACE
                Singleton <CodeProfiler> .instance.Stop("CustomTrafficLights.AddLiveSegmentLights");
#endif
                return;
            }

            //Log.Message($"Adding live segment light: {segmentId} @ {nodeId}");

            var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            RoadBaseAI.TrafficLightState vehicleLightState;
            RoadBaseAI.TrafficLightState pedestrianLightState;
            bool vehicles;
            bool pedestrians;

            RoadBaseAI.GetTrafficLightState(nodeId, ref Singleton <NetManager> .instance.m_segments.m_buffer[segmentId],
                                            currentFrameIndex - 256u, out vehicleLightState, out pedestrianLightState, out vehicles,
                                            out pedestrians);

            AddSegmentLights(nodeId, segmentId,
                             vehicleLightState == RoadBaseAI.TrafficLightState.Green
                                        ? RoadBaseAI.TrafficLightState.Green
                                        : RoadBaseAI.TrafficLightState.Red);
#if TRACE
            Singleton <CodeProfiler> .instance.Stop("CustomTrafficLights.AddLiveSegmentLights");
#endif
        }
コード例 #2
0
        public void UpdateVisuals()
        {
            NetManager instance          = Singleton <NetManager> .instance;
            uint       currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            lastChange      = 0u;
            lastChangeFrame = currentFrameIndex >> 6;

            RoadBaseAI.TrafficLightState trafficLightState3;
            RoadBaseAI.TrafficLightState trafficLightState4;
            bool vehicles;
            bool pedestrians;

            RoadBaseAI.GetTrafficLightState(this.node, ref instance.m_segments.m_buffer[(int)this.segment],
                                            currentFrameIndex - 256u, out trafficLightState3, out trafficLightState4, out vehicles, out pedestrians);

            if (lightMain == RoadBaseAI.TrafficLightState.Red && lightLeft == RoadBaseAI.TrafficLightState.Red && lightRight == RoadBaseAI.TrafficLightState.Red)
            {
                trafficLightState3 = RoadBaseAI.TrafficLightState.Red;
            }
            else
            {
                trafficLightState3 = RoadBaseAI.TrafficLightState.Green;
            }

            trafficLightState4 = lightPedestrian;

            RoadBaseAI.SetTrafficLightState(this.node, ref instance.m_segments.m_buffer[(int)this.segment], currentFrameIndex,
                                            trafficLightState3, trafficLightState4, vehicles, pedestrians);
        }
        /// <summary>
        /// Adds custom traffic lights at the specified node and segment.
        ///     Light states (red, yellow, green) are taken from the "live" state, that is the
        ///     traffic light's light state right before the custom light takes control.
        /// </summary>
        /// <param name="segmentId">SegmentId affected</param>
        /// <param name="startNode">NodeId affected</param>
        private ICustomSegmentLights AddLiveSegmentLights(ushort segmentId, bool startNode)
        {
            if (!Services.NetService.IsSegmentValid(segmentId))
            {
                return(null);
            }

            ushort nodeId            = Services.NetService.GetSegmentNodeId(segmentId, startNode);
            uint   currentFrameIndex = Services.SimulationService.CurrentFrameIndex;

            RoadBaseAI.GetTrafficLightState(
                nodeId,
                ref Singleton <NetManager> .instance.m_segments.m_buffer[segmentId],
                currentFrameIndex - 256u,
                out RoadBaseAI.TrafficLightState vehicleLightState,
                out RoadBaseAI.TrafficLightState _,
                out bool _,
                out bool _);

            return(AddSegmentLights(
                       segmentId,
                       startNode,
                       vehicleLightState == RoadBaseAI.TrafficLightState.Green
                    ? RoadBaseAI.TrafficLightState.Green
                    : RoadBaseAI.TrafficLightState.Red));
        }
        /// <summary>
        /// Adds custom traffic lights at the specified node and segment.
        /// Light states (red, yellow, green) are taken from the "live" state, that is the traffic light's light state right before the custom light takes control.
        /// </summary>
        /// <param name="segmentId"></param>
        /// <param name="startNode"></param>
        public CustomSegmentLights AddLiveSegmentLights(ushort segmentId, bool startNode)
        {
            SegmentGeometry    segGeometry = SegmentGeometry.Get(segmentId);
            SegmentEndGeometry endGeometry = startNode ? segGeometry.StartNodeGeometry : segGeometry.EndNodeGeometry;

            if (!endGeometry.IsValid())
            {
                Log.Error($"CustomTrafficLightsManager.AddLiveSegmentLights: Segment {segmentId} is not connected to a node. startNode={startNode}");
                return(null);
            }

            var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            RoadBaseAI.TrafficLightState vehicleLightState;
            RoadBaseAI.TrafficLightState pedestrianLightState;
            bool vehicles;
            bool pedestrians;

            RoadBaseAI.GetTrafficLightState(endGeometry.NodeId(), ref Singleton <NetManager> .instance.m_segments.m_buffer[segmentId],
                                            currentFrameIndex - 256u, out vehicleLightState, out pedestrianLightState, out vehicles,
                                            out pedestrians);

            return(AddSegmentLights(segmentId, startNode,
                                    vehicleLightState == RoadBaseAI.TrafficLightState.Green
                                        ? RoadBaseAI.TrafficLightState.Green
                                        : RoadBaseAI.TrafficLightState.Red));
        }
コード例 #5
0
        public static bool CanEnableTrafficLights(RoadBaseAI ai, ushort nodeID, ref NetNode data)
        {
            try
            {
                if ((data.m_flags & NetNode.Flags.Junction) == NetNode.Flags.None)
                {
                    return(false);
                }

                int        num      = 0;
                int        num2     = 0;
                int        num3     = 0;
                NetManager instance = Singleton <NetManager> .instance;

                for (int i = 0; i < 8; i++)
                {
                    ushort segment = data.GetSegment(i);

                    if (segment != 0)
                    {
                        NetInfo info = instance.m_segments.m_buffer[(int)segment].Info;

                        if (info == null)
                        {
                            Util.DebugPrint("NetSegment has null NetInfo:", segment, data.Info?.name);
                            data.RemoveSegment(segment);
                            continue;
                        }

                        if (info.m_class == null)
                        {
                            Util.DebugPrint("NetInfo has null ItemClass:", info.name);
                            continue;
                        }

                        if (info.m_class.m_service == ItemClass.Service.Road)
                        {
                            num++;
                        }
                        else if ((info.m_vehicleTypes & VehicleInfo.VehicleType.Train) != VehicleInfo.VehicleType.None)
                        {
                            num2++;
                        }
                        if (info.m_hasPedestrianLanes)
                        {
                            num3++;
                        }
                    }
                }

                return((num < 1 || num2 < 1) && ((data.m_flags & NetNode.Flags.OneWayIn) == NetNode.Flags.None || num3 != 0));
            }
            catch (Exception e)
            {
                Util.DebugPrint("Handled exception from CanEnableTrafficLights:");
                UnityEngine.Debug.LogException(e);
            }

            return(false);
        }
コード例 #6
0
 public static bool Prefix(RoadBaseAI __instance, ushort nodeID, ref NetNode data)
 {
     return(!Options.timedLightsEnabled ||
            !Constants.ManagerFactory
            .TrafficLightSimulationManager
            .TrafficLightSimulations[nodeID]
            .IsSimulationRunning());
 }
コード例 #7
0
        public bool CustomCheckTrafficLights(ushort node, ushort segment)
        {
            var nodeSimulation = TrafficLightSimulation.GetNodeSimulation(node);

            var instance          = Singleton <NetManager> .instance;
            var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            var num  = (uint)((node << 8) / 32768);
            var num2 = currentFrameIndex - num & 255u;

            // NON-STOCK CODE START //
            RoadBaseAI.TrafficLightState pedestrianLightState;
            CustomSegmentLights          lights = CustomTrafficLights.GetSegmentLights(node, segment);

            if (lights == null || nodeSimulation == null || !nodeSimulation.IsSimulationActive())
            {
                RoadBaseAI.TrafficLightState vehicleLightState;
                bool vehicles;
                bool pedestrians;

                RoadBaseAI.GetTrafficLightState(node, ref instance.m_segments.m_buffer[segment], currentFrameIndex - num, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians);
                if ((pedestrianLightState == RoadBaseAI.TrafficLightState.GreenToRed || pedestrianLightState == RoadBaseAI.TrafficLightState.Red) && !pedestrians && num2 >= 196u)
                {
                    RoadBaseAI.SetTrafficLightState(node, ref instance.m_segments.m_buffer[segment], currentFrameIndex - num, vehicleLightState, pedestrianLightState, vehicles, true);
                    return(true);
                }
            }
            else
            {
                if (lights.PedestrianLightState == null)
                {
                    Log._Debug($"A pedestrian wants to cross node {node} at segment {segment} but there is no pedestrian traffic light!");
                    pedestrianLightState = lights.GetAutoPedestrianLightState();
                }
                else
                {
                    pedestrianLightState = (RoadBaseAI.TrafficLightState)lights.PedestrianLightState;
                }
            }
            // NON-STOCK CODE END //

            switch (pedestrianLightState)
            {
            case RoadBaseAI.TrafficLightState.RedToGreen:
                if (num2 < 60u)
                {
                    return(false);
                }
                break;

            case RoadBaseAI.TrafficLightState.Red:
            case RoadBaseAI.TrafficLightState.GreenToRed:
                return(false);
            }
            return(true);
        }
        public void GetTrafficLightState(
#if DEBUG
            ushort vehicleId,
            ref Vehicle vehicleData,
#endif
            ushort nodeId,
            ushort fromSegmentId,
            byte fromLaneIndex,
            ushort toSegmentId,
            ref NetSegment segmentData,
            uint frame,
            out TrafficLightState vehicleLightState,
            out TrafficLightState pedestrianLightState)
        {
            bool callStockMethod = true;

#if BENCHMARK
            using (var bm = new Benchmark(null, "callStockMethod")) {
#endif
            callStockMethod = !Options.timedLightsEnabled ||
                              !Instance.TrafficLightSimulations[nodeId].IsSimulationRunning();
#if BENCHMARK
        }
#endif

            if (callStockMethod)
            {
                RoadBaseAI.GetTrafficLightState(
                    nodeId,
                    ref segmentData,
                    frame,
                    out vehicleLightState,
                    out pedestrianLightState);
            }
            else
            {
#if BENCHMARK
                using (var bm = new Benchmark(null, "GetCustomTrafficLightState")) {
#endif
                GetCustomTrafficLightState(
#if DEBUG
                    vehicleId,
                    ref vehicleData,
#endif
                    nodeId,
                    fromSegmentId,
                    fromLaneIndex,
                    toSegmentId,
                    out vehicleLightState,
                    out pedestrianLightState,
                    ref Instance.TrafficLightSimulations[nodeId]);
#if BENCHMARK
            }
#endif
            }
        }
        public void GetTrafficLightState(
#if DEBUG
            ushort vehicleId,
            ref Vehicle vehicleData,
#endif
            ushort nodeId,
            ushort fromSegmentId,
            byte fromLaneIndex,
            ushort toSegmentId,
            ref NetSegment segmentData,
            uint frame,
            out TrafficLightState vehicleLightState,
            out TrafficLightState pedestrianLightState,
            out bool vehicles,
            out bool pedestrians)
        {
            bool callStockMethod;

            using (var bm = Benchmark.MaybeCreateBenchmark(null, "callStockMethod")) {
                callStockMethod = !Options.timedLightsEnabled ||
                                  !Instance.TrafficLightSimulations[nodeId].IsSimulationRunning();
            }

            if (callStockMethod)
            {
                RoadBaseAI.GetTrafficLightState(
                    nodeId,
                    ref segmentData,
                    frame,
                    out vehicleLightState,
                    out pedestrianLightState,
                    out vehicles,
                    out pedestrians);
            }
            else
            {
                using (var bm = Benchmark.MaybeCreateBenchmark(null, "GetCustomTrafficLightState")) {
                    GetCustomTrafficLightState(
#if DEBUG
                        vehicleId,
                        ref vehicleData,
#endif
                        nodeId,
                        fromSegmentId,
                        fromLaneIndex,
                        toSegmentId,
                        out vehicleLightState,
                        out pedestrianLightState,
                        ref Instance.TrafficLightSimulations[nodeId]);
                }

                vehicles    = false;
                pedestrians = false;
            }
        }
コード例 #10
0
        public bool CustomCheckTrafficLights(ushort node, ushort segment)
        {
            var nodeSimulation = Options.timedLightsEnabled ? TrafficLightSimulationManager.Instance().GetNodeSimulation(node) : null;

            var instance          = Singleton <NetManager> .instance;
            var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            var num  = (uint)((node << 8) / 32768);
            var num2 = currentFrameIndex - num & 255u;

            // NON-STOCK CODE START //
            RoadBaseAI.TrafficLightState pedestrianLightState;
            CustomSegmentLights          lights = CustomTrafficLightsManager.Instance().GetSegmentLights(node, segment);

            if (lights == null || nodeSimulation == null || !nodeSimulation.IsSimulationActive())
            {
                RoadBaseAI.TrafficLightState vehicleLightState;
                bool vehicles;
                bool pedestrians;

                RoadBaseAI.GetTrafficLightState(node, ref instance.m_segments.m_buffer[segment], currentFrameIndex - num, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians);
                if ((pedestrianLightState == RoadBaseAI.TrafficLightState.GreenToRed || pedestrianLightState == RoadBaseAI.TrafficLightState.Red) && !pedestrians && num2 >= 196u)
                {
                    RoadBaseAI.SetTrafficLightState(node, ref instance.m_segments.m_buffer[segment], currentFrameIndex - num, vehicleLightState, pedestrianLightState, vehicles, true);
                    return(true);
                }
            }
            else
            {
                if (lights.InvalidPedestrianLight)
                {
                    pedestrianLightState = RoadBaseAI.TrafficLightState.Green;
                }
                else
                {
                    pedestrianLightState = (RoadBaseAI.TrafficLightState)lights.PedestrianLightState;
                }
            }
            // NON-STOCK CODE END //

            switch (pedestrianLightState)
            {
            case RoadBaseAI.TrafficLightState.RedToGreen:
                if (num2 < 60u)
                {
                    return(false);
                }
                break;

            case RoadBaseAI.TrafficLightState.Red:
            case RoadBaseAI.TrafficLightState.GreenToRed:
                return(false);
            }
            return(true);
        }
		public ManualSegmentLight(ushort nodeId, ushort segmentId, RoadBaseAI.TrafficLightState mainLight, RoadBaseAI.TrafficLightState leftLight, RoadBaseAI.TrafficLightState rightLight, RoadBaseAI.TrafficLightState pedestrianLight) {
			this.nodeId = nodeId;
			this.segmentId = segmentId;

			LightMain = mainLight;
			LightLeft = leftLight;
			LightRight = rightLight;
			LightPedestrian = pedestrianLight;

			UpdateVisuals();
		}
コード例 #12
0
		public CustomSegmentLight(CustomSegmentLights lights, ushort nodeId, ushort segmentId, RoadBaseAI.TrafficLightState mainLight, RoadBaseAI.TrafficLightState leftLight, RoadBaseAI.TrafficLightState rightLight/*, RoadBaseAI.TrafficLightState pedestrianLight*/) {
			this.NodeId = nodeId;
			this.SegmentId = segmentId;
			this.lights = lights;

			LightMain = mainLight;
			LightLeft = leftLight;
			LightRight = rightLight;
			//LightPedestrian = pedestrianLight;

			UpdateVisuals();
		}
コード例 #13
0
		public static void AddSegmentLights(ushort nodeId, ushort segmentId, RoadBaseAI.TrafficLightState light) {
			//Log.Message($"Adding segment light: {segmentId} @ {nodeId}");

			if (ManualSegments.ContainsKey(segmentId)) {
				ManualSegments[segmentId].Node2Lights = new CustomSegmentLights(nodeId, segmentId, light);
				ManualSegments[segmentId].Node2 = nodeId;
			} else {
				ManualSegments.Add(segmentId, new CustomSegment());
				ManualSegments[segmentId].Node1Lights = new CustomSegmentLights(nodeId, segmentId, light);
				ManualSegments[segmentId].Node1 = nodeId;
			}
		}
コード例 #14
0
        public static void Prefix(RoadBaseAI __instance, ushort segmentID, ref NetSegment data)
        {
            // TODO check if this is required *START*
            uint curLaneId = data.m_lanes;
            int  numLanes  = data.Info.m_lanes.Length;
            uint laneIndex = 0;

            while (laneIndex < numLanes && curLaneId != 0u)
            {
                Flags.ApplyLaneArrowFlags(curLaneId);

                laneIndex++;
                curLaneId = Singleton <NetManager> .instance.m_lanes.m_buffer[curLaneId].m_nextLane;
            }

            // ↑↑↑↑
            // TODO check if this is required *END*
#if BENCHMARK
            using (Benchmark.MaybeCreateBenchmark(null, "Traffic-measurement")) {
#endif
            if (segmentID < lastSimulatedSegmentId)
            {
                // segment simulation restart
                ++trafficMeasurementMod;
                if (trafficMeasurementMod >= 4)
                {
                    trafficMeasurementMod = 0;
                }
            }

            lastSimulatedSegmentId = segmentID;

            bool doTrafficMeasurement = true;
            if (Options.simulationAccuracy == SimulationAccuracy.High ||
                Options.simulationAccuracy == SimulationAccuracy.Medium)
            {
                doTrafficMeasurement = (segmentID & 1) == trafficMeasurementMod;
            }
            else if (Options.simulationAccuracy <= SimulationAccuracy.Low)
            {
                doTrafficMeasurement = (segmentID & 3) == trafficMeasurementMod;
            }

            if (doTrafficMeasurement)
            {
                Constants.ManagerFactory.TrafficMeasurementManager.OnBeforeSimulationStep(
                    segmentID,
                    ref data);
            }
#if BENCHMARK
        }
#endif
        }
コード例 #15
0
        public bool CheckTrafficLights(ushort node, ushort segment)
        {
            var nodeSimulation = CustomRoadAI.GetNodeSimulation(node);

            NetManager instance          = Singleton <NetManager> .instance;
            uint       currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
            uint       num  = (uint)(((int)node << 8) / 32768);
            uint       num2 = currentFrameIndex - num & 255u;

            RoadBaseAI.TrafficLightState vehicleLightState;
            RoadBaseAI.TrafficLightState pedestrianLightState;
            bool vehicles;
            bool flag;

            if (nodeSimulation == null || (nodeSimulation.FlagTimedTrafficLights && !nodeSimulation.TimedTrafficLightsActive))
            {
                RoadBaseAI.GetTrafficLightState(node, ref instance.m_segments.m_buffer[(int)segment],
                                                currentFrameIndex - num, out vehicleLightState, out pedestrianLightState, out vehicles, out flag);
                switch (pedestrianLightState)
                {
                case RoadBaseAI.TrafficLightState.RedToGreen:
                    if (num2 < 60u)
                    {
                        return(false);
                    }
                    break;

                case RoadBaseAI.TrafficLightState.Red:
                case RoadBaseAI.TrafficLightState.GreenToRed:
                    if (!flag && num2 >= 196u)
                    {
                        flag = true;
                        RoadBaseAI.SetTrafficLightState(node, ref instance.m_segments.m_buffer[(int)segment],
                                                        currentFrameIndex - num, vehicleLightState, pedestrianLightState, vehicles, flag);
                    }
                    return(false);
                }
                return(true);
            }
            else
            {
                if (TrafficLightsManual.GetSegmentLight(node, segment).GetLightPedestrian() ==
                    RoadBaseAI.TrafficLightState.Red)
                {
                    return(false);
                }
                else
                {
                    return(true);
                }
            }
        }
コード例 #16
0
        public static void GetTrafficLightState(ushort vehicleId, ref Vehicle vehicleData, ushort nodeId, ushort fromSegmentId, ushort toSegmentId, ref NetSegment segmentData, uint frame, out RoadBaseAI.TrafficLightState vehicleLightState, out RoadBaseAI.TrafficLightState pedestrianLightState)
        {
            TrafficLightSimulation nodeSim = TrafficLightSimulation.GetNodeSimulation(nodeId);

            if (nodeSim == null || !nodeSim.IsSimulationActive())
            {
                RoadBaseAI.GetTrafficLightState(nodeId, ref segmentData, frame, out vehicleLightState, out pedestrianLightState);
            }
            else
            {
                GetCustomTrafficLightState(vehicleId, ref vehicleData, nodeId, fromSegmentId, toSegmentId, out vehicleLightState, out pedestrianLightState, nodeSim);
            }
        }
		public ManualSegmentLight(ushort nodeId, ushort segmentId, RoadBaseAI.TrafficLightState mainLight) {
			this.nodeId = nodeId;
			this.segmentId = segmentId;

			LightMain = mainLight;
			LightLeft = mainLight;
			LightRight = mainLight;
			LightPedestrian = mainLight == RoadBaseAI.TrafficLightState.Green
				? RoadBaseAI.TrafficLightState.Red
				: RoadBaseAI.TrafficLightState.Green;

			UpdateVisuals();
		}
コード例 #18
0
        public ManualSegmentLight(ushort node, int segment, RoadBaseAI.TrafficLightState mainLight)
        {
            Node = node;
            Segment = segment;

            LightMain = mainLight;
            LightLeft = mainLight;
            LightRight = mainLight;
            LightPedestrian = mainLight == RoadBaseAI.TrafficLightState.Green
                ? RoadBaseAI.TrafficLightState.Red
                : RoadBaseAI.TrafficLightState.Green;

            UpdateVisuals();
        }
コード例 #19
0
        public static void SetOutsideConnection(NetInfo asset)
        {
            RoadAI netAI = asset.m_netAI as RoadAI;

            netAI.m_outsideConnection = PrefabCollection <BuildingInfo> .FindLoaded("Road Connection");

            RoadBaseAI elevatedAI = netAI.m_elevatedInfo.m_netAI as RoadBaseAI;

            elevatedAI.m_outsideConnection = PrefabCollection <BuildingInfo> .FindLoaded("Road Connection");

            RoadBaseAI tunnelAI = netAI.m_tunnelInfo.m_netAI as RoadBaseAI;

            tunnelAI.m_outsideConnection = PrefabCollection <BuildingInfo> .FindLoaded("Road Connection");
        }
コード例 #20
0
		//public bool PedestrianEnabled;

		public CustomSegmentLight(CustomSegmentLights lights, ushort nodeId, ushort segmentId, RoadBaseAI.TrafficLightState mainLight) {
			this.NodeId = nodeId;
			this.SegmentId = segmentId;
			this.lights = lights;

			LightMain = mainLight;
			LightLeft = mainLight;
			LightRight = mainLight;
			/*LightPedestrian = mainLight == RoadBaseAI.TrafficLightState.Green
				? RoadBaseAI.TrafficLightState.Red
				: RoadBaseAI.TrafficLightState.Green;*/

			UpdateVisuals();
		}
コード例 #21
0
        public void UpdateVisuals()
        {
            var instance = Singleton <NetManager> .instance;

            uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
            uint num = (uint)(((int)nodeId << 8) / 32768);

            LastChange      = 0u;
            LastChangeFrame = currentFrameIndex >> 6;

            RoadBaseAI.TrafficLightState oldVehicleLightState;
            RoadBaseAI.TrafficLightState vehicleLightState;
            RoadBaseAI.TrafficLightState pedestrianLightState;
            bool vehicles;
            bool pedestrians;

            RoadBaseAI.GetTrafficLightState(nodeId, ref instance.m_segments.m_buffer[segmentId],
                                            currentFrameIndex - num, out oldVehicleLightState, out pedestrianLightState, out vehicles, out pedestrians);

            // any green?
            if (LightMain == RoadBaseAI.TrafficLightState.Green ||
                LightLeft == RoadBaseAI.TrafficLightState.Green ||
                LightRight == RoadBaseAI.TrafficLightState.Green)
            {
                vehicleLightState = RoadBaseAI.TrafficLightState.Green;
            }
            else               // all red?
            if (LightMain == RoadBaseAI.TrafficLightState.Red &&
                LightLeft == RoadBaseAI.TrafficLightState.Red &&
                LightRight == RoadBaseAI.TrafficLightState.Red)
            {
                vehicleLightState = RoadBaseAI.TrafficLightState.Red;
            }
            else               // any red+yellow?
            if (LightMain == RoadBaseAI.TrafficLightState.RedToGreen ||
                LightLeft == RoadBaseAI.TrafficLightState.RedToGreen ||
                LightRight == RoadBaseAI.TrafficLightState.RedToGreen)
            {
                vehicleLightState = RoadBaseAI.TrafficLightState.RedToGreen;
            }
            else
            {
                vehicleLightState = RoadBaseAI.TrafficLightState.GreenToRed;
            }

            pedestrianLightState = LightPedestrian;

            RoadBaseAI.SetTrafficLightState(nodeId, ref instance.m_segments.m_buffer[segmentId], currentFrameIndex - num,
                                            vehicleLightState, pedestrianLightState, true, true);
        }
コード例 #22
0
 public static void AddSegmentLight(ushort nodeId, int segmentId, RoadBaseAI.TrafficLightState light)
 {
     if (ManualSegments.ContainsKey(segmentId))
     {
         ManualSegments[segmentId].Node2 = nodeId;
         ManualSegments[segmentId].Instance2 = new ManualSegmentLight(nodeId, segmentId, light);
     }
     else
     {
         ManualSegments.Add(segmentId, new ManualSegment());
         ManualSegments[segmentId].Node1 = nodeId;
         ManualSegments[segmentId].Instance1 = new ManualSegmentLight(nodeId, segmentId, light);
     }
 }
コード例 #23
0
        /// Calls RoadBaseAI.CanEnableTrafficLights
        public static bool IntersectionCanHaveTrafficLights(RoadBaseAI ai, ushort nodeId, ref NetNode node)
        {
            // use delegate to call RoadBaseAI.CanEnableTrafficLights
            // that's much faster than using just reflection:
            //    https://codeblog.jonskeet.uk/2008/08/09/making-reflection-fly-and-exploring-delegates/
            if (_canHaveTrafficLightMethod == null)
            {
                var mi = typeof(RoadBaseAI).GetMethod("CanEnableTrafficLights", BindingFlags.Instance | BindingFlags.NonPublic);
                // Can't use Func<RoadBaseAi,ushort,NetNode,bool> because of ref parameter
                _canHaveTrafficLightMethod =
                    (RoadBaseCanHaveTrafficLight)Delegate.CreateDelegate(typeof(RoadBaseCanHaveTrafficLight), mi);
            }

            return(_canHaveTrafficLightMethod(ai, nodeId, ref node));
        }
コード例 #24
0
        internal static bool CalculateCanHideCrossingsRaw(NetInfo info)
        {
            bool ret = CalculateCanHideMarkingsRaw(info);

            if (!ret)
            {
                return(false);
            }

            RoadBaseAI ai = info.m_netAI as RoadBaseAI;

            ret &= info.m_hasPedestrianLanes || !ai.m_highwayRules || info.name.ToLower().Contains("toll");

            ret &= !exempts_.Contains(info?.name);
            return(ret);
        }
コード例 #25
0
        public static void GetTrafficLightState(ushort nodeId, ushort fromSegmentId, byte fromLaneIndex, ushort toSegmentId, ref NetSegment segmentData, uint frame, out RoadBaseAI.TrafficLightState vehicleLightState, out RoadBaseAI.TrafficLightState pedestrianLightState, out bool vehicles, out bool pedestrians)
        {
            if (!Options.timedLightsEnabled || !TrafficLightSimulationManager.Instance.TrafficLightSimulations[(int)nodeId].IsSimulationRunning())
            {
                RoadBaseAI.GetTrafficLightState(nodeId, ref segmentData, frame, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians);
                SegmentGeometry segmentGeometry = SegmentGeometry.Get(fromSegmentId, false);
                bool            startNode       = segmentGeometry.StartNodeId() == nodeId;

                if (MainDataStore.canUTurn[fromSegmentId])
                {
                    if (fromSegmentId == toSegmentId)
                    {
                        if (vehicleLightState != RoadBaseAI.TrafficLightState.Green)
                        {
                            Random rand = new Random();
                            //Add this to let U turn car low proiority
                            if (rand.Next(2) == 0)
                            {
                                vehicleLightState = RoadBaseAI.TrafficLightState.Green;
                            }
                        }
                    }
                }
                return;
            }



            GetCustomTrafficLightState(nodeId, fromSegmentId, fromLaneIndex, toSegmentId, out vehicleLightState, out pedestrianLightState, ref TrafficLightSimulationManager.Instance.TrafficLightSimulations[(int)nodeId]);
            vehicles    = false;
            pedestrians = false;
            if (MainDataStore.canUTurn[fromSegmentId])
            {
                if (fromSegmentId == toSegmentId)
                {
                    if (vehicleLightState != RoadBaseAI.TrafficLightState.Green)
                    {
                        Random rand = new Random();
                        //Add this to let U turn car low proiority
                        if (rand.Next(2) == 0)
                        {
                            vehicleLightState = RoadBaseAI.TrafficLightState.Green;
                        }
                    }
                }
            }
        }
        public bool CustomCheckTrafficLights(ushort node, ushort segment)
        {
            var nodeSimulation = TrafficPriority.GetNodeSimulation(node);

            var instance          = Singleton <NetManager> .instance;
            var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            var num  = (uint)((node << 8) / 32768);
            var num2 = currentFrameIndex - num & 255u;

            RoadBaseAI.TrafficLightState pedestrianLightState;
            ManualSegmentLight           light = TrafficLightsManual.GetSegmentLight(node, segment);

            if (light == null || nodeSimulation == null || (nodeSimulation.FlagTimedTrafficLights && !nodeSimulation.TimedTrafficLightsActive))
            {
                RoadBaseAI.TrafficLightState vehicleLightState;
                bool vehicles;
                bool pedestrians;

                RoadBaseAI.GetTrafficLightState(node, ref instance.m_segments.m_buffer[segment], currentFrameIndex - num, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians);
                if ((pedestrianLightState == RoadBaseAI.TrafficLightState.GreenToRed || pedestrianLightState == RoadBaseAI.TrafficLightState.Red) && !pedestrians && num2 >= 196u)
                {
                    RoadBaseAI.SetTrafficLightState(node, ref instance.m_segments.m_buffer[segment], currentFrameIndex - num, vehicleLightState, pedestrianLightState, vehicles, true);
                    return(true);
                }
            }
            else
            {
                pedestrianLightState = light.GetLightPedestrian();
            }

            switch (pedestrianLightState)
            {
            case RoadBaseAI.TrafficLightState.RedToGreen:
                if (num2 < 60u)
                {
                    return(false);
                }
                break;

            case RoadBaseAI.TrafficLightState.Red:
            case RoadBaseAI.TrafficLightState.GreenToRed:
                return(false);
            }
            return(true);
        }
コード例 #27
0
 static void Postfix(ref RoadBaseAI __instance, ushort segmentID)
 {
     if (!NetUtil.IsSegmentValid(segmentID))
     {
         return;
     }
     foreach (bool startNode in HelpersExtensions.ALL_BOOL)
     {
         if (AllFlagsAreForward(segmentID, startNode))
         {
             foreach (var lane in NetUtil.IterateLanes(segmentID, startNode:startNode))
             {
                 lane.Flags &= ~NetLane.Flags.LeftForwardRight;
             }
         }
     }
 }
コード例 #28
0
        private void ClickNoneToVehicle(UIComponent component, UIMouseEventParameter eventParam)
        {
            Dictionary <NetInfo, ushort> ret = new Dictionary <NetInfo, ushort>();
            int numLoaded = PrefabCollection <NetInfo> .LoadedCount();

            for (uint i = 0; i < numLoaded; ++i)
            {
                NetInfo info = PrefabCollection <NetInfo> .GetLoaded(i);

                if (!(info.m_netAI is RoadBaseAI))
                {
                    continue;
                }

                RoadBaseAI ai = (RoadBaseAI)info.m_netAI;

                if (!ai.m_highwayRules)
                {
                    continue;
                }

                NetInfo.Lane[] laneInfos = info.m_lanes;

                for (byte k = 0; k < Math.Min(2, laneInfos.Length); ++k)
                {
                    NetInfo.Lane laneInfo = laneInfos[k];

                    if (laneInfo.m_vehicleType == VehicleInfo.VehicleType.None)
                    {
                        laneInfo.m_vehicleType = VehicleInfo.VehicleType.Car;
                        laneInfo.m_laneType    = NetInfo.LaneType.Vehicle;
                        Log._Debug(
                            $"Changing vehicle type of lane {k} @ {info.name} from None to Car, " +
                            $"lane type from None to Vehicle");

                        if (!_customEmergencyLanes.ContainsKey(info.name))
                        {
                            _customEmergencyLanes.Add(info.name, new List <byte>());
                        }

                        _customEmergencyLanes[info.name].Add(k);
                    }
                }
            }
        }
コード例 #29
0
        public new static void LevelCrossingSimulationStep(ushort nodeID, ref NetNode data)
        {
            NetManager netManager        = Singleton <NetManager> .instance;
            uint       currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            bool green = (data.m_finalCounter == 0);

            for (int i = 0; i < 8; ++i)
            {
                ushort segmentID = data.GetSegment(i);

                bool segmentGreen = green;
                if (!segmentGreen)
                {
                    NetSegment segmentData = netManager.m_segments.m_buffer[segmentID];
                    if (segmentData.m_infoIndex == data.m_infoIndex)
                    {
                        segmentGreen = true;
                    }
                }

                RoadBaseAI.GetTrafficLightState(nodeID, ref netManager.m_segments.m_buffer[segmentID], currentFrameIndex - 256, out RoadBaseAI.TrafficLightState vehicleLightState, out RoadBaseAI.TrafficLightState _, out _, out _);

                vehicleLightState &= ~RoadBaseAI.TrafficLightState.IsChanging;

                if (!segmentGreen)
                {
                    if ((vehicleLightState & RoadBaseAI.TrafficLightState.Red) == 0)
                    {
                        vehicleLightState = RoadBaseAI.TrafficLightState.GreenToRed;
                    }
                }
                else
                {
                    if ((vehicleLightState & RoadBaseAI.TrafficLightState.Red) != 0)
                    {
                        vehicleLightState = RoadBaseAI.TrafficLightState.RedToGreen;
                    }
                }
                RoadBaseAI.SetTrafficLightState(nodeID, ref netManager.m_segments.m_buffer[segmentID], currentFrameIndex, vehicleLightState, RoadBaseAI.TrafficLightState.Red, false, false);
            }
        }
コード例 #30
0
        public void GetTrafficLightState(
#if DEBUG
            ushort vehicleId,
            ref Vehicle vehicleData,
#endif
            ushort nodeId,
            ushort fromSegmentId,
            byte fromLaneIndex,
            ushort toSegmentId,
            ref NetSegment segmentData,
            uint frame,
            out TrafficLightState vehicleLightState,
            out TrafficLightState pedestrianLightState)
        {
            bool callStockMethod = !Options.timedLightsEnabled ||
                                   !Instance.TrafficLightSimulations[nodeId].IsSimulationRunning();

            if (callStockMethod)
            {
                RoadBaseAI.GetTrafficLightState(
                    nodeId,
                    ref segmentData,
                    frame,
                    out vehicleLightState,
                    out pedestrianLightState);
            }
            else
            {
                GetCustomTrafficLightState(
#if DEBUG
                    vehicleId,
                    ref vehicleData,
#endif
                    nodeId,
                    fromSegmentId,
                    fromLaneIndex,
                    toSegmentId,
                    out vehicleLightState,
                    out pedestrianLightState,
                    ref Instance.TrafficLightSimulations[nodeId]);
            }
        }
コード例 #31
0
        public static void Prefix(RoadBaseAI __instance, ushort segmentID, ref NetSegment data)
        {
            // TODO check if this is required *START*
            uint curLaneId = data.m_lanes;
            int  numLanes  = data.Info.m_lanes.Length;
            uint laneIndex = 0;

            while (laneIndex < numLanes && curLaneId != 0u)
            {
                Flags.ApplyLaneArrowFlags(curLaneId);

                laneIndex++;
                curLaneId = Singleton <NetManager> .instance.m_lanes.m_buffer[curLaneId].m_nextLane;
            }

            // ↑↑↑↑
            // TODO check if this is required *END*
            Constants.ManagerFactory.TrafficMeasurementManager.OnBeforeSimulationStep(
                segmentID,
                ref data);
        }
コード例 #32
0
        private static bool MustStopAtMovableBridge(ushort prevSegmentID, ushort nextSegmentID, byte prevOffset, byte nextOffset)
        {
            var netManager = NetManager.instance;

            ushort prevTargetNodeId = (prevOffset >= 128) ? netManager.m_segments.m_buffer[prevSegmentID].m_endNode : netManager.m_segments.m_buffer[prevSegmentID].m_startNode;
            ushort nextSourceNodeId = (nextOffset >= 128) ? netManager.m_segments.m_buffer[nextSegmentID].m_endNode : netManager.m_segments.m_buffer[nextSegmentID].m_startNode;

            if (prevTargetNodeId == nextSourceNodeId)
            {
                NetNode.Flags flags = netManager.m_nodes.m_buffer[prevTargetNodeId].m_flags;
                if (flags.IsFlagSet(NetNode.Flags.CustomTrafficLights))
                {
                    var previousSegmentAI = netManager.m_segments.m_buffer[prevSegmentID].Info.m_netAI;
                    if (!(previousSegmentAI is MovableBridgeRoadAI))
                    {
                        return(false);
                    }
                    var nextSegmentAI = netManager.m_segments.m_buffer[nextSegmentID].Info.m_netAI;
                    if (!(nextSegmentAI is MovableBridgeRoadAI))
                    {
                        return(false);
                    }

                    uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
                    uint num6n             = (uint)(prevTargetNodeId << 8) / 32768u;
                    RoadBaseAI.GetTrafficLightState(prevTargetNodeId, ref netManager.m_segments.m_buffer[prevSegmentID], currentFrameIndex - num6n, out RoadBaseAI.TrafficLightState vehicleLightState, out RoadBaseAI.TrafficLightState pedestrianLightState, out bool vehicles, out bool pedestrians);

                    //Debug.Log($"CheckSegmentChange on bridge! state: ${vehicleLightState}");
                    if (vehicleLightState == RoadBaseAI.TrafficLightState.Red)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
コード例 #33
0
        /// <summary>
        /// slightly modified version of TrainAI.ForceTrafficLights(PathUnit.Position)
        /// </summary>
        /// <param name="transitNodeId"></param>
        /// <param name="position"></param>
        private static void ForceTrafficLights(ushort transitNodeId, PathUnit.Position position)
        {
            NetManager netMan = NetManager.instance;

            if ((netMan.m_nodes.m_buffer[transitNodeId].m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None)
            {
                return;
            }

            uint frame    = SimulationManager.instance.m_currentFrameIndex;
            uint simGroup = (uint)transitNodeId >> 7;
            uint rand     = frame - simGroup & 255u;

            RoadBaseAI.GetTrafficLightState(
                transitNodeId,
                ref netMan.m_segments.m_buffer[position.m_segment],
                frame - simGroup,
                out RoadBaseAI.TrafficLightState vehicleLightState,
                out RoadBaseAI.TrafficLightState pedestrianLightState,
                out bool vehicles,
                out bool pedestrians);

            if (vehicles || rand < 196u)
            {
                return;
            }

            vehicles = true;
            RoadBaseAI.SetTrafficLightState(
                transitNodeId,
                ref netMan.m_segments.m_buffer[position.m_segment],
                frame - simGroup,
                vehicleLightState,
                pedestrianLightState,
                true,
                pedestrians);
        }
        /// <summary>
        /// Checks for traffic lights and priority signs when changing segments (for road & rail vehicles).
        /// Sets the maximum allowed speed <paramref name="maxSpeed"/> if segment change is not allowed (otherwise <paramref name="maxSpeed"/> has to be set by the calling method).
        /// </summary>
        /// <param name="vehicleId">vehicle id</param>
        /// <param name="vehicleData">vehicle data</param>
        /// <param name="lastFrameData">last frame data of vehicle</param>
        /// <param name="isRecklessDriver">if true, this vehicle ignores red traffic lights and priority signs</param>
        /// <param name="prevPos">previous path position</param>
        /// <param name="prevTargetNodeId">previous target node</param>
        /// <param name="prevLaneID">previous lane</param>
        /// <param name="position">current path position</param>
        /// <param name="targetNodeId">transit node</param>
        /// <param name="laneID">current lane</param>
        /// <param name="nextPosition">next path position</param>
        /// <param name="nextTargetNodeId">next target node</param>
        /// <param name="maxSpeed">maximum allowed speed (only valid if method returns false)</param>
        /// <returns>true, if the vehicle may change segments, false otherwise.</returns>
        internal static bool MayChangeSegment(ushort vehicleId, ref Vehicle vehicleData, ref Vehicle.Frame lastFrameData, bool isRecklessDriver, ref PathUnit.Position prevPos, ushort prevTargetNodeId, uint prevLaneID, ref PathUnit.Position position, ushort targetNodeId, uint laneID, ref PathUnit.Position nextPosition, ushort nextTargetNodeId, out float maxSpeed, bool debug = false)
        {
            debug = false;
            if (prevTargetNodeId != targetNodeId)
            {
                // method should only be called if targetNodeId == prevTargetNode
                maxSpeed = 0f;
                return(true);
            }

            bool         forceUpdatePos = false;
            VehicleState vehicleState   = null;

            try {
                vehicleState = VehicleStateManager.GetVehicleState(vehicleId);

                if (vehicleState == null)
                {
                    VehicleStateManager.OnPathFindReady(vehicleId, ref vehicleData);
                    vehicleState = VehicleStateManager.GetVehicleState(vehicleId);

                    if (vehicleState == null)
                    {
#if DEBUG
                        Log._Debug($"Could not get vehicle state of {vehicleId}!");
#endif
                    }
                    else
                    {
                        forceUpdatePos = true;
                    }
                }
            } catch (Exception e) {
                Log.Error("VehicleAI MayChangeSegment vehicle state error: " + e.ToString());
            }

            if (forceUpdatePos || Options.simAccuracy >= 2)
            {
                try {
                    VehicleStateManager.UpdateVehiclePos(vehicleId, ref vehicleData, ref prevPos, ref position);
                } catch (Exception e) {
                    Log.Error("VehicleAI MayChangeSegment Error: " + e.ToString());
                }
            }

            var netManager = Singleton <NetManager> .instance;

            uint currentFrameIndex        = Singleton <SimulationManager> .instance.m_currentFrameIndex;
            uint prevTargetNodeLower8Bits = (uint)((prevTargetNodeId << 8) / 32768);
            uint random = currentFrameIndex - prevTargetNodeLower8Bits & 255u;

            bool isRailVehicle = (vehicleData.Info.m_vehicleType & (VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Metro)) != VehicleInfo.VehicleType.None;

            NetNode.Flags targetNodeFlags    = netManager.m_nodes.m_buffer[targetNodeId].m_flags;
            bool          hasTrafficLight    = (targetNodeFlags & NetNode.Flags.TrafficLights) != NetNode.Flags.None;
            bool          checkTrafficLights = false;
            if (!isRailVehicle)
            {
                // check if to check space

#if DEBUG
                if (debug)
                {
                    Log._Debug($"CustomVehicleAI.MayChangeSegment: Vehicle {vehicleId} is not a train.");
                }
#endif

                var  prevLaneFlags    = (NetLane.Flags)netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_flags;
                var  hasCrossing      = (targetNodeFlags & 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 == targetNodeId) && !isRecklessDriver;
                //TrafficLightSimulation nodeSim = TrafficLightSimulation.GetNodeSimulation(destinationNodeId);
                //if (timedNode != null && timedNode.vehiclesMayEnterBlockedJunctions) {
                //	checkSpace = false;
                //}

                if (checkSpace)
                {
                    // check if there is enough space
                    if ((targetNodeFlags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) == NetNode.Flags.Junction &&
                        netManager.m_nodes.m_buffer[targetNodeId].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)
                            {
                                NetNode.Flags nextTargetNodeFlags = netManager.m_nodes.m_buffer[nextTargetNodeId].m_flags;
                                if ((nextTargetNodeFlags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) != NetNode.Flags.Junction ||
                                    netManager.m_nodes.m_buffer[nextTargetNodeId].CountSegments() == 2)
                                {
                                    uint nextLaneId = PathManager.GetLaneID(nextPosition);
                                    if (nextLaneId != 0u)
                                    {
                                        sufficientSpace = netManager.m_lanes.m_buffer[(int)((UIntPtr)nextLaneId)].CheckSpace(len);
                                    }
                                }
                            }
                            if (!sufficientSpace)
                            {
                                maxSpeed = 0f;
                                try {
                                    if (vehicleState != null)
                                    {
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to BLOCKED");
                                        }
#endif

                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Blocked;
                                    }
                                } catch (Exception e) {
                                    Log.Error("VehicleAI MayChangeSegment error while setting junction state to BLOCKED: " + e.ToString());
                                }
                                return(false);
                            }
                        }
                    }
                }

                checkTrafficLights = (!isJoinedJunction || hasCrossing);
            }
            else
            {
#if DEBUG
                if (debug)
                {
                    Log._Debug($"CustomVehicleAI.MayChangeSegment: Vehicle {vehicleId} is a train.");
                }
#endif

                checkTrafficLights = true;
            }

            try {
                if (vehicleState != null && vehicleState.JunctionTransitState == VehicleJunctionTransitState.Blocked)
                {
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState from BLOCKED to ENTER");
                    }
#endif
                    vehicleState.JunctionTransitState = VehicleJunctionTransitState.Enter;
                }

                if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == 0)
                {
                    if (hasTrafficLight && checkTrafficLights)
                    {
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomVehicleAI.MayChangeSegment: Node {targetNodeId} has a traffic light.");
                        }
#endif

                        var destinationInfo = netManager.m_nodes.m_buffer[targetNodeId].Info;

                        if (vehicleState != null && vehicleState.JunctionTransitState == VehicleJunctionTransitState.None)
                        {
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to ENTER (1)");
                            }
#endif
                            vehicleState.JunctionTransitState = VehicleJunctionTransitState.Enter;
                        }

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

                        if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car && isRecklessDriver)                           // no reckless driving at railroad crossings
                        {
                            vehicleLightState = RoadBaseAI.TrafficLightState.Green;
                        }

#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomVehicleAI.MayChangeSegment: Vehicle {vehicleId} has {vehicleLightState} at node {targetNodeId}");
                        }
#endif

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

                        var stopCar = false;
                        switch (vehicleLightState)
                        {
                        case RoadBaseAI.TrafficLightState.RedToGreen:
                            if (random < 60u)
                            {
                                stopCar = true;
                            }
                            else
                            {
#if DEBUG
                                if (debug)
                                {
                                    Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (RedToGreen)");
                                }
#endif
                                if (vehicleState != null)
                                {
                                    vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                }
                            }
                            break;

                        case RoadBaseAI.TrafficLightState.Red:
                            stopCar = true;
                            break;

                        case RoadBaseAI.TrafficLightState.GreenToRed:
                            if (random >= 30u)
                            {
                                stopCar = true;
                            }
                            else if (vehicleState != null)
                            {
#if DEBUG
                                if (debug)
                                {
                                    Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (GreenToRed)");
                                }
#endif
                                vehicleState.JunctionTransitState = 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 == targetNodeId)) {
                         *      var hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, targetNodeId);
                         *
                         *      if (hasIncomingCars) {
                         *              // green light but other cars are incoming and they have priority: stop
                         *              stopCar = true;
                         *      }
                         * }*/

                        if (stopCar)
                        {
                            if (vehicleState != null)
                            {
#if DEBUG
                                if (debug)
                                {
                                    Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to STOP");
                                }
#endif
                                vehicleState.JunctionTransitState = VehicleJunctionTransitState.Stop;
                            }
                            maxSpeed = 0f;
                            return(false);
                        }
                    }
                    else if (vehicleState != null)
                    {
#if DEBUG
                        //bool debug = destinationNodeId == 10864;
                        //bool debug = destinationNodeId == 13531;
                        //bool debug = false;// targetNodeId == 5027;
#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 {targetNodeId} which is not a traffic light.");
                        }
#endif

                        var prioritySegment = TrafficPriority.GetPrioritySegment(targetNodeId, 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 {targetNodeId} 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 DEBUG
                            if (debug)
                            {
                                Log._Debug($"Vehicle {vehicleId}: global target position found. carState = {vehicleState.JunctionTransitState.ToString()}");
                            }
#endif
                            var   currentFrameIndex2 = Singleton <SimulationManager> .instance.m_currentFrameIndex;
                            var   frame = currentFrameIndex2 >> 4;
                            float speed = lastFrameData.m_velocity.magnitude;

                            if (vehicleState.JunctionTransitState == VehicleJunctionTransitState.None)
                            {
#if DEBUG
                                if (debug)
                                {
                                    Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to ENTER (prio)");
                                }
#endif
                                vehicleState.JunctionTransitState = VehicleJunctionTransitState.Enter;
                            }

                            if (vehicleState.JunctionTransitState != VehicleJunctionTransitState.Leave)
                            {
                                bool hasIncomingCars;
                                switch (prioritySegment.Type)
                                {
                                case SegmentEnd.PriorityType.Stop:
#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"Vehicle {vehicleId}: STOP sign. waittime={vehicleState.WaitTime}, vel={speed}");
                                    }
#endif

                                    if (Options.simAccuracy <= 2 || (Options.simAccuracy >= 3 && vehicleState.WaitTime < MaxPriorityWaitTime))
                                    {
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to STOP (wait)");
                                        }
#endif
                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Stop;

                                        if (speed <= TrafficPriority.maxStopVelocity)
                                        {
                                            vehicleState.WaitTime++;

                                            float minStopWaitTime = UnityEngine.Random.Range(0f, 3f);
                                            if (vehicleState.WaitTime >= minStopWaitTime)
                                            {
                                                if (Options.simAccuracy >= 4)
                                                {
                                                    vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                                }
                                                else
                                                {
                                                    hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, ref vehicleData, ref prevPos, ref position);
#if DEBUG
                                                    if (debug)
                                                    {
                                                        Log._Debug($"hasIncomingCars: {hasIncomingCars}");
                                                    }
#endif

                                                    if (hasIncomingCars)
                                                    {
                                                        maxSpeed = 0f;
                                                        return(false);
                                                    }
#if DEBUG
                                                    if (debug)
                                                    {
                                                        Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (min wait timeout)");
                                                    }
#endif
                                                    vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                                }
                                            }
                                            else
                                            {
                                                maxSpeed = 0;
                                                return(false);
                                            }
                                        }
                                        else
                                        {
                                            vehicleState.WaitTime = 0;
                                            maxSpeed = 0f;
                                            return(false);
                                        }
                                    }
                                    else
                                    {
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (max wait timeout)");
                                        }
#endif
                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                    }
                                    break;

                                case SegmentEnd.PriorityType.Yield:
#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"Vehicle {vehicleId}: YIELD sign. waittime={vehicleState.WaitTime}");
                                    }
#endif

                                    if (Options.simAccuracy <= 2 || (Options.simAccuracy >= 3 && vehicleState.WaitTime < MaxPriorityWaitTime))
                                    {
                                        vehicleState.WaitTime++;
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to STOP (wait)");
                                        }
#endif
                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Stop;

                                        if (speed <= TrafficPriority.maxYieldVelocity || Options.simAccuracy <= 2)
                                        {
                                            if (Options.simAccuracy >= 4)
                                            {
                                                vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                            }
                                            else
                                            {
                                                hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, ref vehicleData, ref prevPos, ref position);
#if DEBUG
                                                if (debug)
                                                {
                                                    Log._Debug($"Vehicle {vehicleId}: hasIncomingCars: {hasIncomingCars}");
                                                }
#endif

                                                if (hasIncomingCars)
                                                {
                                                    maxSpeed = 0f;
                                                    return(false);
                                                }
                                                else
                                                {
#if DEBUG
                                                    if (debug)
                                                    {
                                                        Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (no incoming cars)");
                                                    }
#endif
                                                    vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                                }
                                            }
                                        }
                                        else
                                        {
#if DEBUG
                                            if (debug)
                                            {
                                                Log._Debug($"Vehicle {vehicleId}: Vehicle has not yet reached yield speed (reduce {speed} by {vehicleState.ReduceSpeedByValueToYield})");
                                            }
#endif

                                            // vehicle has not yet reached yield speed
                                            maxSpeed = TrafficPriority.maxYieldVelocity;
                                            return(false);
                                        }
                                    }
                                    else
                                    {
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (max wait timeout)");
                                        }
#endif
                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                    }
                                    break;

                                case SegmentEnd.PriorityType.Main:
                                case SegmentEnd.PriorityType.None:
#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"Vehicle {vehicleId}: MAIN sign. waittime={vehicleState.WaitTime}");
                                    }
#endif
                                    maxSpeed = 0f;

                                    if (Options.simAccuracy == 4)
                                    {
                                        return(true);
                                    }

                                    if (Options.simAccuracy <= 2 || (Options.simAccuracy == 3 && vehicleState.WaitTime < MaxPriorityWaitTime))
                                    {
                                        vehicleState.WaitTime++;
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to STOP (wait)");
                                        }
#endif
                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Stop;

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

                                        if (hasIncomingCars)
                                        {
                                            return(false);
                                        }
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (no conflicting car)");
                                        }
#endif
                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                    }
                                    return(true);
                                }
                            }
                            else if (speed <= TrafficPriority.maxStopVelocity)
                            {
                                // vehicle is not moving. reset allowance to leave junction
#if DEBUG
                                if (debug)
                                {
                                    Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState from LEAVE to BLOCKED (speed to low)");
                                }
#endif
                                vehicleState.JunctionTransitState = VehicleJunctionTransitState.Blocked;

                                maxSpeed = 0f;
                                return(false);
                            }
                        }
                    }
                }
            } catch (Exception e) {
                Log.Error($"Error occured in MayChangeSegment: {e.ToString()}");
            }
            maxSpeed = 0f;             // maxSpeed should be set by caller
            return(true);
        }
        public void TmCalculateSegmentPosition(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)
        {
            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);

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

            if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car)
            {
                // add vehicle to our vehicle list
                if (!TrafficPriority.VehicleList.ContainsKey(vehicleId))
                {
                    TrafficPriority.VehicleList.Add(vehicleId, new PriorityCar());
                }
            }

            HandleVehicle(vehicleId, ref vehicleData);

            // 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 interestingNodeId = 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 == interestingNodeId)
            {
                if (Vector3.Distance(lastFrameVehiclePos, vehiclePosOnBezier) >= crazyValue - 1f)
                {
                    var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
                    var num5 = (uint)((interestingNodeId << 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;
                    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;
                            }
                        }
                    }

                    if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car)
                    {
                        if (hasTrafficLight && (!isJoinedJunction || hasCrossing))
                        {
                            var nodeSimulation = TrafficPriority.GetNodeSimulation(interestingNodeId);

                            var destinationInfo = netManager.m_nodes.m_buffer[destinationNodeId].Info;
                            RoadBaseAI.TrafficLightState vehicleLightState;
                            ManualSegmentLight           light = TrafficLightsManual.GetSegmentLight(interestingNodeId, prevPos.m_segment);                   // TODO rework

                            if (light == null || nodeSimulation == null ||
                                (nodeSimulation.FlagTimedTrafficLights && !nodeSimulation.TimedTrafficLightsActive))
                            {
                                RoadBaseAI.TrafficLightState pedestrianLightState;
                                bool flag5;
                                bool pedestrians;
                                RoadBaseAI.GetTrafficLightState(interestingNodeId,
                                                                ref netManager.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(interestingNodeId,
                                                                    ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - num5,
                                                                    vehicleLightState, pedestrianLightState, flag5, pedestrians);
                                }

                                if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == Vehicle.Flags.None ||
                                    destinationInfo.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
                            {
                                // traffic light simulation is active
                                var stopCar = false;

                                // determine responsible traffic light (left, right or main)
                                if (TrafficPriority.IsLeftSegment(prevPos.m_segment, position.m_segment, destinationNodeId))
                                {
                                    vehicleLightState = light.GetLightLeft();
                                }
                                else if (TrafficPriority.IsRightSegment(prevPos.m_segment, position.m_segment, destinationNodeId))
                                {
                                    vehicleLightState = light.GetLightRight();
                                }
                                else
                                {
                                    vehicleLightState = light.GetLightMain();
                                }

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

                                    if (hasIncomingCars)
                                    {
                                        // green light but other cars are incoming: slow approach
                                        maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f) * 0.01f;
                                        //stopCar = true;
                                    }
                                }

                                if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == Vehicle.Flags.None ||
                                    destinationInfo.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 (TrafficPriority.VehicleList.ContainsKey(vehicleId) &&
                                TrafficPriority.IsPrioritySegment(destinationNodeId, prevPos.m_segment))
                            {
                                var currentFrameIndex2 = Singleton <SimulationManager> .instance.m_currentFrameIndex;
                                var frame = currentFrameIndex2 >> 4;

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

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

                                if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == Vehicle.Flags.None &&
                                    TrafficPriority.VehicleList[vehicleId].CarState != CarState.Leave)
                                {
                                    bool hasIncomingCars;
                                    switch (prioritySegment.Type)
                                    {
                                    case PrioritySegment.PriorityType.Stop:
                                        if (TrafficPriority.VehicleList[vehicleId].WaitTime < 75)
                                        {
                                            TrafficPriority.VehicleList[vehicleId].CarState = CarState.Stop;

                                            if (lastFrameData.m_velocity.sqrMagnitude < 0.1f ||
                                                TrafficPriority.VehicleList[vehicleId].Stopped)
                                            {
                                                TrafficPriority.VehicleList[vehicleId].Stopped = true;
                                                TrafficPriority.VehicleList[vehicleId].WaitTime++;

                                                if (TrafficPriority.VehicleList[vehicleId].WaitTime > 2)
                                                {
                                                    hasIncomingCars = TrafficPriority.HasIncomingVehicles(vehicleId, destinationNodeId);

                                                    if (hasIncomingCars)
                                                    {
                                                        maxSpeed = 0f;
                                                        return;
                                                    }
                                                    TrafficPriority.VehicleList[vehicleId].CarState =
                                                        CarState.Leave;
                                                }
                                                else
                                                {
                                                    maxSpeed = 0f;
                                                    return;
                                                }
                                            }
                                            else
                                            {
                                                maxSpeed = 0f;
                                                return;
                                            }
                                        }
                                        else
                                        {
                                            TrafficPriority.VehicleList[vehicleId].CarState = CarState.Leave;
                                        }
                                        break;

                                    case PrioritySegment.PriorityType.Yield:
                                        if (TrafficPriority.VehicleList[vehicleId].WaitTime < 75)
                                        {
                                            TrafficPriority.VehicleList[vehicleId].WaitTime++;
                                            TrafficPriority.VehicleList[vehicleId].CarState = CarState.Stop;
                                            maxSpeed = 0f;

                                            if (lastFrameData.m_velocity.sqrMagnitude <
                                                TrafficPriority.VehicleList[vehicleId].ReduceSpeedByValueToYield)
                                            {
                                                hasIncomingCars = TrafficPriority.HasIncomingVehicles(vehicleId, destinationNodeId);

                                                if (hasIncomingCars)
                                                {
                                                    return;
                                                }
                                            }
                                            else
                                            {
                                                maxSpeed = lastFrameData.m_velocity.sqrMagnitude -
                                                           TrafficPriority.VehicleList[vehicleId]
                                                           .ReduceSpeedByValueToYield;
                                                return;
                                            }
                                        }
                                        else
                                        {
                                            TrafficPriority.VehicleList[vehicleId].CarState = CarState.Leave;
                                        }
                                        break;

                                    case PrioritySegment.PriorityType.Main:
                                        TrafficPriority.VehicleList[vehicleId].WaitTime++;
                                        TrafficPriority.VehicleList[vehicleId].CarState = CarState.Stop;
                                        maxSpeed = 0f;

                                        hasIncomingCars = TrafficPriority.HasIncomingVehicles(vehicleId, destinationNodeId);

                                        if (hasIncomingCars)
                                        {
                                            TrafficPriority.VehicleList[vehicleId].Stopped = true;
                                            return;
                                        }
                                        TrafficPriority.VehicleList[vehicleId].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;
                                        }
                                        else
                                        {
                                            maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f) *
                                                       0.8f;
                                        }
                                        return;
                                    }
                                }
                                else
                                {
                                    TrafficPriority.VehicleList[vehicleId].CarState = CarState.Transit;
                                }
                            }
                        }
                    }
                }
            }

            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 = 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,
                                                netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve);
            }
            else
            {
                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
            }
        }
コード例 #36
0
		public static void GetTrafficLightState(ushort vehicleId, ref Vehicle vehicleData, ushort nodeId, ushort fromSegmentId, ushort toSegmentId, ref NetSegment segmentData, uint frame, out RoadBaseAI.TrafficLightState vehicleLightState, out RoadBaseAI.TrafficLightState pedestrianLightState, out bool vehicles, out bool pedestrians) {
			TrafficLightSimulation nodeSim = TrafficLightSimulation.GetNodeSimulation(nodeId);
			if (nodeSim == null || !nodeSim.IsSimulationActive()) {
				RoadBaseAI.GetTrafficLightState(nodeId, ref segmentData, frame, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians);
			} else {
				GetCustomTrafficLightState(vehicleId, ref vehicleData, nodeId, fromSegmentId, toSegmentId, out vehicleLightState, out pedestrianLightState, nodeSim);
				vehicles = false;
				pedestrians = false;
			}
		}
コード例 #37
0
		private static void GetCustomTrafficLightState(ushort vehicleId, ref Vehicle vehicleData, ushort nodeId, ushort fromSegmentId, ushort toSegmentId, out RoadBaseAI.TrafficLightState vehicleLightState, out RoadBaseAI.TrafficLightState pedestrianLightState, TrafficLightSimulation nodeSim = null) {
			if (nodeSim == null) {
				nodeSim = TrafficLightSimulation.GetNodeSimulation(nodeId);
				if (nodeSim == null) {
					Log.Error($"GetCustomTrafficLightState: node traffic light simulation not found at node {nodeId}! Vehicle {vehicleId} comes from segment {fromSegmentId} and goes to node {nodeId}");
					throw new ApplicationException($"GetCustomTrafficLightState: node traffic light simulation not found at node {nodeId}! Vehicle {vehicleId} comes from segment {fromSegmentId} and goes to node {nodeId}");
				}
			}

			// get vehicle position
			/*VehiclePosition vehiclePos = TrafficPriority.GetVehiclePosition(vehicleId);
			if (!vehiclePos.Valid || vehiclePos.FromSegment != fromSegmentId || vehiclePos.ToNode != nodeId) {
				Log._Debug($"GetTrafficLightState: Recalculating position for vehicle {vehicleId}! FromSegment={vehiclePos.FromSegment} Valid={vehiclePos.Valid}");
				try {
					HandleVehicle(vehicleId, ref Singleton<VehicleManager>.instance.m_vehicles.m_buffer[vehicleId], false, false);
				} catch (Exception e) {
					Log.Error("VehicleAI GetTrafficLightState Error: " + e.ToString());
				}
			}

			if (!vehiclePos.Valid || vehiclePos.FromSegment != fromSegmentId || vehiclePos.ToNode != nodeId) {
				Log.Warning($"GetTrafficLightState: Vehicle {vehicleId} is not moving at segment {fromSegmentId} to node {nodeId}! FromSegment={vehiclePos.FromSegment} ToNode={vehiclePos.ToNode} Valid={vehiclePos.Valid}");
				vehicleLightState = RoadBaseAI.TrafficLightState.Red;
				pedestrianLightState = RoadBaseAI.TrafficLightState.Red;
				return;
			}*/

			// get vehicle type
			ExtVehicleType? vehicleType = CustomVehicleAI.DetermineVehicleTypeFromVehicle(vehicleId, ref vehicleData);
			if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Tram && vehicleType != ExtVehicleType.Tram)
				Log.Warning($"vehicleType={vehicleType} ({(int)vehicleType}) for Tram");
			//Log._Debug($"GetCustomTrafficLightState: Vehicle {vehicleId} is a {vehicleType}");
			if (vehicleType == null) {
				Log.Warning($"GetTrafficLightState: Could not determine vehicle type of vehicle {vehicleId}!");
				vehicleLightState = RoadBaseAI.TrafficLightState.Red;
				pedestrianLightState = RoadBaseAI.TrafficLightState.Red;
				return;
			}

			// get responsible traffic light
			CustomSegmentLights lights = CustomTrafficLights.GetSegmentLights(nodeId, fromSegmentId);
			CustomSegmentLight light = lights == null ? null : lights.GetCustomLight((ExtVehicleType)vehicleType);
			if (lights == null || light == null) {
				Log.Warning($"GetTrafficLightState: No custom light for vehicleType {vehicleType} @ node {nodeId}, segment {fromSegmentId} found. lights null? {lights == null} light null? {light == null}");
				vehicleLightState = RoadBaseAI.TrafficLightState.Red;
				pedestrianLightState = RoadBaseAI.TrafficLightState.Red;
				return;
			}

			SegmentGeometry geometry = CustomRoadAI.GetSegmentGeometry(fromSegmentId);

			// get traffic light state from responsible traffic light
			if (geometry.IsLeftSegment(toSegmentId, nodeId)) {
				vehicleLightState = light.GetLightLeft();
			} else if (geometry.IsRightSegment(toSegmentId, nodeId)) {
				vehicleLightState = light.GetLightRight();
			} else {
				vehicleLightState = light.GetLightMain();
			}

			// get traffic lights state for pedestrians
			pedestrianLightState = (lights.PedestrianLightState != null) ? (RoadBaseAI.TrafficLightState)lights.PedestrianLightState : RoadBaseAI.TrafficLightState.Red;
		}
コード例 #38
0
		public CustomSegmentLights(ushort nodeId, ushort segmentId, RoadBaseAI.TrafficLightState mainState) {
			this.nodeId = nodeId;
			this.segmentId = segmentId;
			PedestrianLightState = null;
			OnChange();

			RoadBaseAI.TrafficLightState pedState = mainState == RoadBaseAI.TrafficLightState.Green
				? RoadBaseAI.TrafficLightState.Red
				: RoadBaseAI.TrafficLightState.Green;
			housekeeping(false, mainState, mainState, mainState, pedState);
		}
コード例 #39
0
		private RoadBaseAI.TrafficLightState calcLightState(RoadBaseAI.TrafficLightState previousState, RoadBaseAI.TrafficLightState currentState, RoadBaseAI.TrafficLightState nextState, bool atStartTransition, bool atEndTransition) {
			if (atStartTransition && currentState == RoadBaseAI.TrafficLightState.Green && previousState == RoadBaseAI.TrafficLightState.Red)
				return RoadBaseAI.TrafficLightState.RedToGreen;
			else if (atEndTransition && currentState == RoadBaseAI.TrafficLightState.Green && nextState == RoadBaseAI.TrafficLightState.Red)
				return RoadBaseAI.TrafficLightState.GreenToRed;
			else
				return currentState;
		}
		private RoadBaseAI.TrafficLightState invertLight(RoadBaseAI.TrafficLightState light) {
			switch (light) {
				case RoadBaseAI.TrafficLightState.Red:
				case RoadBaseAI.TrafficLightState.GreenToRed:
					return RoadBaseAI.TrafficLightState.Green;
				case RoadBaseAI.TrafficLightState.Green:
				case RoadBaseAI.TrafficLightState.RedToGreen:
				default:
					return RoadBaseAI.TrafficLightState.Red;
			}
		}
コード例 #41
0
 public static void AddSegmentLight(ushort nodeID, int segmentID, RoadBaseAI.TrafficLightState light)
 {
     if (ManualSegments.ContainsKey(segmentID))
     {
         ManualSegments[segmentID].node_2 = nodeID;
         ManualSegments[segmentID].instance_2 = new ManualSegmentLight(nodeID, segmentID, light);
     }
     else
     {
         ManualSegments.Add(segmentID, new ManualSegment());
         ManualSegments[segmentID].node_1 = nodeID;
         ManualSegments[segmentID].instance_1 = new ManualSegmentLight(nodeID, segmentID, light);
     }
 }
コード例 #42
0
        public override void SimulationStep(ushort segmentID, ref NetSegment data)
        {
            //Start PlayerNEtAI.SimulationStep

            if (this.HasMaintenanceCost(segmentID, ref data))
            {
                NetManager playerNetAIinstance  = Singleton <NetManager> .instance;
                Vector3    playerNetAIposition  = playerNetAIinstance.m_nodes.m_buffer[(int)data.m_startNode].m_position;
                Vector3    playerNetAIposition2 = playerNetAIinstance.m_nodes.m_buffer[(int)data.m_endNode].m_position;
                int        playerNetAInum       = this.GetMaintenanceCost(playerNetAIposition, playerNetAIposition2);
                bool       playerNetAIflag      = (ulong)(Singleton <SimulationManager> .instance.m_currentFrameIndex >> 8 & 15u) == (ulong)((long)(segmentID & 15));
                if (playerNetAInum != 0)
                {
                    if (playerNetAIflag)
                    {
                        playerNetAInum = playerNetAInum * 16 / 100 - playerNetAInum / 100 * 15;
                    }
                    else
                    {
                        playerNetAInum /= 100;
                    }
                    Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.Maintenance, playerNetAInum, this.m_info.m_class);
                }
                if (playerNetAIflag)
                {
                    float playerNetAInum2 = (float)playerNetAIinstance.m_nodes.m_buffer[(int)data.m_startNode].m_elevation;
                    float playerNetAInum3 = (float)playerNetAIinstance.m_nodes.m_buffer[(int)data.m_endNode].m_elevation;
                    if (this.IsUnderground())
                    {
                        playerNetAInum2 = -playerNetAInum2;
                        playerNetAInum3 = -playerNetAInum3;
                    }
                    int constructionCost = this.GetConstructionCost(playerNetAIposition, playerNetAIposition2, playerNetAInum2, playerNetAInum3);
                    if (constructionCost != 0)
                    {
                        StatisticBase statisticBase = Singleton <StatisticsManager> .instance.Acquire <StatisticInt64>(StatisticType.CityValue);

                        if (statisticBase != null)
                        {
                            statisticBase.Add(constructionCost);
                        }
                    }
                }
            }
            //End  PlayerNEtAI.SimulationStep


            SimulationManager instance  = Singleton <SimulationManager> .instance;
            NetManager        instance2 = Singleton <NetManager> .instance;

            Notification.Problem problem = Notification.RemoveProblems(data.m_problems, Notification.Problem.Flood | Notification.Problem.Snow);
            if ((data.m_flags & NetSegment.Flags.AccessFailed) != NetSegment.Flags.None && Singleton <SimulationManager> .instance.m_randomizer.Int32(16u) == 0)
            {
                data.m_flags &= ~NetSegment.Flags.AccessFailed;
            }
            float num  = 0f;
            uint  num2 = data.m_lanes;
            int   num3 = 0;

            while (num3 < this.m_info.m_lanes.Length && num2 != 0u)
            {
                NetInfo.Lane lane = this.m_info.m_lanes[num3];
                if ((byte)(lane.m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0 && (lane.m_vehicleType & ~VehicleInfo.VehicleType.Bicycle) != VehicleInfo.VehicleType.None)
                {
                    num += instance2.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_length;
                }
                num2 = instance2.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_nextLane;
                num3++;
            }
            int num4 = 0;

            if (data.m_trafficBuffer == 65535)
            {
                if ((data.m_flags & NetSegment.Flags.Blocked) == NetSegment.Flags.None)
                {
                    data.m_flags        |= NetSegment.Flags.Blocked;
                    data.m_modifiedIndex = instance.m_currentBuildIndex++;
                }
            }
            else
            {
                data.m_flags &= ~NetSegment.Flags.Blocked;
                int num5 = Mathf.RoundToInt(num) << 4;
                if (num5 != 0)
                {
                    num4 = (int)((byte)Mathf.Min((int)(data.m_trafficBuffer * 100) / num5, 100));
                }
            }
            data.m_trafficBuffer = 0;
            if (num4 > (int)data.m_trafficDensity)
            {
                data.m_trafficDensity = (byte)Mathf.Min((int)(data.m_trafficDensity + 5), num4);
            }
            else if (num4 < (int)data.m_trafficDensity)
            {
                data.m_trafficDensity = (byte)Mathf.Max((int)(data.m_trafficDensity - 5), num4);
            }
            Vector3 position  = instance2.m_nodes.m_buffer[(int)data.m_startNode].m_position;
            Vector3 position2 = instance2.m_nodes.m_buffer[(int)data.m_endNode].m_position;
            Vector3 vector    = (position + position2) * 0.5f;
            bool    flag      = false;

            if ((this.m_info.m_setVehicleFlags & Vehicle.Flags.Underground) == (Vehicle.Flags) 0)
            {
                float num6 = Singleton <TerrainManager> .instance.WaterLevel(VectorUtils.XZ(vector));

                // NON-STOCK CODE START
                if (num6 > vector.y + (float)ModSettings.RoadwayFloodedTolerance / 100)
                {
                    flag          = true;
                    data.m_flags |= NetSegment.Flags.Flooded;
                    //Debug.Log("[RF] Successfully detoured roadway flooded tolerance");
                    problem = Notification.AddProblems(problem, Notification.Problem.Flood | Notification.Problem.MajorProblem);

                    /*DisasterData floodedSinkHoleData = new DisasterData();
                     * floodedSinkHoleData.m_targetPosition = data.m_middlePosition;
                     * floodedSinkHoleData.m_intensity = (byte)instance.m_randomizer.Int32(100u);
                     */
                    Vector3 min = data.m_bounds.min;
                    Vector3 max = data.m_bounds.max;
                    RoadBaseAI.FloodParkedCars(min.x, min.z, max.x, max.z);
                }

                else
                {
                    data.m_flags &= ~NetSegment.Flags.Flooded;

                    // Rainfall compatibility
                    float add = (float)ModSettings.RoadwayFloodingTolerance / 100;
                    //Debug.Log("[RF] Successfully detoured roadway flooding tolerance");
                    if (num6 > vector.y + add)
                    {
                        flag    = true;
                        problem = Notification.AddProblems(problem, Notification.Problem.Flood);
                    }
                }
                //Debug.Log("[RF] Successfully detoured roadway flooding tolerance: not flooding");
                // NON-STOCK CODE END
            }
            DistrictManager instance3 = Singleton <DistrictManager> .instance;
            byte            district  = instance3.GetDistrict(vector);

            DistrictPolicies.CityPlanning cityPlanningPolicies = instance3.m_districts.m_buffer[(int)district].m_cityPlanningPolicies;
            int num7 = (int)(100 - (data.m_trafficDensity - 100) * (data.m_trafficDensity - 100) / 100);

            if ((this.m_info.m_vehicleTypes & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None)
            {
                if ((this.m_info.m_setVehicleFlags & Vehicle.Flags.Underground) == (Vehicle.Flags) 0)
                {
                    if (flag && (data.m_flags & (NetSegment.Flags.AccessFailed | NetSegment.Flags.Blocked)) == NetSegment.Flags.None && instance.m_randomizer.Int32(10u) == 0)
                    {
                        TransferManager.TransferOffer offer = default(TransferManager.TransferOffer);
                        offer.Priority   = 4;
                        offer.NetSegment = segmentID;
                        offer.Position   = vector;
                        offer.Amount     = 1;
                        Singleton <TransferManager> .instance.AddOutgoingOffer(TransferManager.TransferReason.FloodWater, offer);
                    }
                    int num8 = (int)data.m_wetness;
                    if (!instance2.m_treatWetAsSnow)
                    {
                        if (flag)
                        {
                            num8 = 255;
                        }
                        else
                        {
                            int   num9  = -(num8 + 63 >> 5);
                            float num10 = Singleton <WeatherManager> .instance.SampleRainIntensity(vector, false);

                            if (num10 != 0f)
                            {
                                int num11 = Mathf.RoundToInt(Mathf.Min(num10 * 4000f, 1000f));
                                num9 += instance.m_randomizer.Int32(num11, num11 + 99) / 100;
                            }
                            num8 = Mathf.Clamp(num8 + num9, 0, 255);
                        }
                    }
                    else if (this.m_accumulateSnow)
                    {
                        if (flag)
                        {
                            num8 = 128;
                        }
                        else
                        {
                            float num12 = Singleton <WeatherManager> .instance.SampleRainIntensity(vector, false);

                            if (num12 != 0f)
                            {
                                int num13 = Mathf.RoundToInt(num12 * 400f);
                                int num14 = instance.m_randomizer.Int32(num13, num13 + 99) / 100;
                                if (Singleton <UnlockManager> .instance.Unlocked(UnlockManager.Feature.Snowplow))
                                {
                                    num8 = Mathf.Min(num8 + num14, 255);
                                }
                                else
                                {
                                    num8 = Mathf.Min(num8 + num14, 128);
                                }
                            }
                            else if (Singleton <SimulationManager> .instance.m_randomizer.Int32(4u) == 0)
                            {
                                num8 = Mathf.Max(num8 - 1, 0);
                            }
                            if (num8 >= 64 && (data.m_flags & (NetSegment.Flags.AccessFailed | NetSegment.Flags.Blocked | NetSegment.Flags.Flooded)) == NetSegment.Flags.None && instance.m_randomizer.Int32(10u) == 0)
                            {
                                TransferManager.TransferOffer offer2 = default(TransferManager.TransferOffer);
                                offer2.Priority   = num8 / 50;
                                offer2.NetSegment = segmentID;
                                offer2.Position   = vector;
                                offer2.Amount     = 1;
                                Singleton <TransferManager> .instance.AddOutgoingOffer(TransferManager.TransferReason.Snow, offer2);
                            }
                            if (num8 >= 192)
                            {
                                problem = Notification.AddProblems(problem, Notification.Problem.Snow);
                            }
                            District[] expr_5B7_cp_0_cp_0 = instance3.m_districts.m_buffer;
                            byte       expr_5B7_cp_0_cp_1 = district;
                            expr_5B7_cp_0_cp_0[(int)expr_5B7_cp_0_cp_1].m_productionData.m_tempSnowCover = expr_5B7_cp_0_cp_0[(int)expr_5B7_cp_0_cp_1].m_productionData.m_tempSnowCover + (uint)num8;
                        }
                    }
                    if (num8 != (int)data.m_wetness)
                    {
                        if (Mathf.Abs((int)data.m_wetness - num8) > 10)
                        {
                            data.m_wetness = (byte)num8;
                            InstanceID empty = InstanceID.Empty;
                            empty.NetSegment = segmentID;
                            instance2.AddSmoothColor(empty);
                            empty.NetNode = data.m_startNode;
                            instance2.AddSmoothColor(empty);
                            empty.NetNode = data.m_endNode;
                            instance2.AddSmoothColor(empty);
                        }
                        else
                        {
                            data.m_wetness             = (byte)num8;
                            instance2.m_wetnessChanged = 256;
                        }
                    }
                }
                int num15;
                if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.StuddedTires) != DistrictPolicies.CityPlanning.None)
                {
                    num7  = num7 * 3 + 1 >> 1;
                    num15 = Mathf.Min(700, (int)(50 + data.m_trafficDensity * 6));
                }
                else
                {
                    num15 = Mathf.Min(500, (int)(50 + data.m_trafficDensity * 4));
                }
                if (!this.m_highwayRules)
                {
                    int num16 = instance.m_randomizer.Int32(num15, num15 + 99) / 100;
                    data.m_condition = (byte)Mathf.Max((int)data.m_condition - num16, 0);
                    if (data.m_condition < 192 && (data.m_flags & (NetSegment.Flags.AccessFailed | NetSegment.Flags.Blocked | NetSegment.Flags.Flooded)) == NetSegment.Flags.None && instance.m_randomizer.Int32(20u) == 0)
                    {
                        TransferManager.TransferOffer offer3 = default(TransferManager.TransferOffer);
                        offer3.Priority   = (int)((255 - data.m_condition) / 50);
                        offer3.NetSegment = segmentID;
                        offer3.Position   = vector;
                        offer3.Amount     = 1;
                        Singleton <TransferManager> .instance.AddIncomingOffer(TransferManager.TransferReason.RoadMaintenance, offer3);
                    }
                }
            }
            if (!this.m_highwayRules)
            {
                if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.HeavyTrafficBan) != DistrictPolicies.CityPlanning.None)
                {
                    data.m_flags |= NetSegment.Flags.HeavyBan;
                }
                else
                {
                    data.m_flags &= ~NetSegment.Flags.HeavyBan;
                }
                if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.BikeBan) != DistrictPolicies.CityPlanning.None)
                {
                    data.m_flags |= NetSegment.Flags.BikeBan;
                }
                else
                {
                    data.m_flags &= ~NetSegment.Flags.BikeBan;
                }
                if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.OldTown) != DistrictPolicies.CityPlanning.None)
                {
                    data.m_flags |= NetSegment.Flags.CarBan;
                }
                else
                {
                    data.m_flags &= ~NetSegment.Flags.CarBan;
                }
            }
            int num17 = this.m_noiseAccumulation * num7 / 100;

            if (num17 != 0)
            {
                float num18 = Vector3.Distance(position, position2);
                int   num19 = Mathf.FloorToInt(num18 / this.m_noiseRadius);
                for (int i = 0; i < num19; i++)
                {
                    Vector3 position3 = Vector3.Lerp(position, position2, (float)(i + 1) / (float)(num19 + 1));
                    Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.NoisePollution, num17, position3, this.m_noiseRadius);
                }
            }
            if (data.m_trafficDensity >= 50 && data.m_averageLength < 25f && (instance2.m_nodes.m_buffer[(int)data.m_startNode].m_flags & (NetNode.Flags.LevelCrossing | NetNode.Flags.TrafficLights)) == NetNode.Flags.TrafficLights && (instance2.m_nodes.m_buffer[(int)data.m_endNode].m_flags & (NetNode.Flags.LevelCrossing | NetNode.Flags.TrafficLights)) == NetNode.Flags.TrafficLights)
            {
                GuideController properties = Singleton <GuideManager> .instance.m_properties;
                if (properties != null)
                {
                    Singleton <NetManager> .instance.m_shortRoadTraffic.Activate(properties.m_shortRoadTraffic, segmentID);
                }
            }
            if ((data.m_flags & NetSegment.Flags.Collapsed) != NetSegment.Flags.None)
            {
                GuideController properties2 = Singleton <GuideManager> .instance.m_properties;
                if (properties2 != null)
                {
                    Singleton <NetManager> .instance.m_roadDestroyed.Activate(properties2.m_roadDestroyed, segmentID);

                    Singleton <NetManager> .instance.m_roadDestroyed2.Activate(properties2.m_roadDestroyed2, this.m_info.m_class.m_service);
                }
                if ((ulong)(instance.m_currentFrameIndex >> 8 & 15u) == (ulong)((long)(segmentID & 15)))
                {
                    int           delta         = Mathf.RoundToInt(data.m_averageLength);
                    StatisticBase statisticBase = Singleton <StatisticsManager> .instance.Acquire <StatisticInt32>(StatisticType.DestroyedLength);

                    statisticBase.Add(delta);
                }
            }
            data.m_problems = problem;
        }
コード例 #43
0
        public static bool Prefix(ushort nodeID,
                                  ref NetNode nodeData,
                                  ushort segmentID,
                                  ref NetSegment segmentData,
                                  ref NetNode.Flags flags,
                                  ref Color color)
        {
            if (!Options.timedLightsEnabled ||
                !Constants.ManagerFactory
                .TrafficLightSimulationManager
                .TrafficLightSimulations[nodeID]
                .IsSimulationRunning())
            {
                return(true);
            }

            uint frame    = Singleton <SimulationManager> .instance.m_referenceFrameIndex - 15u;
            uint simGroup = (uint)nodeID >> 7;

            RoadBaseAI.TrafficLightState vehicleLightState;
            RoadBaseAI.TrafficLightState pedLightState;
            RoadBaseAI.GetTrafficLightState(
                nodeID,
                ref segmentData,
                frame - simGroup,
                out vehicleLightState,
                out pedLightState);

            color.a = 0.5f;
            switch (vehicleLightState)
            {
            case RoadBaseAI.TrafficLightState.Green:
                color.g = 1f;
                break;

            case RoadBaseAI.TrafficLightState.RedToGreen:
                color.r = 1f;
                break;

            case RoadBaseAI.TrafficLightState.Red:
                color.g = 0f;
                break;

            case RoadBaseAI.TrafficLightState.GreenToRed:
                color.r = 1f;
                break;
            }

            switch (pedLightState)
            {
            case RoadBaseAI.TrafficLightState.Green:
                color.b = 1f;
                break;

            case RoadBaseAI.TrafficLightState.RedToGreen:
                color.b = 0f;
                break;

            case RoadBaseAI.TrafficLightState.Red:
                color.b = 0f;
                break;

            case RoadBaseAI.TrafficLightState.GreenToRed:
                color.b = 0f;
                break;
            }

            return(false);
        }
コード例 #44
0
		public static void OriginalSetTrafficLightState(bool customCall, ushort nodeID, ref NetSegment segmentData, uint frame, RoadBaseAI.TrafficLightState vehicleLightState, RoadBaseAI.TrafficLightState pedestrianLightState, bool vehicles, bool pedestrians) {
			/// NON-STOCK CODE START ///
			TrafficLightSimulation nodeSim = TrafficLightSimulation.GetNodeSimulation(nodeID);
			if (nodeSim == null || !nodeSim.IsSimulationActive() || customCall) {
			/// NON-STOCK CODE END ///
				int num = (int)pedestrianLightState << 2 | (int)vehicleLightState;
				if (segmentData.m_startNode == nodeID) {
					if ((frame >> 8 & 1u) == 0u) {
						segmentData.m_trafficLightState0 = (byte)((int)(segmentData.m_trafficLightState0 & 240) | num);
					} else {
						segmentData.m_trafficLightState1 = (byte)((int)(segmentData.m_trafficLightState1 & 240) | num);
					}
					if (vehicles) {
						segmentData.m_flags |= NetSegment.Flags.TrafficStart;
					} else {
						segmentData.m_flags &= ~NetSegment.Flags.TrafficStart;
					}
					if (pedestrians) {
						segmentData.m_flags |= NetSegment.Flags.CrossingStart;
					} else {
						segmentData.m_flags &= ~NetSegment.Flags.CrossingStart;
					}
				} else {
					if ((frame >> 8 & 1u) == 0u) {
						segmentData.m_trafficLightState0 = (byte)((int)(segmentData.m_trafficLightState0 & 15) | num << 4);
					} else {
						segmentData.m_trafficLightState1 = (byte)((int)(segmentData.m_trafficLightState1 & 15) | num << 4);
					}
					if (vehicles) {
						segmentData.m_flags |= NetSegment.Flags.TrafficEnd;
					} else {
						segmentData.m_flags &= ~NetSegment.Flags.TrafficEnd;
					}
					if (pedestrians) {
						segmentData.m_flags |= NetSegment.Flags.CrossingEnd;
					} else {
						segmentData.m_flags &= ~NetSegment.Flags.CrossingEnd;
					}
				}
			} // NON-STOCK CODE
		}
コード例 #45
0
		internal void housekeeping(bool mayDelete, RoadBaseAI.TrafficLightState mainState = RoadBaseAI.TrafficLightState.Red, RoadBaseAI.TrafficLightState leftState = RoadBaseAI.TrafficLightState.Red, RoadBaseAI.TrafficLightState rightState = RoadBaseAI.TrafficLightState.Red, RoadBaseAI.TrafficLightState pedState = RoadBaseAI.TrafficLightState.Red) {
			// we intentionally never delete vehicle types (because we may want to retain traffic light states if a segment is upgraded or replaced)

			HashSet<ExtVehicleType> setupLights = new HashSet<ExtVehicleType>();
			HashSet<ExtVehicleType> allAllowedTypes = VehicleRestrictionsManager.GetAllowedVehicleTypesAsSet(segmentId, nodeId);
			ExtVehicleType allAllowedMask = VehicleRestrictionsManager.GetAllowedVehicleTypes(segmentId, nodeId);
			SeparateVehicleTypes = ExtVehicleType.None;
#if DEBUGHK
			Log._Debug($"CustomSegmentLights: housekeeping @ seg. {segmentId}, node {nodeId}, allAllowedTypes={string.Join(", ", allAllowedTypes.Select(x => x.ToString()).ToArray())}");
#endif
			bool addPedestrianLight = false;
			uint numLights = 0;
			foreach (ExtVehicleType allowedTypes in allAllowedTypes) {
				foreach (ExtVehicleType mask in singleLaneVehicleTypes) {
					if (setupLights.Contains(mask))
						continue;

					if ((allowedTypes & mask) != ExtVehicleType.None && (allowedTypes & ~(mask | ExtVehicleType.Emergency)) == ExtVehicleType.None) {
#if DEBUGHK
						Log._Debug($"CustomSegmentLights: housekeeping @ seg. {segmentId}, node {nodeId}: adding {mask} light");
#endif

						if (!CustomLights.ContainsKey(mask)) {
							CustomLights.Add(mask, new TrafficLight.CustomSegmentLight(this, nodeId, segmentId, mainState, leftState, rightState));
							VehicleTypes.AddFirst(mask);
						}
						++numLights;
						addPedestrianLight = true;
						autoPedestrianVehicleType = mask;
						mainSegmentLight = CustomLights[mask];
						setupLights.Add(mask);
						SeparateVehicleTypes |= mask;
						break;
					}
				}
			}

			if (allAllowedTypes.Count > numLights) {
#if DEBUGHK
				Log._Debug($"CustomSegmentLights: housekeeping @ seg. {segmentId}, node {nodeId}: adding main vehicle light: {mainVehicleType}");
#endif

				// traffic lights for cars
				if (!CustomLights.ContainsKey(mainVehicleType)) {
					CustomLights.Add(mainVehicleType, new TrafficLight.CustomSegmentLight(this, nodeId, segmentId, mainState, leftState, rightState));
					VehicleTypes.AddFirst(mainVehicleType);
				}
				autoPedestrianVehicleType = mainVehicleType;
				mainSegmentLight = CustomLights[mainVehicleType];
				addPedestrianLight = allAllowedMask == ExtVehicleType.None || (allAllowedMask & ~ExtVehicleType.RailVehicle) != ExtVehicleType.None;
			} else {
				addPedestrianLight = true;
			}

#if DEBUGHK
			if (addPedestrianLight) {
				Log._Debug($"CustomSegmentLights: housekeeping @ seg. {segmentId}, node {nodeId}: adding ped. light");
			}
#endif

			if (mayDelete) {
				// delete traffic lights for non-existing configurations
				HashSet<ExtVehicleType> vehicleTypesToDelete = new HashSet<ExtVehicleType>();
				foreach (KeyValuePair<ExtVehicleType, CustomSegmentLight> e in CustomLights) {
					if (e.Key == mainVehicleType)
						continue;
					if (!setupLights.Contains(e.Key))
						vehicleTypesToDelete.Add(e.Key);
				}

				foreach (ExtVehicleType vehicleType in vehicleTypesToDelete) {
#if DEBUGHK
					Log._Debug($"Deleting traffic light for {vehicleType} at segment {segmentId}, node {nodeId}");
#endif
					CustomLights.Remove(vehicleType);
					VehicleTypes.Remove(vehicleType);
				}
			}

			if (CustomLights.ContainsKey(mainVehicleType) && VehicleTypes.First.Value != mainVehicleType) {
				VehicleTypes.Remove(mainVehicleType);
				VehicleTypes.AddFirst(mainVehicleType);
			}

			if (addPedestrianLight) {
#if DEBUGHK
				Log._Debug($"CustomSegmentLights: housekeeping @ seg. {segmentId}, node {nodeId}: adding pedestrian light");
#endif
				if (pedestrianLightState == null)
					pedestrianLightState = pedState;
			} else {
				pedestrianLightState = null;
			}
		}
コード例 #46
0
		public static void CustomSetTrafficLightState(ushort nodeID, ref NetSegment segmentData, uint frame, RoadBaseAI.TrafficLightState vehicleLightState, RoadBaseAI.TrafficLightState pedestrianLightState, bool vehicles, bool pedestrians) {
			OriginalSetTrafficLightState(false, nodeID, ref segmentData, frame, vehicleLightState, pedestrianLightState, vehicles, pedestrians);
		}
コード例 #47
0
		public static RoadBaseAI.TrafficLightState InvertLight(RoadBaseAI.TrafficLightState light) { // TODO refactor
			switch (light) {
				case RoadBaseAI.TrafficLightState.Red:
				case RoadBaseAI.TrafficLightState.GreenToRed:
					return RoadBaseAI.TrafficLightState.Green;
				case RoadBaseAI.TrafficLightState.Green:
				case RoadBaseAI.TrafficLightState.RedToGreen:
				default:
					return RoadBaseAI.TrafficLightState.Red;
			}
		}
コード例 #48
0
		private void drawMainLightTexture(RoadBaseAI.TrafficLightState state, Rect rect) {
			switch (state) {
				case RoadBaseAI.TrafficLightState.Green:
					GUI.DrawTexture(rect, TrafficLightToolTextureResources.GreenLightTexture2D);
					break;
				case RoadBaseAI.TrafficLightState.GreenToRed:
					GUI.DrawTexture(rect, TrafficLightToolTextureResources.YellowLightTexture2D);
					break;
				case RoadBaseAI.TrafficLightState.Red:
				default:
					GUI.DrawTexture(rect, TrafficLightToolTextureResources.RedLightTexture2D);
					break;
				case RoadBaseAI.TrafficLightState.RedToGreen:
					GUI.DrawTexture(rect, TrafficLightToolTextureResources.YellowRedLightTexture2D);
					break;
			}
		}