public static NetInfo.Lane Clone(this NetInfo.Lane templateLane, string newName)
        {
            var newLane = new NetInfo.Lane();

            newLane.m_direction = templateLane.m_direction;
            newLane.m_finalDirection = templateLane.m_finalDirection;
            newLane.m_allowConnect = templateLane.m_allowConnect;
            newLane.m_allowStop = false;
            newLane.m_stopOffset = 0;
            newLane.m_laneType = templateLane.m_laneType;
            newLane.m_speedLimit = templateLane.m_speedLimit;
            newLane.m_vehicleType = templateLane.m_vehicleType;
            newLane.m_verticalOffset = templateLane.m_verticalOffset;
            newLane.m_width = templateLane.m_width;

            var templateLaneProps = templateLane.m_laneProps ?? ScriptableObject.CreateInstance<NetLaneProps>();
            if (templateLaneProps.m_props == null)
            {
                templateLaneProps.m_props = new NetLaneProps.Prop[0];
            }

            newLane.m_laneProps = ScriptableObject.CreateInstance<NetLaneProps>();
            newLane.m_laneProps.name = newName;
            newLane.m_laneProps.m_props = templateLaneProps
                .m_props
                .Select(p => p.ShallowClone())
                .ToArray();

            return newLane;
        }
        public static NetInfo.Lane CloneWithoutStops(this NetInfo.Lane templateLane, string newName = null)
        {
            var newLane = new NetInfo.Lane();

            newLane.m_direction = templateLane.m_direction;
            newLane.m_finalDirection = templateLane.m_finalDirection;
            newLane.m_allowConnect = templateLane.m_allowConnect;
            newLane.m_stopType = VehicleInfo.VehicleType.None;
            newLane.m_stopOffset = 0;
            newLane.m_laneType = templateLane.m_laneType;
            newLane.m_speedLimit = templateLane.m_speedLimit;
            newLane.m_vehicleType = templateLane.m_vehicleType;
            newLane.m_verticalOffset = templateLane.m_verticalOffset;
            newLane.m_width = templateLane.m_width;
            newLane.m_laneProps = templateLane.m_laneProps.Clone(newName);

            return newLane;
        }
        /// <summary>
        /// Displays segment ids over segments
        /// </summary>
        private void _guiSegments()
        {
            GUIStyle             _counterStyle = new GUIStyle();
            Array16 <NetSegment> segments      = Singleton <NetManager> .instance.m_segments;

            for (int i = 1; i < segments.m_size; ++i)
            {
                if (segments.m_buffer[i].m_flags == NetSegment.Flags.None)                 // segment is unused
                {
                    continue;
                }
#if !DEBUG
                if ((segments.m_buffer[i].m_flags & NetSegment.Flags.Untouchable) != NetSegment.Flags.None)
                {
                    continue;
                }
#endif
                var segmentInfo = segments.m_buffer[i].Info;

                Vector3 centerPos = segments.m_buffer[i].m_bounds.center;
                var     screenPos = Camera.main.WorldToScreenPoint(centerPos);
                screenPos.y = Screen.height - screenPos.y;

                if (screenPos.z < 0)
                {
                    continue;
                }

                var camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position;
                var diff   = centerPos - camPos;
                if (diff.magnitude > DebugCloseLod)
                {
                    continue;                     // do not draw if too distant
                }
                if (Options.nodesOverlay)
                {
                    var zoom = 1.0f / diff.magnitude * 150f;

                    _counterStyle.fontSize         = (int)(12f * zoom);
                    _counterStyle.normal.textColor = new Color(1f, 0f, 0f);

                    String labelStr = "Segment " + i;
#if DEBUGx
                    labelStr += ", flags: " + segments.m_buffer[i].m_flags.ToString() + ", condition: " + segments.m_buffer[i].m_condition;
#endif
#if DEBUG
                    SegmentEnd startEnd = TrafficPriority.GetPrioritySegment(segments.m_buffer[i].m_startNode, (ushort)i);
                    SegmentEnd endEnd   = TrafficPriority.GetPrioritySegment(segments.m_buffer[i].m_endNode, (ushort)i);
                    labelStr += "\nstart? " + (startEnd != null) + " veh.: " + startEnd?.GetRegisteredVehicleCount() + ", end? " + (endEnd != null) + " veh.: " + endEnd?.GetRegisteredVehicleCount();
#endif
                    labelStr += "\nTraffic: " + segments.m_buffer[i].m_trafficDensity + " %";
#if MARKCONGESTEDSEGMENTS
                    if (CustomRoadAI.initDone && CustomRoadAI.segmentCongestion[i])
                    {
                        labelStr += " congested!";
                    }
#endif

                    float meanLaneSpeed = 0f;

                    int  lIndex     = 0;
                    uint laneId     = segments.m_buffer[i].m_lanes;
                    int  validLanes = 0;
                    while (lIndex < segmentInfo.m_lanes.Length && laneId != 0u)
                    {
                        NetInfo.Lane lane = segmentInfo.m_lanes[lIndex];
                        if (lane.CheckType(NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car))
                        {
                            if (CustomRoadAI.laneMeanSpeeds[i] != null && lIndex < CustomRoadAI.laneMeanSpeeds[i].Length)
                            {
                                if (CustomRoadAI.laneMeanSpeeds[i][lIndex] >= 0)
                                {
                                    meanLaneSpeed += (float)CustomRoadAI.laneMeanSpeeds[i][lIndex];
                                    ++validLanes;
                                }
                            }
                        }
                        lIndex++;
                        laneId = Singleton <NetManager> .instance.m_lanes.m_buffer[laneId].m_nextLane;
                    }

                    if (validLanes > 0)
                    {
                        meanLaneSpeed /= Convert.ToSingle(validLanes);
                    }

                    /*if (CustomRoadAI.InStartupPhase)
                     *      labelStr += " (in start-up phase)";
                     * else*/
                    labelStr += " (avg. speed: " + String.Format("{0:0.##}", meanLaneSpeed) + " %)";

#if DEBUG
                    labelStr += "\nstart: " + segments.m_buffer[i].m_startNode + ", end: " + segments.m_buffer[i].m_endNode;
#endif

                    Vector2 dim       = _counterStyle.CalcSize(new GUIContent(labelStr));
                    Rect    labelRect = new Rect(screenPos.x - dim.x / 2f, screenPos.y, dim.x, dim.y);

                    GUI.Label(labelRect, labelStr, _counterStyle);

                    if (Options.showLanes)
                    {
                        _guiLanes((ushort)i, ref segments.m_buffer[i], ref segmentInfo);
                    }
                }
            }
        }
        private static void SetupTurningLaneProps(NetInfo.Lane lane)
        {
            var isLeftDriving = Singleton <SimulationManager> .instance.m_metaData.m_invertTraffic == SimulationMetaData.MetaBool.True;

            if (lane.m_laneProps == null)
            {
                return;
            }

            if (lane.m_laneProps.m_props == null)
            {
                return;
            }

            var fwd   = lane.m_laneProps.m_props.FirstOrDefault(p => p.m_flagsRequired == NetLane.Flags.Forward);
            var left  = lane.m_laneProps.m_props.FirstOrDefault(p => p.m_flagsRequired == NetLane.Flags.Left);
            var right = lane.m_laneProps.m_props.FirstOrDefault(p => p.m_flagsRequired == NetLane.Flags.Right);

            if (fwd == null)
            {
                return;
            }

            if (left == null)
            {
                return;
            }

            if (right == null)
            {
                return;
            }


            // Existing props
            //var r0 = NetLane.Flags.Forward;
            //var r1 = NetLane.Flags.ForwardRight;
            //var r2 = NetLane.Flags.Left;
            //var r3 = NetLane.Flags.LeftForward;
            //var r4 = NetLane.Flags.LeftForwardRight;
            //var r5 = NetLane.Flags.LeftRight;
            //var r6 = NetLane.Flags.Right;

            //var f0 = NetLane.Flags.LeftRight;
            //var f1 = NetLane.Flags.Left;
            //var f2 = NetLane.Flags.ForwardRight;
            //var f3 = NetLane.Flags.Right;
            //var f4 = NetLane.Flags.None;
            //var f5 = NetLane.Flags.Forward;
            //var f6 = NetLane.Flags.LeftForward;


            var newProps = new FastList <NetLaneProps.Prop>();

            newProps.Add(fwd);
            newProps.Add(left);
            newProps.Add(right);

            var fl = left.ShallowClone();

            fl.m_flagsRequired  = NetLane.Flags.LeftForward;
            fl.m_flagsForbidden = NetLane.Flags.Right;
            newProps.Add(fl);

            var fr = right.ShallowClone();

            fr.m_flagsRequired  = NetLane.Flags.ForwardRight;
            fr.m_flagsForbidden = NetLane.Flags.Left;
            newProps.Add(fr);

            var flr = isLeftDriving ? right.ShallowClone() : left.ShallowClone();

            flr.m_flagsRequired  = NetLane.Flags.LeftForwardRight;
            flr.m_flagsForbidden = NetLane.Flags.None;
            newProps.Add(flr);

            var lr = isLeftDriving ? right.ShallowClone() : left.ShallowClone();

            lr.m_flagsRequired  = NetLane.Flags.LeftRight;
            lr.m_flagsForbidden = NetLane.Flags.Forward;
            newProps.Add(lr);

            lane.m_laneProps = new NetLaneProps
            {
                name    = "TurningLane",
                m_props = newProps.ToArray()
            };
        }
        internal bool GetLaneEndPoint(ushort segmentId, bool startNode, byte laneIndex, uint?laneId, NetInfo.Lane laneInfo, out bool outgoing, out bool incoming, out Vector3?pos)
        {
            NetManager netManager = Singleton <NetManager> .instance;

            pos      = null;
            outgoing = false;
            incoming = false;

            if ((netManager.m_segments.m_buffer[segmentId].m_flags & (NetSegment.Flags.Created | NetSegment.Flags.Deleted)) != NetSegment.Flags.Created)
            {
                return(false);
            }

            if (laneId == null)
            {
                laneId = FindLaneId(segmentId, laneIndex);
                if (laneId == null)
                {
                    return(false);
                }
            }

            if ((netManager.m_lanes.m_buffer[(uint)laneId].m_flags & ((ushort)NetLane.Flags.Created | (ushort)NetLane.Flags.Deleted)) != (ushort)NetLane.Flags.Created)
            {
                return(false);
            }

            if (laneInfo == null)
            {
                if (laneIndex < netManager.m_segments.m_buffer[segmentId].Info.m_lanes.Length)
                {
                    laneInfo = netManager.m_segments.m_buffer[segmentId].Info.m_lanes[laneIndex];
                }
                else
                {
                    return(false);
                }
            }

            NetInfo.Direction laneDir = ((NetManager.instance.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? laneInfo.m_finalDirection : NetInfo.InvertDirection(laneInfo.m_finalDirection);

            if (startNode)
            {
                if ((laneDir & NetInfo.Direction.Backward) != NetInfo.Direction.None)
                {
                    outgoing = true;
                }
                if ((laneDir & NetInfo.Direction.Forward) != NetInfo.Direction.None)
                {
                    incoming = true;
                }
                pos = NetManager.instance.m_lanes.m_buffer[(uint)laneId].m_bezier.a;
            }
            else
            {
                if ((laneDir & NetInfo.Direction.Forward) != NetInfo.Direction.None)
                {
                    outgoing = true;
                }
                if ((laneDir & NetInfo.Direction.Backward) != NetInfo.Direction.None)
                {
                    incoming = true;
                }
                pos = NetManager.instance.m_lanes.m_buffer[(uint)laneId].m_bezier.d;
            }

            return(true);
        }
        /// <summary>
        /// Determines the allowed vehicle types that may approach the given node from the given segment (lane-wise).
        /// </summary>
        /// <param name="segmentId"></param>
        /// <param name="nodeId"></param>
        /// <returns></returns>
        public IDictionary <byte, ExtVehicleType> GetAllowedVehicleTypesAsDict(
            ushort segmentId,
            ushort nodeId,
            VehicleRestrictionsMode busLaneMode)
        {
            IDictionary <byte, ExtVehicleType> ret = new TinyDictionary <byte, ExtVehicleType>();
            NetManager netManager = Singleton <NetManager> .instance;

            if (segmentId == 0 ||
                (netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Created)
                == NetSegment.Flags.None ||
                nodeId == 0 ||
                (netManager.m_nodes.m_buffer[nodeId].m_flags & NetNode.Flags.Created)
                == NetNode.Flags.None)
            {
                return(ret);
            }

            const NetInfo.Direction DIR = NetInfo.Direction.Forward;

            NetInfo.Direction dir2 =
                ((netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Invert)
                 == NetSegment.Flags.None)
                    ? DIR
                    : NetInfo.InvertDirection(DIR);

            NetInfo segmentInfo = netManager.m_segments.m_buffer[segmentId].Info;
            uint    curLaneId   = netManager.m_segments.m_buffer[segmentId].m_lanes;
            int     numLanes    = segmentInfo.m_lanes.Length;
            uint    laneIndex   = 0;

            while (laneIndex < numLanes && curLaneId != 0u)
            {
                NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex];

                if (laneInfo.m_laneType == NetInfo.LaneType.Vehicle ||
                    laneInfo.m_laneType == NetInfo.LaneType.TransportVehicle)
                {
                    if ((laneInfo.m_vehicleType & VEHICLE_TYPES) != VehicleInfo.VehicleType.None)
                    {
                        ushort toNodeId =
                            (laneInfo.m_finalDirection & dir2) != NetInfo.Direction.None
                                ? netManager.m_segments.m_buffer[segmentId].m_endNode
                                : netManager.m_segments.m_buffer[segmentId].m_startNode;

                        if ((laneInfo.m_finalDirection & NetInfo.Direction.Both) ==
                            NetInfo.Direction.Both || toNodeId == nodeId)
                        {
                            ExtVehicleType vehicleTypes = GetAllowedVehicleTypes(
                                segmentId,
                                segmentInfo,
                                laneIndex,
                                laneInfo,
                                busLaneMode);
                            ret[(byte)laneIndex] = vehicleTypes;
                        }
                    }
                }

                curLaneId = netManager.m_lanes.m_buffer[curLaneId].m_nextLane;
                ++laneIndex;
            }

            return(ret);
        }
 public bool IsRoadLane(NetInfo.Lane laneInfo)
 {
     return((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Car) !=
            VehicleInfo.VehicleType.None);
 }
        public ExtVehicleType GetDefaultAllowedVehicleTypes(NetInfo.Lane laneInfo,
                                                            VehicleRestrictionsMode busLaneMode)
        {
            var ret = ExtVehicleType.None;

            if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Bicycle) !=
                VehicleInfo.VehicleType.None)
            {
                ret |= ExtVehicleType.Bicycle;
            }

            if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Tram) !=
                VehicleInfo.VehicleType.None)
            {
                ret |= ExtVehicleType.Tram;
            }

            switch (busLaneMode)
            {
            case VehicleRestrictionsMode.Restricted:
            case VehicleRestrictionsMode.Configured when Options.banRegularTrafficOnBusLanes: {
                    if ((laneInfo.m_laneType & NetInfo.LaneType.TransportVehicle) !=
                        NetInfo.LaneType.None)
                    {
                        ret |= ExtVehicleType.RoadPublicTransport
                               | ExtVehicleType.Service
                               | ExtVehicleType.Emergency;
                    }
                    else if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Car) !=
                             VehicleInfo.VehicleType.None)
                    {
                        ret |= ExtVehicleType.RoadVehicle;
                    }

                    break;
            }

            default: {
                    if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Car) !=
                        VehicleInfo.VehicleType.None)
                    {
                        ret |= ExtVehicleType.RoadVehicle;
                    }

                    break;
            }
            }

            // TODO: Mapping from VehicleInfo.VehicleType to bit flags can be improved by a lookup table
            if ((laneInfo.m_vehicleType & (VehicleInfo.VehicleType.Train |
                                           VehicleInfo.VehicleType.Metro |
                                           VehicleInfo.VehicleType.Monorail)) !=
                VehicleInfo.VehicleType.None)
            {
                ret |= ExtVehicleType.RailVehicle;
            }

            if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Ship) !=
                VehicleInfo.VehicleType.None)
            {
                ret |= ExtVehicleType.Ship;
            }

            if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Plane) !=
                VehicleInfo.VehicleType.None)
            {
                ret |= ExtVehicleType.Plane;
            }

            if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Ferry) !=
                VehicleInfo.VehicleType.None)
            {
                ret |= ExtVehicleType.Ferry;
            }

            if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Blimp) !=
                VehicleInfo.VehicleType.None)
            {
                ret |= ExtVehicleType.Blimp;
            }

            if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.CableCar) !=
                VehicleInfo.VehicleType.None)
            {
                ret |= ExtVehicleType.CableCar;
            }

            return(ret);
        }
