private static void AddLaneData(int i, Configuration configuration)
        {
            try {
                NetLane       lane  = Singleton <NetManager> .instance.m_lanes.m_buffer[i];
                NetLane.Flags flags = (NetLane.Flags)lane.m_flags;
                if ((flags & NetLane.Flags.LeftForwardRight) == NetLane.Flags.None)                 // only save lanes with explicit lane arrows
                {
                    return;
                }
                var laneSegmentId = lane.m_segment;
                if (laneSegmentId <= 0)
                {
                    return;
                }
                NetSegment segment = Singleton <NetManager> .instance.m_segments.m_buffer[laneSegmentId];
                if (segment.m_flags == NetSegment.Flags.None)
                {
                    return;
                }

                //if (TrafficPriority.PrioritySegments.ContainsKey(laneSegmentId)) {
                Log.Message($"Saving lane data for lane {i}, segment {laneSegmentId}");
                configuration.LaneFlags += $"{i}:{Singleton<NetManager>.instance.m_lanes.m_buffer[i].m_flags},";
                //}
            } catch (Exception e) {
                Log.Error($"Error saving NodeLaneData {e.Message}");
            }
        }
        static bool Prefix(NetLane.Flags ___m_stopFlag, VehicleInfo.VehicleType ___m_vehicleType, ushort nodeID, ref NetNode data, uint laneID, byte offset)
        {
            if (nodeID == 0 || !___m_vehicleType.IsValidTransport())
            {
                return(true);
            }
            var segment = Singleton <NetManager> .instance.m_lanes.m_buffer[laneID].m_segment;

            Log.Debug($"AddLaneConn on segment {segment}");
            var roadAi = Singleton <NetManager> .instance.m_segments.m_buffer[segment].Info.m_netAI;

            if (roadAi is not RoadBridgeAI)
            {
                return(true);
            }

            var flags = (NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[laneID].m_flags;

            flags |= ___m_stopFlag;
            Singleton <NetManager> .instance.m_lanes.m_buffer[laneID].m_flags = (ushort)flags;
            Log.Debug($"lane flags updated {(NetLane.Flags)Singleton<NetManager>.instance.m_lanes.m_buffer[laneID].m_flags}");
            if (roadAi is RoadBridgeAI roadBridgeAI)
            {
                roadBridgeAI.UpdateSegmentStopFlags(segment,
                                                    ref Singleton <NetManager> .instance.m_segments.m_buffer[segment]);
            }
            Log.Debug($"segment flags updated {Singleton<NetManager>.instance.m_segments.m_buffer[segment].m_flags}");
            return(true);
        }
Esempio n. 3
0
        static bool Prefix(NetLane.Flags ___m_stopFlag, VehicleInfo.VehicleType ___m_vehicleType, ushort nodeID, ref NetNode data)
        {
            if (nodeID == 0 || !___m_vehicleType.IsValidTransport())
            {
                return(true);
            }
            ushort segment = Singleton <NetManager> .instance.m_lanes.m_buffer[data.m_lane].m_segment;

            Log.Debug($"RemoveLaneConn on segment {segment}");
            NetAI roadAi = Singleton <NetManager> .instance.m_segments.m_buffer[segment].Info.m_netAI;

            if (!(roadAi is RoadBridgeAI))
            {
                return(true);
            }

            NetLane.Flags flags = (NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[data.m_lane].m_flags;
            flags &= ~___m_stopFlag;
            Singleton <NetManager> .instance.m_lanes.m_buffer[data.m_lane].m_flags = (ushort)flags;
            Log.Debug($"lane flags updated {(NetLane.Flags)Singleton<NetManager>.instance.m_lanes.m_buffer[data.m_lane].m_flags}");
            if (roadAi is RoadBridgeAI roadBridgeAI)
            {
                roadBridgeAI.UpdateSegmentStopFlags(segment, ref Singleton <NetManager> .instance.m_segments.m_buffer[segment]);
            }
            Log.Debug($"segment flags updated {Singleton<NetManager>.instance.m_segments.m_buffer[segment].m_flags}");
            return(true);
        }
        static void Postfix(uint __state)
        {
            if (__state == 0)
            {
                return;
            }

            NetLane lane = Singleton <NetManager> .instance.m_lanes.m_buffer[__state];

            int index = Singleton <SharedStopsTool> .instance.sharedStopSegments.FindIndex(s => s.m_lanes.Keys.Contains(__state));

            if (index == -1)
            {
                return;
            }

            foreach (var line in Singleton <SharedStopsTool> .instance.sharedStopSegments[index].m_lanes[__state])
            {
                NetLane.Flags stopflag = Singleton <TransportManager> .instance.m_lines.m_buffer[line].Info.m_stopFlag;
                if (((NetLane.Flags)lane.m_flags & stopflag) == stopflag)
                {
                    continue;
                }

                lane.m_flags |= (ushort)stopflag;
            }
            Singleton <NetManager> .instance.m_lanes.m_buffer[__state].m_flags = lane.m_flags;
            Log.Debug($"lane flags after update: {(NetLane.Flags)Singleton<NetManager>.instance.m_lanes.m_buffer[__state].m_flags}");

            Singleton <NetManager> .instance.UpdateSegmentFlags(Singleton <NetManager> .instance.m_lanes.m_buffer[__state].m_segment);

            Singleton <NetManager> .instance.UpdateSegmentRenderer(Singleton <NetManager> .instance.m_lanes.m_buffer[__state].m_segment, true);
        }
        static bool Prefix(out uint __state, VehicleInfo.VehicleType ___m_vehicleType, ushort nodeID, ref NetNode data)
        {
            __state = 0;
            if (nodeID == 0 || !___m_vehicleType.IsSharedStopTransport())
            {
                return(true);
            }
            ushort segment = Singleton <NetManager> .instance.m_lanes.m_buffer[data.m_lane].m_segment;

            ushort        lineID = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeID].m_transportLine;
            TransportLine line   = Singleton <TransportManager> .instance.m_lines.m_buffer[lineID];

            __state = data.m_lane;
            NetLane.Flags flags = (NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[data.m_lane].m_flags;
            if (!Singleton <SharedStopsTool> .instance.sharedStopSegments.Any(s => s.m_segment == segment))
            {
                return(true);
            }
            NetSegment segData = Singleton <NetManager> .instance.m_segments.m_buffer[segment];

            Log.Debug($"RemoveLaneConn on segment {segment}, {segData}");
            Singleton <SharedStopsTool> .instance.RemoveSharedStop(segment, lineID, data.m_lane);

            return(true);
        }
Esempio n. 6
0
        NetLanes(NetLane.Flags flags = NetLane.Flags.Created)
        {
            var mgr = Singleton <Cities::NetManager> .instance;

            return(mgr.m_lanes.m_buffer.Where(e =>
                                              ((NetLane.Flags)e.m_flags & flags) != NetLane.Flags.None
                                              ));
        }
Esempio n. 7
0
        /// <summary>
        /// Check lane flags contain at least one of the flags in <paramref name="flagMask"/>.
        /// </summary>
        ///
        /// <param name="laneId">The id of the lane to inspect.</param>
        /// <param name="flagMask">The flags to test for.</param>
        /// <param name="expectedResult">If specified, ensure only the expected flags are found.</param>
        ///
        /// <returns>Returns <c>true</c> if the test passes, otherwise <c>false</c>.</returns>
        public bool CheckLaneFlags(uint laneId,
                                   NetLane.Flags flagMask,
                                   NetLane.Flags?expectedResult = null)
        {
            uint result = Singleton <NetManager> .instance.m_lanes.m_buffer[laneId].m_flags & (uint)flagMask;

            return(expectedResult == null ? result != 0 : result == (uint)expectedResult);
        }
Esempio n. 8
0
 public static bool AllFlagsAreForward(ushort segmentID, bool startNode)
 {
     NetLane.Flags flags = 0;
     foreach (var lane in NetUtil.IterateLanes(segmentID, startNode:startNode))
     {
         flags |= lane.Flags;
     }
     return((flags & NetLane.Flags.LeftForwardRight) == NetLane.Flags.Forward);
 }
        public bool CheckLaneFlags(uint laneId, NetLane.Flags flagMask, NetLane.Flags?expectedResult = null)
        {
            bool ret = false;

            ProcessLane(laneId, delegate(uint lId, ref NetLane lane) {
                ret = LogicUtil.CheckFlags((uint)lane.m_flags, (uint)flagMask, (uint?)expectedResult);
                return(true);
            });
            return(ret);
        }
        protected override bool IsActive()
        {
            if (LaneId == 0)
            {
                Log.Error("LaneArrowButton: LaneId is 0, too bad");
                return(false);
            }

            NetLane.Flags flags = (NetLane.Flags)LaneId.ToLane().m_flags;
            return((flags & NetlaneFlagsMask) == NetlaneFlagsMask);
        }
 protected override bool IsActive()
 {
     if (LaneId == 0)
     {
         Log.Error("LaneArrowButton: LaneId is 0, too bad");
         return(false);
     }
     NetLane[]     lanesBuffer = Singleton <NetManager> .instance.m_lanes.m_buffer;
     NetLane.Flags flags       = (NetLane.Flags)lanesBuffer[LaneId].m_flags;
     return((flags & NetlaneFlagsMask) == NetlaneFlagsMask);
 }
Esempio n. 12
0
            public void UpdateArrows()
            {
                VerifyConnections();
                NetLane    lane    = NetManager.instance.m_lanes.m_buffer[m_laneId];
                NetSegment segment = NetManager.instance.m_segments.m_buffer[lane.m_segment];

                if ((m_nodeId == 0 && !FindNode(segment)) || NetManager.instance.m_nodes.m_buffer[m_nodeId].CountSegments() <= 2)
                {
                    return;
                }

                if (ConnectionCount() == 0)
                {
                    if ((lane.m_flags & TrafficManager_ImprovedAI.SerializableDataExtension.CONTROL_BIT) != TrafficManager_ImprovedAI.SerializableDataExtension.CONTROL_BIT)
                    {
                        SetDefaultArrows(lane.m_segment, ref NetManager.instance.m_segments.m_buffer[lane.m_segment]);
                    }
                    return;
                }

                NetLane.Flags flags = (NetLane.Flags)lane.m_flags;
                flags &= ~(NetLane.Flags.LeftForwardRight);

                Vector3 segDir = segment.GetDirection(m_nodeId);

                uint[] connections = GetConnectionsAsArray();
                foreach (uint connection in connections)
                {
                    ushort  seg = NetManager.instance.m_lanes.m_buffer[connection].m_segment;
                    Vector3 dir = NetManager.instance.m_segments.m_buffer[seg].GetDirection(m_nodeId);
                    if (Vector3.Angle(segDir, dir) > 150f)
                    {
                        flags |= NetLane.Flags.Forward;
                    }
                    else
                    {
                        if (Vector3.Dot(Vector3.Cross(segDir, -dir), Vector3.up) > 0f)
                        {
                            flags |= NetLane.Flags.Right;
                        }
                        else
                        {
                            flags |= NetLane.Flags.Left;
                        }
                    }
                }

                NetManager.instance.m_lanes.m_buffer[m_laneId].m_flags = (ushort)flags;
            }
Esempio n. 13
0
 public void DrawButton(uint lane, NetLane.Flags flag, Vector3 relativePosition)
 {
     this.laneId           = lane;
     this.toggleFlag       = (ushort)flag;
     this.relativePosition = relativePosition;
     this.normalBgSprite   = "ButtonMenu";
     this.disabledBgSprite = "ButtonMenuDisabled";
     this.hoveredBgSprite  = "ButtonMenuHovered";
     this.pressedBgSprite  = "ButtonMenuPressed";
     this.pressedColor     = new Color(0f, 0.6f, 0f);
     this.eventClick      += ButtonClick;
     this.text             = flag == NetLane.Flags.Forward ? "F" : flag == NetLane.Flags.Left ? "L" : "R";
     this.height           = 30;
     this.width            = 30;
     UpdateButtonState();
 }
        public static void UpdateSegmentStopFlags(this RoadBridgeAI roadbridge, ushort segmentID, ref NetSegment data)
        {
            Log.Debug($"updateflags on {segmentID}");
            roadbridge.UpdateSegmentFlags(segmentID, ref data);
            NetSegment.Flags flags = data.m_flags & ~(NetSegment.Flags.StopRight | NetSegment.Flags.StopLeft | NetSegment.Flags.StopRight2 | NetSegment.Flags.StopLeft2);
            if (roadbridge.m_info.m_lanes == null)
            {
                return;
            }
            NetManager instance = Singleton <NetManager> .instance;
            bool       inverted = (data.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None;
            uint       lane     = instance.m_segments.m_buffer[(int)segmentID].m_lanes;
            int        i        = 0;

            while (i < roadbridge.m_info.m_lanes.Length && lane != 0U)
            {
                NetLane.Flags laneFlags = (NetLane.Flags)instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].m_flags;
                if ((laneFlags & NetLane.Flags.Stop) != NetLane.Flags.None)
                {
                    if (roadbridge.m_info.m_lanes[i].m_position < 0f != inverted)
                    {
                        flags |= NetSegment.Flags.StopLeft;
                    }
                    else
                    {
                        flags |= NetSegment.Flags.StopRight;
                    }
                }
                else if ((laneFlags & NetLane.Flags.Stop2) != NetLane.Flags.None)
                {
                    if (roadbridge.m_info.m_lanes[i].m_position < 0f != inverted)
                    {
                        flags |= NetSegment.Flags.StopLeft2;
                    }
                    else
                    {
                        flags |= NetSegment.Flags.StopRight2;
                    }
                }
                lane = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].m_nextLane;
                i++;
            }
            data.m_flags = flags;
            Log.Debug($"flags {flags}");
        }
        public static void UpdateSegmentStopFlags(this RoadBridgeAI roadbridge, ushort segmentID, ref NetSegment data)
        {
            roadbridge.UpdateSegmentFlags(segmentID, ref data);
            var oldflags = data.m_flags;

            NetSegment.Flags flags = data.m_flags & ~(NetSegment.Flags.StopRight | NetSegment.Flags.StopLeft | NetSegment.Flags.StopRight2 | NetSegment.Flags.StopLeft2);
            if (roadbridge.m_info.m_lanes != null)
            {
                NetManager instance = Singleton <NetManager> .instance;
                bool       flag     = (data.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None;
                uint       num      = instance.m_segments.m_buffer[(int)segmentID].m_lanes;
                int        num2     = 0;
                while (num2 < roadbridge.m_info.m_lanes.Length && num != 0U)
                {
                    NetLane.Flags flags2 = (NetLane.Flags)instance.m_lanes.m_buffer[(int)((UIntPtr)num)].m_flags;
                    if ((flags2 & NetLane.Flags.Stop) != NetLane.Flags.None)
                    {
                        if (roadbridge.m_info.m_lanes[num2].m_position < 0f != flag)
                        {
                            flags |= NetSegment.Flags.StopLeft;
                        }
                        else
                        {
                            flags |= NetSegment.Flags.StopRight;
                        }
                    }
                    if ((flags2 & NetLane.Flags.Stop2) != NetLane.Flags.None)
                    {
                        if (roadbridge.m_info.m_lanes[num2].m_position < 0f != flag)
                        {
                            flags |= NetSegment.Flags.StopLeft2;
                        }
                        else
                        {
                            flags |= NetSegment.Flags.StopRight2;
                        }
                    }
                    num = instance.m_lanes.m_buffer[(int)((UIntPtr)num)].m_nextLane;
                    num2++;
                }
            }
            Log.Debug($"oldflags {oldflags} newflags {flags} on segment {segmentID} bridge");
            data.m_flags = flags;
        }
Esempio n. 16
0
        private static void UpdateLaneMarker(NetLane.Flags flag, NetInfo.Direction direction, NetSegment segment)
        {
            NetManager netManager  = NetManager.instance;
            NetLane    currentLane = netManager.m_lanes.m_buffer[segment.m_lanes];
            ulong      laneID      = segment.m_lanes;

            for (int i = 0; i < segment.Info.m_lanes.Length; i++)
            {
                if (segment.Info.m_lanes[i].m_direction == direction && segment.Info.m_lanes[i].m_laneType == NetInfo.LaneType.Vehicle && ((NetLane.Flags)currentLane.m_flags & flag) == flag)
                {
                    NetLane.Flags newFlags = (NetLane.Flags)currentLane.m_flags;
                    newFlags &= ~flag;
                    newFlags |= NetLane.Flags.Forward;
                    netManager.m_lanes.m_buffer[laneID].m_flags = (ushort)newFlags;
                }
                laneID      = currentLane.m_nextLane;
                currentLane = netManager.m_lanes.m_buffer[currentLane.m_nextLane];
            }
        }
        static bool Prefix(NetLane.Flags ___m_stopFlag, VehicleInfo.VehicleType ___m_vehicleType, ushort nodeID, ref NetNode data, uint laneID, byte offset)
        {
            if (nodeID == 0 || !___m_vehicleType.IsSharedStopTransport())
            {
                return(true);
            }

            ushort segment = Singleton <NetManager> .instance.m_lanes.m_buffer[laneID].m_segment;
            ushort lineID  = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeID].m_transportLine;

            if (Singleton <NetManager> .instance.m_segments.m_buffer[segment].Info.m_netAI is RoadBridgeAI roadBridgeAI)
            {
                NetLane.Flags flags = (NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[laneID].m_flags;
                flags |= ___m_stopFlag;
                Singleton <NetManager> .instance.m_lanes.m_buffer[laneID].m_flags = (ushort)flags;
                roadBridgeAI.UpdateSegmentStopFlags(segment, ref Singleton <NetManager> .instance.m_segments.m_buffer[segment]);
            }

            Singleton <SharedStopsTool> .instance.AddSharedStop(segment, lineID, laneID);

            return(true);
        }
Esempio n. 18
0
        public static bool CheckLaneConnection(uint lane1, uint lane2, ushort nodeID)
        {
            if ((NetManager.instance.m_lanes.m_buffer[lane1].m_flags & Lane.CONTROL_BIT) == Lane.CONTROL_BIT)
            {
                var lane = GetLane(lane1);
                if (lane != null && lane.ConnectionCount() > 0)
                {
                    return(CheckLaneConnection(lane1, lane2));
                }
            }

            ushort  seg1 = NetManager.instance.m_lanes.m_buffer[lane1].m_segment;
            ushort  seg2 = NetManager.instance.m_lanes.m_buffer[lane2].m_segment;
            Vector3 dir1 = NetManager.instance.m_segments.m_buffer[seg1].GetDirection(nodeID);
            Vector3 dir2 = NetManager.instance.m_segments.m_buffer[seg2].GetDirection(nodeID);

            NetLane.Flags flags = (NetLane.Flags)NetManager.instance.m_lanes.m_buffer[lane1].m_flags;

            if ((flags & NetLane.Flags.LeftForwardRight) == 0 || seg1 == seg2)
            {
                return(true);
            }
            else if (Vector3.Angle(dir1, dir2) > 150f)
            {
                return((flags & NetLane.Flags.Forward) == NetLane.Flags.Forward);
            }
            else
            {
                if (Vector3.Dot(Vector3.Cross(dir1, -dir2), Vector3.up) > 0f)
                {
                    return((flags & NetLane.Flags.Right) == NetLane.Flags.Right);
                }
                else
                {
                    return((flags & NetLane.Flags.Left) == NetLane.Flags.Left);
                }
            }
        }
Esempio n. 19
0
        private static void Mirror(ref NetLane.Flags direction)
        {
            switch (direction)
            {
            case NetLane.Flags.Left:
                direction = NetLane.Flags.Right;
                break;

            case NetLane.Flags.Right:
                direction = NetLane.Flags.Left;
                break;

            case NetLane.Flags.LeftForward:
                direction = NetLane.Flags.ForwardRight;
                break;

            case NetLane.Flags.ForwardRight:
                direction = NetLane.Flags.LeftForward;
                break;

            default:
                break;
            }
        }
Esempio n. 20
0
        protected override void CalculateSegmentPosition(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, int index, out Vector3 pos, out Vector3 dir, out float maxSpeed)
        {
            NetManager instance = Singleton <NetManager> .instance;

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

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

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

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

            if (info2.m_lanes != null && info2.m_lanes.Length > (int)position.m_lane)
            {
                maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, LaneManager.GetLaneSpeed(laneID, info2.m_lanes[(int)position.m_lane]), instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve);
            }
            else
            {
                maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1f, 0f);
            }
            if (instance.m_treatWetAsSnow)
            {
                DistrictManager instance2 = Singleton <DistrictManager> .instance;
                byte            district  = instance2.GetDistrict(pos);
                DistrictPolicies.CityPlanning cityPlanningPolicies = instance2.m_districts.m_buffer[(int)district].m_cityPlanningPolicies;
                if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.StuddedTires) != DistrictPolicies.CityPlanning.None)
                {
                    maxSpeed *= 1f - (float)instance.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.0005882353f;
                    District[] expr_5C2_cp_0 = instance2.m_districts.m_buffer;
                    byte       expr_5C2_cp_1 = district;
                    expr_5C2_cp_0[(int)expr_5C2_cp_1].m_cityPlanningPoliciesEffect = (expr_5C2_cp_0[(int)expr_5C2_cp_1].m_cityPlanningPoliciesEffect | DistrictPolicies.CityPlanning.StuddedTires);
                }
                else
                {
                    maxSpeed *= 1f - (float)instance.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.00117647066f;
                }
            }
            else
            {
                maxSpeed *= 1f - (float)instance.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.0005882353f;
            }
            maxSpeed *= 1f + (float)instance.m_segments.m_buffer[(int)position.m_segment].m_condition * 0.0005882353f;
        }
 internal static bool IsFlagSet(this NetLane.Flags value, NetLane.Flags flag) => (value & flag) != 0;
        //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;
                        }
                    }
                }
            }
        }
