/// <summary> /// build outgoing segment lists /// </summary> private void rebuildOutSegments() { var node = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId]; leftOutSegmentIds = new List <int>(); forwardOutSegmentIds = new List <int>(); rightOutSegmentIds = new List <int>(); for (var s = 0; s < 8; s++) { var toSegmentId = node.GetSegment(s); if (toSegmentId == 0) { continue; } if (TrafficPriority.IsLeftSegment(segmentId, toSegmentId, nodeId)) { leftOutSegmentIds.Add(toSegmentId); } else if (TrafficPriority.IsRightSegment(segmentId, toSegmentId, nodeId)) { rightOutSegmentIds.Add(toSegmentId); } else { forwardOutSegmentIds.Add(toSegmentId); } } }
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); } }