Esempio n. 9
0
 /// <summary>
 /// Determines if custom speed limits may be assigned to the given lane info
 /// </summary>
 /// <param name="laneInfo"></param>
 /// <returns></returns>
 public bool MayHaveCustomSpeedLimits(NetInfo.Lane laneInfo)
 {
     return((laneInfo.m_laneType & LANE_TYPES) != NetInfo.LaneType.None &&
            (laneInfo.m_vehicleType & VEHICLE_TYPES) != VehicleInfo.VehicleType.None);
 }
        /// <summary>
        /// Determines the default set of allowed vehicle types for a given segment and lane.
        /// </summary>
        /// <param name="segmentId"></param>
        /// <param name="segmentInfo"></param>
        /// <param name="laneIndex"></param>
        /// <param name="laneInfo"></param>
        /// <returns></returns>
        public ExtVehicleType GetDefaultAllowedVehicleTypes(ushort segmentId, NetInfo segmentInfo, uint laneIndex, NetInfo.Lane laneInfo)
        {
            // manage cached default vehicle types
            if (defaultVehicleTypeCache == null)
            {
                defaultVehicleTypeCache = new ExtVehicleType?[NetManager.MAX_SEGMENT_COUNT][];
            }

            ExtVehicleType?[] cachedDefaultTypes = defaultVehicleTypeCache[segmentId];
            if (cachedDefaultTypes == null || cachedDefaultTypes.Length != segmentInfo.m_lanes.Length)
            {
                defaultVehicleTypeCache[segmentId] = cachedDefaultTypes = new ExtVehicleType?[segmentInfo.m_lanes.Length];
            }

            ExtVehicleType?defaultVehicleType = cachedDefaultTypes[laneIndex];

            if (defaultVehicleType == null)
            {
                ExtVehicleType ret = ExtVehicleType.None;
                if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Bicycle) != VehicleInfo.VehicleType.None)
                {
                    ret |= ExtVehicleType.Bicycle;
                }
                if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Tram) != VehicleInfo.VehicleType.None)
                {
                    ret |= ExtVehicleType.Tram;
                }
                if ((laneInfo.m_laneType & NetInfo.LaneType.TransportVehicle) != NetInfo.LaneType.None)
                {
                    ret |= ExtVehicleType.RoadPublicTransport | ExtVehicleType.Service | ExtVehicleType.Emergency;
                }
                else if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None)
                {
                    ret |= ExtVehicleType.RoadVehicle;
                }
                if ((laneInfo.m_vehicleType & (VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Metro)) != VehicleInfo.VehicleType.None)
                {
                    ret |= ExtVehicleType.RailVehicle;
                }
                if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Ship) != VehicleInfo.VehicleType.None)
                {
                    ret |= ExtVehicleType.Ship;
                }
                if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Plane) != VehicleInfo.VehicleType.None)
                {
                    ret |= ExtVehicleType.Plane;
                }
                cachedDefaultTypes[laneIndex] = ret;
                return(ret);
            }
            else
            {
                return((ExtVehicleType)defaultVehicleType);
            }
        }
        /// <summary>
        /// Determines the allowed vehicle types for the given segment and lane.
        /// </summary>
        /// <param name="segmentId"></param>
        /// <param name="laneIndex"></param>
        /// <param name="segmetnInfo"></param>
        /// <param name="laneInfo"></param>
        /// <returns></returns>
        internal ExtVehicleType GetAllowedVehicleTypes(ushort segmentId, NetInfo segmentInfo, uint laneIndex, NetInfo.Lane laneInfo)
        {
            ExtVehicleType?[] fastArray = Flags.laneAllowedVehicleTypesArray[segmentId];
            if (fastArray != null && fastArray.Length > laneIndex && fastArray[laneIndex] != null)
            {
                return((ExtVehicleType)fastArray[laneIndex]);
            }

            return(GetDefaultAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo));
        }
        private static NetInfo.Lane FindNearestVehicleStopLane(NetInfo.Lane[] laneGroup, NetInfo.Lane refLane, out ushort laneId)
        {
            NetInfo.Lane nearestLane = null;
            float        nearestDist = float.MaxValue;

            laneId = 0xffff;
            for (ushort i = 0; i < laneGroup.Length; i++)
            {
                NetInfo.Lane lane = laneGroup[i];
                if ((lane.m_vehicleType & refLane.m_stopType) != VehicleInfo.VehicleType.None)
                {
                    float dist = Mathf.Abs(lane.m_position - refLane.m_position);
                    if (dist < nearestDist)
                    {
                        nearestDist = dist;
                        nearestLane = lane;
                        laneId      = i;
                    }
                }
            }

            return(nearestLane);
        }
        public static StopPointDescriptorLanes[] MapStopPoints(BuildingInfo buildingInfo, float thresold)
        {
            var result = new List <StopPointDescriptorLanes>();

            if (buildingInfo?.m_paths != null)
            {
                foreach (BuildingInfo.PathInfo path in buildingInfo.m_paths)
                {
                    if (path.m_nodes.Length < 2)
                    {
                        continue;
                    }

                    Vector3 position  = path.m_nodes[0];
                    Vector3 position2 = path.m_nodes[1];


                    position.z  *= -1;
                    position2.z *= -1;
                    Vector3 directionPath = Quaternion.AngleAxis(90, Vector3.up) * (position2 - position).normalized;

                    foreach (NetInfo.Lane refLane in path.m_netInfo.m_lanes)
                    {
                        if (refLane.m_stopType == VehicleInfo.VehicleType.None)
                        {
                            continue;
                        }
                        NetInfo.Lane lane = FindNearestVehicleStopLane(path.m_netInfo.m_lanes, refLane, out ushort laneId);
                        if (lane == null)
                        {
                            continue;
                        }


                        LogUtils.DoLog($"[{buildingInfo}] pos + dir = ({position} {position2} + {directionPath})");
                        Vector3 lanePos = position + (lane.m_position / 2 * directionPath) + new Vector3(0, lane.m_verticalOffset);
                        Vector3 lanePos2 = position2 + (lane.m_position / 2 * directionPath) + new Vector3(0, lane.m_verticalOffset);
                        Vector3 b3, c;
                        if (path.m_curveTargets == null || path.m_curveTargets.Length == 0)
                        {
                            NetSegment.CalculateMiddlePoints(lanePos, Vector3.zero, lanePos2, Vector3.zero, true, true, out b3, out c);
                        }
                        else
                        {
                            GetMiddlePointsFor(path, out b3, out c);
                            LogUtils.DoLog($"[{buildingInfo}] GetMiddlePointsFor path =  ({b3} {c})");
                            b3  += (lane.m_position * directionPath) + new Vector3(0, lane.m_verticalOffset);
                            c   += (lane.m_position * directionPath) + new Vector3(0, lane.m_verticalOffset);
                            b3.y = c.y = (lanePos.y + lanePos2.y) / 2;
                        }
                        var refBezier = new Bezier3(lanePos, b3, c, lanePos2);
                        LogUtils.DoLog($"[{buildingInfo}]refBezier = {refBezier} ({lanePos} {b3} {c} {lanePos2})");


                        Vector3 positionR = refBezier.Position(m_defaultStopOffset);
                        Vector3 direction = refBezier.Tangent(m_defaultStopOffset);
                        LogUtils.DoLog($"[{buildingInfo}]1positionR = {positionR}; direction = {direction}");

                        Vector3 normalized = Vector3.Cross(Vector3.up, direction).normalized;
                        positionR += normalized * (MathUtils.SmootherStep(0.5f, 0f, Mathf.Abs(m_defaultStopOffset - 0.5f)) * lane.m_stopOffset);
                        LogUtils.DoLog($"[{buildingInfo}]2positionR = {positionR}; direction = {direction}; {normalized}");
                        result.Add(new StopPointDescriptorLanes
                        {
                            platformLine  = refBezier,
                            width         = lane.m_width,
                            vehicleType   = refLane.m_stopType,
                            laneId        = laneId,
                            subbuildingId = -1,
                            directionPath = directionPath * (path.m_invertSegments == (refLane.m_finalDirection == NetInfo.Direction.AvoidForward || refLane.m_finalDirection == NetInfo.Direction.Backward) ? 1 : -1)
                        });
                    }
                }
            }
            for (int i = 0; i < (buildingInfo.m_subBuildings?.Length ?? 0); i++)
            {
                StopPointDescriptorLanes[] subPlats = MapStopPoints(buildingInfo.m_subBuildings[i].m_buildingInfo, thresold);
                if (subPlats != null)
                {
                    var rotationToApply = Quaternion.AngleAxis(buildingInfo.m_subBuildings[i].m_angle, Vector3.up);
                    result.AddRange(subPlats.Select(x =>
                    {
                        x.platformLine.a = (rotationToApply * x.platformLine.a) + buildingInfo.m_subBuildings[i].m_position;
                        x.platformLine.b = (rotationToApply * x.platformLine.b) + buildingInfo.m_subBuildings[i].m_position;
                        x.platformLine.c = (rotationToApply * x.platformLine.c) + buildingInfo.m_subBuildings[i].m_position;
                        x.platformLine.d = (rotationToApply * x.platformLine.d) + buildingInfo.m_subBuildings[i].m_position;
                        x.subbuildingId  = (sbyte)i;
                        x.directionPath  = (rotationToApply * x.directionPath).normalized;
                        return(x);
                    }));
                }
            }
            result.Sort((x, y) =>
            {
                int priorityX = VehicleToPriority(x.vehicleType);
                int priorityY = VehicleToPriority(y.vehicleType);
                if (priorityX != priorityY)
                {
                    return(priorityX.CompareTo(priorityY));
                }

                Vector3 centerX = (x.platformLine.Position(0.5f));
                Vector3 centerY = (y.platformLine.Position(0.5f));
                if (Mathf.Abs(centerX.y - centerY.y) >= thresold)
                {
                    return(-centerX.y.CompareTo(centerY.y));
                }

                if (Mathf.Abs(centerX.z - centerY.z) >= thresold)
                {
                    return(-centerX.z.CompareTo(centerY.z));
                }

                return(-centerX.x.CompareTo(centerY.x));
            });
            if (CommonProperties.DebugMode)
            {
                LogUtils.DoLog($"{buildingInfo.name} PLAT ORDER:\n{string.Join("\n", result.Select((x, y) => $"{y}=> {x.ToString()}").ToArray())}");
            }
            return(result.ToArray());
        }
        private static List <NodeLaneMarker> GetNodeMarkers(ushort nodeId, ref NetNode node)
        {
            if (nodeId == 0)
            {
                return(null);
            }

            if ((node.m_flags & NetNode.Flags.Created) == NetNode.Flags.None)
            {
                return(null);
            }

            List <NodeLaneMarker> nodeMarkers = new List <NodeLaneMarker>();
            int nodeMarkerColorIndex          = 0;
            LaneConnectionManager connManager = LaneConnectionManager.Instance;

            int offsetMultiplier = node.CountSegments() <= 2 ? 3 : 1;

            for (int i = 0; i < 8; i++)
            {
                ushort segmentId = node.GetSegment(i);

                if (segmentId == 0)
                {
                    continue;
                }

                NetSegment[] segmentsBuffer = NetManager.instance.m_segments.m_buffer;
                bool         startNode      = segmentsBuffer[segmentId].m_startNode == nodeId;
                Vector3      offset         = segmentsBuffer[segmentId]
                                              .FindDirection(segmentId, nodeId) * offsetMultiplier;
                NetInfo.Lane[] lanes  = segmentsBuffer[segmentId].Info.m_lanes;
                uint           laneId = segmentsBuffer[segmentId].m_lanes;

                for (byte laneIndex = 0; (laneIndex < lanes.Length) && (laneId != 0); laneIndex++)
                {
                    NetInfo.Lane laneInfo = lanes[laneIndex];

                    if (((laneInfo.m_laneType & LaneConnectionManager.LANE_TYPES) != NetInfo.LaneType.None) &&
                        ((laneInfo.m_vehicleType & LaneConnectionManager.VEHICLE_TYPES)
                         != VehicleInfo.VehicleType.None))
                    {
                        if (connManager.GetLaneEndPoint(
                                segmentId,
                                startNode,
                                laneIndex,
                                laneId,
                                laneInfo,
                                out bool isSource,
                                out bool isTarget,
                                out Vector3? pos))
                        {
                            pos = pos.Value + offset;

                            float terrainY =
                                Singleton <TerrainManager> .instance.SampleDetailHeightSmooth(pos.Value);

                            var finalPos = new Vector3(pos.Value.x, terrainY, pos.Value.z);

                            Color32 nodeMarkerColor
                                = isSource
                                      ? COLOR_CHOICES[nodeMarkerColorIndex % COLOR_CHOICES.Length]
                                      : default; // or black (not used while rendering)

                            NetLane lane   = NetManager.instance.m_lanes.m_buffer[laneId];
                            Bezier3 bezier = lane.m_bezier;
                            if (startNode)
                            {
                                bezier.a = (Vector3)pos;
                            }
                            else
                            {
                                bezier.d = (Vector3)pos;
                            }
                            SegmentLaneMarker segmentLaneMarker = new SegmentLaneMarker {
                                renderBezier  = bezier,
                                raycastBezier = bezier,
                                laneID        = laneId,
                                laneIndex     = laneIndex,
                            };

                            nodeMarkers.Add(
                                new NodeLaneMarker {
                                SegmentId             = segmentId,
                                LaneId                = laneId,
                                NodeId                = nodeId,
                                StartNode             = startNode,
                                Position              = finalPos,
                                SecondaryPosition     = (Vector3)pos,
                                Color                 = nodeMarkerColor,
                                IsSource              = isSource,
                                IsTarget              = isTarget,
                                LaneType              = laneInfo.m_laneType,
                                VehicleType           = laneInfo.m_vehicleType,
                                InnerSimilarLaneIndex =
                                    ((byte)(laneInfo.m_direction & NetInfo.Direction.Forward) != 0)
                                            ? laneInfo.m_similarLaneIndex
                                            : laneInfo.m_similarLaneCount -
                                    laneInfo.m_similarLaneIndex - 1,
                                SegmentIndex      = i,
                                segmentLaneMarker = segmentLaneMarker,
                            });

                            if (isSource)
                            {
                                nodeMarkerColorIndex++;
                            }
                        }
                    }

                    laneId = NetManager.instance.m_lanes.m_buffer[laneId].m_nextLane;
                }
            }

            if (nodeMarkers.Count == 0)
            {
                return(null);
            }

            foreach (NodeLaneMarker laneMarker1 in nodeMarkers)
            {
                if (!laneMarker1.IsSource)
                {
                    continue;
                }

                uint[] connections =
                    LaneConnectionManager.Instance.GetLaneConnections(
                        laneMarker1.LaneId,
                        laneMarker1.StartNode);

                if ((connections == null) || (connections.Length == 0))
                {
                    continue;
                }

                foreach (NodeLaneMarker laneMarker2 in nodeMarkers)
                {
                    if (!laneMarker2.IsTarget)
                    {
                        continue;
                    }

                    if (connections.Contains(laneMarker2.LaneId))
                    {
                        laneMarker1.ConnectedMarkers.Add(laneMarker2);
                    }
                }
            }

            return(nodeMarkers);
        }
        private List <NodeLaneMarker> GetNodeMarkers(ushort nodeId, ref NetNode node)
        {
            if (nodeId == 0)
            {
                return(null);
            }
            if ((node.m_flags & NetNode.Flags.Created) == NetNode.Flags.None)
            {
                return(null);
            }

            List <NodeLaneMarker> nodeMarkers = new List <NodeLaneMarker>();
            LaneConnectionManager connManager = LaneConnectionManager.Instance;

            int offsetMultiplier = node.CountSegments() <= 2 ? 3 : 1;

            for (int i = 0; i < 8; i++)
            {
                ushort segmentId = node.GetSegment(i);
                if (segmentId == 0)
                {
                    continue;
                }

                bool           isEndNode = NetManager.instance.m_segments.m_buffer[segmentId].m_endNode == nodeId;
                Vector3        offset    = NetManager.instance.m_segments.m_buffer[segmentId].FindDirection(segmentId, nodeId) * offsetMultiplier;
                NetInfo.Lane[] lanes     = NetManager.instance.m_segments.m_buffer[segmentId].Info.m_lanes;
                uint           laneId    = NetManager.instance.m_segments.m_buffer[segmentId].m_lanes;
                for (byte laneIndex = 0; laneIndex < lanes.Length && laneId != 0; laneIndex++)
                {
                    NetInfo.Lane laneInfo = lanes[laneIndex];
                    if ((laneInfo.m_laneType & LaneConnectionManager.LANE_TYPES) != NetInfo.LaneType.None &&
                        (laneInfo.m_vehicleType & LaneConnectionManager.VEHICLE_TYPES) != VehicleInfo.VehicleType.None)
                    {
                        Vector3?pos      = null;
                        bool    isSource = false;
                        bool    isTarget = false;
                        if (connManager.GetLaneEndPoint(segmentId, !isEndNode, laneIndex, laneId, laneInfo, out isSource, out isTarget, out pos))
                        {
                            pos = (Vector3)pos + offset;
                            float terrainY = Singleton <TerrainManager> .instance.SampleDetailHeightSmooth(((Vector3)pos));

                            Vector3 finalPos = new Vector3(((Vector3)pos).x, terrainY, ((Vector3)pos).z);

                            nodeMarkers.Add(new NodeLaneMarker()
                            {
                                segmentId             = segmentId,
                                laneId                = laneId,
                                nodeId                = nodeId,
                                startNode             = !isEndNode,
                                position              = finalPos,
                                secondaryPosition     = (Vector3)pos,
                                color                 = colors[nodeMarkers.Count % colors.Length],
                                isSource              = isSource,
                                isTarget              = isTarget,
                                laneType              = laneInfo.m_laneType,
                                vehicleType           = laneInfo.m_vehicleType,
                                innerSimilarLaneIndex = ((byte)(laneInfo.m_direction & NetInfo.Direction.Forward) != 0) ? laneInfo.m_similarLaneIndex : laneInfo.m_similarLaneCount - laneInfo.m_similarLaneIndex - 1,
                                segmentIndex          = i
                            });
                        }
                    }

                    laneId = NetManager.instance.m_lanes.m_buffer[laneId].m_nextLane;
                }
            }

            if (nodeMarkers.Count == 0)
            {
                return(null);
            }

            foreach (NodeLaneMarker laneMarker1 in nodeMarkers)
            {
                if (!laneMarker1.isSource)
                {
                    continue;
                }

                uint[] connections = LaneConnectionManager.Instance.GetLaneConnections(laneMarker1.laneId, laneMarker1.startNode);
                if (connections == null || connections.Length == 0)
                {
                    continue;
                }

                foreach (NodeLaneMarker laneMarker2 in nodeMarkers)
                {
                    if (!laneMarker2.isTarget)
                    {
                        continue;
                    }

                    if (connections.Contains(laneMarker2.laneId))
                    {
                        laneMarker1.connectedMarkers.Add(laneMarker2);
                    }
                }
            }

            return(nodeMarkers);
        }