Esempio n. 23
0
        public static void Postfix(ref NetSegment __instance)
        {
            if (__instance.m_flags != NetSegment.Flags.None)
            {
                var m_info = __instance.Info;
                if (m_info == null)
                {
                    return;
                }

                if (__instance.m_lanes != 0u || (m_info.m_lanes != null && m_info.m_lanes.Length != 0))
                {
                    //Patch Begin
                    NetManager instance  = Singleton <NetManager> .instance;
                    uint       firstLane = __instance.m_lanes;
                    float      num       = 0f;
                    float      num2      = 0f;
                    if ((m_info.m_netAI is RoadAI) || (m_info.m_netAI is RoadBridgeAI) || (m_info.m_netAI is RoadTunnelAI))
                    {
                        if (CSURUtil.IsCSURLaneOffset(m_info))
                        {
                            for (int i = 0; i < m_info.m_lanes.Length; i++)
                            {
                                if (firstLane == 0)
                                {
                                    break;
                                }
                                float        laneOffset     = 0;
                                NetInfo.Lane lane           = m_info.m_lanes[i];
                                float        laneOffsetUnit = CSURUtil.CSURLaneOffset(m_info, lane);
                                laneOffset = laneOffsetUnit * 3.75f;
                                //DebugLog.LogToFileOnly("lanepostion = " + lane.m_position.ToString() + " laneoffset = " + laneOffset.ToString());
                                float effort = (OptionUI.smoothLevel == 2) ? 0.002f : (OptionUI.smoothLevel == 1) ? 0.01f : 0.05f;
                                //EG: before patch: point1-point4 is 1.5*3.75
                                //After patch, point1-point4 is (1 1.3333 1.6667 2)*3.75
                                var     bezier        = instance.m_lanes.m_buffer[firstLane].m_bezier;
                                Vector3 newBezierA    = bezier.Position(0) + (new Vector3(-bezier.Tangent(0).z, 0, bezier.Tangent(0).x).normalized) * (laneOffset * 0.5f);
                                Vector3 newBezierA1   = bezier.Position(effort) + (new Vector3(-bezier.Tangent(effort).z, 0, bezier.Tangent(effort).x).normalized) * (laneOffset * (0.5f - effort));
                                Vector3 newBezierADir = VectorUtils.NormalizeXZ(newBezierA1 - newBezierA);
                                Vector3 newBezierD    = bezier.Position(1) + (new Vector3(bezier.Tangent(1).z, 0, -bezier.Tangent(1).x).normalized) * (laneOffset * 0.5f);
                                Vector3 newBezierD1   = bezier.Position(1f - effort) + (new Vector3(bezier.Tangent(1f - effort).z, 0, -bezier.Tangent(1f - effort).x).normalized) * (laneOffset * (0.5f - effort));
                                Vector3 newBezierDDir = VectorUtils.NormalizeXZ(newBezierD1 - newBezierD);

                                Bezier3 newBezier = default(Bezier3);
                                newBezier.a = newBezierA;
                                newBezier.d = newBezierD;

                                //Try to get smooth bezier as close as real roadmesh
                                NetSegment.CalculateMiddlePoints(newBezierA, newBezierADir, newBezierD, newBezierDDir, true, true, out newBezier.b, out newBezier.c);

                                instance.m_lanes.m_buffer[firstLane].m_bezier = newBezier;
                                num      += instance.m_lanes.m_buffer[firstLane].UpdateLength();
                                num2     += 1f;
                                firstLane = instance.m_lanes.m_buffer[firstLane].m_nextLane;
                            }

                            if (num2 != 0f)
                            {
                                __instance.m_averageLength = num / num2;
                            }
                            else
                            {
                                __instance.m_averageLength = 0f;
                            }
                            bool flag7 = false;
                            if (__instance.m_averageLength < 11f && (instance.m_nodes.m_buffer[__instance.m_startNode].m_flags & NetNode.Flags.Junction) != 0 && (instance.m_nodes.m_buffer[__instance.m_endNode].m_flags & NetNode.Flags.Junction) != 0)
                            {
                                flag7 = true;
                            }
                            firstLane = __instance.m_lanes;
                            for (int j = 0; j < m_info.m_lanes.Length; j++)
                            {
                                if (firstLane == 0)
                                {
                                    break;
                                }
                                NetLane.Flags flags4 = (NetLane.Flags)(instance.m_lanes.m_buffer[firstLane].m_flags & -9);
                                if (flag7)
                                {
                                    flags4 |= NetLane.Flags.JoinedJunction;
                                }
                                instance.m_lanes.m_buffer[firstLane].m_flags = (ushort)flags4;
                                firstLane = instance.m_lanes.m_buffer[firstLane].m_nextLane;
                            }
                        }
                        //Patch End
                    }
                }
            }
        }
