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); }
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 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); } } }
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 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); }
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); } }
/// <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); }
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); } }
/// <summary> /// Checks for traffic lights and priority signs when changing segments (for road & rail vehicles). /// Sets the maximum allowed speed <paramref name="maxSpeed"/> if segment change is not allowed (otherwise <paramref name="maxSpeed"/> has to be set by the calling method). /// </summary> /// <param name="vehicleId">vehicle id</param> /// <param name="vehicleData">vehicle data</param> /// <param name="lastFrameData">last frame data of vehicle</param> /// <param name="isRecklessDriver">if true, this vehicle ignores red traffic lights and priority signs</param> /// <param name="prevPos">previous path position</param> /// <param name="prevTargetNodeId">previous target node</param> /// <param name="prevLaneID">previous lane</param> /// <param name="position">current path position</param> /// <param name="targetNodeId">transit node</param> /// <param name="laneID">current lane</param> /// <param name="nextPosition">next path position</param> /// <param name="nextTargetNodeId">next target node</param> /// <param name="maxSpeed">maximum allowed speed (only valid if method returns false)</param> /// <returns>true, if the vehicle may change segments, false otherwise.</returns> internal static bool MayChangeSegment(ushort vehicleId, ref Vehicle vehicleData, ref Vehicle.Frame lastFrameData, bool isRecklessDriver, ref PathUnit.Position prevPos, ushort prevTargetNodeId, uint prevLaneID, ref PathUnit.Position position, ushort targetNodeId, uint laneID, ref PathUnit.Position nextPosition, ushort nextTargetNodeId, out float maxSpeed, bool debug = false) { debug = false; if (prevTargetNodeId != targetNodeId) { // method should only be called if targetNodeId == prevTargetNode maxSpeed = 0f; return(true); } bool forceUpdatePos = false; VehicleState vehicleState = null; try { vehicleState = VehicleStateManager.GetVehicleState(vehicleId); if (vehicleState == null) { VehicleStateManager.OnPathFindReady(vehicleId, ref vehicleData); vehicleState = VehicleStateManager.GetVehicleState(vehicleId); if (vehicleState == null) { #if DEBUG Log._Debug($"Could not get vehicle state of {vehicleId}!"); #endif } else { forceUpdatePos = true; } } } catch (Exception e) { Log.Error("VehicleAI MayChangeSegment vehicle state error: " + e.ToString()); } if (forceUpdatePos || Options.simAccuracy >= 2) { try { VehicleStateManager.UpdateVehiclePos(vehicleId, ref vehicleData, ref prevPos, ref position); } catch (Exception e) { Log.Error("VehicleAI MayChangeSegment Error: " + e.ToString()); } } var netManager = Singleton <NetManager> .instance; uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; uint prevTargetNodeLower8Bits = (uint)((prevTargetNodeId << 8) / 32768); uint random = currentFrameIndex - prevTargetNodeLower8Bits & 255u; bool isRailVehicle = (vehicleData.Info.m_vehicleType & (VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Metro)) != VehicleInfo.VehicleType.None; NetNode.Flags targetNodeFlags = netManager.m_nodes.m_buffer[targetNodeId].m_flags; bool hasTrafficLight = (targetNodeFlags & NetNode.Flags.TrafficLights) != NetNode.Flags.None; bool checkTrafficLights = false; if (!isRailVehicle) { // check if to check space #if DEBUG if (debug) { Log._Debug($"CustomVehicleAI.MayChangeSegment: Vehicle {vehicleId} is not a train."); } #endif var prevLaneFlags = (NetLane.Flags)netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_flags; var hasCrossing = (targetNodeFlags & NetNode.Flags.LevelCrossing) != NetNode.Flags.None; var isJoinedJunction = (prevLaneFlags & NetLane.Flags.JoinedJunction) != NetLane.Flags.None; bool checkSpace = !Flags.getEnterWhenBlockedAllowed(prevPos.m_segment, netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode == targetNodeId) && !isRecklessDriver; //TrafficLightSimulation nodeSim = TrafficLightSimulation.GetNodeSimulation(destinationNodeId); //if (timedNode != null && timedNode.vehiclesMayEnterBlockedJunctions) { // checkSpace = false; //} if (checkSpace) { // check if there is enough space if ((targetNodeFlags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) == NetNode.Flags.Junction && netManager.m_nodes.m_buffer[targetNodeId].CountSegments() != 2) { var len = vehicleData.CalculateTotalLength(vehicleId) + 2f; if (!netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(len)) { var sufficientSpace = false; if (nextPosition.m_segment != 0 && netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_length < 30f) { NetNode.Flags nextTargetNodeFlags = netManager.m_nodes.m_buffer[nextTargetNodeId].m_flags; if ((nextTargetNodeFlags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) != NetNode.Flags.Junction || netManager.m_nodes.m_buffer[nextTargetNodeId].CountSegments() == 2) { uint nextLaneId = PathManager.GetLaneID(nextPosition); if (nextLaneId != 0u) { sufficientSpace = netManager.m_lanes.m_buffer[(int)((UIntPtr)nextLaneId)].CheckSpace(len); } } } if (!sufficientSpace) { maxSpeed = 0f; try { if (vehicleState != null) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to BLOCKED"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Blocked; } } catch (Exception e) { Log.Error("VehicleAI MayChangeSegment error while setting junction state to BLOCKED: " + e.ToString()); } return(false); } } } } checkTrafficLights = (!isJoinedJunction || hasCrossing); } else { #if DEBUG if (debug) { Log._Debug($"CustomVehicleAI.MayChangeSegment: Vehicle {vehicleId} is a train."); } #endif checkTrafficLights = true; } try { if (vehicleState != null && vehicleState.JunctionTransitState == VehicleJunctionTransitState.Blocked) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState from BLOCKED to ENTER"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Enter; } if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == 0) { if (hasTrafficLight && checkTrafficLights) { #if DEBUG if (debug) { Log._Debug($"CustomVehicleAI.MayChangeSegment: Node {targetNodeId} has a traffic light."); } #endif var destinationInfo = netManager.m_nodes.m_buffer[targetNodeId].Info; if (vehicleState != null && vehicleState.JunctionTransitState == VehicleJunctionTransitState.None) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to ENTER (1)"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Enter; } RoadBaseAI.TrafficLightState vehicleLightState; RoadBaseAI.TrafficLightState pedestrianLightState; bool vehicles; bool pedestrians; CustomRoadAI.GetTrafficLightState(vehicleId, ref vehicleData, targetNodeId, prevPos.m_segment, prevPos.m_lane, position.m_segment, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - prevTargetNodeLower8Bits, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians); if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car && isRecklessDriver) // no reckless driving at railroad crossings { vehicleLightState = RoadBaseAI.TrafficLightState.Green; } #if DEBUG if (debug) { Log._Debug($"CustomVehicleAI.MayChangeSegment: Vehicle {vehicleId} has {vehicleLightState} at node {targetNodeId}"); } #endif if (!vehicles && random >= 196u) { vehicles = true; RoadBaseAI.SetTrafficLightState(targetNodeId, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - prevTargetNodeLower8Bits, vehicleLightState, pedestrianLightState, vehicles, pedestrians); } var stopCar = false; switch (vehicleLightState) { case RoadBaseAI.TrafficLightState.RedToGreen: if (random < 60u) { stopCar = true; } else { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (RedToGreen)"); } #endif if (vehicleState != null) { vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave; } } break; case RoadBaseAI.TrafficLightState.Red: stopCar = true; break; case RoadBaseAI.TrafficLightState.GreenToRed: if (random >= 30u) { stopCar = true; } else if (vehicleState != null) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (GreenToRed)"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave; } break; } /*if ((vehicleLightState == RoadBaseAI.TrafficLightState.Green || vehicleLightState == RoadBaseAI.TrafficLightState.RedToGreen) && !Flags.getEnterWhenBlockedAllowed(prevPos.m_segment, netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode == targetNodeId)) { * var hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, targetNodeId); * * if (hasIncomingCars) { * // green light but other cars are incoming and they have priority: stop * stopCar = true; * } * }*/ if (stopCar) { if (vehicleState != null) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to STOP"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Stop; } maxSpeed = 0f; return(false); } } else if (vehicleState != null) { #if DEBUG //bool debug = destinationNodeId == 10864; //bool debug = destinationNodeId == 13531; //bool debug = false;// targetNodeId == 5027; #endif //bool debug = false; #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId} is arriving @ seg. {prevPos.m_segment} ({position.m_segment}, {nextPosition.m_segment}), node {targetNodeId} which is not a traffic light."); } #endif var prioritySegment = TrafficPriority.GetPrioritySegment(targetNodeId, prevPos.m_segment); if (prioritySegment != null) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId} is arriving @ seg. {prevPos.m_segment} ({position.m_segment}, {nextPosition.m_segment}), node {targetNodeId} which is not a traffic light and is a priority segment."); } #endif //if (prioritySegment.HasVehicle(vehicleId)) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: segment target position found"); } #endif #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: global target position found. carState = {vehicleState.JunctionTransitState.ToString()}"); } #endif var currentFrameIndex2 = Singleton <SimulationManager> .instance.m_currentFrameIndex; var frame = currentFrameIndex2 >> 4; float speed = lastFrameData.m_velocity.magnitude; if (vehicleState.JunctionTransitState == VehicleJunctionTransitState.None) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to ENTER (prio)"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Enter; } if (vehicleState.JunctionTransitState != VehicleJunctionTransitState.Leave) { bool hasIncomingCars; switch (prioritySegment.Type) { case SegmentEnd.PriorityType.Stop: #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: STOP sign. waittime={vehicleState.WaitTime}, vel={speed}"); } #endif if (Options.simAccuracy <= 2 || (Options.simAccuracy >= 3 && vehicleState.WaitTime < MaxPriorityWaitTime)) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to STOP (wait)"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Stop; if (speed <= TrafficPriority.maxStopVelocity) { vehicleState.WaitTime++; float minStopWaitTime = UnityEngine.Random.Range(0f, 3f); if (vehicleState.WaitTime >= minStopWaitTime) { if (Options.simAccuracy >= 4) { vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave; } else { hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, ref vehicleData, ref prevPos, ref position); #if DEBUG if (debug) { Log._Debug($"hasIncomingCars: {hasIncomingCars}"); } #endif if (hasIncomingCars) { maxSpeed = 0f; return(false); } #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (min wait timeout)"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave; } } else { maxSpeed = 0; return(false); } } else { vehicleState.WaitTime = 0; maxSpeed = 0f; return(false); } } else { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (max wait timeout)"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave; } break; case SegmentEnd.PriorityType.Yield: #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: YIELD sign. waittime={vehicleState.WaitTime}"); } #endif if (Options.simAccuracy <= 2 || (Options.simAccuracy >= 3 && vehicleState.WaitTime < MaxPriorityWaitTime)) { vehicleState.WaitTime++; #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to STOP (wait)"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Stop; if (speed <= TrafficPriority.maxYieldVelocity || Options.simAccuracy <= 2) { if (Options.simAccuracy >= 4) { vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave; } else { hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, ref vehicleData, ref prevPos, ref position); #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: hasIncomingCars: {hasIncomingCars}"); } #endif if (hasIncomingCars) { maxSpeed = 0f; return(false); } else { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (no incoming cars)"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave; } } } else { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Vehicle has not yet reached yield speed (reduce {speed} by {vehicleState.ReduceSpeedByValueToYield})"); } #endif // vehicle has not yet reached yield speed maxSpeed = TrafficPriority.maxYieldVelocity; return(false); } } else { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (max wait timeout)"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave; } break; case SegmentEnd.PriorityType.Main: case SegmentEnd.PriorityType.None: #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: MAIN sign. waittime={vehicleState.WaitTime}"); } #endif maxSpeed = 0f; if (Options.simAccuracy == 4) { return(true); } if (Options.simAccuracy <= 2 || (Options.simAccuracy == 3 && vehicleState.WaitTime < MaxPriorityWaitTime)) { vehicleState.WaitTime++; #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to STOP (wait)"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Stop; hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, ref vehicleData, ref prevPos, ref position); #if DEBUG if (debug) { Log._Debug($"hasIncomingCars: {hasIncomingCars}"); } #endif if (hasIncomingCars) { return(false); } #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (no conflicting car)"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave; } return(true); } } else if (speed <= TrafficPriority.maxStopVelocity) { // vehicle is not moving. reset allowance to leave junction #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState from LEAVE to BLOCKED (speed to low)"); } #endif vehicleState.JunctionTransitState = VehicleJunctionTransitState.Blocked; maxSpeed = 0f; return(false); } } } } } catch (Exception e) { Log.Error($"Error occured in MayChangeSegment: {e.ToString()}"); } maxSpeed = 0f; // maxSpeed should be set by caller return(true); }
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; }
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); } }
public void CustomCheckNextLane(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)) { 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 (CustomTrainAI.CheckOverlap(vehicleID, ref vehicleData, segment, vehicleID)) { maxSpeed = 0f; return; } } segment = new Segment3(vector, bezier.d); if (segment.LengthSqr() >= 1f && CustomTrainAI.CheckOverlap(vehicleID, ref vehicleData, segment, vehicleID)) { maxSpeed = 0f; return; } 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; if ((flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None) { uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; uint num4 = (uint)(((int)num3 << 8) / 32768); uint num5 = currentFrameIndex - num4 & 255u; RoadBaseAI.TrafficLightState vehicleLightState; RoadBaseAI.TrafficLightState pedestrianLightState; bool flag; bool pedestrians; /// NON-STOCK CODE START /// CustomRoadAI.GetTrafficLightState(vehicleID, ref vehicleData, num3, prevPos.m_segment, position.m_segment, ref instance.m_segments.m_buffer[(int)prevPos.m_segment], currentFrameIndex - num4, out vehicleLightState, out pedestrianLightState, out flag, out pedestrians); /// NON-STOCK CODE END /// //RoadBaseAI.GetTrafficLightState(num3, ref instance.m_segments.m_buffer[(int)prevPos.m_segment], currentFrameIndex - num4, out vehicleLightState, out pedestrianLightState, out flag, out pedestrians); if (!flag && num5 >= 196u) { flag = true; RoadBaseAI.SetTrafficLightState(num3, ref instance.m_segments.m_buffer[(int)prevPos.m_segment], currentFrameIndex - num4, vehicleLightState, pedestrianLightState, flag, pedestrians); } switch (vehicleLightState) { case RoadBaseAI.TrafficLightState.RedToGreen: if (num5 < 60u) { maxSpeed = 0f; return; } break; case RoadBaseAI.TrafficLightState.Red: maxSpeed = 0f; return; case RoadBaseAI.TrafficLightState.GreenToRed: if (num5 >= 30u) { maxSpeed = 0f; return; } break; } } } } }
public void CustomCalculateSegmentPosition(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, int index, out Vector3 pos, out Vector3 dir, out float maxSpeed) { var netManager = Singleton <NetManager> .instance; //var vehicleManager = Singleton<VehicleManager>.instance; netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir); bool isRecklessDriver = IsRecklessDriver(vehicleId, ref vehicleData); var lastFrameData = vehicleData.GetLastFrameData(); var lastFrameVehiclePos = lastFrameData.m_position; var camPos = Camera.main.transform.position; bool simulatePrioritySigns = (lastFrameVehiclePos - camPos).sqrMagnitude < FarLod && !isRecklessDriver; if (Options.simAccuracy <= 0) { if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car) { VehiclePosition vehiclePos = TrafficPriority.GetVehiclePosition(vehicleId); if (vehiclePos.Valid && simulatePrioritySigns) // TODO check if this should be !vehiclePos.Valid { try { CustomVehicleAI.HandleVehicle(vehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleId], false, false); } catch (Exception e) { Log.Error("CarAI TmCalculateSegmentPosition Error: " + e.ToString()); } } } else { //Log._Debug($"TmCalculateSegmentPosition does not handle vehicles of type {vehicleData.Info.m_vehicleType}"); } } // I think this is supposed to be the lane position? // [VN, 12/23/2015] It's the 3D car position on the Bezier curve of the lane. // This crazy 0.003921569f equals to 1f/255 and prevOffset is the byte value (0..255) of the car position. var vehiclePosOnBezier = netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].CalculatePosition(prevOffset * 0.003921569f); //ushort currentSegmentId = netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_segment; ushort destinationNodeId; ushort sourceNodeId; if (offset < position.m_offset) { destinationNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode; sourceNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode; } else { destinationNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode; sourceNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode; } var previousDestinationNode = prevOffset == 0 ? netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode : netManager.m_segments.m_buffer[prevPos.m_segment].m_endNode; // this seems to be like the required braking force in order to stop the vehicle within its half length. var crazyValue = 0.5f * lastFrameData.m_velocity.sqrMagnitude / m_info.m_braking + m_info.m_generatedInfo.m_size.z * 0.5f; // Essentially, this is true if the car has enough time and space to brake (e.g. for a red traffic light) if (destinationNodeId == previousDestinationNode) { if (Vector3.Distance(lastFrameVehiclePos, vehiclePosOnBezier) >= crazyValue - 1f) { var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; var num5 = (uint)((previousDestinationNode << 8) / 32768); var num6 = currentFrameIndex - num5 & 255u; var nodeFlags = netManager.m_nodes.m_buffer[destinationNodeId].m_flags; var prevLaneFlags = (NetLane.Flags)netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_flags; var hasTrafficLight = (nodeFlags & NetNode.Flags.TrafficLights) != NetNode.Flags.None; var hasCrossing = (nodeFlags & NetNode.Flags.LevelCrossing) != NetNode.Flags.None; var isJoinedJunction = (prevLaneFlags & NetLane.Flags.JoinedJunction) != NetLane.Flags.None; bool checkSpace = !Flags.getEnterWhenBlockedAllowed(prevPos.m_segment, netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode == destinationNodeId) && !isRecklessDriver; //TrafficLightSimulation nodeSim = TrafficLightSimulation.GetNodeSimulation(destinationNodeId); /*if (timedNode != null && timedNode.vehiclesMayEnterBlockedJunctions) { * checkSpace = false; * }*/ if (checkSpace) { // check if there is enough space if ((nodeFlags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) == NetNode.Flags.Junction && netManager.m_nodes.m_buffer[destinationNodeId].CountSegments() != 2) { var len = vehicleData.CalculateTotalLength(vehicleId) + 2f; if (!netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(len)) { var sufficientSpace = false; if (nextPosition.m_segment != 0 && netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_length < 30f) { var flags3 = netManager.m_nodes.m_buffer[sourceNodeId].m_flags; if ((flags3 & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) != NetNode.Flags.Junction || netManager.m_nodes.m_buffer[sourceNodeId].CountSegments() == 2) { var laneId2 = PathManager.GetLaneID(nextPosition); if (laneId2 != 0u) { sufficientSpace = netManager.m_lanes.m_buffer[(int)((UIntPtr)laneId2)].CheckSpace(len); } } } if (!sufficientSpace) { maxSpeed = 0f; return; } } } } try { VehiclePosition globalTargetPos = TrafficPriority.GetVehiclePosition(vehicleId); if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == 0) { if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car) { if (hasTrafficLight && (!isJoinedJunction || hasCrossing)) { var destinationInfo = netManager.m_nodes.m_buffer[destinationNodeId].Info; if (globalTargetPos.CarState == VehicleJunctionTransitState.None) { globalTargetPos.CarState = VehicleJunctionTransitState.Enter; } RoadBaseAI.TrafficLightState vehicleLightState; RoadBaseAI.TrafficLightState pedestrianLightState; bool vehicles; bool pedestrians; CustomRoadAI.GetTrafficLightState(vehicleId, ref vehicleData, destinationNodeId, prevPos.m_segment, position.m_segment, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - num5, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians); if (isRecklessDriver && (destinationInfo.GetConnectionClass().m_service & ItemClass.Service.PublicTransport) == ItemClass.Service.None) // no reckless driving at railroad crossings { vehicleLightState = RoadBaseAI.TrafficLightState.Green; } if (!vehicles && num6 >= 196u) { vehicles = true; RoadBaseAI.SetTrafficLightState(destinationNodeId, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - num5, vehicleLightState, pedestrianLightState, vehicles, pedestrians); } var stopCar = false; switch (vehicleLightState) { case RoadBaseAI.TrafficLightState.RedToGreen: if (num6 < 60u) { stopCar = true; } else { globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } break; case RoadBaseAI.TrafficLightState.Red: stopCar = true; break; case RoadBaseAI.TrafficLightState.GreenToRed: if (num6 >= 30u) { stopCar = true; } else { globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } break; } if ((vehicleLightState == RoadBaseAI.TrafficLightState.Green || vehicleLightState == RoadBaseAI.TrafficLightState.RedToGreen) && !Flags.getEnterWhenBlockedAllowed(prevPos.m_segment, netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode == destinationNodeId)) { var hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId); if (hasIncomingCars) { // green light but other cars are incoming and they have priority: stop stopCar = true; } } if (stopCar) { globalTargetPos.CarState = VehicleJunctionTransitState.Stop; maxSpeed = 0f; return; } } else if (simulatePrioritySigns) { #if DEBUG //bool debug = destinationNodeId == 10864; //bool debug = destinationNodeId == 13531; bool debug = false; #endif //bool debug = false; #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId} is arriving @ seg. {prevPos.m_segment} ({position.m_segment}, {nextPosition.m_segment}), node {destinationNodeId} which is not a traffic light."); } #endif var prioritySegment = TrafficPriority.GetPrioritySegment(destinationNodeId, prevPos.m_segment); if (prioritySegment != null) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId} is arriving @ seg. {prevPos.m_segment} ({position.m_segment}, {nextPosition.m_segment}), node {destinationNodeId} which is not a traffic light and is a priority segment."); } #endif if (prioritySegment.HasVehicle(vehicleId)) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: segment target position found"); } #endif if (globalTargetPos.Valid) { #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: global target position found. carState = {globalTargetPos.CarState.ToString()}"); } #endif var currentFrameIndex2 = Singleton <SimulationManager> .instance.m_currentFrameIndex; var frame = currentFrameIndex2 >> 4; if (globalTargetPos.CarState == VehicleJunctionTransitState.None) { globalTargetPos.CarState = VehicleJunctionTransitState.Enter; } if (globalTargetPos.CarState != VehicleJunctionTransitState.Leave) { bool hasIncomingCars; switch (prioritySegment.Type) { case SegmentEnd.PriorityType.Stop: #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: STOP sign. waittime={globalTargetPos.WaitTime}, vel={lastFrameData.m_velocity.magnitude}"); } #endif if (globalTargetPos.WaitTime < MaxPriorityWaitTime) { globalTargetPos.CarState = VehicleJunctionTransitState.Stop; if (lastFrameData.m_velocity.magnitude < 0.5f || globalTargetPos.Stopped) { globalTargetPos.Stopped = true; globalTargetPos.WaitTime++; float minStopWaitTime = Random.Range(0f, 3f); if (globalTargetPos.WaitTime >= minStopWaitTime) { hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId); #if DEBUG if (debug) { Log._Debug($"hasIncomingCars: {hasIncomingCars}"); } #endif if (hasIncomingCars) { maxSpeed = 0f; return; } globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } else { maxSpeed = 0; return; } } else { maxSpeed = 0f; return; } } else { globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } break; case SegmentEnd.PriorityType.Yield: #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: YIELD sign. waittime={globalTargetPos.WaitTime}"); } #endif if (globalTargetPos.WaitTime < MaxPriorityWaitTime) { globalTargetPos.WaitTime++; globalTargetPos.CarState = VehicleJunctionTransitState.Stop; hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId); #if DEBUG if (debug) { Log._Debug($"hasIncomingCars: {hasIncomingCars}"); } #endif if (hasIncomingCars) { if (lastFrameData.m_velocity.magnitude > 0) { maxSpeed = Math.Max(0f, lastFrameData.m_velocity.magnitude - globalTargetPos.ReduceSpeedByValueToYield); } else { maxSpeed = 0; } #if DEBUG /*if (TrafficPriority.Vehicles[vehicleId].ToNode == 8621) * Log.Message($"Vehicle {vehicleId} is yielding at node {destinationNodeId}. Speed: {maxSpeed}, Waiting time: {TrafficPriority.Vehicles[vehicleId].WaitTime}");*/ #endif return; } else { #if DEBUG /*if (TrafficPriority.Vehicles[vehicleId].ToNode == 8621) * Log.Message($"Vehicle {vehicleId} is NOT yielding at node {destinationNodeId}.");*/ #endif if (lastFrameData.m_velocity.magnitude > 0) { maxSpeed = Math.Max(1f, lastFrameData.m_velocity.magnitude - globalTargetPos.ReduceSpeedByValueToYield * 0.5f); } } globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } else { globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } break; case SegmentEnd.PriorityType.Main: #if DEBUG if (debug) { Log._Debug($"Vehicle {vehicleId}: MAIN sign. waittime={globalTargetPos.WaitTime}"); } #endif if (globalTargetPos.WaitTime < MaxPriorityWaitTime) { globalTargetPos.WaitTime++; globalTargetPos.CarState = VehicleJunctionTransitState.Stop; maxSpeed = 0f; hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId); #if DEBUG if (debug) { Log._Debug($"hasIncomingCars: {hasIncomingCars}"); } #endif if (hasIncomingCars) { globalTargetPos.Stopped = true; return; } globalTargetPos.CarState = VehicleJunctionTransitState.Leave; globalTargetPos.Stopped = false; } var info3 = netManager.m_segments.m_buffer[position.m_segment].Info; if (info3.m_lanes != null && info3.m_lanes.Length > position.m_lane) { //maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, info3.m_lanes[position.m_lane].m_speedLimit, netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve) * 0.8f; maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info3.m_lanes[position.m_lane]), netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve); } else { maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f); } return; } } else { globalTargetPos.CarState = VehicleJunctionTransitState.Leave; } } else { #if DEBUG if (debug) { Log._Debug($"globalTargetPos is null! {vehicleId} @ seg. {prevPos.m_segment} @ node {destinationNodeId}"); } #endif } } else { #if DEBUG if (debug) { Log._Debug($"targetPos is null! {vehicleId} @ seg. {prevPos.m_segment} @ node {destinationNodeId}"); } #endif } } } } } } catch (Exception e) { Log.Error($"Error occured in TmCalculateSegmentPosition: {e.ToString()}"); } } } var info2 = netManager.m_segments.m_buffer[position.m_segment].Info; if (info2.m_lanes != null && info2.m_lanes.Length > position.m_lane) { var laneSpeedLimit = SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info2.m_lanes[position.m_lane]); // info2.m_lanes[position.m_lane].m_speedLimit; #if DEBUG /*if (position.m_segment == 275) { * Log._Debug($"Applying lane speed limit of {laneSpeedLimit} to lane {laneID} @ seg. {position.m_segment}"); * }*/ #endif /*if (TrafficRoadRestrictions.IsSegment(position.m_segment)) { * var restrictionSegment = TrafficRoadRestrictions.GetSegment(position.m_segment); * * if (restrictionSegment.SpeedLimits[position.m_lane] > 0.1f) { * laneSpeedLimit = restrictionSegment.SpeedLimits[position.m_lane]; * } * }*/ maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve); } else { maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f); } maxSpeed = CalcMaxSpeed(vehicleId, ref vehicleData, position, pos, maxSpeed, isRecklessDriver); }
//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; } } } } }
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); } } }
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); }
public void CustomCalculateSegmentPosition(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, int index, out Vector3 pos, out Vector3 dir, out float maxSpeed) { NetManager instance = Singleton <NetManager> .instance; instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection((float)offset * 0.003921569f, out pos, out dir); Vector3 b = instance.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].CalculatePosition((float)prevOffset * 0.003921569f); Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData(); Vector3 a = lastFrameData.m_position; Vector3 a2 = lastFrameData.m_position; Vector3 b2 = lastFrameData.m_rotation * new Vector3(0f, 0f, this.m_info.m_generatedInfo.m_wheelBase * 0.5f); a += b2; a2 -= b2; float num = 0.5f * lastFrameData.m_velocity.sqrMagnitude / this.m_info.m_braking; float a3 = Vector3.Distance(a, b); float b3 = Vector3.Distance(a2, b); if (Mathf.Min(a3, b3) >= 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; bool checkSpace = !Options.allowEnterBlockedJunctions; // NON-STOCK CODE if (checkSpace && (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; RoadBaseAI.TrafficLightState vehicleLightState; RoadBaseAI.TrafficLightState pedestrianLightState; bool flag5; bool pedestrians; /// NON-STOCK CODE START /// CustomRoadAI.GetTrafficLightState(vehicleID, ref vehicleData, num4, prevPos.m_segment, position.m_segment, ref instance.m_segments.m_buffer[(int)prevPos.m_segment], currentFrameIndex - num5, out vehicleLightState, out pedestrianLightState, out flag5, out pedestrians); /// NON-STOCK CODE END /// //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); } 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 info = instance.m_segments.m_buffer[(int)position.m_segment].Info; if (info.m_lanes != null && info.m_lanes.Length > (int)position.m_lane) { //maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, info.m_lanes[(int)position.m_lane].m_speedLimit, instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve); maxSpeed = CalculateTargetSpeed(vehicleID, ref vehicleData, SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info.m_lanes[position.m_lane]), instance.m_lanes.m_buffer[laneID].m_curve); } else { maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1f, 0f); } }
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); }