Esempio n. 16
0
 public static bool IsDriveLane(this NetInfo.Lane info) => (info.m_vehicleType & DriveType) != VehicleInfo.VehicleType.None;
        internal float GetLockFreeGameSpeedLimit(ushort segmentId, uint laneIndex, uint laneId, NetInfo.Lane laneInfo)
        {
#if TRACE
            Singleton <CodeProfiler> .instance.Start("SpeedLimitManager.GetLockFreeGameSpeedLimit");
#endif
            if (Flags.IsInitDone())
            {
                if (Flags.laneSpeedLimitArray.Length <= segmentId)
                {
                    Log.Error($"laneSpeedLimitArray.Length = {Flags.laneSpeedLimitArray.Length}, segmentId={segmentId}. Out of range!");
#if TRACE
                    Singleton <CodeProfiler> .instance.Stop("SpeedLimitManager.GetLockFreeGameSpeedLimit");
#endif
                    return(laneInfo.m_speedLimit);
                }

                float     speedLimit = 0;
                ushort?[] fastArray  = Flags.laneSpeedLimitArray[segmentId];
                if (fastArray != null && fastArray.Length > laneIndex && fastArray[laneIndex] != null)
                {
                    speedLimit = ToGameSpeedLimit((ushort)fastArray[laneIndex]);
                }
                else
                {
                    speedLimit = laneInfo.m_speedLimit;
                }
#if TRACE
                Singleton <CodeProfiler> .instance.Stop("SpeedLimitManager.GetLockFreeGameSpeedLimit");
#endif
                return(speedLimit);
            }
            else
            {
                float ret = GetGameSpeedLimit(laneId);
#if TRACE
                Singleton <CodeProfiler> .instance.Stop("SpeedLimitManager.GetLockFreeGameSpeedLimit");
#endif
                return(ret);
            }
        }
        /// <summary>
        /// Removes the given vehicle type from the set of allowed vehicles at the specified lane
        /// </summary>
        /// <param name="segmentId"></param>
        /// <param name="laneIndex"></param>
        /// <param name="laneId"></param>
        /// <param name="laneInfo"></param>
        /// <param name="road"></param>
        /// <param name="vehicleType"></param>
        public void RemoveAllowedType(ushort segmentId, NetInfo segmentInfo, uint laneIndex, uint laneId, NetInfo.Lane laneInfo, ExtVehicleType vehicleType)
        {
            if (segmentId == 0 || (Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Created) == NetSegment.Flags.None || ((NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[laneId].m_flags & NetLane.Flags.Created) == NetLane.Flags.None)
            {
                return;
            }

            ExtVehicleType allowedTypes = GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo);

            allowedTypes &= ~vehicleType;
            allowedTypes &= GetBaseMask(segmentInfo.m_lanes[laneIndex]);             // ensure default base mask
            Flags.setLaneAllowedVehicleTypes(segmentId, laneIndex, laneId, allowedTypes);
            SubscribeToSegmentGeometry(segmentId);
            NotifyStartEndNode(segmentId);
        }
 // NetSegment.GetClosestLane -- it's only called by the PathManager
 public static bool GetClosestLanePosition(NetSegment seg, Vector3 point, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, out Vector3 positionA, out int laneIndexA, out float laneOffsetA, out Vector3 positionB, out int laneIndexB, out float laneOffsetB, RoadManager.VehicleType vehicleType)
 {
     positionA   = point;
     laneIndexA  = -1;
     laneOffsetA = 0f;
     positionB   = point;
     laneIndexB  = -1;
     laneOffsetB = 0f;
     if (seg.m_flags != NetSegment.Flags.None && seg.m_lanes != 0u)
     {
         NetInfo info = seg.Info;
         if (info.m_lanes != null)
         {
             float num  = 1E+09f;
             float num2 = 1E+09f;
             uint  num3 = seg.m_lanes;
             int   num4 = 0;
             while (num4 < info.m_lanes.Length && num3 != 0u)
             {
                 NetInfo.Lane lane = info.m_lanes[num4];
                 if (lane.CheckType(laneTypes, vehicleTypes) && RoadManager.CanUseLane(vehicleType, num3))
                 {
                     Vector3 vector;
                     float   num5;
                     Singleton <NetManager> .instance.m_lanes.m_buffer[(int)((UIntPtr)num3)].GetClosestPosition(point, out vector, out num5);
                     float num6 = Vector3.SqrMagnitude(point - vector);
                     if (lane.m_finalDirection == NetInfo.Direction.Backward || lane.m_finalDirection == NetInfo.Direction.AvoidForward)
                     {
                         if (num6 < num2)
                         {
                             num2        = num6;
                             positionB   = vector;
                             laneIndexB  = num4;
                             laneOffsetB = num5;
                         }
                     }
                     else if (num6 < num)
                     {
                         num         = num6;
                         positionA   = vector;
                         laneIndexA  = num4;
                         laneOffsetA = num5;
                     }
                 }
                 num3 = Singleton <NetManager> .instance.m_lanes.m_buffer[(int)((UIntPtr)num3)].m_nextLane;
                 num4++;
             }
             if (num2 < num)
             {
                 Vector3 vector2 = positionA;
                 int     num7    = laneIndexA;
                 float   num8    = laneOffsetA;
                 positionA   = positionB;
                 laneIndexA  = laneIndexB;
                 laneOffsetA = laneOffsetB;
                 positionB   = vector2;
                 laneIndexB  = num7;
                 laneOffsetB = num8;
             }
             if (!info.m_canCrossLanes)
             {
                 positionB   = point;
                 laneIndexB  = -1;
                 laneOffsetB = 0f;
             }
         }
     }
     return(laneIndexA != -1);
 }
 public void ToggleAllowedType(ushort segmentId, NetInfo segmentInfo, uint laneIndex, uint laneId, NetInfo.Lane laneInfo, ExtVehicleType vehicleType, bool add)
 {
     if (add)
     {
         AddAllowedType(segmentId, segmentInfo, laneIndex, laneId, laneInfo, vehicleType);
     }
     else
     {
         RemoveAllowedType(segmentId, segmentInfo, laneIndex, laneId, laneInfo, vehicleType);
     }
 }
 /// <summary>
 /// Determines the maximum allowed set of vehicles (the base mask) for a given lane
 /// </summary>
 /// <param name="laneInfo"></param>
 /// <returns></returns>
 public ExtVehicleType GetBaseMask(NetInfo.Lane laneInfo,
                                   VehicleRestrictionsMode includeBusLanes)
 {
     return(GetDefaultAllowedVehicleTypes(laneInfo, includeBusLanes));
 }
