/// <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));
        }
        /// <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));
        }
        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);
        }
Example #4
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
        }
Example #5
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;
            }
        }
Example #8
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 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);
                }
            }
        }
Example #10
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);
            }
        }
Example #11
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);
        }
        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);
        }
Example #14
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]);
            }
        }
        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);
            }
        }
Example #16
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);
        }
        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);
        }
        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);
        }
        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);
            }
        }
        public void CalculateSegmentPosition(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position nextPosition,
                                             PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID,
                                             byte prevOffset, out Vector3 pos, out Vector3 dir, out float maxSpeed)
        {
            NetManager instance = Singleton <NetManager> .instance;

            instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection((float)offset * 0.003921569f, out pos, out dir);
            Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData();
            Vector3       position2     = lastFrameData.m_position;
            Vector3       b             = instance.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].CalculatePosition((float)prevOffset * 0.003921569f);
            float         num           = 0.5f * lastFrameData.m_velocity.sqrMagnitude / this.m_info.m_braking + this.m_info.m_generatedInfo.m_size.z * 0.5f;

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

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

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

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

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

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

                                if (TrafficPriority.isPrioritySegment(oldNode, oldSegment))
                                {
                                    var oldPrioritySegment = TrafficPriority.getPrioritySegment(oldNode, oldSegment);
                                    TrafficPriority.vehicleList[vehicleID].waitTime = 0;
                                    TrafficPriority.vehicleList[vehicleID].stopped  = false;
                                    oldPrioritySegment.RemoveCar(vehicleID);
                                }
                            }

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

                            prioritySegment.AddCar(vehicleID);
                        }

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

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

                        NetInfo info = instance.m_nodes.m_buffer[(int)num2].Info;
                        RoadBaseAI.TrafficLightState vehicleLightState;
                        RoadBaseAI.TrafficLightState pedestrianLightState;
                        bool flag5;
                        bool pedestrians;

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

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

                                case RoadBaseAI.TrafficLightState.Red:
                                    maxSpeed = 0f;
                                    return;

                                case RoadBaseAI.TrafficLightState.GreenToRed:
                                    if (num6 >= 30u)
                                    {
                                        maxSpeed = 0f;
                                        return;
                                    }
                                    break;
                                }
                            }
                        }
                        else
                        {
                            var stopCar = false;

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

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

                                if (hasIncomingCars)
                                {
                                    stopCar = true;
                                }
                            }

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

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

                                case RoadBaseAI.TrafficLightState.GreenToRed:
                                    if (num6 >= 30u)
                                    {
                                        stopCar = true;
                                    }
                                    break;
                                }
                            }

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

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

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

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

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

                                            if (TrafficPriority.vehicleList[vehicleID].waitTime > 2)
                                            {
                                                var hasIncomingCars = TrafficPriority.incomingVehicles(vehicleID, num2);

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

                                        if (vehicleData.GetLastFrameData().m_velocity.sqrMagnitude <
                                            TrafficPriority.vehicleList[vehicleID].yieldSpeedReduce)
                                        {
                                            var hasIncomingCars = TrafficPriority.incomingVehicles(vehicleID, num2);

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

                                    var hasIncomingCars = TrafficPriority.incomingVehicles(vehicleID, num2);

                                    if (hasIncomingCars)
                                    {
                                        TrafficPriority.vehicleList[vehicleID].stopped = true;
                                        return;
                                    }
                                    else
                                    {
                                        TrafficPriority.vehicleList[vehicleID].stopped = false;

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

            NetInfo info2 = instance.m_segments.m_buffer[(int)position.m_segment].Info;

            if (info2.m_lanes != null && info2.m_lanes.Length > (int)position.m_lane)
            {
                var laneSpeedLimit = info2.m_lanes[(int)position.m_lane].m_speedLimit;

                if (TrafficRoadRestrictions.isSegment(position.m_segment))
                {
                    var restrictionSegment = TrafficRoadRestrictions.getSegment(position.m_segment);

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

                maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, laneSpeedLimit, instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve);
            }
            else
            {
                maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1f, 0f);
            }
        }
Example #21
0
        protected override void CalculateSegmentPosition(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, int index, out Vector3 pos, out Vector3 dir, out float maxSpeed)
        {
            NetManager instance = Singleton <NetManager> .instance;

            instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection((float)offset * 0.003921569f, out pos, out dir);
            Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData();
            Vector3       position2     = lastFrameData.m_position;
            Vector3       b             = instance.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].CalculatePosition((float)prevOffset * 0.003921569f);
            float         num           = 0.5f * lastFrameData.m_velocity.sqrMagnitude / this.m_info.m_braking + this.m_info.m_generatedInfo.m_size.z * 0.5f;

            if (Vector3.Distance(position2, b) >= num - 1f)
            {
                Segment3 segment;
                segment.a = pos;
                ushort num2;
                ushort num3;
                if (offset < position.m_offset)
                {
                    segment.b = pos + dir.normalized * this.m_info.m_generatedInfo.m_size.z;
                    num2      = instance.m_segments.m_buffer[(int)position.m_segment].m_startNode;
                    num3      = instance.m_segments.m_buffer[(int)position.m_segment].m_endNode;
                }
                else
                {
                    segment.b = pos - dir.normalized * this.m_info.m_generatedInfo.m_size.z;
                    num2      = instance.m_segments.m_buffer[(int)position.m_segment].m_endNode;
                    num3      = instance.m_segments.m_buffer[(int)position.m_segment].m_startNode;
                }
                ushort num4;
                if (prevOffset == 0)
                {
                    num4 = instance.m_segments.m_buffer[(int)prevPos.m_segment].m_startNode;
                }
                else
                {
                    num4 = instance.m_segments.m_buffer[(int)prevPos.m_segment].m_endNode;
                }
                if (num2 == num4)
                {
                    NetNode.Flags flags  = instance.m_nodes.m_buffer[(int)num2].m_flags;
                    NetLane.Flags flags2 = (NetLane.Flags)instance.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_flags;
                    bool          flag   = (flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None;
                    bool          flag2  = (flags & NetNode.Flags.LevelCrossing) != NetNode.Flags.None;
                    bool          flag3  = (flags2 & NetLane.Flags.JoinedJunction) != NetLane.Flags.None;
                    if ((flags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) == NetNode.Flags.Junction && instance.m_nodes.m_buffer[(int)num2].CountSegments() != 2)
                    {
                        float len = vehicleData.CalculateTotalLength(vehicleID) + 2f;
                        if (!instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(len))
                        {
                            bool flag4 = false;
                            if (nextPosition.m_segment != 0 && instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_length < 30f)
                            {
                                NetNode.Flags flags3 = instance.m_nodes.m_buffer[(int)num3].m_flags;
                                if ((flags3 & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) != NetNode.Flags.Junction || instance.m_nodes.m_buffer[(int)num3].CountSegments() == 2)
                                {
                                    uint laneID2 = PathManager.GetLaneID(nextPosition);
                                    if (laneID2 != 0u)
                                    {
                                        flag4 = instance.m_lanes.m_buffer[(int)((UIntPtr)laneID2)].CheckSpace(len);
                                    }
                                }
                            }
                            if (!flag4)
                            {
                                maxSpeed = 0f;
                                return;
                            }
                        }
                    }
                    if (flag && (!flag3 || flag2))
                    {
                        uint    currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
                        uint    num5 = (uint)(((int)num4 << 8) / 32768);
                        uint    num6 = currentFrameIndex - num5 & 255u;
                        NetInfo info = instance.m_nodes.m_buffer[(int)num2].Info;
                        RoadBaseAI.TrafficLightState vehicleLightState;
                        RoadBaseAI.TrafficLightState pedestrianLightState;
                        bool flag5;
                        bool pedestrians;
                        RoadBaseAI.GetTrafficLightState(num4, ref instance.m_segments.m_buffer[(int)prevPos.m_segment], currentFrameIndex - num5, out vehicleLightState, out pedestrianLightState, out flag5, out pedestrians);
                        if (!flag5 && num6 >= 196u)
                        {
                            flag5 = true;
                            RoadBaseAI.SetTrafficLightState(num4, ref instance.m_segments.m_buffer[(int)prevPos.m_segment], currentFrameIndex - num5, vehicleLightState, pedestrianLightState, flag5, pedestrians);
                        }
                        if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == 0 || info.m_class.m_service != ItemClass.Service.Road)
                        {
                            switch (vehicleLightState)
                            {
                            case RoadBaseAI.TrafficLightState.RedToGreen:
                                if (num6 < 60u)
                                {
                                    maxSpeed = 0f;
                                    return;
                                }
                                break;

                            case RoadBaseAI.TrafficLightState.Red:
                                maxSpeed = 0f;
                                return;

                            case RoadBaseAI.TrafficLightState.GreenToRed:
                                if (num6 >= 30u)
                                {
                                    maxSpeed = 0f;
                                    return;
                                }
                                break;
                            }
                        }
                    }
                }
            }
            NetInfo info2 = instance.m_segments.m_buffer[(int)position.m_segment].Info;

            if (info2.m_lanes != null && info2.m_lanes.Length > (int)position.m_lane)
            {
                maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, LaneManager.GetLaneSpeed(laneID, info2.m_lanes[(int)position.m_lane]), instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve);
            }
            else
            {
                maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1f, 0f);
            }
            if (instance.m_treatWetAsSnow)
            {
                DistrictManager instance2 = Singleton <DistrictManager> .instance;
                byte            district  = instance2.GetDistrict(pos);
                DistrictPolicies.CityPlanning cityPlanningPolicies = instance2.m_districts.m_buffer[(int)district].m_cityPlanningPolicies;
                if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.StuddedTires) != DistrictPolicies.CityPlanning.None)
                {
                    maxSpeed *= 1f - (float)instance.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.0005882353f;
                    District[] expr_5C2_cp_0 = instance2.m_districts.m_buffer;
                    byte       expr_5C2_cp_1 = district;
                    expr_5C2_cp_0[(int)expr_5C2_cp_1].m_cityPlanningPoliciesEffect = (expr_5C2_cp_0[(int)expr_5C2_cp_1].m_cityPlanningPoliciesEffect | DistrictPolicies.CityPlanning.StuddedTires);
                }
                else
                {
                    maxSpeed *= 1f - (float)instance.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.00117647066f;
                }
            }
            else
            {
                maxSpeed *= 1f - (float)instance.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.0005882353f;
            }
            maxSpeed *= 1f + (float)instance.m_segments.m_buffer[(int)position.m_segment].m_condition * 0.0005882353f;
        }
        //from source code
        private void CheckNextLane(ushort vehicleID, ref Vehicle vehicleData, ref float maxSpeed, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, Bezier3 bezier)
        {
            NetManager instance = Singleton <NetManager> .instance;

            Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData();
            Vector3       a             = lastFrameData.m_position;
            Vector3       a2            = lastFrameData.m_position;
            Vector3       b             = lastFrameData.m_rotation * new Vector3(0f, 0f, this.m_info.m_generatedInfo.m_wheelBase * 0.5f);

            a  += b;
            a2 -= b;
            float num = 0.5f * lastFrameData.m_velocity.sqrMagnitude / this.m_info.m_braking;
            float a3  = Vector3.Distance(a, bezier.a);
            float b2  = Vector3.Distance(a2, bezier.a);

            if (Mathf.Min(a3, b2) >= num - 5f)
            {
                if (!instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(1000f, vehicleID))
                {
                    vehicleData.m_flags2     |= Vehicle.Flags2.Yielding;
                    vehicleData.m_waitCounter = 0;
                    maxSpeed = 0f;
                    return;
                }
                Vector3  vector = bezier.Position(0.5f);
                Segment3 segment;
                if (Vector3.SqrMagnitude(vehicleData.m_segment.a - vector) < Vector3.SqrMagnitude(bezier.a - vector))
                {
                    segment = new Segment3(vehicleData.m_segment.a, vector);
                }
                else
                {
                    segment = new Segment3(bezier.a, vector);
                }
                if (segment.LengthSqr() >= 3f)
                {
                    segment.a += (segment.b - segment.a).normalized * 2.5f;
                    if (SingleTrainTrackAI.CheckOverlap(vehicleID, ref vehicleData, segment, vehicleID))
                    {
                        vehicleData.m_flags2     |= Vehicle.Flags2.Yielding;
                        vehicleData.m_waitCounter = 0;
                        maxSpeed = 0f;
                        return;
                    }
                }
                segment = new Segment3(vector, bezier.d);
                if (segment.LengthSqr() >= 1f && SingleTrainTrackAI.CheckOverlap(vehicleID, ref vehicleData, segment, vehicleID))
                {
                    vehicleData.m_flags2     |= Vehicle.Flags2.Yielding;
                    vehicleData.m_waitCounter = 0;
                    maxSpeed = 0f;
                    return;
                }
                if (this.m_info.m_vehicleType != VehicleInfo.VehicleType.Monorail)
                {
                    ushort num2;
                    if (offset < position.m_offset)
                    {
                        num2 = instance.m_segments.m_buffer[(int)position.m_segment].m_startNode;
                    }
                    else
                    {
                        num2 = instance.m_segments.m_buffer[(int)position.m_segment].m_endNode;
                    }
                    ushort num3;
                    if (prevOffset == 0)
                    {
                        num3 = instance.m_segments.m_buffer[(int)prevPos.m_segment].m_startNode;
                    }
                    else
                    {
                        num3 = instance.m_segments.m_buffer[(int)prevPos.m_segment].m_endNode;
                    }
                    if (num2 == num3)
                    {
                        NetNode.Flags flags  = instance.m_nodes.m_buffer[(int)num2].m_flags;
                        NetLane.Flags flags2 = (NetLane.Flags)instance.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_flags;
                        bool          flag   = (flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None;
                        bool          flag2  = (flags2 & (NetLane.Flags.YieldStart | NetLane.Flags.YieldEnd)) != NetLane.Flags.None && (flags & (NetNode.Flags.Junction | NetNode.Flags.TrafficLights | NetNode.Flags.OneWayIn)) == NetNode.Flags.Junction;
                        if (flag)
                        {
                            uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
                            uint num4 = (uint)(((int)num3 << 8) / 32768);
                            uint num5 = currentFrameIndex - num4 & 255u;
                            RoadBaseAI.TrafficLightState trafficLightState;
                            RoadBaseAI.TrafficLightState pedestrianLightState;
                            bool flag3;
                            bool pedestrians;
                            RoadBaseAI.GetTrafficLightState(num3, ref instance.m_segments.m_buffer[(int)prevPos.m_segment], currentFrameIndex - num4, out trafficLightState, out pedestrianLightState, out flag3, out pedestrians);
                            if (!flag3 && num5 >= 196u)
                            {
                                flag3 = true;
                                RoadBaseAI.SetTrafficLightState(num3, ref instance.m_segments.m_buffer[(int)prevPos.m_segment], currentFrameIndex - num4, trafficLightState, pedestrianLightState, flag3, pedestrians);
                            }
                            if (trafficLightState != RoadBaseAI.TrafficLightState.RedToGreen)
                            {
                                if (trafficLightState != RoadBaseAI.TrafficLightState.GreenToRed)
                                {
                                    if (trafficLightState == RoadBaseAI.TrafficLightState.Red)
                                    {
                                        vehicleData.m_flags2     |= Vehicle.Flags2.Yielding;
                                        vehicleData.m_waitCounter = 0;
                                        maxSpeed = 0f;
                                        return;
                                    }
                                }
                                else if (num5 >= 30u)
                                {
                                    vehicleData.m_flags2     |= Vehicle.Flags2.Yielding;
                                    vehicleData.m_waitCounter = 0;
                                    maxSpeed = 0f;
                                    return;
                                }
                            }
                            else if (num5 < 60u)
                            {
                                vehicleData.m_flags2     |= Vehicle.Flags2.Yielding;
                                vehicleData.m_waitCounter = 0;
                                maxSpeed = 0f;
                                return;
                            }
                        }
                        if (flag2 && (vehicleData.m_flags2 & Vehicle.Flags2.Yielding) != (Vehicle.Flags2) 0)
                        {
                            vehicleData.m_waitCounter = (byte)Mathf.Min((int)(vehicleData.m_waitCounter + 1), 4);
                            if (vehicleData.m_waitCounter < 4)
                            {
                                maxSpeed = 0f;
                                return;
                            }
                            vehicleData.m_flags2     &= ~Vehicle.Flags2.Yielding;
                            vehicleData.m_waitCounter = 0;
                        }
                    }
                }
            }
        }
Example #23
0
        public bool CustomCheckTrafficLights(ushort nodeId, ushort segmentId)
        {
#if DEBUGTTL
            bool debug = GlobalConfig.Instance.Debug.Switches[7] && GlobalConfig.Instance.Debug.NodeId == nodeId;
#endif

            var netManager = Singleton <NetManager> .instance;

            var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
            var num          = (uint)(((int)nodeId << 8) / 32768);
            var stepWaitTime = currentFrameIndex - num & 255u;

            // NON-STOCK CODE START //

            bool customSim = false;
#if BENCHMARK
            using (var bm = new Benchmark(null, "GetNodeSimulation")) {
#endif
            customSim = Options.timedLightsEnabled && TrafficLightSimulationManager.Instance.HasActiveSimulation(nodeId);
#if BENCHMARK
        }
#endif
            RoadBaseAI.TrafficLightState pedestrianLightState;
            bool startNode = netManager.m_segments.m_buffer[segmentId].m_startNode == nodeId;

            ICustomSegmentLights lights = null;
#if BENCHMARK
            using (var bm = new Benchmark(null, "GetSegmentLights")) {
#endif
            if (customSim)
            {
                lights = CustomSegmentLightsManager.Instance.GetSegmentLights(segmentId, startNode, false);
            }
#if BENCHMARK
        }
#endif

            if (lights == null)
            {
                // NON-STOCK CODE END //
                RoadBaseAI.TrafficLightState vehicleLightState;
                bool vehicles;
                bool pedestrians;

#if DEBUGTTL
                if (debug)
                {
                    Log._Debug($"CustomHumanAI.CustomCheckTrafficLights({nodeId}, {segmentId}): No custom simulation!");
                }
#endif

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

#if DEBUGTTL
                if (debug)
                {
                    Log._Debug($"CustomHumanAI.CustomCheckTrafficLights({nodeId}, {segmentId}): Custom simulation! pedestrianLightState={pedestrianLightState}, lights.InvalidPedestrianLight={lights.InvalidPedestrianLight}");
                }
#endif
            }
            // NON-STOCK CODE END //

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

            case RoadBaseAI.TrafficLightState.Red:
            case RoadBaseAI.TrafficLightState.GreenToRed:
                return(false);
            }
            return(true);
        }
