Beispiel #1
0
        public void SetLights(bool noTransition)
        {
            try {
                bool atEndTransition   = !noTransition && isInEndTransition();                       // = yellow
                bool atStartTransition = !noTransition && !atEndTransition && isInStartTransition(); // = red + yellow

                TimedTrafficStep previousStep = timedNode.Steps[(timedNode.CurrentStep + timedNode.Steps.Count - 1) % timedNode.Steps.Count];
                TimedTrafficStep nextStep     = timedNode.Steps[(timedNode.CurrentStep + 1) % timedNode.Steps.Count];

                foreach (KeyValuePair <ushort, ManualSegmentLight> e in segmentLightStates)
                {
                    var segmentId      = e.Key;
                    var segLightState  = e.Value;
                    var prevLightState = previousStep.segmentLightStates[segmentId];
                    var nextLightState = nextStep.segmentLightStates[segmentId];

                    var segmentLight = TrafficLightsManual.GetSegmentLight(nodeId, segmentId);
                    if (segmentLight == null)
                    {
                        continue;
                    }

                    segmentLight.LightMain       = calcLightState(prevLightState.LightMain, segLightState.LightMain, nextLightState.LightMain, atStartTransition, atEndTransition);
                    segmentLight.LightLeft       = calcLightState(prevLightState.LightLeft, segLightState.LightLeft, nextLightState.LightLeft, atStartTransition, atEndTransition);
                    segmentLight.LightRight      = calcLightState(prevLightState.LightRight, segLightState.LightRight, nextLightState.LightRight, atStartTransition, atEndTransition);
                    segmentLight.LightPedestrian = calcLightState(prevLightState.LightPedestrian, segLightState.LightPedestrian, nextLightState.LightPedestrian, atStartTransition, atEndTransition);

                    segmentLight.UpdateVisuals();
                }
            } catch (Exception e) {
                Log.Error($"Exception in TimedTrafficStep.SetLights: {e.Message}");
                invalid = true;
            }
        }
        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);
        }
Beispiel #3
0
        /// <summary>
        /// Updates timed segment lights according to "real-world" traffic light states
        /// </summary>
        public void UpdateLights()
        {
            foreach (KeyValuePair <ushort, ManualSegmentLight> e in segmentLightStates)
            {
                var segmentId     = e.Key;
                var segLightState = e.Value;

                //if (segment == 0) continue;
                var segmentLight = TrafficLightsManual.GetSegmentLight(nodeId, segmentId);
                if (segmentLight == null)
                {
                    continue;
                }

                segLightState.LightMain       = segmentLight.LightMain;
                segLightState.LightLeft       = segmentLight.LightLeft;
                segLightState.LightRight      = segmentLight.LightRight;
                segLightState.LightPedestrian = segmentLight.LightPedestrian;
            }
        }
        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 static bool HasIncomingVehicles(ushort targetCar, ushort nodeId)
        {
            var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
            var frame             = currentFrameIndex >> 4;
            var node = TrafficLightTool.GetNetNode(nodeId);

            var fromPrioritySegment = GetPrioritySegment(nodeId, VehicleList[targetCar].FromSegment);

            if (fromPrioritySegment == null)
            {
                return(false);
            }

            var removeCarList = new List <ushort>();

            var numCars = 0;

            // get all cars
            for (var s = 0; s < 8; s++)
            {
                var segment = node.GetSegment(s);

                if (segment == 0 || segment == VehicleList[targetCar].FromSegment)
                {
                    continue;
                }
                if (!IsPrioritySegment(nodeId, segment))
                {
                    continue;
                }

                var prioritySegment = GetPrioritySegment(nodeId, segment);
                if (prioritySegment == null)
                {
                    continue;                     // should not happen
                }
                // select outdated cars
                removeCarList.AddRange(from car in prioritySegment.Cars where VehicleList[car].LastFrame < frame - 32u select car);

                // remove outdated cars
                foreach (var rcar in removeCarList)
                {
                    VehicleList[rcar].ResetCar();
                    //Log.Message("Removing *OUTDATED* vehicle " + rcar + " from segment " + segment + " @ node " + nodeId);
                    prioritySegment.RemoveCar(rcar);
                    CustomCarAI.watchedVehicleIds.Remove(rcar);
                }

                removeCarList.Clear();

                if ((node.m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None)
                {
                    if (fromPrioritySegment.Type == PrioritySegment.PriorityType.Main)
                    {
                        if (prioritySegment.Type != PrioritySegment.PriorityType.Main)
                        {
                            continue;
                        }

                        numCars += prioritySegment.NumCars;

                        foreach (var car in prioritySegment.Cars)
                        {
                            if (Singleton <VehicleManager> .instance.m_vehicles.m_buffer[car].m_frame0.m_velocity.magnitude > 0.1f)
                            {
                                numCars = CheckSameRoadIncomingCar(targetCar, car, nodeId)
                                                                        ? numCars - 1
                                                                        : numCars;
                            }
                            else
                            {
                                numCars--;
                            }
                        }
                    }
                    else
                    {
                        numCars += prioritySegment.NumCars;

                        foreach (var car in prioritySegment.Cars)
                        {
                            if (prioritySegment.Type == PrioritySegment.PriorityType.Main)
                            {
                                if (!VehicleList[car].Stopped)
                                {
                                    numCars = CheckPriorityRoadIncomingCar(targetCar, car, nodeId)
                                                                                ? numCars - 1
                                                                                : numCars;
                                }
                                else
                                {
                                    numCars--;
                                }
                            }
                            else
                            {
                                if (Singleton <VehicleManager> .instance.m_vehicles.m_buffer[car].m_frame0.m_velocity.magnitude > 0.1f)
                                {
                                    numCars = CheckSameRoadIncomingCar(targetCar, car, nodeId)
                                                                                ? numCars - 1
                                                                                : numCars;
                                }
                                else
                                {
                                    numCars--;
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (!TrafficLightsManual.IsSegmentLight(nodeId, segment))
                    {
                        continue;
                    }

                    var segmentLight = TrafficLightsManual.GetSegmentLight(nodeId, segment);

                    if (segmentLight.GetLightMain() != RoadBaseAI.TrafficLightState.Green)
                    {
                        continue;
                    }

                    numCars += prioritySegment.NumCars;

                    foreach (var car in prioritySegment.Cars)
                    {
                        if (Singleton <VehicleManager> .instance.m_vehicles.m_buffer[car].m_frame0.m_velocity.magnitude > 1f)
                        {
                            numCars = CheckSameRoadIncomingCar(targetCar, car, nodeId)
                                                                ? numCars - 1
                                                                : numCars;
                        }
                        else
                        {
                            numCars--;
                        }
                    }
                }
            }

            return(numCars > 0);
        }