Esempio n. 22
0
        public void OnBeforeSimulationStep(ushort segmentId, ref NetSegment segment)
        {
            GlobalConfig conf = GlobalConfig.Instance;

            // calculate traffic density
            NetInfo segmentInfo = segment.Info;
            int     numLanes    = segmentInfo.m_lanes.Length;

            if (LaneTrafficData[segmentId] == null || LaneTrafficData[segmentId].Length < numLanes)
            {
                LaneTrafficData[segmentId] = new LaneTrafficData[numLanes];
                for (int i = 0; i < numLanes; ++i)
                {
                    // laneTrafficData[segmentId][i] = new LaneTrafficData();
                    LaneTrafficData[segmentId][i].meanSpeed = REF_REL_SPEED;
                }
            }

            // calculate max./min. lane speed
            for (var i = 0; i < 2; ++i)
            {
                meanSpeeds[i]     = 0;
                meanSpeedLanes[i] = 0;
            }

            uint curLaneId = segment.m_lanes;

            byte laneIndex = 0;

            while (laneIndex < numLanes && curLaneId != 0u)
            {
                NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex];

                if ((laneInfo.m_laneType & LANE_TYPES) != NetInfo.LaneType.None &&
                    (laneInfo.m_vehicleType & VEHICLE_TYPES) != VehicleInfo.VehicleType.None)
                {
                    int dirIndex = GetDirIndex(laneInfo.m_finalDirection);

                    // calculate reported mean speed
                    ushort newRelSpeed = CalcLaneRelativeMeanSpeed(
                        segmentId,
                        laneIndex,
                        curLaneId,
                        segment.Info.m_lanes[laneIndex]);

                    meanSpeeds[dirIndex] += newRelSpeed;
                    ++meanSpeedLanes[dirIndex];

                    LaneTrafficData[segmentId][laneIndex].meanSpeed = newRelSpeed;

                    ushort trafficBuffer = LaneTrafficData[segmentId][laneIndex].trafficBuffer;

                    // remember historic data
                    LaneTrafficData[segmentId][laneIndex].lastTrafficBuffer = trafficBuffer;

                    if (trafficBuffer > LaneTrafficData[segmentId][laneIndex].maxTrafficBuffer)
                    {
                        LaneTrafficData[segmentId][laneIndex].maxTrafficBuffer = trafficBuffer;
                    }

                    // reset buffers
                    if (conf.AdvancedVehicleAI.MaxTrafficBuffer > 0)
                    {
                        if (LaneTrafficData[segmentId][laneIndex].trafficBuffer >
                            conf.AdvancedVehicleAI.MaxTrafficBuffer)
                        {
                            LaneTrafficData[segmentId][laneIndex].accumulatedSpeeds /=
                                LaneTrafficData[segmentId][laneIndex].trafficBuffer
                                / conf.AdvancedVehicleAI.MaxTrafficBuffer;
                            LaneTrafficData[segmentId][laneIndex].trafficBuffer =
                                (ushort)conf.AdvancedVehicleAI.MaxTrafficBuffer;
                        }
                        else if (LaneTrafficData[segmentId][laneIndex].trafficBuffer ==
                                 conf.AdvancedVehicleAI.MaxTrafficBuffer)
                        {
                            LaneTrafficData[segmentId][laneIndex].accumulatedSpeeds = 0;
                            LaneTrafficData[segmentId][laneIndex].trafficBuffer     = 0;
                        }
                    }
                    else
                    {
                        LaneTrafficData[segmentId][laneIndex].accumulatedSpeeds = 0;
                        LaneTrafficData[segmentId][laneIndex].trafficBuffer     = 0;
                    }
                }

                laneIndex++;
                curLaneId = curLaneId.ToLane().m_nextLane;
            }

            for (int i = 0; i < 2; ++i)
            {
                int segDirIndex = i == 0
                                      ? GetDirIndex(segmentId, NetInfo.Direction.Forward)
                                      : GetDirIndex(segmentId, NetInfo.Direction.Backward);

                if (meanSpeedLanes[i] > 0)
                {
                    SegmentDirTrafficData[segDirIndex].meanSpeed = (ushort)Math.Min(
                        REF_REL_SPEED,
                        meanSpeeds[i] / meanSpeedLanes[i]);
                }
                else
                {
                    SegmentDirTrafficData[segDirIndex].meanSpeed = REF_REL_SPEED;
                }
            }
        }
 public bool IsTramLane(NetInfo.Lane laneInfo)
 {
     return((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Tram) !=
            VehicleInfo.VehicleType.None);
 }
        public void BuildUp(NetInfo info, NetInfoVersion version)
        {
            ///////////////////////////
            // Template              //
            ///////////////////////////
            if (version == NetInfoVersion.GroundGrass || version == NetInfoVersion.GroundTrees)
            {
                var roadInfo = Prefabs.Find <NetInfo>(NetInfos.Vanilla.ROAD_2L);
                info.m_segments = roadInfo.m_segments.Select(x => x.ShallowClone()).ToArray();
                info.m_nodes    = roadInfo.m_nodes.Select(x => x.ShallowClone()).ToArray();
                info.m_lanes    = roadInfo.m_lanes.Select(x => x.ShallowClone()).ToArray();
            }

            ///////////////////////////
            // 3DModeling            //
            ///////////////////////////
            info.Setup16m3mSW3mMdnMesh(version);

            ///////////////////////////
            // Texturing             //
            ///////////////////////////
            SetupTextures(info, version);

            ///////////////////////////
            // Set up                //
            ///////////////////////////
            info.m_hasParkingSpaces = false;

            info.m_pavementWidth = (version != NetInfoVersion.Slope && version != NetInfoVersion.Tunnel ? 3 : 6);
            info.m_halfWidth     = (version != NetInfoVersion.Slope && version != NetInfoVersion.Tunnel ? 8 : 11);
            info.m_canCrossLanes = false;
            if (version == NetInfoVersion.Tunnel)
            {
                info.m_setVehicleFlags = Vehicle.Flags.Transition | Vehicle.Flags.Underground;
                info.m_setCitizenFlags = CitizenInstance.Flags.Transition | CitizenInstance.Flags.Underground;
                info.m_class           = info.m_class.Clone("NEXTbasicroadmedian" + version.ToString());
            }
            else
            {
                info.m_class = info.m_class.Clone("NEXTbasicroadmedian" + version.ToString());
            }

            // Setting up lanes
            info.SetRoadLanes(version, new LanesConfiguration
            {
                IsTwoWay        = true,
                LaneWidth       = 3.3f,
                SpeedLimit      = 0.8f,
                CenterLane      = CenterLaneType.Median,
                CenterLaneWidth = 3.3f
            });
            var leftPedLane  = info.GetLeftRoadShoulder();
            var rightPedLane = info.GetRightRoadShoulder();

            //Setting Up Props
            var leftRoadProps  = leftPedLane.m_laneProps.m_props.ToList();
            var rightRoadProps = rightPedLane.m_laneProps.m_props.ToList();
            var centerLane     = new NetInfo.Lane();

            centerLane.m_position       = 0;
            centerLane.m_laneProps      = ScriptableObject.CreateInstance <NetLaneProps>();
            centerLane.m_laneProps.name = "Center Lane Props";
            centerLane.m_vehicleType    = VehicleInfo.VehicleType.None;
            var centerLaneProps = new List <NetLaneProps.Prop>();

            if (version == NetInfoVersion.GroundTrees)
            {
                var treeProp = new NetLaneProps.Prop()
                {
                    m_tree           = Prefabs.Find <TreeInfo>("Tree2variant"),
                    m_repeatDistance = 20,
                    m_probability    = 100,
                };
                treeProp.m_position.x = 0;
                centerLaneProps.Add(treeProp);
            }
            else if (version == NetInfoVersion.Slope)
            {
                leftRoadProps.AddLeftWallLights(info.m_pavementWidth);
                rightRoadProps.AddRightWallLights(info.m_pavementWidth);
            }
            centerLane.m_laneProps.m_props   = centerLaneProps.ToArray();
            leftPedLane.m_laneProps.m_props  = leftRoadProps.ToArray();
            rightPedLane.m_laneProps.m_props = rightRoadProps.ToArray();
            var lanes = info.m_lanes.ToList();

            lanes.Add(centerLane);
            info.m_lanes = lanes.ToArray();
            //info.TrimAboveGroundProps(version);
            //info.SetupNewSpeedLimitProps(50, 40);


            // AI
            //var owPlayerNetAI = roadInfo.GetComponent<PlayerNetAI>();
            //var playerNetAI = info.GetComponent<PlayerNetAI>();

            //if (owPlayerNetAI != null && playerNetAI != null)
            //{
            //    playerNetAI.m_constructionCost = owPlayerNetAI.m_constructionCost ; // Charge by the lane?
            //    playerNetAI.m_maintenanceCost = owPlayerNetAI.m_maintenanceCost; // Charge by the lane?
            //}

            var roadBaseAI = info.GetComponent <RoadBaseAI>();

            if (roadBaseAI != null)
            {
                roadBaseAI.m_trafficLights = false;
            }
        }
        protected void CustomUpdatePathTargetPositions(ushort vehicleID, ref Vehicle vehicleData, Vector3 refPos, ref int index, int max, float minSqrDistanceA, float minSqrDistanceB)
        {
            PathManager pathMan    = Singleton <PathManager> .instance;
            NetManager  netManager = Singleton <NetManager> .instance;
            Vector4     targetPos0 = vehicleData.m_targetPos0;

            targetPos0.w = 1000f;
            float minSqrDistA    = minSqrDistanceA;
            uint  pathId         = vehicleData.m_path;
            byte  pathPosIndex   = vehicleData.m_pathPositionIndex;
            byte  lastPathOffset = vehicleData.m_lastPathOffset;

            if (pathPosIndex == 255)
            {
                pathPosIndex = 0;
                if (index <= 0)
                {
                    vehicleData.m_pathPositionIndex = 0;
                }
                if (!Singleton <PathManager> .instance.m_pathUnits.m_buffer[pathId].CalculatePathPositionOffset(pathPosIndex >> 1, targetPos0, out lastPathOffset))
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }
            }

            PathUnit.Position position;
            if (!pathMan.m_pathUnits.m_buffer[pathId].GetPosition(pathPosIndex >> 1, out position))
            {
                this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                return;
            }

            NetInfo curSegmentInfo = netManager.m_segments.m_buffer[(int)position.m_segment].Info;

            if (curSegmentInfo.m_lanes.Length <= (int)position.m_lane)
            {
                this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                return;
            }

            uint curLaneId = PathManager.GetLaneID(position);

            NetInfo.Lane laneInfo = curSegmentInfo.m_lanes[(int)position.m_lane];
            Bezier3      bezier;
            bool         firstIter = true;     // NON-STOCK CODE

            while (true)
            {
                if ((pathPosIndex & 1) == 0)
                {
                    if (laneInfo.m_laneType != NetInfo.LaneType.CargoVehicle)
                    {
                        bool first = true;
                        while (lastPathOffset != position.m_offset)
                        {
                            if (first)
                            {
                                first = false;
                            }
                            else
                            {
                                float distDiff = Mathf.Sqrt(minSqrDistA) - Vector3.Distance(targetPos0, refPos);
                                int   pathOffsetDelta;
                                if (distDiff < 0f)
                                {
                                    pathOffsetDelta = 4;
                                }
                                else
                                {
                                    pathOffsetDelta = 4 + Mathf.Max(0, Mathf.CeilToInt(distDiff * 256f / (netManager.m_lanes.m_buffer[curLaneId].m_length + 1f)));
                                }
                                if (lastPathOffset > position.m_offset)
                                {
                                    lastPathOffset = (byte)Mathf.Max((int)lastPathOffset - pathOffsetDelta, (int)position.m_offset);
                                }
                                else if (lastPathOffset < position.m_offset)
                                {
                                    lastPathOffset = (byte)Mathf.Min((int)lastPathOffset + pathOffsetDelta, (int)position.m_offset);
                                }
                            }
                            Vector3 curSegPos;
                            Vector3 curSegDir;
                            float   curSegOffset;
                            this.CalculateSegmentPosition(vehicleID, ref vehicleData, position, curLaneId, lastPathOffset, out curSegPos, out curSegDir, out curSegOffset);
                            targetPos0.Set(curSegPos.x, curSegPos.y, curSegPos.z, Mathf.Min(targetPos0.w, curSegOffset));
                            float refPosSqrDist = (curSegPos - refPos).sqrMagnitude;
                            if (refPosSqrDist >= minSqrDistA)
                            {
                                if (index <= 0)
                                {
                                    vehicleData.m_lastPathOffset = lastPathOffset;
                                }
                                vehicleData.SetTargetPos(index++, targetPos0);
                                minSqrDistA  = minSqrDistanceB;
                                refPos       = targetPos0;
                                targetPos0.w = 1000f;
                                if (index == max)
                                {
                                    return;
                                }
                            }
                        }
                    }
                    pathPosIndex  += 1;
                    lastPathOffset = 0;
                    if (index <= 0)
                    {
                        vehicleData.m_pathPositionIndex = pathPosIndex;
                        vehicleData.m_lastPathOffset    = lastPathOffset;
                    }
                }

                int  nextPathPosIndex = (pathPosIndex >> 1) + 1;
                uint nextPathId       = pathId;
                if (nextPathPosIndex >= (int)pathMan.m_pathUnits.m_buffer[pathId].m_positionCount)
                {
                    nextPathPosIndex = 0;
                    nextPathId       = pathMan.m_pathUnits.m_buffer[pathId].m_nextPathUnit;
                    if (nextPathId == 0u)
                    {
                        if (index <= 0)
                        {
                            Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);

                            vehicleData.m_path = 0u;
                        }
                        targetPos0.w = 1f;
                        vehicleData.SetTargetPos(index++, targetPos0);
                        return;
                    }
                }

                PathUnit.Position nextPathPos;
                if (!pathMan.m_pathUnits.m_buffer[nextPathId].GetPosition(nextPathPosIndex, out nextPathPos))
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }

                NetInfo nextSegmentInfo = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].Info;
                if (nextSegmentInfo.m_lanes.Length <= (int)nextPathPos.m_lane)
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }

                int bestLaneIndex = nextPathPos.m_lane;
                if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) != (Vehicle.Flags) 0)
                {
                    bestLaneIndex = FindBestLane(vehicleID, ref vehicleData, nextPathPos);
                }
                else
                {
                    // NON-STOCK CODE START
                    if (firstIter &&
                        this.m_info.m_vehicleType == VehicleInfo.VehicleType.Car &&
                        !this.m_info.m_isLargeVehicle
                        )
                    {
                        bool mayFindBestLane = false;
#if BENCHMARK
                        using (var bm = new Benchmark(null, "MayFindBestLane")) {
#endif
                        mayFindBestLane = VehicleBehaviorManager.Instance.MayFindBestLane(vehicleID, ref vehicleData, ref VehicleStateManager.Instance.VehicleStates[vehicleID]);
#if BENCHMARK
                    }
#endif

                        if (mayFindBestLane)
                        {
                            uint next2PathId       = nextPathId;
                            int  next2PathPosIndex = nextPathPosIndex;
                            bool next2Invalid;
                            PathUnit.Position next2PathPos;
                            NetInfo           next2SegmentInfo = null;
                            PathUnit.Position next3PathPos;
                            NetInfo           next3SegmentInfo = null;
                            PathUnit.Position next4PathPos;
                            if (PathUnit.GetNextPosition(ref next2PathId, ref next2PathPosIndex, out next2PathPos, out next2Invalid))
                            {
                                next2SegmentInfo = netManager.m_segments.m_buffer[(int)next2PathPos.m_segment].Info;

                                uint next3PathId       = next2PathId;
                                int  next3PathPosIndex = next2PathPosIndex;
                                bool next3Invalid;
                                if (PathUnit.GetNextPosition(ref next3PathId, ref next3PathPosIndex, out next3PathPos, out next3Invalid))
                                {
                                    next3SegmentInfo = netManager.m_segments.m_buffer[(int)next3PathPos.m_segment].Info;

                                    uint next4PathId       = next3PathId;
                                    int  next4PathPosIndex = next3PathPosIndex;
                                    bool next4Invalid;
                                    if (!PathUnit.GetNextPosition(ref next4PathId, ref next4PathPosIndex, out next4PathPos, out next4Invalid))
                                    {
                                        next4PathPos = default(PathUnit.Position);
                                    }
                                }
                                else
                                {
                                    next3PathPos = default(PathUnit.Position);
                                    next4PathPos = default(PathUnit.Position);
                                }
                            }
                            else
                            {
                                next2PathPos = default(PathUnit.Position);
                                next3PathPos = default(PathUnit.Position);
                                next4PathPos = default(PathUnit.Position);
                            }

#if BENCHMARK
                            using (var bm = new Benchmark(null, "FindBestLane")) {
#endif
                            bestLaneIndex = VehicleBehaviorManager.Instance.FindBestLane(vehicleID, ref vehicleData, ref VehicleStateManager.Instance.VehicleStates[vehicleID], curLaneId, position, curSegmentInfo, nextPathPos, nextSegmentInfo, next2PathPos, next2SegmentInfo, next3PathPos, next3SegmentInfo, next4PathPos);
#if BENCHMARK
                        }
#endif
                        }
                        // NON-STOCK CODE END
                    }
                }

                if (bestLaneIndex != (int)nextPathPos.m_lane)
                {
                    nextPathPos.m_lane = (byte)bestLaneIndex;
                    pathMan.m_pathUnits.m_buffer[nextPathId].SetPosition(nextPathPosIndex, nextPathPos);
#if BENCHMARK
                    using (var bm = new Benchmark(null, "AddTraffic")) {
#endif
                    // prevent multiple lane changes to the same lane from happening at the same time
                    TrafficMeasurementManager.Instance.AddTraffic(nextPathPos.m_segment, nextPathPos.m_lane
#if MEASUREDENSITY
                                                                  , VehicleStateManager.Instance.VehicleStates[vehicleID].totalLength
#endif
                                                                  , 0); // NON-STOCK CODE
#if BENCHMARK
                }
#endif
                }

                uint nextLaneId           = PathManager.GetLaneID(nextPathPos);
                NetInfo.Lane nextLaneInfo = nextSegmentInfo.m_lanes[(int)nextPathPos.m_lane];
                ushort curSegStartNodeId  = netManager.m_segments.m_buffer[(int)position.m_segment].m_startNode;
                ushort curSegEndNodeId    = netManager.m_segments.m_buffer[(int)position.m_segment].m_endNode;
                ushort nextSegStartNodeId = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_startNode;
                ushort nextSegEndNodeId   = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_endNode;
                if (nextSegStartNodeId != curSegStartNodeId &&
                    nextSegStartNodeId != curSegEndNodeId &&
                    nextSegEndNodeId != curSegStartNodeId &&
                    nextSegEndNodeId != curSegEndNodeId &&
                    ((netManager.m_nodes.m_buffer[(int)curSegStartNodeId].m_flags | netManager.m_nodes.m_buffer[(int)curSegEndNodeId].m_flags) & NetNode.Flags.Disabled) == NetNode.Flags.None &&
                    ((netManager.m_nodes.m_buffer[(int)nextSegStartNodeId].m_flags | netManager.m_nodes.m_buffer[(int)nextSegEndNodeId].m_flags) & NetNode.Flags.Disabled) != NetNode.Flags.None)
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }

                if (nextLaneInfo.m_laneType == NetInfo.LaneType.Pedestrian)
                {
                    if (vehicleID != 0 && (vehicleData.m_flags & Vehicle.Flags.Parking) == (Vehicle.Flags) 0)
                    {
                        byte inOffset  = position.m_offset;
                        byte outOffset = position.m_offset;
                        if (this.ParkVehicle(vehicleID, ref vehicleData, position, nextPathId, nextPathPosIndex << 1, out outOffset))
                        {
                            if (outOffset != inOffset)
                            {
                                if (index <= 0)
                                {
                                    vehicleData.m_pathPositionIndex = (byte)((int)vehicleData.m_pathPositionIndex & -2);
                                    vehicleData.m_lastPathOffset    = inOffset;
                                }
                                position.m_offset = outOffset;
                                pathMan.m_pathUnits.m_buffer[(int)((UIntPtr)pathId)].SetPosition(pathPosIndex >> 1, position);
                            }
                            vehicleData.m_flags |= Vehicle.Flags.Parking;
                        }
                        else
                        {
                            this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                        }
                    }
                    return;
                }

                if ((byte)(nextLaneInfo.m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.CargoVehicle | NetInfo.LaneType.TransportVehicle)) == 0)
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }

                if (nextLaneInfo.m_vehicleType != this.m_info.m_vehicleType &&
                    this.NeedChangeVehicleType(vehicleID, ref vehicleData, nextPathPos, nextLaneId, nextLaneInfo.m_vehicleType, ref targetPos0)
                    )
                {
                    float targetPos0ToRefPosSqrDist = ((Vector3)targetPos0 - refPos).sqrMagnitude;
                    if (targetPos0ToRefPosSqrDist >= minSqrDistA)
                    {
                        vehicleData.SetTargetPos(index++, targetPos0);
                    }
                    if (index <= 0)
                    {
                        while (index < max)
                        {
                            vehicleData.SetTargetPos(index++, targetPos0);
                        }
                        if (nextPathId != vehicleData.m_path)
                        {
                            Singleton <PathManager> .instance.ReleaseFirstUnit(ref vehicleData.m_path);
                        }
                        vehicleData.m_pathPositionIndex = (byte)(nextPathPosIndex << 1);
                        PathUnit.CalculatePathPositionOffset(nextLaneId, targetPos0, out vehicleData.m_lastPathOffset);
                        if (vehicleID != 0 && !this.ChangeVehicleType(vehicleID, ref vehicleData, nextPathPos, nextLaneId))
                        {
                            this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                        }
                    }
                    else
                    {
                        while (index < max)
                        {
                            vehicleData.SetTargetPos(index++, targetPos0);
                        }
                    }
                    return;
                }

                if (nextPathPos.m_segment != position.m_segment && vehicleID != 0)
                {
                    vehicleData.m_flags &= ~Vehicle.Flags.Leaving;
                }

                byte nextSegOffset = 0;
                if ((vehicleData.m_flags & Vehicle.Flags.Flying) != (Vehicle.Flags) 0)
                {
                    nextSegOffset = (byte)((nextPathPos.m_offset < 128) ? 255 : 0);
                }
                else if (curLaneId != nextLaneId && laneInfo.m_laneType != NetInfo.LaneType.CargoVehicle)
                {
                    PathUnit.CalculatePathPositionOffset(nextLaneId, targetPos0, out nextSegOffset);
                    bezier = default(Bezier3);
                    Vector3 curSegDir;
                    float   maxSpeed;
                    this.CalculateSegmentPosition(vehicleID, ref vehicleData, position, curLaneId, position.m_offset, out bezier.a, out curSegDir, out maxSpeed);
                    bool calculateNextNextPos = lastPathOffset == 0;
                    if (calculateNextNextPos)
                    {
                        if ((vehicleData.m_flags & Vehicle.Flags.Reversed) != (Vehicle.Flags) 0)
                        {
                            calculateNextNextPos = (vehicleData.m_trailingVehicle == 0);
                        }
                        else
                        {
                            calculateNextNextPos = (vehicleData.m_leadingVehicle == 0);
                        }
                    }
                    Vector3 nextSegDir;
                    float   nextMaxSpeed;
                    if (calculateNextNextPos)
                    {
                        PathUnit.Position nextNextPathPos;
                        if (!pathMan.m_pathUnits.m_buffer[nextPathId].GetNextPosition(nextPathPosIndex, out nextNextPathPos))
                        {
                            nextNextPathPos = default(PathUnit.Position);
                        }
                        this.CalculateSegmentPosition(vehicleID, ref vehicleData, nextNextPathPos, nextPathPos, nextLaneId, nextSegOffset, position, curLaneId, position.m_offset, index, out bezier.d, out nextSegDir, out nextMaxSpeed);
                    }
                    else
                    {
                        this.CalculateSegmentPosition(vehicleID, ref vehicleData, nextPathPos, nextLaneId, nextSegOffset, out bezier.d, out nextSegDir, out nextMaxSpeed);
                    }
                    if (nextMaxSpeed < 0.01f || (netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_flags & (NetSegment.Flags.Collapsed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None)
                    {
                        if (index <= 0)
                        {
                            vehicleData.m_lastPathOffset = lastPathOffset;
                        }
                        targetPos0   = bezier.a;
                        targetPos0.w = 0f;
                        while (index < max)
                        {
                            vehicleData.SetTargetPos(index++, targetPos0);
                        }
                        return;
                    }
                    if (position.m_offset == 0)
                    {
                        curSegDir = -curSegDir;
                    }
                    if (nextSegOffset < nextPathPos.m_offset)
                    {
                        nextSegDir = -nextSegDir;
                    }
                    curSegDir.Normalize();
                    nextSegDir.Normalize();
                    float dist;
                    NetSegment.CalculateMiddlePoints(bezier.a, curSegDir, bezier.d, nextSegDir, true, true, out bezier.b, out bezier.c, out dist);
                    if (dist > 1f)
                    {
                        ushort nextNodeId;
                        if (nextSegOffset == 0)
                        {
                            nextNodeId = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_startNode;
                        }
                        else if (nextSegOffset == 255)
                        {
                            nextNodeId = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_endNode;
                        }
                        else
                        {
                            nextNodeId = 0;
                        }
                        float curve = 1.57079637f * (1f + Vector3.Dot(curSegDir, nextSegDir));
                        if (dist > 1f)
                        {
                            curve /= dist;
                        }
                        nextMaxSpeed = Mathf.Min(nextMaxSpeed, this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, curve));
                        while (lastPathOffset < 255)
                        {
                            float distDiff = Mathf.Sqrt(minSqrDistA) - Vector3.Distance(targetPos0, refPos);
                            int   pathOffsetDelta;
                            if (distDiff < 0f)
                            {
                                pathOffsetDelta = 8;
                            }
                            else
                            {
                                pathOffsetDelta = 8 + Mathf.Max(0, Mathf.CeilToInt(distDiff * 256f / (dist + 1f)));
                            }
                            lastPathOffset = (byte)Mathf.Min((int)lastPathOffset + pathOffsetDelta, 255);
                            Vector3 bezierPos = bezier.Position((float)lastPathOffset * 0.003921569f);
                            targetPos0.Set(bezierPos.x, bezierPos.y, bezierPos.z, Mathf.Min(targetPos0.w, nextMaxSpeed));
                            float sqrMagnitude2 = (bezierPos - refPos).sqrMagnitude;
                            if (sqrMagnitude2 >= minSqrDistA)
                            {
                                if (index <= 0)
                                {
                                    vehicleData.m_lastPathOffset = lastPathOffset;
                                }
                                if (nextNodeId != 0)
                                {
                                    this.UpdateNodeTargetPos(vehicleID, ref vehicleData, nextNodeId, ref netManager.m_nodes.m_buffer[(int)nextNodeId], ref targetPos0, index);
                                }
                                vehicleData.SetTargetPos(index++, targetPos0);
                                minSqrDistA  = minSqrDistanceB;
                                refPos       = targetPos0;
                                targetPos0.w = 1000f;
                                if (index == max)
                                {
                                    return;
                                }
                            }
                        }
                    }
                }
                else
                {
                    PathUnit.CalculatePathPositionOffset(nextLaneId, targetPos0, out nextSegOffset);
                }

                if (index <= 0)
                {
                    if (nextPathPosIndex == 0)
                    {
                        Singleton <PathManager> .instance.ReleaseFirstUnit(ref vehicleData.m_path);
                    }
                    if (nextPathPosIndex >= (int)(pathMan.m_pathUnits.m_buffer[(int)((UIntPtr)nextPathId)].m_positionCount - 1) && pathMan.m_pathUnits.m_buffer[(int)((UIntPtr)nextPathId)].m_nextPathUnit == 0u && vehicleID != 0)
                    {
                        this.ArrivingToDestination(vehicleID, ref vehicleData);
                    }
                }

                pathId         = nextPathId;
                pathPosIndex   = (byte)(nextPathPosIndex << 1);
                lastPathOffset = nextSegOffset;
                if (index <= 0)
                {
                    vehicleData.m_pathPositionIndex = pathPosIndex;
                    vehicleData.m_lastPathOffset    = lastPathOffset;
                    vehicleData.m_flags             = ((vehicleData.m_flags & ~(Vehicle.Flags.OnGravel | Vehicle.Flags.Underground | Vehicle.Flags.Transition)) | nextSegmentInfo.m_setVehicleFlags);
                    if (this.LeftHandDrive(nextLaneInfo))
                    {
                        vehicleData.m_flags |= Vehicle.Flags.LeftHandDrive;
                    }
                    else
                    {
                        vehicleData.m_flags &= (Vehicle.Flags.Created | Vehicle.Flags.Deleted | Vehicle.Flags.Spawned | Vehicle.Flags.Inverted | Vehicle.Flags.TransferToTarget | Vehicle.Flags.TransferToSource | Vehicle.Flags.Emergency1 | Vehicle.Flags.Emergency2 | Vehicle.Flags.WaitingPath | Vehicle.Flags.Stopped | Vehicle.Flags.Leaving | Vehicle.Flags.Arriving | Vehicle.Flags.Reversed | Vehicle.Flags.TakingOff | Vehicle.Flags.Flying | Vehicle.Flags.Landing | Vehicle.Flags.WaitingSpace | Vehicle.Flags.WaitingCargo | Vehicle.Flags.GoingBack | Vehicle.Flags.WaitingTarget | Vehicle.Flags.Importing | Vehicle.Flags.Exporting | Vehicle.Flags.Parking | Vehicle.Flags.CustomName | Vehicle.Flags.OnGravel | Vehicle.Flags.WaitingLoading | Vehicle.Flags.Congestion | Vehicle.Flags.DummyTraffic | Vehicle.Flags.Underground | Vehicle.Flags.Transition | Vehicle.Flags.InsideBuilding);
                    }
                }
                position  = nextPathPos;
                curLaneId = nextLaneId;
                laneInfo  = nextLaneInfo;
                firstIter = false;                 // NON-STOCK CODE
            }
        }