Example #24
0
        public void OriginalSimulationStep(ushort nodeID, ref NetNode data)
        {
            NetManager instance = Singleton <NetManager> .instance;

            if ((data.m_flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None)
            {
                uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
                int  num   = (int)(data.m_maxWaitTime & 3);
                int  num2  = data.m_maxWaitTime >> 2 & 7;
                int  num3  = data.m_maxWaitTime >> 5;
                int  num4  = -1;
                int  num5  = -1;
                int  num6  = -1;
                int  num7  = -1;
                int  num8  = -1;
                int  num9  = -1;
                int  num10 = 0;
                int  num11 = 0;
                int  num12 = 0;
                int  num13 = 0;
                int  num14 = 0;
                for (int i = 0; i < 8; i++)
                {
                    ushort segment = data.GetSegment(i);
                    if (segment != 0)
                    {
                        int num15 = 0;
                        int num16 = 0;
                        instance.m_segments.m_buffer[(int)segment].CountLanes(segment, NetInfo.LaneType.Vehicle, VehicleInfo.VehicleType.Car, ref num15, ref num16);
                        bool flag  = instance.m_segments.m_buffer[(int)segment].m_startNode == nodeID;
                        bool flag2 = (!flag) ? (num15 != 0) : (num16 != 0);
                        bool flag3 = (!flag) ? (num16 != 0) : (num15 != 0);
                        if (flag2)
                        {
                            num10 |= 1 << i;
                        }
                        if (flag3)
                        {
                            num11 |= 1 << i;
                            num13++;
                        }
                        RoadBaseAI.TrafficLightState trafficLightState;
                        RoadBaseAI.TrafficLightState trafficLightState2;
                        bool flag4;
                        bool flag5;
                        RoadBaseAI.GetTrafficLightState(nodeID, ref instance.m_segments.m_buffer[(int)segment], currentFrameIndex - 256u, out trafficLightState, out trafficLightState2, out flag4, out flag5);
                        if ((trafficLightState2 & RoadBaseAI.TrafficLightState.Red) != RoadBaseAI.TrafficLightState.Green && flag5)
                        {
                            if (num7 == -1)
                            {
                                num7 = i;
                            }
                            if (num9 == -1 && num14 >= num3)
                            {
                                num9 = i;
                            }
                        }
                        num14++;
                        if (flag2 || flag4)
                        {
                            if ((trafficLightState & RoadBaseAI.TrafficLightState.Red) == RoadBaseAI.TrafficLightState.Green)
                            {
                                num5 = i;
                                if (flag4)
                                {
                                    num4 = i;
                                }
                            }
                            else if (flag4)
                            {
                                if (num6 == -1)
                                {
                                    num6 = i;
                                }
                                if (num8 == -1 && num12 >= num2)
                                {
                                    num8 = i;
                                }
                            }
                            num12++;
                        }
                    }
                }
                if (num8 == -1)
                {
                    num8 = num6;
                }
                if (num9 == -1)
                {
                    num9 = num7;
                }
                if (num5 != -1 && num4 != -1 && num <= 1)
                {
                    num8 = -1;
                    num9 = -1;
                    num++;
                }
                if (num9 != -1 && num8 != -1 && Singleton <SimulationManager> .instance.m_randomizer.Int32(3u) != 0)
                {
                    num9 = -1;
                }
                if (num8 != -1)
                {
                    num5 = num8;
                }
                if (num9 == num5)
                {
                    num5 = -1;
                }
                Vector3 vector = Vector3.zero;
                if (num9 != -1)
                {
                    ushort segment2 = data.GetSegment(num9);
                    vector = instance.m_segments.m_buffer[(int)segment2].GetDirection(nodeID);
                    if (num5 != -1)
                    {
                        segment2 = data.GetSegment(num5);
                        Vector3 direction = instance.m_segments.m_buffer[(int)segment2].GetDirection(nodeID);
                        if (direction.x * vector.x + direction.z * vector.z < -0.5f)
                        {
                            num5 = -1;
                        }
                    }
                    if (num5 == -1)
                    {
                        for (int j = 0; j < 8; j++)
                        {
                            if (j != num9 && (num10 & 1 << j) != 0)
                            {
                                segment2 = data.GetSegment(j);
                                if (segment2 != 0)
                                {
                                    Vector3 direction2 = instance.m_segments.m_buffer[(int)segment2].GetDirection(nodeID);
                                    if (direction2.x * vector.x + direction2.z * vector.z >= -0.5f)
                                    {
                                        num5 = j;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                int     num17   = -1;
                Vector3 vector2 = Vector3.zero;
                Vector3 vector3 = Vector3.zero;
                if (num5 != -1)
                {
                    ushort segment3 = data.GetSegment(num5);
                    vector2 = instance.m_segments.m_buffer[(int)segment3].GetDirection(nodeID);
                    if ((num10 & num11 & 1 << num5) != 0)
                    {
                        for (int k = 0; k < 8; k++)
                        {
                            if (k != num5 && k != num9 && (num10 & num11 & 1 << k) != 0)
                            {
                                segment3 = data.GetSegment(k);
                                if (segment3 != 0)
                                {
                                    vector3 = instance.m_segments.m_buffer[(int)segment3].GetDirection(nodeID);
                                    if (num9 == -1 || vector3.x * vector.x + vector3.z * vector.z >= -0.5f)
                                    {
                                        if (num13 == 2)
                                        {
                                            num17 = k;
                                            break;
                                        }
                                        if (vector3.x * vector2.x + vector3.z * vector2.z < -0.9396926f)
                                        {
                                            num17 = k;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                for (int l = 0; l < 8; l++)
                {
                    ushort segment4 = data.GetSegment(l);
                    if (segment4 != 0)
                    {
                        RoadBaseAI.TrafficLightState trafficLightState3;
                        RoadBaseAI.TrafficLightState trafficLightState4;
                        RoadBaseAI.GetTrafficLightState(nodeID, ref instance.m_segments.m_buffer[(int)segment4], currentFrameIndex - 256u, out trafficLightState3, out trafficLightState4);
                        trafficLightState3 &= ~RoadBaseAI.TrafficLightState.RedToGreen;
                        trafficLightState4 &= ~RoadBaseAI.TrafficLightState.RedToGreen;
                        if (num5 == l || num17 == l)
                        {
                            if ((trafficLightState3 & RoadBaseAI.TrafficLightState.Red) != RoadBaseAI.TrafficLightState.Green)
                            {
                                trafficLightState3 = RoadBaseAI.TrafficLightState.RedToGreen;
                                num = 0;
                                if (++num2 >= num12)
                                {
                                    num2 = 0;
                                }
                            }
                            if ((trafficLightState4 & RoadBaseAI.TrafficLightState.Red) == RoadBaseAI.TrafficLightState.Green)
                            {
                                trafficLightState4 = RoadBaseAI.TrafficLightState.GreenToRed;
                            }
                        }
                        else
                        {
                            if ((trafficLightState3 & RoadBaseAI.TrafficLightState.Red) == RoadBaseAI.TrafficLightState.Green)
                            {
                                trafficLightState3 = RoadBaseAI.TrafficLightState.GreenToRed;
                            }
                            Vector3 direction3 = instance.m_segments.m_buffer[(int)segment4].GetDirection(nodeID);
                            if ((num11 & 1 << l) != 0 && num9 != l && ((num5 != -1 && direction3.x * vector2.x + direction3.z * vector2.z < -0.5f) || (num17 != -1 && direction3.x * vector3.x + direction3.z * vector3.z < -0.5f)))
                            {
                                if ((trafficLightState4 & RoadBaseAI.TrafficLightState.Red) == RoadBaseAI.TrafficLightState.Green)
                                {
                                    trafficLightState4 = RoadBaseAI.TrafficLightState.GreenToRed;
                                }
                            }
                            else if ((trafficLightState4 & RoadBaseAI.TrafficLightState.Red) != RoadBaseAI.TrafficLightState.Green)
                            {
                                trafficLightState4 = RoadBaseAI.TrafficLightState.RedToGreen;
                                if (++num3 >= num14)
                                {
                                    num3 = 0;
                                }
                            }
                        }
                        RoadBaseAI.SetTrafficLightState(nodeID, ref instance.m_segments.m_buffer[(int)segment4], currentFrameIndex, trafficLightState3, trafficLightState4, false, false);
                    }
                }
                data.m_maxWaitTime = (byte)(num3 << 5 | num2 << 2 | num);
            }
            int num18 = 0;

            if (this.m_noiseAccumulation != 0)
            {
                int num19 = 0;
                for (int m = 0; m < 8; m++)
                {
                    ushort segment5 = data.GetSegment(m);
                    if (segment5 != 0)
                    {
                        num18 += (int)instance.m_segments.m_buffer[(int)segment5].m_trafficDensity;
                        num19++;
                    }
                }
                if (num19 != 0)
                {
                    num18 /= num19;
                }
            }
            int num20 = 100 - (num18 - 100) * (num18 - 100) / 100;
            int num21 = this.m_noiseAccumulation * num20 / 100;

            if (num21 != 0)
            {
                Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.NoisePollution, num21, data.m_position, this.m_noiseRadius);
            }
            if ((data.m_problems & Notification.Problem.RoadNotConnected) != Notification.Problem.None && (data.m_flags & NetNode.Flags.Original) != NetNode.Flags.None)
            {
                GuideController properties = Singleton <GuideManager> .instance.m_properties;
                if (properties != null)
                {
                    instance.m_outsideNodeNotConnected.Activate(properties.m_outsideNotConnected, nodeID, Notification.Problem.RoadNotConnected);
                }
            }
        }
Example #25
0
        public bool CustomCheckTrafficLights(ushort nodeId, ushort segmentId)
        {
#if DEBUG
            bool logTimedLights = DebugSwitch.TimedTrafficLights.Get() &&
                                  DebugSettings.NodeId == nodeId;
#endif
            NetManager netManager        = Singleton <NetManager> .instance;
            uint       currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
            uint       simGroup          = (uint)nodeId >> 7;
            uint       stepWaitTime      = currentFrameIndex - simGroup & 255u;

            // NON-STOCK CODE START
            bool customSim = Options.timedLightsEnabled &&
                             TrafficLightSimulationManager.Instance.HasActiveSimulation(nodeId);

            RoadBaseAI.TrafficLightState pedestrianLightState;
            NetSegment[] segmentsBuffer = netManager.m_segments.m_buffer;
            bool         startNode      = segmentsBuffer[segmentId].m_startNode == nodeId;

            ICustomSegmentLights lights = null;
            using (var bm = Benchmark.MaybeCreateBenchmark(null, "GetSegmentLights")) {
                if (customSim)
                {
                    lights = CustomSegmentLightsManager.Instance.GetSegmentLights(
                        segmentId,
                        startNode,
                        false);
                }
            }

            if (lights == null)
            {
                // NON-STOCK CODE END
#if DEBUG
                Log._DebugIf(
                    logTimedLights,
                    () => $"CustomHumanAI.CustomCheckTrafficLights({nodeId}, " +
                    $"{segmentId}): No custom simulation!");
#endif

                RoadBaseAI.GetTrafficLightState(
                    nodeId,
                    ref segmentsBuffer[segmentId],
                    currentFrameIndex - simGroup,
                    out RoadBaseAI.TrafficLightState vehicleLightState,
                    out pedestrianLightState,
                    out bool vehicles,
                    out bool pedestrians);

                if (pedestrianLightState == RoadBaseAI.TrafficLightState.GreenToRed ||
                    pedestrianLightState == RoadBaseAI.TrafficLightState.Red)
                {
                    if (!pedestrians && stepWaitTime >= 196u)
                    {
                        RoadBaseAI.SetTrafficLightState(
                            nodeId,
                            ref segmentsBuffer[segmentId],
                            currentFrameIndex - simGroup,
                            vehicleLightState,
                            pedestrianLightState,
                            vehicles,
                            true);
                    }

                    return(false);
                }

                // NON-STOCK CODE START
            }
            else
            {
                if (lights.InvalidPedestrianLight)
                {
                    pedestrianLightState = RoadBaseAI.TrafficLightState.Green;
                }
                else
                {
                    pedestrianLightState = (RoadBaseAI.TrafficLightState)lights.PedestrianLightState;
                }

#if DEBUG
                Log._DebugIf(
                    logTimedLights,
                    () => $"CustomHumanAI.CustomCheckTrafficLights({nodeId}, {segmentId}): " +
                    $"Custom simulation! pedestrianLightState={pedestrianLightState}, " +
                    $"lights.InvalidPedestrianLight={lights.InvalidPedestrianLight}");
#endif
            }

            // NON-STOCK CODE END
            switch (pedestrianLightState)
            {
            case RoadBaseAI.TrafficLightState.RedToGreen:
                if (stepWaitTime < 60u)
                {
                    return(false);
                }

                break;

            case RoadBaseAI.TrafficLightState.Red:
            case RoadBaseAI.TrafficLightState.GreenToRed:
                return(false);
            }

            return(true);
        }