Esempio n. 24
0
        public static void Postfix(ref NetSegment __instance)
        {
            if (__instance.m_flags != NetSegment.Flags.None)
            {
                var m_info = __instance.Info;
                if (m_info == null)
                {
                    return;
                }

                if (__instance.m_lanes != 0u || (m_info.m_lanes != null && m_info.m_lanes.Length != 0))
                {
                    //Patch Begin
                    NetManager instance  = Singleton <NetManager> .instance;
                    uint       firstLane = __instance.m_lanes;
                    float      num       = 0f;
                    float      num2      = 0f;
                    if ((m_info.m_netAI is RoadAI) || (m_info.m_netAI is RoadBridgeAI) || (m_info.m_netAI is RoadTunnelAI))
                    {
                        if (CSURUtil.IsCSURLaneOffset(m_info))
                        {
                            for (int i = 0; i < m_info.m_lanes.Length; i++)
                            {
                                if (firstLane == 0)
                                {
                                    break;
                                }

                                //Thanks for macsergey to optimize this
                                var laneInfo       = m_info.m_lanes[i];
                                var laneOffsetUnit = CSURUtil.CSURLaneOffset(m_info, laneInfo);
                                var laneOffset     = laneOffsetUnit * 3.75f;
                                var startDir       = __instance.m_startDirection;
                                var endDir         = __instance.m_endDirection;
                                var bezier         = instance.m_lanes.m_buffer[firstLane].m_bezier;

                                var newBezier = MathLine(startDir, endDir, bezier, laneOffset);
                                //Thanks end.

                                instance.m_lanes.m_buffer[firstLane].m_bezier = newBezier;
                                instance.m_lanes.m_buffer[firstLane].UpdateLength();
                                num2     += 1f;
                                firstLane = instance.m_lanes.m_buffer[firstLane].m_nextLane;
                            }

                            if (num2 != 0f)
                            {
                                __instance.m_averageLength = num / num2;
                            }
                            else
                            {
                                __instance.m_averageLength = 0f;
                            }
                            bool flag7 = false;
                            if (__instance.m_averageLength < 11f && (instance.m_nodes.m_buffer[__instance.m_startNode].m_flags & NetNode.Flags.Junction) != 0 && (instance.m_nodes.m_buffer[__instance.m_endNode].m_flags & NetNode.Flags.Junction) != 0)
                            {
                                flag7 = true;
                            }
                            firstLane = __instance.m_lanes;
                            for (int j = 0; j < m_info.m_lanes.Length; j++)
                            {
                                if (firstLane == 0)
                                {
                                    break;
                                }
                                NetLane.Flags flags4 = (NetLane.Flags)(instance.m_lanes.m_buffer[firstLane].m_flags & -9);
                                if (flag7)
                                {
                                    flags4 |= NetLane.Flags.JoinedJunction;
                                }
                                instance.m_lanes.m_buffer[firstLane].m_flags = (ushort)flags4;
                                firstLane = instance.m_lanes.m_buffer[firstLane].m_nextLane;
                            }
                        }
                        //Patch End
                    }
                }
            }
        }
        private bool GetStopPosition(TransportInfo info, ushort segment, ushort building, ushort firstStop, ref Vector3 hitPos, out bool fixedPlatform)
        {
            //begin mod(+): detect key
            bool alternateMode = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
            //end mod

            NetManager       instance1 = Singleton <NetManager> .instance;
            BuildingManager  instance2 = Singleton <BuildingManager> .instance;
            TransportManager instance3 = Singleton <TransportManager> .instance;

            fixedPlatform = false;
            if (info.m_transportType == TransportInfo.TransportType.Pedestrian)
            {
                Vector3 position   = Vector3.zero;
                float   laneOffset = 0.0f;
                uint    laneID     = 0;
                int     laneIndex;
                if ((int)segment != 0 && !instance1.m_segments.m_buffer[(int)segment].GetClosestLanePosition(hitPos, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, VehicleInfo.VehicleType.None, out position, out laneID, out laneIndex, out laneOffset))
                {
                    laneID = 0U;
                    if ((instance1.m_segments.m_buffer[(int)segment].m_flags & NetSegment.Flags.Untouchable) != NetSegment.Flags.None && (int)building == 0)
                    {
                        building = NetSegment.FindOwnerBuilding(segment, 363f);
                    }
                }
                if ((int)building != 0)
                {
                    if (instance2.m_buildings.m_buffer[(int)building].Info.m_hasPedestrianPaths)
                    {
                        laneID = instance2.m_buildings.m_buffer[(int)building].FindLane(NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, hitPos, out position, out laneOffset);
                    }
                    if ((int)laneID == 0)
                    {
                        Vector3 sidewalkPosition = instance2.m_buildings.m_buffer[(int)building].CalculateSidewalkPosition();
                        laneID = instance2.m_buildings.m_buffer[(int)building].FindAccessLane(NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, sidewalkPosition, out position, out laneOffset);
                    }
                }
                if ((int)laneID == 0)
                {
                    return(false);
                }
                if ((double)laneOffset < 0.00392156885936856)
                {
                    laneOffset = 0.003921569f;
                    position   = instance1.m_lanes.m_buffer[laneID].CalculatePosition(laneOffset);
                }
                else if ((double)laneOffset > 0.996078431606293)
                {
                    laneOffset = 0.9960784f;
                    position   = instance1.m_lanes.m_buffer[laneID].CalculatePosition(laneOffset);
                }
                if ((int)this.m_line != 0)
                {
                    firstStop = instance3.m_lines.m_buffer[(int)this.m_line].m_stops;
                    ushort stop = firstStop;
                    int    num  = 0;
                    while ((int)stop != 0)
                    {
                        if ((int)instance1.m_nodes.m_buffer[(int)stop].m_lane == (int)laneID)
                        {
                            hitPos        = instance1.m_nodes.m_buffer[(int)stop].m_position;
                            fixedPlatform = true;
                            return(true);
                        }
                        stop = TransportLine.GetNextStop(stop);
                        if ((int)stop != (int)firstStop)
                        {
                            if (++num >= 32768)
                            {
                                CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + System.Environment.StackTrace);

                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                hitPos        = position;
                fixedPlatform = true;
                return(true);
            }
            if ((int)segment != 0)
            {
                if ((instance1.m_segments.m_buffer[(int)segment].m_flags & NetSegment.Flags.Untouchable) != NetSegment.Flags.None)
                {
                    building = NetSegment.FindOwnerBuilding(segment, 363f);
                    if ((int)building != 0)
                    {
                        BuildingInfo  info1 = instance2.m_buildings.m_buffer[(int)building].Info;
                        TransportInfo transportLineInfo1 = info1.m_buildingAI.GetTransportLineInfo();
                        TransportInfo transportLineInfo2 = info1.m_buildingAI.GetSecondaryTransportLineInfo();
                        //begin mod(*): check for !alternateMode
                        if (!alternateMode && transportLineInfo1 != null && transportLineInfo1.m_transportType == info.m_transportType || !alternateMode && transportLineInfo2 != null && transportLineInfo2.m_transportType == info.m_transportType)
                        {
                            //end mod
                            segment = (ushort)0;
                        }
                        else
                        {
                            building = (ushort)0;
                        }
                    }
                }
                Vector3 position1;
                uint    laneID1;
                int     laneIndex1;
                float   laneOffset1;
                if ((int)segment != 0 && instance1.m_segments.m_buffer[(int)segment].GetClosestLanePosition(hitPos, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, info.m_vehicleType, out position1, out laneID1, out laneIndex1, out laneOffset1))
                {
                    if (info.m_vehicleType == VehicleInfo.VehicleType.None)
                    {
                        NetLane.Flags flags1 = (NetLane.Flags)((int)instance1.m_lanes.m_buffer[laneID1].m_flags & 768);
                        NetLane.Flags flags2 = info.m_stopFlag;
                        NetInfo       info1  = instance1.m_segments.m_buffer[(int)segment].Info;
                        if (info1.m_vehicleTypes != VehicleInfo.VehicleType.None)
                        {
                            flags2 = NetLane.Flags.None;
                        }
                        if (flags1 != NetLane.Flags.None && flags2 != NetLane.Flags.None && flags1 != flags2)
                        {
                            return(false);
                        }
                        float stopOffset = info1.m_lanes[laneIndex1].m_stopOffset;
                        if ((instance1.m_segments.m_buffer[(int)segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
                        {
                            stopOffset = -stopOffset;
                        }
                        Vector3 direction;
                        instance1.m_lanes.m_buffer[laneID1].CalculateStopPositionAndDirection(0.5019608f, stopOffset, out hitPos, out direction);
                        fixedPlatform = true;
                        return(true);
                    }
                    Vector3 position2;
                    uint    laneID2;
                    int     laneIndex2;
                    float   laneOffset2;
                    if (instance1.m_segments.m_buffer[(int)segment].GetClosestLanePosition(position1, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, out position2, out laneID2, out laneIndex2, out laneOffset2))
                    {
                        NetLane.Flags flags = (NetLane.Flags)((int)instance1.m_lanes.m_buffer[laneID1].m_flags & 768);
                        if (flags != NetLane.Flags.None && info.m_stopFlag != NetLane.Flags.None && flags != info.m_stopFlag)
                        {
                            return(false);
                        }
                        float stopOffset = instance1.m_segments.m_buffer[(int)segment].Info.m_lanes[laneIndex2].m_stopOffset;
                        if ((instance1.m_segments.m_buffer[(int)segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
                        {
                            stopOffset = -stopOffset;
                        }
                        Vector3 direction;
                        instance1.m_lanes.m_buffer[laneID2].CalculateStopPositionAndDirection(0.5019608f, stopOffset, out hitPos, out direction);
                        fixedPlatform = true;
                        return(true);
                    }
                }
            }
            //begin mod(*): check for !alternateMode
            if (!alternateMode && (int)building != 0)
            {
                //end mod
                ushort num1 = 0;
                if ((instance2.m_buildings.m_buffer[(int)building].m_flags & Building.Flags.Untouchable) != Building.Flags.None)
                {
                    num1 = Building.FindParentBuilding(building);
                }
                if (this.m_building != 0 && (int)firstStop != 0 && (this.m_building == (int)building || this.m_building == (int)num1))
                {
                    hitPos = instance1.m_nodes.m_buffer[(int)firstStop].m_position;
                    return(true);
                }
                VehicleInfo randomVehicleInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(ref Singleton <SimulationManager> .instance.m_randomizer, info.m_class.m_service, info.m_class.m_subService, info.m_class.m_level);

                if (randomVehicleInfo != null)
                {
                    BuildingInfo  info1 = instance2.m_buildings.m_buffer[(int)building].Info;
                    TransportInfo transportLineInfo1 = info1.m_buildingAI.GetTransportLineInfo();
                    if (transportLineInfo1 == null && (int)num1 != 0)
                    {
                        building           = num1;
                        info1              = instance2.m_buildings.m_buffer[(int)building].Info;
                        transportLineInfo1 = info1.m_buildingAI.GetTransportLineInfo();
                    }
                    TransportInfo transportLineInfo2 = info1.m_buildingAI.GetSecondaryTransportLineInfo();
                    if (transportLineInfo1 != null && transportLineInfo1.m_transportType == info.m_transportType || transportLineInfo2 != null && transportLineInfo2.m_transportType == info.m_transportType)
                    {
                        Vector3 vector3 = Vector3.zero;
                        int     num2    = 1000000;
                        for (int index = 0; index < 12; ++index)
                        {
                            Randomizer randomizer = new Randomizer((ulong)index);
                            Vector3    position;
                            Vector3    target;
                            info1.m_buildingAI.CalculateSpawnPosition(building, ref instance2.m_buildings.m_buffer[(int)building], ref randomizer, randomVehicleInfo, out position, out target);
                            int num3 = 0;
                            if (info.m_avoidSameStopPlatform)
                            {
                                num3 = this.GetLineCount(position, target - position, info.m_transportType);
                            }
                            if (num3 < num2)
                            {
                                vector3 = position;
                                num2    = num3;
                            }
                            else if (num3 == num2 && (double)Vector3.SqrMagnitude(position - hitPos) < (double)Vector3.SqrMagnitude(vector3 - hitPos))
                            {
                                vector3 = position;
                            }
                        }
                        if ((int)firstStop != 0)
                        {
                            Vector3 position = instance1.m_nodes.m_buffer[(int)firstStop].m_position;
                            if ((double)Vector3.SqrMagnitude(position - vector3) < 16384.0)
                            {
                                uint lane = instance1.m_nodes.m_buffer[(int)firstStop].m_lane;
                                if ((int)lane != 0)
                                {
                                    ushort segment1 = instance1.m_lanes.m_buffer[lane].m_segment;
                                    if ((int)segment1 != 0 && (instance1.m_segments.m_buffer[(int)segment1].m_flags & NetSegment.Flags.Untouchable) != NetSegment.Flags.None)
                                    {
                                        ushort ownerBuilding = NetSegment.FindOwnerBuilding(segment1, 363f);
                                        if ((int)building == (int)ownerBuilding)
                                        {
                                            hitPos = position;
                                            return(true);
                                        }
                                    }
                                }
                            }
                        }
                        hitPos = vector3;
                        return(num2 != 1000000);
                    }
                }
            }
            return(false);
        }
Esempio n. 26
0
        // RoadBaseAI
        public override void UpdateLanes(ushort segmentID, ref NetSegment segment, bool loading)
        {
            bool LHT = Singleton <SimulationManager> .instance.m_metaData.m_invertTraffic == SimulationMetaData.MetaBool.True;

            segment.CalculateCorner(segmentID, heightOffset: true, start: true, true,
                                    out var cornerPosStartLeft, out var cornerDirStartLeft, out _);
            segment.CalculateCorner(segmentID, heightOffset: true, start: false, leftSide: true,
                                    out var cornerPosEndLeft, out var cornerDirEndLeft, out bool smoothStart);
            segment.CalculateCorner(segmentID, heightOffset: true, start: true, leftSide: false,
                                    out var cornerPosStartRight, out var cornerDirStartRight, out _);
            segment.CalculateCorner(segmentID, heightOffset: true, start: false, leftSide: false,
                                    out var cornerPosEndRight, out var cornerDirEndRight, out bool smoothEnd);

            if (segment.m_flags.IsFlagSet(NetSegment.Flags.Invert))
            {
                segment.m_cornerAngleStart = (byte)(Mathf.RoundToInt(Mathf.Atan2(cornerPosStartRight.z - cornerPosStartLeft.z, cornerPosStartRight.x - cornerPosStartLeft.x) * 40.7436638f) & 255);
                segment.m_cornerAngleEnd   = (byte)(Mathf.RoundToInt(Mathf.Atan2(cornerPosEndLeft.z - cornerPosEndRight.z, cornerPosEndLeft.x - cornerPosEndRight.x) * 40.7436638f) & 255);
            }
            else
            {
                segment.m_cornerAngleStart = (byte)(Mathf.RoundToInt(Mathf.Atan2(cornerPosStartLeft.z - cornerPosStartRight.z, cornerPosStartLeft.x - cornerPosStartRight.x) * 40.7436638f) & 255);
                segment.m_cornerAngleEnd   = (byte)(Mathf.RoundToInt(Mathf.Atan2(cornerPosEndRight.z - cornerPosEndLeft.z, cornerPosEndRight.x - cornerPosEndLeft.x) * 40.7436638f) & 255);
            }
            int  endLeft     = 0;
            int  endForward  = 0;
            int  endRight    = 0;
            int  endLeft2    = 0;
            int  endForward2 = 0;
            int  endRight2   = 0;
            bool flag2       = false;
            bool flag3       = false;

            segment.m_endNode.ToNode().CountLanes(segment.m_endNode, segmentID,
                                                  NetInfo.Direction.Forward, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car,
                                                  -segment.m_endDirection, ref endLeft, ref endForward, ref endRight, ref endLeft2, ref endForward2, ref endRight2);
            if (segment.m_endNode.ToNode().m_flags.IsFlagSet(
                    NetNode.Flags.End | NetNode.Flags.Middle | NetNode.Flags.Bend | NetNode.Flags.Outside))
            {
                if (endLeft + endForward + endRight == 0)
                {
                    flag3 = true;
                }
                else
                {
                    flag2 = true;
                }
            }
            int  startLeft     = 0;
            int  startForward  = 0;
            int  startRight    = 0;
            int  startLeft2    = 0;
            int  startForward2 = 0;
            int  startRight2   = 0;
            bool hasStartLanes = false;
            bool noStartLanes  = false;

            segment.m_startNode.ToNode().CountLanes(
                segment.m_startNode, segmentID,
                NetInfo.Direction.Forward, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car,
                -segment.m_startDirection, ref startLeft, ref startForward, ref startRight, ref startLeft2, ref startForward2, ref startRight2);
            if (segment.m_startNode.ToNode().m_flags.IsFlagSet(NetNode.Flags.End | NetNode.Flags.Middle | NetNode.Flags.Bend | NetNode.Flags.Outside))
            {
                if (startLeft + startForward + startRight == 0)
                {
                    noStartLanes = true;
                }
                else
                {
                    hasStartLanes = true;
                }
            }
            NetLane.Flags flags = NetLane.Flags.None;
            if (endLeft2 != 0 && endLeft == 0)
            {
                flags |= segment.m_flags.IsFlagSet(NetSegment.Flags.Invert) ? NetLane.Flags.EndOneWayLeft : NetLane.Flags.StartOneWayLeft;
            }
            if (endRight2 != 0 && endRight == 0)
            {
                flags |= segment.m_flags.IsFlagSet(NetSegment.Flags.Invert) ? NetLane.Flags.EndOneWayRight : NetLane.Flags.StartOneWayRight;
            }
            if (startLeft2 != 0 && startLeft == 0)
            {
                flags |= segment.m_flags.IsFlagSet(NetSegment.Flags.Invert)? NetLane.Flags.StartOneWayLeft : NetLane.Flags.EndOneWayLeft;
            }
            if (startRight2 != 0 && startRight == 0)
            {
                flags |= segment.m_flags.IsFlagSet(NetSegment.Flags.Invert)  ? NetLane.Flags.StartOneWayRight : NetLane.Flags.EndOneWayRight;
            }
            if ((segment.m_flags.IsFlagSet(NetSegment.Flags.YieldStart)))
            {
                flags |= segment.m_flags.IsFlagSet(NetSegment.Flags.Invert)  ? NetLane.Flags.YieldStart : NetLane.Flags.YieldEnd;
            }
            if ((segment.m_flags.IsFlagSet(NetSegment.Flags.YieldEnd)))
            {
                flags |= segment.m_flags.IsFlagSet(NetSegment.Flags.Invert)? NetLane.Flags.YieldEnd : NetLane.Flags.YieldStart;
            }
            float lengthAcc   = 0f;
            float lengthCount = 0f;
            uint  prevLaneID  = 0u;
            uint  laneID      = segment.m_lanes;

            for (int i = 0; i < this.m_info.m_lanes.Length; i++)
            {
                if (laneID == 0u)
                {
                    if (!NetManager.instance.CreateLanes(out laneID, ref Singleton <SimulationManager> .instance.m_randomizer, segmentID, 1))
                    {
                        break;
                    }
                    if (prevLaneID != 0u)
                    {
                        NetManager.instance.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_nextLane = laneID;
                    }
                    else
                    {
                        segment.m_lanes = laneID;
                    }
                }
                NetInfo.Lane lane      = this.m_info.m_lanes[i];
                float        lanePos01 = lane.m_position / (this.m_info.m_halfWidth * 2f) + 0.5f;
                if ((segment.m_flags.IsFlagSet(NetSegment.Flags.Invert)))
                {
                    lanePos01 = 1f - lanePos01;
                }
                Vector3 startPos = cornerPosStartLeft + (cornerPosStartRight - cornerPosStartLeft) * lanePos01;
                Vector3 startDir = Vector3.Lerp(cornerDirStartLeft, cornerDirStartRight, lanePos01);
                Vector3 endPos   = cornerPosEndRight + (cornerPosEndLeft - cornerPosEndRight) * lanePos01;
                Vector3 endDir   = Vector3.Lerp(cornerDirEndRight, cornerDirEndLeft, lanePos01);
                startPos.y += lane.m_verticalOffset;
                endPos.y   += lane.m_verticalOffset;
                NetSegment.CalculateMiddlePoints(startPos, startDir, endPos, endDir, smoothStart, smoothEnd, out var b, out var c);
                NetLane.Flags flags2 = laneID.ToLane().Flags();
                NetLane.Flags flags3 = flags;
                flags2 &= ~(NetLane.Flags.Forward | NetLane.Flags.Left | NetLane.Flags.Right | NetLane.Flags.Merge | NetLane.Flags.YieldStart | NetLane.Flags.YieldEnd | NetLane.Flags.StartOneWayLeft | NetLane.Flags.StartOneWayRight | NetLane.Flags.EndOneWayLeft | NetLane.Flags.EndOneWayRight);
                if ((byte)(lane.m_finalDirection & NetInfo.Direction.Both) == 2)
                {
                    flags3 &= ~NetLane.Flags.YieldEnd;
                }
                if ((byte)(lane.m_finalDirection & NetInfo.Direction.Both) == 1)
                {
                    flags3 &= ~NetLane.Flags.YieldStart;
                }
                if ((lane.m_vehicleType & VehicleInfo.VehicleType.Monorail) != VehicleInfo.VehicleType.None)
                {
                    flags3 &= ~(NetLane.Flags.YieldStart | NetLane.Flags.YieldEnd);
                }
                flags2 |= flags3;
                if (LHT)
                {
                    flags2 |= NetLane.Flags.Inverted;
                }
                else
                {
                    flags2 &= ~NetLane.Flags.Inverted;
                }
                int tailInnerPortion = 0;
                int tailOuterPortion = 255;
                if ((byte)(lane.m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0)
                {
                    bool backward = lane.m_finalDirection.IsFlagSet(NetInfo.Direction.Forward) == segment.m_flags.IsFlagSet(NetSegment.Flags.Invert);
                    int  tailLeft;
                    int  tailForward;
                    int  tailRight;
                    if (backward)
                    {
                        tailLeft    = endLeft;
                        tailForward = endForward;
                        tailRight   = endRight;
                    }
                    else
                    {
                        tailLeft    = startLeft;
                        tailForward = startForward;
                        tailRight   = startRight;
                    }
                    int innterSimilarLaneIndex;
                    int outerSimilarLaneIndex;
                    if ((byte)(lane.m_finalDirection & NetInfo.Direction.Forward) != 0)
                    {
                        innterSimilarLaneIndex = lane.m_similarLaneIndex;
                        outerSimilarLaneIndex  = lane.m_similarLaneCount - lane.m_similarLaneIndex - 1;
                    }
                    else
                    {
                        innterSimilarLaneIndex = lane.m_similarLaneCount - lane.m_similarLaneIndex - 1;
                        outerSimilarLaneIndex  = lane.m_similarLaneIndex;
                    }
                    int totalTail = tailLeft + tailForward + tailRight;
                    tailInnerPortion = 255;
                    tailOuterPortion = 0;
                    if (totalTail != 0)
                    {
                        if (lane.m_similarLaneCount > totalTail && totalTail > 0)
                        {
                            tailInnerPortion = totalTail * innterSimilarLaneIndex / lane.m_similarLaneCount;
                            tailOuterPortion = totalTail - totalTail * outerSimilarLaneIndex / lane.m_similarLaneCount;
                            flags2          |= NetLane.Flags.Merge;
                            if (tailInnerPortion < tailLeft)
                            {
                                flags2 |= NetLane.Flags.Left;
                            }
                            if (totalTail - tailOuterPortion < tailRight)
                            {
                                flags2 |= NetLane.Flags.Right;
                            }
                            if (tailForward != 0 && tailInnerPortion < tailLeft + tailForward && tailOuterPortion > tailLeft)
                            {
                                flags2 |= NetLane.Flags.Forward;
                            }
                        }
                        else
                        {
                            int num26;
                            int num27;
                            if (lane.m_similarLaneCount >= totalTail)
                            {
                                num26 = tailLeft;
                                num27 = tailRight;
                            }
                            else
                            {
                                num26 = tailLeft * lane.m_similarLaneCount / (totalTail + (tailForward >> 1));
                                num27 = tailRight * lane.m_similarLaneCount / (totalTail + (tailForward >> 1));
                            }
                            int num28 = num26;
                            int num29 = lane.m_similarLaneCount - num26 - num27;
                            int num30 = num27;
                            if (num29 > 0)
                            {
                                if (tailLeft > num26)
                                {
                                    num28++;
                                }
                                if (tailRight > num27)
                                {
                                    num30++;
                                }
                            }
                            if (innterSimilarLaneIndex < num28)
                            {
                                int num31 = (innterSimilarLaneIndex * tailLeft + num28 - 1) / num28;
                                int num32 = ((innterSimilarLaneIndex + 1) * tailLeft + num28 - 1) / num28;
                                if (num32 > num31)
                                {
                                    flags2          |= NetLane.Flags.Left;
                                    tailInnerPortion = Mathf.Min(tailInnerPortion, num31);
                                    tailOuterPortion = Mathf.Max(tailOuterPortion, num32);
                                }
                            }
                            if (innterSimilarLaneIndex >= num26 && outerSimilarLaneIndex >= num27 && tailForward != 0)
                            {
                                if (lane.m_similarLaneCount > totalTail)
                                {
                                    num26++;
                                }
                                int num33 = tailLeft + ((innterSimilarLaneIndex - num26) * tailForward + num29 - 1) / num29;
                                int num34 = tailLeft + ((innterSimilarLaneIndex + 1 - num26) * tailForward + num29 - 1) / num29;
                                if (num34 > num33)
                                {
                                    flags2          |= NetLane.Flags.Forward;
                                    tailInnerPortion = Mathf.Min(tailInnerPortion, num33);
                                    tailOuterPortion = Mathf.Max(tailOuterPortion, num34);
                                }
                            }
                            if (outerSimilarLaneIndex < num30)
                            {
                                int num35 = totalTail - ((outerSimilarLaneIndex + 1) * tailRight + num30 - 1) / num30;
                                int num36 = totalTail - (outerSimilarLaneIndex * tailRight + num30 - 1) / num30;
                                if (num36 > num35)
                                {
                                    flags2          |= NetLane.Flags.Right;
                                    tailInnerPortion = Mathf.Min(tailInnerPortion, num35);
                                    tailOuterPortion = Mathf.Max(tailOuterPortion, num36);
                                }
                            }
                            if (this.m_highwayRules)
                            {
                                if ((flags2 & NetLane.Flags.LeftRight) == NetLane.Flags.Left)
                                {
                                    if ((flags2 & NetLane.Flags.Forward) == NetLane.Flags.None || (tailForward >= 2 && tailLeft == 1))
                                    {
                                        tailOuterPortion = Mathf.Min(tailOuterPortion, tailInnerPortion + 1);
                                    }
                                }
                                else if ((flags2 & NetLane.Flags.LeftRight) == NetLane.Flags.Right && ((flags2 & NetLane.Flags.Forward) == NetLane.Flags.None || (tailForward >= 2 && tailRight == 1)))
                                {
                                    tailInnerPortion = Mathf.Max(tailInnerPortion, tailOuterPortion - 1);
                                }
                            }
                        }
                    }
                    if (backward)
                    {
                        if (flag2)
                        {
                            flags2 &= ~(NetLane.Flags.Forward | NetLane.Flags.Left | NetLane.Flags.Right);
                        }
                        else if (flag3)
                        {
                            flags2 |= NetLane.Flags.Forward;
                        }
                    }
                    else if (hasStartLanes)
                    {
                        flags2 &= ~(NetLane.Flags.Forward | NetLane.Flags.Left | NetLane.Flags.Right);
                    }
                    else if (noStartLanes)
                    {
                        flags2 |= NetLane.Flags.Forward;
                    }
                }
                laneID.ToLane().m_bezier      = new Bezier3(startPos, b, c, endPos);
                laneID.ToLane().m_segment     = segmentID;
                laneID.ToLane().m_flags       = (ushort)flags2;
                laneID.ToLane().m_firstTarget = (byte)tailInnerPortion;
                laneID.ToLane().m_lastTarget  = (byte)tailOuterPortion;
                lengthAcc   += laneID.ToLane().UpdateLength();
                lengthCount += 1f;
                prevLaneID   = laneID;
                laneID       = laneID.ToLane().m_nextLane;
            }
            if (lengthCount != 0f)
            {
                segment.m_averageLength = lengthAcc / lengthCount;
            }
            else
            {
                segment.m_averageLength = 0f;
            }
            bool joinedJunction = segment.m_averageLength < 11f &&
                                  segment.m_startNode.ToNode().m_flags.IsFlagSet(NetNode.Flags.Junction) &&
                                  segment.m_endNode.ToNode().m_flags.IsFlagSet(NetNode.Flags.Junction);

            laneID = segment.m_lanes;
            int laneIndex = 0;

            while (laneIndex < m_info.m_lanes.Length && laneID != 0u)
            {
                NetLane.Flags flags4 = laneID.ToLane().Flags() & ~NetLane.Flags.JoinedJunction;
                if (joinedJunction)
                {
                    flags4 |= NetLane.Flags.JoinedJunction;
                }
                laneID.ToLane().m_flags = (ushort)flags4;
                laneID = laneID.ToLane().m_nextLane;
                laneIndex++;
            }
            if (!loading)
            {
                int xBountStart = Mathf.Max((int)((segment.m_bounds.min.x - 16f) / 64f + 135f), 0);
                int zBountStart = Mathf.Max((int)((segment.m_bounds.min.z - 16f) / 64f + 135f), 0);
                int xBountEnd   = Mathf.Min((int)((segment.m_bounds.max.x + 16f) / 64f + 135f), 269);
                int zBoundEnd   = Mathf.Min((int)((segment.m_bounds.max.z + 16f) / 64f + 135f), 269);
                for (int zBound = zBountStart; zBound <= zBoundEnd; zBound++)
                {
                    for (int xBound = xBountStart; xBound <= xBountEnd; xBound++)
                    {
                        ushort gridIndex = NetManager.instance.m_nodeGrid[zBound * 270 + xBound];
                        int    watchDog  = 0;
                        while (gridIndex != 0)
                        {
                            NetInfo info     = NetManager.instance.m_nodes.m_buffer[(int)gridIndex].Info;
                            Vector3 position = NetManager.instance.m_nodes.m_buffer[(int)gridIndex].m_position;
                            float   num44    = Mathf.Max(Mathf.Max(segment.m_bounds.min.x - 16f - position.x, segment.m_bounds.min.z - 16f - position.z), Mathf.Max(position.x - segment.m_bounds.max.x - 16f, position.z - segment.m_bounds.max.z - 16f));
                            if (num44 < 0f)
                            {
                                info.m_netAI.NearbyLanesUpdated(gridIndex, ref NetManager.instance.m_nodes.m_buffer[(int)gridIndex]);
                            }
                            gridIndex = NetManager.instance.m_nodes.m_buffer[(int)gridIndex].m_nextGridNode;
                            if (++watchDog >= 32768)
                            {
                                CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                                break;
                            }
                        }
                    }
                }
                if (this.m_info.m_hasPedestrianLanes && (this.m_info.m_hasForwardVehicleLanes || this.m_info.m_hasBackwardVehicleLanes))
                {
                    RoadBaseAI.CheckBuildings(segmentID, ref segment);
                }
            }
        }
Esempio n. 27
0
        public virtual void UpdateLanes(ushort segmentID, ref NetSegment segment, bool loading)
        {
            bool flag       = Singleton <SimulationManager> .instance.m_metaData.m_invertTraffic == SimulationMetaData.MetaBool.True;
            uint prevLaneID = 0u;
            uint laneID     = segment.m_lanes;

            segment.CalculateCorner(segmentID, heightOffset: true, start: true, true,
                                    out var cornerPosStartLeft, out var cornerDirStartLeft, out _);
            segment.CalculateCorner(segmentID, heightOffset: true, start: false, leftSide: true,
                                    out var cornerPosEndLeft, out var cornerDirEndLeft, out bool smoothStart);
            segment.CalculateCorner(segmentID, heightOffset: true, start: true, leftSide: false,
                                    out var cornerPosStartRight, out var cornerDirStartRight, out _);
            segment.CalculateCorner(segmentID, heightOffset: true, start: false, leftSide: false,
                                    out var cornerPosEndRight, out var cornerDirEndRight, out bool smoothEnd);

            bool segmentInverted = segment.m_flags.IsFlagSet(NetSegment.Flags.Invert);

            float   cc            = 128 / Mathf.PI;//40.7436638f
            Vector3 deltaPosStart = cornerPosStartRight - cornerPosStartLeft;
            Vector3 deltaPosEnd   = cornerPosEndRight - cornerPosEndLeft;

            if (segmentInverted)
            {
                segment.m_cornerAngleStart = (byte)(Mathf.RoundToInt(Mathf.Atan2(deltaPosStart.z, deltaPosStart.x) * cc) & 255);
                segment.m_cornerAngleEnd   = (byte)(Mathf.RoundToInt(Mathf.Atan2(-deltaPosEnd.z, -deltaPosEnd.x) * cc) & 255);
            }
            else
            {
                segment.m_cornerAngleStart = (byte)(Mathf.RoundToInt(Mathf.Atan2(-deltaPosStart.z, -deltaPosStart.x) * cc) & 255);
                segment.m_cornerAngleEnd   = (byte)(Mathf.RoundToInt(Mathf.Atan2(deltaPosEnd.z, deltaPosEnd.x) * cc) & 255);
            }
            NetLane.Flags flags = NetLane.Flags.None;
            if (segment.m_flags.IsFlagSet(NetSegment.Flags.YieldStart))
            {
                flags |= segmentInverted ? NetLane.Flags.YieldStart : NetLane.Flags.YieldEnd;
            }
            if (segment.m_flags.IsFlagSet(NetSegment.Flags.YieldEnd))
            {
                flags |= segmentInverted ? NetLane.Flags.YieldEnd : NetLane.Flags.YieldStart;
            }
            float lengthAcc = 0f;
            float laneCount = 0f;

            for (int i = 0; i < this.m_info.m_lanes.Length; i++)
            {
                if (laneID == 0u)
                {
                    if (!Singleton <NetManager> .instance.CreateLanes(
                            out laneID, ref Singleton <SimulationManager> .instance.m_randomizer, segmentID, 1))
                    {
                        break;
                    }
                    if (prevLaneID != 0u)
                    {
                        prevLaneID.ToLane().m_nextLane = laneID;
                    }
                    else
                    {
                        segment.m_lanes = laneID;
                    }
                }
                NetInfo.Lane laneInfo  = this.m_info.m_lanes[i];
                float        lanePos01 = laneInfo.m_position / (this.m_info.m_halfWidth * 2f) + 0.5f; // lane pos rescaled between 0~1
                if (segmentInverted)
                {
                    lanePos01 = 1f - lanePos01;
                }
                Vector3 startPos = cornerPosStartLeft + (cornerPosStartRight - cornerPosStartLeft) * lanePos01;
                Vector3 startDir = Vector3.Lerp(cornerDirStartLeft, cornerDirStartRight, lanePos01);
                Vector3 endPos   = cornerPosEndRight + (cornerPosEndLeft - cornerPosEndRight) * lanePos01;
                Vector3 endDir   = Vector3.Lerp(cornerDirEndRight, cornerDirEndLeft, lanePos01);
                startPos.y += laneInfo.m_verticalOffset;
                endPos.y   += laneInfo.m_verticalOffset;
                Vector3 b;
                Vector3 c;
                NetSegment.CalculateMiddlePoints(startPos, startDir, endPos, endDir, smoothStart, smoothEnd, out b, out c);
                NetLane.Flags flags2 = laneID.ToLane().Flags();
                NetLane.Flags flags3 = flags;
                flags2 &= ~(NetLane.Flags.YieldStart | NetLane.Flags.YieldEnd);
                if ((byte)(laneInfo.m_finalDirection & NetInfo.Direction.Both) == 2)
                {
                    flags3 &= ~NetLane.Flags.YieldEnd;
                }
                if ((byte)(laneInfo.m_finalDirection & NetInfo.Direction.Both) == 1)
                {
                    flags3 &= ~NetLane.Flags.YieldStart;
                }
                flags2 |= flags3;
                if (flag)
                {
                    flags2 |= NetLane.Flags.Inverted;
                }
                else
                {
                    flags2 &= ~NetLane.Flags.Inverted;
                }
                laneID.ToLane().m_bezier      = new Bezier3(startPos, b, c, endPos);
                laneID.ToLane().m_segment     = segmentID;
                laneID.ToLane().m_flags       = (ushort)flags2;
                laneID.ToLane().m_firstTarget = 0;
                laneID.ToLane().m_lastTarget  = byte.MaxValue;
                lengthAcc += laneID.ToLane().UpdateLength();
                laneCount += 1f;
                prevLaneID = laneID;
                laneID     = laneID.ToLane().m_nextLane;
            }
            if (laneCount != 0f)
            {
                segment.m_averageLength = lengthAcc / laneCount;
            }
            else
            {
                segment.m_averageLength = 0f;
            }
        }
 internal static bool CheckFlags(this NetLane.Flags value, NetLane.Flags required, NetLane.Flags forbidden = 0) =>
 (value & (required | forbidden)) == required;
 public LaneConnectionInfo(NetLane.Flags direction, byte firstTarget, byte lastTarget)
 {
     this.direction   = direction;
     this.firstTarget = firstTarget;
     this.lastTarget  = lastTarget;
 }
        public static void AssignLanes(LaneInfo inLanes, Vector3 outVector, ushort segmentID, ushort nodeID, NetNode junctionNode, bool lht)
        {
            var nodeInfo = AnalyseNode(junctionNode,
                                       nodeID,
                                       segmentID,
                                       vehicleLaneTypes,
                                       VehicleInfo.VehicleType.Car,
                                       outVector);

            if (nodeInfo.GetLaneCount() == 0)
            {
                // This can happen if multiple one-way roads meet creating a dead end.
                return;
            }

            if (lht)
            {
                inLanes.Mirror();
                nodeInfo.Mirror();
            }

            var busLaneHandler = new BusLaneHandler();

            busLaneHandler.PreProcess(ref inLanes, ref nodeInfo);

            AdjustSharpTurns(inLanes.GetLaneCount(), ref nodeInfo);

            List <LaneConnectionInfo> lanesInfo = AssignLanes(inLanes.lanes.Count, nodeInfo.laneCounts[Direction.Left], nodeInfo.laneCounts[Direction.Forward], nodeInfo.laneCounts[Direction.Right]);

            AccountForSharpTurnLanes(ref lanesInfo, (byte)nodeInfo.laneCounts[Direction.SharpLeft], (byte)nodeInfo.laneCounts[Direction.SharpRight]);

            busLaneHandler.PostProcess(ref inLanes, ref lanesInfo);

            if (lht)
            {
                inLanes.Mirror();
                LHTHandler.Mirror(ref lanesInfo);
            }

            int        i          = 0;
            NetManager netManager = Singleton <NetManager> .instance;

            foreach (var lane in inLanes.lanes)
            {
                var laneInfo = lanesInfo[i];
                var laneId   = lane.Value;

                // Note: NetLane is a value type

                netManager.m_lanes.m_buffer[laneId].m_firstTarget = (byte)(laneInfo.firstTarget);
                netManager.m_lanes.m_buffer[laneId].m_lastTarget  = (byte)(laneInfo.lastTarget + 1);

                NetLane.Flags flags = (NetLane.Flags)netManager.m_lanes.m_buffer[laneId].m_flags;
                flags &= noDirections;
                flags |= laneInfo.direction;

                netManager.m_lanes.m_buffer[laneId].m_flags = (ushort)flags;

                i += 1;
            }
        }