Esempio n. 26
0
        /// <summary>
        /// coppies vehicle restrictions of the current segment
        /// and applies them to all segments until the next junction.
        /// </summary>
        /// <param name="sortedLaneIndex">if provided only current lane is considered</param>
        /// <param name="vehicleTypes">
        /// if provided only bits for which vehicleTypes is set are considered.
        /// </param>
        private void ApplyRestrictionsToAllSegments(
            int?sortedLaneIndex         = null,
            ExtVehicleType?vehicleTypes = null)
        {
            NetManager netManager = Singleton <NetManager> .instance;

            NetInfo selectedSegmentInfo = netManager.m_segments.m_buffer[SelectedSegmentId].Info;

            bool LaneVisitorFun(SegmentLaneVisitData data)
            {
                if (data.SegVisitData.Initial)
                {
                    return(true);
                }

                if (sortedLaneIndex != null && data.SortedLaneIndex != sortedLaneIndex)
                {
                    return(true);
                }

                ushort  segmentId   = data.SegVisitData.CurSeg.segmentId;
                NetInfo segmentInfo = netManager.m_segments.m_buffer[segmentId].Info;

                byte selectedLaneIndex = data.InitLanePos.laneIndex;

                NetInfo.Lane selectedLaneInfo = selectedSegmentInfo.m_lanes[selectedLaneIndex];

                uint laneId    = data.CurLanePos.laneId;
                byte laneIndex = data.CurLanePos.laneIndex;

                NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex];

                // apply restrictions of selected segment & lane
                ExtVehicleType mask =
                    VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(
                        SelectedSegmentId,
                        selectedSegmentInfo,
                        selectedLaneIndex,
                        selectedLaneInfo,
                        VehicleRestrictionsMode.Configured);;

                if (vehicleTypes != null)
                {
                    ExtVehicleType currentMask =
                        VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(
                            segmentId,
                            segmentInfo,
                            laneIndex,
                            laneInfo,
                            VehicleRestrictionsMode.Configured);

                    // only apply changes where types is 1. that means:
                    // for bits where types is 0, use currentMask,
                    // for bits where types is 1, use initial mask.
                    ExtVehicleType types2 = (ExtVehicleType)vehicleTypes; //cast
                    mask = (types2 & mask) | (~types2 & currentMask);
                }

                VehicleRestrictionsManager.Instance.SetAllowedVehicleTypes(
                    segmentId,
                    segmentInfo,
                    laneIndex,
                    laneInfo,
                    laneId,
                    mask);

                RefreshCurrentRestrictedSegmentIds(segmentId);

                return(true);
            }

            SegmentLaneTraverser.Traverse(
                SelectedSegmentId,
                SegmentTraverser.TraverseDirection.AnyDirection,
                SegmentTraverser.TraverseSide.AnySide,
                SegmentLaneTraverser.LaneStopCriterion.LaneCount,
                SegmentTraverser.SegmentStopCriterion.Junction,
                VehicleRestrictionsManager.LANE_TYPES,
                VehicleRestrictionsManager.VEHICLE_TYPES,
                LaneVisitorFun);
        }
Esempio n. 27
0
        private NetInfo.Direction DrawParkingRestrictionHandles(ushort segmentId,
                                                                bool clicked,
                                                                ref NetSegment segment,
                                                                bool viewOnly,
                                                                ref Vector3 camPos)
        {
            if (viewOnly && !Options.parkingRestrictionsOverlay && !MassEditOverlay.IsActive)
            {
                return(NetInfo.Direction.None);
            }

            NetManager netManager = Singleton <NetManager> .instance;
            ParkingRestrictionsManager parkingManager = ParkingRestrictionsManager.Instance;

            NetInfo.Direction hoveredDirection = NetInfo.Direction.None;

            // draw parking restriction signs over mean middle points of lane beziers
            if (!segmentCenterByDir.TryGetValue(
                    segmentId,
                    out Dictionary <NetInfo.Direction, Vector3> segCenter))
            {
                segCenter = new Dictionary <NetInfo.Direction, Vector3>();
                segmentCenterByDir.Add(segmentId, segCenter);
                GeometryUtil.CalculateSegmentCenterByDir(
                    segmentId,
                    segCenter,
                    SIGN_SIZE * TrafficManagerTool.MAX_ZOOM);
            }

            foreach (KeyValuePair <NetInfo.Direction, Vector3> e in segCenter)
            {
                bool allowed = parkingManager.IsParkingAllowed(segmentId, e.Key);
                if (allowed && viewOnly)
                {
                    continue;
                }

                bool visible = GeometryUtil.WorldToScreenPoint(e.Value, out Vector3 screenPos);

                if (!visible)
                {
                    continue;
                }

                float zoom        = (1.0f / (e.Value - camPos).magnitude) * 100f * MainTool.GetBaseZoom();
                float size        = (viewOnly ? 0.8f : 1f) * SIGN_SIZE * zoom;
                Color guiColor    = GUI.color;
                Rect  boundingBox = new Rect(
                    screenPos.x - (size / 2),
                    screenPos.y - (size / 2),
                    size,
                    size);

                if (Options.speedLimitsOverlay || MassEditOverlay.IsActive)
                {
                    boundingBox.y -= size + 10f;
                }

                bool hoveredHandle = !viewOnly && TrafficManagerTool.IsMouseOver(boundingBox);

                guiColor.a = TrafficManagerTool.GetHandleAlpha(hoveredHandle);

                if (hoveredHandle)
                {
                    // mouse hovering over sign
                    hoveredDirection = e.Key;
                }

                GUI.color = GUI.color.WithAlpha(TrafficManagerTool.OverlayAlpha);
                GUI.DrawTexture(boundingBox, RoadUI.ParkingRestrictionTextures[allowed]);
                GUI.color = guiColor;

                if (hoveredHandle && clicked && !IsCursorInPanel() &&
                    parkingManager.ToggleParkingAllowed(segmentId, hoveredDirection))
                {
                    allowed = !allowed;

                    if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
                    {
                        NetInfo.Direction normDir = e.Key;

                        if ((netManager.m_segments.m_buffer[segmentId].m_flags &
                             NetSegment.Flags.Invert) != NetSegment.Flags.None)
                        {
                            normDir = NetInfo.InvertDirection(normDir);
                        }

                        bool LaneVisitor(SegmentLaneVisitData data)
                        {
                            if (data.SegVisitData.Initial)
                            {
                                return(true);
                            }

                            bool reverse = data.SegVisitData.ViaStartNode ==
                                           data.SegVisitData.ViaInitialStartNode;

                            ushort  otherSegmentId   = data.SegVisitData.CurSeg.segmentId;
                            NetInfo otherSegmentInfo =
                                netManager.m_segments.m_buffer[otherSegmentId].Info;
                            byte laneIndex = data.CurLanePos.laneIndex;

                            NetInfo.Lane laneInfo = otherSegmentInfo.m_lanes[laneIndex];

                            NetInfo.Direction otherNormDir = laneInfo.m_finalDirection;
                            if (((netManager.m_segments.m_buffer[otherSegmentId].m_flags &
                                  NetSegment.Flags.Invert) != NetSegment.Flags.None) ^ reverse)
                            {
                                otherNormDir = NetInfo.InvertDirection(otherNormDir);
                            }

                            if (otherNormDir == normDir)
                            {
                                parkingManager.SetParkingAllowed(
                                    otherSegmentId,
                                    laneInfo.m_finalDirection,
                                    allowed);
                            }

                            return(true);
                        }

                        SegmentLaneTraverser.Traverse(
                            segmentId,
                            SegmentTraverser.TraverseDirection.AnyDirection,
                            SegmentTraverser.TraverseSide.AnySide,
                            SegmentLaneTraverser.LaneStopCriterion.LaneCount,
                            SegmentTraverser.SegmentStopCriterion.Junction,
                            ParkingRestrictionsManager.LANE_TYPES,
                            ParkingRestrictionsManager.VEHICLE_TYPES,
                            LaneVisitor);
                    }
                }

                guiColor.a = 1f;
                GUI.color  = guiColor;
            }

            return(hoveredDirection);
        }
Esempio n. 28
0
        private bool DrawVehicleRestrictionHandles(ushort segmentId,
                                                   ref NetSegment segment,
                                                   bool viewOnly,
                                                   out bool stateUpdated)
        {
            stateUpdated = false;

            if (viewOnly && !Options.vehicleRestrictionsOverlay &&
                MainTool.GetToolMode() != ToolMode.VehicleRestrictions)
            {
                return(false);
            }

            Vector3 center = segment.m_bounds.center;

            bool visible = GeometryUtil.WorldToScreenPoint(center, out Vector3 _);

            if (!visible)
            {
                return(false);
            }

            Vector3 camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position;
            Vector3 diff   = center - camPos;

            if (diff.sqrMagnitude > TrafficManagerTool.MAX_OVERLAY_DISTANCE_SQR)
            {
                return(false); // do not draw if too distant
            }

            int numLanes = GeometryUtil.GetSegmentNumVehicleLanes(
                segmentId,
                null,
                out int numDirections,
                VehicleRestrictionsManager.VEHICLE_TYPES);

            // draw vehicle restrictions over each lane
            NetInfo segmentInfo = segment.Info;
            Vector3 yu          = (segment.m_endDirection - segment.m_startDirection).normalized;

            // if ((segment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None)
            //        yu = -yu;
            Vector3 xu          = Vector3.Cross(yu, new Vector3(0, 1f, 0)).normalized;
            float   f           = viewOnly ? 4f : 7f; // reserved sign size in game coordinates
            int     maxNumSigns = 0;

            if (VehicleRestrictionsManager.Instance.IsRoadSegment(segmentInfo))
            {
                maxNumSigns = RoadVehicleTypes.Length;
            }
            else if (VehicleRestrictionsManager.Instance.IsRailSegment(segmentInfo))
            {
                maxNumSigns = RailVehicleTypes.Length;
            }

            // Vector3 zero = center - 0.5f * (float)(numLanes + numDirections - 1) * f * (xu + yu); // "bottom left"
            Vector3 zero = center - (0.5f * (numLanes - 1 + numDirections - 1) * f * xu)
                           - (0.5f * maxNumSigns * f * yu);        // "bottom left"

            // if (!viewOnly)
            //     Log._Debug($"xu: {xu.ToString()} yu: {yu.ToString()} center: {center.ToString()}
            //     zero: {zero.ToString()} numLanes: {numLanes} numDirections: {numDirections}");*/

            uint            x           = 0;
            Color           guiColor    = GUI.color;
            IList <LanePos> sortedLanes = Constants.ServiceFactory.NetService.GetSortedLanes(
                segmentId,
                ref segment,
                null,
                VehicleRestrictionsManager.LANE_TYPES,
                VehicleRestrictionsManager.VEHICLE_TYPES);
            bool hovered = false;
            HashSet <NetInfo.Direction> directions = new HashSet <NetInfo.Direction>();
            int sortedLaneIndex = -1;

            foreach (LanePos laneData in sortedLanes)
            {
                ++sortedLaneIndex;
                uint laneId    = laneData.laneId;
                byte laneIndex = laneData.laneIndex;

                NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex];

                if (!directions.Contains(laneInfo.m_finalDirection))
                {
                    if (directions.Count > 0)
                    {
                        ++x; // space between different directions
                    }

                    directions.Add(laneInfo.m_finalDirection);
                }

                ExtVehicleType[] possibleVehicleTypes;

                if (VehicleRestrictionsManager.Instance.IsRoadLane(laneInfo))
                {
                    possibleVehicleTypes = RoadVehicleTypes;
                }
                else if (VehicleRestrictionsManager.Instance.IsRailLane(laneInfo))
                {
                    possibleVehicleTypes = RailVehicleTypes;
                }
                else
                {
                    ++x;
                    continue;
                }

                ExtVehicleType allowedTypes =
                    VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(
                        segmentId,
                        segmentInfo,
                        laneIndex,
                        laneInfo,
                        VehicleRestrictionsMode.Configured);

                uint y = 0;
#if DEBUG_disabled_xxx
                Vector3 labelCenter = zero + f * (float)x * xu + f * (float)y * yu; // in game coordinates

                Vector3 labelScreenPos;
                bool    visible = GeometryUtil.WorldToScreenPoint(labelCenter, out labelScreenPos);
                // BUGBUG: Using screen.height might be wrong, consider U.UIScaler.ScreenHeight (from UIView.fixedHeight)
                labelScreenPos.y = Screen.height - labelScreenPos.y;
                diff             = labelCenter - camPos;

                var labelZoom = 1.0f / diff.magnitude * 100f;
                _counterStyle.fontSize         = (int)(11f * labelZoom);
                _counterStyle.normal.textColor = new Color(1f, 1f, 0f);

                string  labelStr  = $"Idx {laneIndex}";
                Vector2 dim       = _counterStyle.CalcSize(new GUIContent(labelStr));
                Rect    labelRect = new Rect(labelScreenPos.x - dim.x / 2f, labelScreenPos.y, dim.x, dim.y);
                GUI.Label(labelRect, labelStr, _counterStyle);

                ++y;
#endif
                Color guiColor2 = GUI.color;
                GUI.color = GUI.color.WithAlpha(TrafficManagerTool.OverlayAlpha);
                foreach (ExtVehicleType vehicleType in possibleVehicleTypes)
                {
                    bool allowed = VehicleRestrictionsManager.Instance.IsAllowed(allowedTypes, vehicleType);

                    if (allowed && viewOnly)
                    {
                        continue; // do not draw allowed vehicles in view-only mode
                    }


                    bool hoveredHandle = MainTool.DrawGenericSquareOverlayGridTexture(
                        RoadUI.VehicleRestrictionTextures[vehicleType][allowed],
                        camPos,
                        zero,
                        f,
                        xu,
                        yu,
                        x,
                        y,
                        vehicleRestrictionsSignSize,
                        !viewOnly);

                    if (hoveredHandle)
                    {
                        hovered = true;
                        renderData_.segmentId       = segmentId;
                        renderData_.laneId          = laneId;
                        renderData_.laneIndex       = laneIndex;
                        renderData_.laneInfo        = laneInfo;
                        renderData_.SortedLaneIndex = sortedLaneIndex;
                    }

                    if (hoveredHandle && MainTool.CheckClicked())
                    {
                        // toggle vehicle restrictions
                        // Log._Debug($"Setting vehicle restrictions of segment {segmentId}, lane
                        //     idx {laneIndex}, {vehicleType.ToString()} to {!allowed}");
                        VehicleRestrictionsManager.Instance.ToggleAllowedType(
                            segmentId,
                            segmentInfo,
                            laneIndex,
                            laneId,
                            laneInfo,
                            vehicleType,
                            !allowed);
                        stateUpdated = true;
                        RefreshCurrentRestrictedSegmentIds(segmentId);
                        if (RoadMode)
                        {
                            ApplyRestrictionsToAllSegments(sortedLaneIndex, vehicleType);
                        }
                    }

                    ++y;
                }

                GUI.color = guiColor2;

                ++x;
            }

            guiColor.a = 1f;
            GUI.color  = guiColor;

            return(hovered);
        }
        /// <summary>
        /// Displays lane ids over lanes
        /// </summary>
        private void _guiLanes(ushort segmentId, ref NetSegment segment, ref NetInfo segmentInfo)
        {
            GUIStyle _counterStyle = new GUIStyle();
            Vector3  centerPos     = segment.m_bounds.center;
            var      screenPos     = Camera.main.WorldToScreenPoint(centerPos);

            screenPos.y = Screen.height - screenPos.y - 200;

            if (screenPos.z < 0)
            {
                return;
            }

            var camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position;
            var diff   = centerPos - camPos;

            if (diff.magnitude > DebugCloseLod)
            {
                return;                 // do not draw if too distant
            }
            var zoom = 1.0f / diff.magnitude * 150f;

            _counterStyle.fontSize         = (int)(11f * zoom);
            _counterStyle.normal.textColor = new Color(1f, 1f, 0f);

            uint totalDensity = 0u;
            uint curLaneId    = segment.m_lanes;

            for (int i = 0; i < segmentInfo.m_lanes.Length; ++i)
            {
                if (curLaneId == 0)
                {
                    break;
                }

                if (CustomRoadAI.currentLaneDensities[segmentId] != null && i < CustomRoadAI.currentLaneDensities[segmentId].Length)
                {
                    totalDensity += CustomRoadAI.currentLaneDensities[segmentId][i];
                }

                curLaneId = Singleton <NetManager> .instance.m_lanes.m_buffer[curLaneId].m_nextLane;
            }

            curLaneId = segment.m_lanes;
            String labelStr = "";

            for (int i = 0; i < segmentInfo.m_lanes.Length; ++i)
            {
                if (curLaneId == 0)
                {
                    break;
                }

                NetInfo.Lane laneInfo = segmentInfo.m_lanes[i];

                labelStr += "Lane idx " + i + ", id " + curLaneId;
#if DEBUG
                labelStr += ", flags: " + ((NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[curLaneId].m_flags).ToString() + ", limit: " + SpeedLimitManager.GetCustomSpeedLimit(curLaneId) + " km/h, dir: " + laneInfo.m_direction + ", final: " + laneInfo.m_finalDirection + ", pos: " + String.Format("{0:0.##}", laneInfo.m_position) + ", sim. idx: " + laneInfo.m_similarLaneIndex + " for " + laneInfo.m_vehicleType + "/" + laneInfo.m_laneType;
#endif

                /*if (CustomRoadAI.InStartupPhase)
                 *      labelStr += ", in start-up phase";
                 * else*/
                labelStr += ", avg. speed: " + (CustomRoadAI.laneMeanSpeeds[segmentId] != null && i < CustomRoadAI.laneMeanSpeeds[segmentId].Length ? "" + CustomRoadAI.laneMeanSpeeds[segmentId][i] : "?") + " %";
                labelStr += ", rel. density: " + (CustomRoadAI.laneMeanRelDensities[segmentId] != null && i < CustomRoadAI.laneMeanRelDensities[segmentId].Length ? "" + CustomRoadAI.laneMeanRelDensities[segmentId][i] : "?") + " %";
#if ABSDENSITY
                labelStr += ", abs. density: " + (CustomRoadAI.laneMeanAbsDensities[segmentId] != null && i < CustomRoadAI.laneMeanAbsDensities[segmentId].Length ? "" + CustomRoadAI.laneMeanAbsDensities[segmentId][i] : "?") + " %";
#endif
#if DEBUG
                labelStr += " (" + (CustomRoadAI.currentLaneDensities[segmentId] != null && i < CustomRoadAI.currentLaneDensities[segmentId].Length ? "" + CustomRoadAI.currentLaneDensities[segmentId][i] : "?") + "/" + totalDensity + ")";
#endif
                labelStr += "\n";

                curLaneId = Singleton <NetManager> .instance.m_lanes.m_buffer[curLaneId].m_nextLane;
            }

            Vector2 dim       = _counterStyle.CalcSize(new GUIContent(labelStr));
            Rect    labelRect = new Rect(screenPos.x - dim.x / 2f, screenPos.y, dim.x, dim.y);

            GUI.Label(labelRect, labelStr, _counterStyle);
        }
Esempio n. 30
0
        public override void SimulationStep(ushort segmentID, ref NetSegment data)
        {
            //Start PlayerNEtAI.SimulationStep

            if (this.HasMaintenanceCost(segmentID, ref data))
            {
                NetManager playerNetAIinstance  = Singleton <NetManager> .instance;
                Vector3    playerNetAIposition  = playerNetAIinstance.m_nodes.m_buffer[(int)data.m_startNode].m_position;
                Vector3    playerNetAIposition2 = playerNetAIinstance.m_nodes.m_buffer[(int)data.m_endNode].m_position;
                int        playerNetAInum       = this.GetMaintenanceCost(playerNetAIposition, playerNetAIposition2);
                bool       playerNetAIflag      = (ulong)(Singleton <SimulationManager> .instance.m_currentFrameIndex >> 8 & 15u) == (ulong)((long)(segmentID & 15));
                if (playerNetAInum != 0)
                {
                    if (playerNetAIflag)
                    {
                        playerNetAInum = playerNetAInum * 16 / 100 - playerNetAInum / 100 * 15;
                    }
                    else
                    {
                        playerNetAInum /= 100;
                    }
                    Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.Maintenance, playerNetAInum, this.m_info.m_class);
                }
                if (playerNetAIflag)
                {
                    float playerNetAInum2 = (float)playerNetAIinstance.m_nodes.m_buffer[(int)data.m_startNode].m_elevation;
                    float playerNetAInum3 = (float)playerNetAIinstance.m_nodes.m_buffer[(int)data.m_endNode].m_elevation;
                    if (this.IsUnderground())
                    {
                        playerNetAInum2 = -playerNetAInum2;
                        playerNetAInum3 = -playerNetAInum3;
                    }
                    int constructionCost = this.GetConstructionCost(playerNetAIposition, playerNetAIposition2, playerNetAInum2, playerNetAInum3);
                    if (constructionCost != 0)
                    {
                        StatisticBase statisticBase = Singleton <StatisticsManager> .instance.Acquire <StatisticInt64>(StatisticType.CityValue);

                        if (statisticBase != null)
                        {
                            statisticBase.Add(constructionCost);
                        }
                    }
                }
            }
            //End  PlayerNEtAI.SimulationStep


            SimulationManager instance  = Singleton <SimulationManager> .instance;
            NetManager        instance2 = Singleton <NetManager> .instance;

            Notification.Problem problem = Notification.RemoveProblems(data.m_problems, Notification.Problem.Flood | Notification.Problem.Snow);
            if ((data.m_flags & NetSegment.Flags.AccessFailed) != NetSegment.Flags.None && Singleton <SimulationManager> .instance.m_randomizer.Int32(16u) == 0)
            {
                data.m_flags &= ~NetSegment.Flags.AccessFailed;
            }
            float num  = 0f;
            uint  num2 = data.m_lanes;
            int   num3 = 0;

            while (num3 < this.m_info.m_lanes.Length && num2 != 0u)
            {
                NetInfo.Lane lane = this.m_info.m_lanes[num3];
                if ((byte)(lane.m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0 && (lane.m_vehicleType & ~VehicleInfo.VehicleType.Bicycle) != VehicleInfo.VehicleType.None)
                {
                    num += instance2.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_length;
                }
                num2 = instance2.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_nextLane;
                num3++;
            }
            int num4 = 0;

            if (data.m_trafficBuffer == 65535)
            {
                if ((data.m_flags & NetSegment.Flags.Blocked) == NetSegment.Flags.None)
                {
                    data.m_flags        |= NetSegment.Flags.Blocked;
                    data.m_modifiedIndex = instance.m_currentBuildIndex++;
                }
            }
            else
            {
                data.m_flags &= ~NetSegment.Flags.Blocked;
                int num5 = Mathf.RoundToInt(num) << 4;
                if (num5 != 0)
                {
                    num4 = (int)((byte)Mathf.Min((int)(data.m_trafficBuffer * 100) / num5, 100));
                }
            }
            data.m_trafficBuffer = 0;
            if (num4 > (int)data.m_trafficDensity)
            {
                data.m_trafficDensity = (byte)Mathf.Min((int)(data.m_trafficDensity + 5), num4);
            }
            else if (num4 < (int)data.m_trafficDensity)
            {
                data.m_trafficDensity = (byte)Mathf.Max((int)(data.m_trafficDensity - 5), num4);
            }
            Vector3 position  = instance2.m_nodes.m_buffer[(int)data.m_startNode].m_position;
            Vector3 position2 = instance2.m_nodes.m_buffer[(int)data.m_endNode].m_position;
            Vector3 vector    = (position + position2) * 0.5f;
            bool    flag      = false;

            if ((this.m_info.m_setVehicleFlags & Vehicle.Flags.Underground) == (Vehicle.Flags) 0)
            {
                float num6 = Singleton <TerrainManager> .instance.WaterLevel(VectorUtils.XZ(vector));

                // NON-STOCK CODE START
                if (num6 > vector.y + (float)ModSettings.RoadwayFloodedTolerance / 100)
                {
                    flag          = true;
                    data.m_flags |= NetSegment.Flags.Flooded;
                    //Debug.Log("[RF] Successfully detoured roadway flooded tolerance");
                    problem = Notification.AddProblems(problem, Notification.Problem.Flood | Notification.Problem.MajorProblem);

                    /*DisasterData floodedSinkHoleData = new DisasterData();
                     * floodedSinkHoleData.m_targetPosition = data.m_middlePosition;
                     * floodedSinkHoleData.m_intensity = (byte)instance.m_randomizer.Int32(100u);
                     */
                    Vector3 min = data.m_bounds.min;
                    Vector3 max = data.m_bounds.max;
                    RoadBaseAI.FloodParkedCars(min.x, min.z, max.x, max.z);
                }

                else
                {
                    data.m_flags &= ~NetSegment.Flags.Flooded;

                    // Rainfall compatibility
                    float add = (float)ModSettings.RoadwayFloodingTolerance / 100;
                    //Debug.Log("[RF] Successfully detoured roadway flooding tolerance");
                    if (num6 > vector.y + add)
                    {
                        flag    = true;
                        problem = Notification.AddProblems(problem, Notification.Problem.Flood);
                    }
                }
                //Debug.Log("[RF] Successfully detoured roadway flooding tolerance: not flooding");
                // NON-STOCK CODE END
            }
            DistrictManager instance3 = Singleton <DistrictManager> .instance;
            byte            district  = instance3.GetDistrict(vector);

            DistrictPolicies.CityPlanning cityPlanningPolicies = instance3.m_districts.m_buffer[(int)district].m_cityPlanningPolicies;
            int num7 = (int)(100 - (data.m_trafficDensity - 100) * (data.m_trafficDensity - 100) / 100);

            if ((this.m_info.m_vehicleTypes & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None)
            {
                if ((this.m_info.m_setVehicleFlags & Vehicle.Flags.Underground) == (Vehicle.Flags) 0)
                {
                    if (flag && (data.m_flags & (NetSegment.Flags.AccessFailed | NetSegment.Flags.Blocked)) == NetSegment.Flags.None && instance.m_randomizer.Int32(10u) == 0)
                    {
                        TransferManager.TransferOffer offer = default(TransferManager.TransferOffer);
                        offer.Priority   = 4;
                        offer.NetSegment = segmentID;
                        offer.Position   = vector;
                        offer.Amount     = 1;
                        Singleton <TransferManager> .instance.AddOutgoingOffer(TransferManager.TransferReason.FloodWater, offer);
                    }
                    int num8 = (int)data.m_wetness;
                    if (!instance2.m_treatWetAsSnow)
                    {
                        if (flag)
                        {
                            num8 = 255;
                        }
                        else
                        {
                            int   num9  = -(num8 + 63 >> 5);
                            float num10 = Singleton <WeatherManager> .instance.SampleRainIntensity(vector, false);

                            if (num10 != 0f)
                            {
                                int num11 = Mathf.RoundToInt(Mathf.Min(num10 * 4000f, 1000f));
                                num9 += instance.m_randomizer.Int32(num11, num11 + 99) / 100;
                            }
                            num8 = Mathf.Clamp(num8 + num9, 0, 255);
                        }
                    }
                    else if (this.m_accumulateSnow)
                    {
                        if (flag)
                        {
                            num8 = 128;
                        }
                        else
                        {
                            float num12 = Singleton <WeatherManager> .instance.SampleRainIntensity(vector, false);

                            if (num12 != 0f)
                            {
                                int num13 = Mathf.RoundToInt(num12 * 400f);
                                int num14 = instance.m_randomizer.Int32(num13, num13 + 99) / 100;
                                if (Singleton <UnlockManager> .instance.Unlocked(UnlockManager.Feature.Snowplow))
                                {
                                    num8 = Mathf.Min(num8 + num14, 255);
                                }
                                else
                                {
                                    num8 = Mathf.Min(num8 + num14, 128);
                                }
                            }
                            else if (Singleton <SimulationManager> .instance.m_randomizer.Int32(4u) == 0)
                            {
                                num8 = Mathf.Max(num8 - 1, 0);
                            }
                            if (num8 >= 64 && (data.m_flags & (NetSegment.Flags.AccessFailed | NetSegment.Flags.Blocked | NetSegment.Flags.Flooded)) == NetSegment.Flags.None && instance.m_randomizer.Int32(10u) == 0)
                            {
                                TransferManager.TransferOffer offer2 = default(TransferManager.TransferOffer);
                                offer2.Priority   = num8 / 50;
                                offer2.NetSegment = segmentID;
                                offer2.Position   = vector;
                                offer2.Amount     = 1;
                                Singleton <TransferManager> .instance.AddOutgoingOffer(TransferManager.TransferReason.Snow, offer2);
                            }
                            if (num8 >= 192)
                            {
                                problem = Notification.AddProblems(problem, Notification.Problem.Snow);
                            }
                            District[] expr_5B7_cp_0_cp_0 = instance3.m_districts.m_buffer;
                            byte       expr_5B7_cp_0_cp_1 = district;
                            expr_5B7_cp_0_cp_0[(int)expr_5B7_cp_0_cp_1].m_productionData.m_tempSnowCover = expr_5B7_cp_0_cp_0[(int)expr_5B7_cp_0_cp_1].m_productionData.m_tempSnowCover + (uint)num8;
                        }
                    }
                    if (num8 != (int)data.m_wetness)
                    {
                        if (Mathf.Abs((int)data.m_wetness - num8) > 10)
                        {
                            data.m_wetness = (byte)num8;
                            InstanceID empty = InstanceID.Empty;
                            empty.NetSegment = segmentID;
                            instance2.AddSmoothColor(empty);
                            empty.NetNode = data.m_startNode;
                            instance2.AddSmoothColor(empty);
                            empty.NetNode = data.m_endNode;
                            instance2.AddSmoothColor(empty);
                        }
                        else
                        {
                            data.m_wetness             = (byte)num8;
                            instance2.m_wetnessChanged = 256;
                        }
                    }
                }
                int num15;
                if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.StuddedTires) != DistrictPolicies.CityPlanning.None)
                {
                    num7  = num7 * 3 + 1 >> 1;
                    num15 = Mathf.Min(700, (int)(50 + data.m_trafficDensity * 6));
                }
                else
                {
                    num15 = Mathf.Min(500, (int)(50 + data.m_trafficDensity * 4));
                }
                if (!this.m_highwayRules)
                {
                    int num16 = instance.m_randomizer.Int32(num15, num15 + 99) / 100;
                    data.m_condition = (byte)Mathf.Max((int)data.m_condition - num16, 0);
                    if (data.m_condition < 192 && (data.m_flags & (NetSegment.Flags.AccessFailed | NetSegment.Flags.Blocked | NetSegment.Flags.Flooded)) == NetSegment.Flags.None && instance.m_randomizer.Int32(20u) == 0)
                    {
                        TransferManager.TransferOffer offer3 = default(TransferManager.TransferOffer);
                        offer3.Priority   = (int)((255 - data.m_condition) / 50);
                        offer3.NetSegment = segmentID;
                        offer3.Position   = vector;
                        offer3.Amount     = 1;
                        Singleton <TransferManager> .instance.AddIncomingOffer(TransferManager.TransferReason.RoadMaintenance, offer3);
                    }
                }
            }
            if (!this.m_highwayRules)
            {
                if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.HeavyTrafficBan) != DistrictPolicies.CityPlanning.None)
                {
                    data.m_flags |= NetSegment.Flags.HeavyBan;
                }
                else
                {
                    data.m_flags &= ~NetSegment.Flags.HeavyBan;
                }
                if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.BikeBan) != DistrictPolicies.CityPlanning.None)
                {
                    data.m_flags |= NetSegment.Flags.BikeBan;
                }
                else
                {
                    data.m_flags &= ~NetSegment.Flags.BikeBan;
                }
                if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.OldTown) != DistrictPolicies.CityPlanning.None)
                {
                    data.m_flags |= NetSegment.Flags.CarBan;
                }
                else
                {
                    data.m_flags &= ~NetSegment.Flags.CarBan;
                }
            }
            int num17 = this.m_noiseAccumulation * num7 / 100;

            if (num17 != 0)
            {
                float num18 = Vector3.Distance(position, position2);
                int   num19 = Mathf.FloorToInt(num18 / this.m_noiseRadius);
                for (int i = 0; i < num19; i++)
                {
                    Vector3 position3 = Vector3.Lerp(position, position2, (float)(i + 1) / (float)(num19 + 1));
                    Singleton <ImmaterialResourceManager> .instance.AddResource(ImmaterialResourceManager.Resource.NoisePollution, num17, position3, this.m_noiseRadius);
                }
            }
            if (data.m_trafficDensity >= 50 && data.m_averageLength < 25f && (instance2.m_nodes.m_buffer[(int)data.m_startNode].m_flags & (NetNode.Flags.LevelCrossing | NetNode.Flags.TrafficLights)) == NetNode.Flags.TrafficLights && (instance2.m_nodes.m_buffer[(int)data.m_endNode].m_flags & (NetNode.Flags.LevelCrossing | NetNode.Flags.TrafficLights)) == NetNode.Flags.TrafficLights)
            {
                GuideController properties = Singleton <GuideManager> .instance.m_properties;
                if (properties != null)
                {
                    Singleton <NetManager> .instance.m_shortRoadTraffic.Activate(properties.m_shortRoadTraffic, segmentID);
                }
            }
            if ((data.m_flags & NetSegment.Flags.Collapsed) != NetSegment.Flags.None)
            {
                GuideController properties2 = Singleton <GuideManager> .instance.m_properties;
                if (properties2 != null)
                {
                    Singleton <NetManager> .instance.m_roadDestroyed.Activate(properties2.m_roadDestroyed, segmentID);

                    Singleton <NetManager> .instance.m_roadDestroyed2.Activate(properties2.m_roadDestroyed2, this.m_info.m_class.m_service);
                }
                if ((ulong)(instance.m_currentFrameIndex >> 8 & 15u) == (ulong)((long)(segmentID & 15)))
                {
                    int           delta         = Mathf.RoundToInt(data.m_averageLength);
                    StatisticBase statisticBase = Singleton <StatisticsManager> .instance.Acquire <StatisticInt32>(StatisticType.DestroyedLength);

                    statisticBase.Add(delta);
                }
            }
            data.m_problems = problem;
        }
Esempio n. 31
0
        internal float GetLockFreeGameSpeedLimit(ushort segmentId, uint laneIndex, uint laneId, NetInfo.Lane laneInfo)
        {
            float speedLimit = 0;

            ushort?[] fastArray = Flags.laneSpeedLimitArray[segmentId];
            if (fastArray != null && fastArray.Length > laneIndex && fastArray[laneIndex] != null)
            {
                speedLimit = ToGameSpeedLimit((ushort)fastArray[laneIndex]);
            }
            else
            {
                speedLimit = laneInfo.m_speedLimit;
            }
            return(speedLimit);
        }
        private bool GetStopPosition(TransportInfo info, ushort segment, ushort building, ushort firstStop, ref Vector3 hitPos, out bool fixedPlatform)
        {
            bool alternateMode = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);

            fixedPlatform = false;
            if (segment != 0)
            {
                NetManager instance = Singleton <NetManager> .instance;
                if (!alternateMode && (instance.m_segments.m_buffer [(int)segment].m_flags & NetSegment.Flags.Untouchable) != NetSegment.Flags.None)
                {
                    building = NetSegment.FindOwnerBuilding(segment, 363f);
                    if (building != 0)
                    {
                        BuildingManager instance3         = Singleton <BuildingManager> .instance;
                        BuildingInfo    info3             = instance3.m_buildings.m_buffer[(int)building].Info;
                        TransportInfo   transportLineInfo = info3.m_buildingAI.GetTransportLineInfo();
                        if (transportLineInfo != null && transportLineInfo.m_transportType == info.m_transportType)
                        {
                            segment = 0;
                        }
                        else
                        {
                            building = 0;
                        }
                    }
                }
                Vector3 point;
                int     num;
                float   num2;
                Vector3 vector;
                int     num3;
                float   num4;
                if (segment != 0 && instance.m_segments.m_buffer[(int)segment].GetClosestLanePosition(hitPos, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, out point, out num, out num2) && instance.m_segments.m_buffer[(int)segment].GetClosestLanePosition(point, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, out vector, out num3, out num4))
                {
                    PathUnit.Position pathPos;
                    pathPos.m_segment = segment;
                    pathPos.m_lane    = (byte)num3;
                    pathPos.m_offset  = 128;
                    NetInfo.Lane lane = instance.m_segments.m_buffer[(int)segment].Info.m_lanes[num3];
                    if (!lane.m_allowStop)
                    {
                        return(false);
                    }
                    float num5 = lane.m_stopOffset;
                    if ((instance.m_segments.m_buffer[(int)segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
                    {
                        num5 = -num5;
                    }
                    uint    laneID = PathManager.GetLaneID(pathPos);
                    Vector3 vector2;
                    instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculateStopPositionAndDirection((float)pathPos.m_offset * 0.003921569f, num5, out hitPos, out vector2);
                    fixedPlatform = true;
                    return(true);
                }
            }
            if (!alternateMode && building != 0)
            {
                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)
                {
                    BuildingManager instance2 = Singleton <BuildingManager> .instance;
                    BuildingInfo    info2     = instance2.m_buildings.m_buffer[(int)building].Info;
                    if (info2.m_buildingAI.GetTransportLineInfo() != null)
                    {
                        Vector3 vector3 = Vector3.zero;
                        int     num6    = 1000000;
                        for (int i = 0; i < 12; i++)
                        {
                            Randomizer randomizer = new Randomizer(i);
                            Vector3    vector4;
                            Vector3    a;
                            info2.m_buildingAI.CalculateSpawnPosition(building, ref instance2.m_buildings.m_buffer[(int)building], ref randomizer, randomVehicleInfo, out vector4, out a);
                            int lineCount = this.GetLineCount(vector4, a - vector4, info.m_transportType);
                            if (lineCount < num6)
                            {
                                vector3 = vector4;
                                num6    = lineCount;
                            }
                        }
                        if (firstStop != 0)
                        {
                            Vector3 position = Singleton <NetManager> .instance.m_nodes.m_buffer[(int)firstStop].m_position;
                            if (Vector3.SqrMagnitude(position - vector3) < 16384f && instance2.FindBuilding(vector3, 128f, info.m_class.m_service, info.m_class.m_subService, Building.Flags.None, Building.Flags.None) == building)
                            {
                                hitPos = position;
                                return(true);
                            }
                        }
                        hitPos = vector3;
                        return(true);
                    }
                }
            }
            return(false);
        }