public void AddSharedStop(ushort segment, ushort line, uint lane)
        {
            if (sharedStopSegments.Any(s => s.m_segment == segment))
            {
                var sharedStopSegment = sharedStopSegments[sharedStopSegments.FindIndex(s => s.m_segment == segment)];
                if (sharedStopSegment.m_lanes.Keys.Contains(lane))
                {
                    sharedStopSegment.m_lanes[lane].Add(line);
                    Log.Debug($"add to existing segment {segment}, lane: {lane}, line:{line}");
                }
                else
                {
                    sharedStopSegment.m_lanes.Add(lane, new List <ushort>()
                    {
                        line
                    });
                }
            }
            else
            {
                var newSegment = new SharedStopSegment(segment, line, lane);
                sharedStopSegments.Add(newSegment);
                Log.Debug($"add sharedsegment {segment}, {sharedStopSegments.Count}, lane: {lane}");
            }
            NetAI roadAi = Singleton <NetManager> .instance.m_segments.m_buffer[segment].Info.m_netAI;

            if (roadAi is RoadBridgeAI roadBridgeAI)
            {
                roadBridgeAI.UpdateSegmentStopFlags(segment, ref Singleton <NetManager> .instance.m_segments.m_buffer[segment]);
            }
        }
        public static byte GetElevation(Vector3 position, NetAI net_ai)
        {
            if (!net_ai.IsUnderground() && !net_ai.IsOverground())
            {
                return(0); // on ground.
            }

            net_ai.GetElevationLimits(out int min, out int max);
            if (min == max)
            {
                return(0); // From NetTool.GetElevation()
            }

            float elevation = position.y - TerrainHeight(position);

#if DEBUG
            // tolerated error = +-1
            if (!(min * 12 - 1 <= elevation && elevation <= max * 12 + 1))
            {
                Debug.LogWarning($"RoundaboutBuilder: ELevation out of range expected {min * 12 - 1} <= {elevation} <={max * 12 + 1}");
            }
#endif

            elevation = Mathf.Clamp(elevation, min * 12, max * 12); // 12 is from NetTool.GetElevation()
            elevation = Mathf.Abs(elevation);
            return((byte)Mathf.Clamp(elevation, 1, 255));           // underground/overground road should not have 0 elevation.
        }
        public static void Prefix(NetInfo __instance)
        {
            if (!Mod.IsInGame)
            {
                return;
            }

            bool movableNet = (__instance.editorCategory == "MovableBridge_Movable");
            bool staticNet  = (__instance.editorCategory == "MovableBridge_Static");

            if (movableNet || staticNet)
            {
                UnityEngine.Debug.Log($"Adding MovableBridgeRoadAI to ${__instance.name}");

                NetAI oldAI = __instance.gameObject.GetComponent <NetAI>();

                if (oldAI is RoadBridgeAI)
                {
                    MovableBridgeRoadAI newAI = __instance.gameObject.AddComponent <MovableBridgeRoadAI>();
                    newAI.CopyFrom(oldAI);
                    newAI.m_Movable = movableNet;

                    UnityEngine.Object.DestroyImmediate(oldAI);
                }
                else if (oldAI is TrainTrackBridgeAI)
                {
                    MovableBridgeTrainTrackAI newAI = __instance.gameObject.AddComponent <MovableBridgeTrainTrackAI>();
                    newAI.CopyFrom(oldAI);
                    newAI.m_Movable = movableNet;

                    UnityEngine.Object.DestroyImmediate(oldAI);
                }
            }
        }
Example #4
0
        // Patch for NetAI.CheckBuildPosition that makes it possible to upgrade a segment to a NetInfo of the same type if the skin is different
        public static ToolBase.ToolErrors CheckBuildPosition(NetAI netAi, bool test, bool visualize, bool overlay, bool autofix, ref global::NetTool.ControlPoint startPoint, ref global::NetTool.ControlPoint middlePoint, ref global::NetTool.ControlPoint endPoint, out BuildingInfo ownerBuilding, out Vector3 ownerPosition, out Vector3 ownerDirection, out int productionRate)
        {
            var toolErrors = netAi.CheckBuildPosition(test, visualize, overlay, autofix, ref startPoint, ref middlePoint, ref endPoint, out ownerBuilding, out ownerPosition, out ownerDirection, out productionRate);

            ushort upgradedSegment = middlePoint.m_segment;

            if (startPoint.m_segment == upgradedSegment || endPoint.m_segment == upgradedSegment)
            {
                upgradedSegment = 0;
            }

            if (upgradedSegment != 0 && (toolErrors & ToolBase.ToolErrors.CannotUpgrade) != 0)
            {
                NetInfo upgradedSegmentInfo = global::NetManager.instance.m_segments.m_buffer[upgradedSegment].Info;
                if (!(upgradedSegmentInfo.m_netAI.IsUnderground() && !netAi.SupportUnderground()))
                {
                    // Check if skin is different. If so, allow upgrade!
                    var activeSkin          = NetworkSkinManager.instance.GetActiveSkin(upgradedSegmentInfo);
                    var upgradedSegmentSkin = NetworkSkinManager.SegmentSkins[upgradedSegment];
                    if (!Equals(activeSkin, upgradedSegmentSkin))
                    {
                        toolErrors &= ~ToolBase.ToolErrors.CannotUpgrade;
                    }
                }
            }

            return(toolErrors);
        }
        public static void GetActiveNodeBuilding(NetAI netAI, ushort nodeID, ref global::NetNode data, out BuildingInfo building, out float heightOffset)
        {
            var patcherState = Apply(netAI.m_info, NetworkSkinManager.instance.GetActiveSkin(netAI.m_info));

            netAI.GetNodeBuilding(nodeID, ref data, out building, out heightOffset);
            Revert(netAI.m_info, patcherState);
        }
Example #6
0
        static bool Prefix(NetLane.Flags ___m_stopFlag, VehicleInfo.VehicleType ___m_vehicleType, ushort nodeID, ref NetNode data)
        {
            if (nodeID == 0 || !___m_vehicleType.IsValidTransport())
            {
                return(true);
            }
            ushort segment = Singleton <NetManager> .instance.m_lanes.m_buffer[data.m_lane].m_segment;

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

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

            NetLane.Flags flags = (NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[data.m_lane].m_flags;
            flags &= ~___m_stopFlag;
            Singleton <NetManager> .instance.m_lanes.m_buffer[data.m_lane].m_flags = (ushort)flags;
            Log.Debug($"lane flags updated {(NetLane.Flags)Singleton<NetManager>.instance.m_lanes.m_buffer[data.m_lane].m_flags}");
            if (roadAi is RoadBridgeAI roadBridgeAI)
            {
                roadBridgeAI.UpdateSegmentStopFlags(segment, ref Singleton <NetManager> .instance.m_segments.m_buffer[segment]);
            }
            Log.Debug($"segment flags updated {Singleton<NetManager>.instance.m_segments.m_buffer[segment].m_flags}");
            return(true);
        }
Example #7
0
        public static Color GetNodeColor(NetAI netAI, ushort nodeID, ref global::NetNode data, InfoManager.InfoMode infoMode)
        {
            var patcherState = Apply(netAI.m_info, NetworkSkinManager.NodeSkins[nodeID]);
            var segmentColor = netAI.GetColor(nodeID, ref data, infoMode);

            Revert(netAI.m_info, patcherState);
            return(segmentColor);
        }
 public static ToolBase.ToolErrors CheckBuildPosition(NetAI ai, bool test, bool visualize, bool overlay, bool autofix, ref NetTool.ControlPoint startPoint, ref NetTool.ControlPoint middlePoint, ref NetTool.ControlPoint endPoint, out BuildingInfo ownerBuilding, out Vector3 ownerPosition, out Vector3 ownerDirection, out int productionRate)
 {
     UnityEngine.Debug.Log("Failed to override CheckBuildPosition()");
     ownerBuilding  = null;
     ownerPosition  = new Vector3();
     ownerDirection = new Vector3();
     productionRate = 0;
     return(ToolBase.ToolErrors.None);
 }
Example #9
0
        private static void RecalculateFlags(uint laneId)
        {
            NetLane[] laneBuffer = NetManager.instance.m_lanes.m_buffer;
            ushort    segmentId  = laneBuffer[laneId].m_segment;
            NetAI     ai         = GetSeg(segmentId).Info.m_netAI;

#if DEBUGFLAGS
            Log._Debug($"Flags.RecalculateFlags: Recalculateing lane arrows of segment {segmentId}.");
#endif
            ai.UpdateLanes(segmentId, ref GetSeg(segmentId), true);
        }
Example #10
0
        public static bool IsValidNet(NetInfo info)
        {
            if (info == null)
            {
                return(false);
            }
            NetAI ai = info.m_netAI;

            return(ai is RoadBaseAI ||
                   ai is TrainTrackBaseAI ||
                   ai is PedestrianBridgeAI ||
                   ai is PedestrianPathAI ||
                   ai is PedestrianTunnelAI ||
                   ai is PedestrianWayAI);
        }
Example #11
0
 static void SimulationStep(NetAI _this, ushort segmentID, ref NetSegment data)
 {
     try
     {
         _this.SimulationStep(segmentID, ref data);
     }
     catch (Exception e)
     {
         string info = $"An exception occured during NetAI simulation step.\nAsset: {_this.m_info.name}" +
                       $"\nSegmentID: {segmentID}\nType: {_this.GetType().Name}\nSeverity: High";
         HealkitException e2 = new HealkitException(info, e);
         e2.m_uniqueData   = _this.m_info.name;
         e2.m_supperessMsg = "Suppress similar exceptions caused by this asset";
         UIView.ForwardException(e2);
     }
 }
Example #12
0
        public static bool IsExempt(NetInfo info)
        {
            Extensions.Assert(info != null, "info!=null");
            NetAI ai = info.m_netAI;

            Extensions.Assert(ai is RoadBaseAI, "ai is RoadBaseAI");
            if (!(ai is RoadAI))
            {
                info = GetGroundInfo(info);
            }
            if (info == null || !IsNormalGroundRoad(info))
            {
                return(false);
            }
            string name = GetRoadTitle(info);

            return(Options.instance?.Never?.Contains(name) ?? false);
        }
Example #13
0
        public RoadAIWrapper(NetAI ai)
        {
            m_ai = ai;

            try
            {
                m_elevated  = m_ai.GetType().GetField("m_elevatedInfo");
                m_bridge    = m_ai.GetType().GetField("m_bridgeInfo");
                m_slope     = m_ai.GetType().GetField("m_slopeInfo");
                m_tunnel    = m_ai.GetType().GetField("m_tunnelInfo");
                m_invisible = m_ai.GetType().GetField("m_invisible");
            }
            catch
            {
                m_elevated  = null;
                m_bridge    = null;
                m_slope     = null;
                m_tunnel    = null;
                m_invisible = null;
            }
        }
Example #14
0
        public static NetInfo GetSlope(this NetInfo info)
        {
            NetAI ai = info.m_netAI;

            if (ai is PedestrianTunnelAI || ai is RoadTunnelAI)
            {
                return(info);
            }

            if (ai is PedestrianPathAI)
            {
                return((ai as PedestrianPathAI).m_slopeInfo);
            }

            if (ai is RoadAI)
            {
                return((ai as RoadAI).m_slopeInfo);
            }

            Log.Error($"GetSlope({info} returns null. ai={ai}");
            return(null);
        }
Example #15
0
        public static NetInfo GetElevated(this NetInfo info)
        {
            NetAI ai = info.m_netAI;

            if (ai is PedestrianBridgeAI || ai is RoadBridgeAI)
            {
                return(info);
            }

            if (ai is PedestrianPathAI)
            {
                return((ai as PedestrianPathAI).m_elevatedInfo);
            }

            if (ai is RoadAI)
            {
                return((ai as RoadAI).m_elevatedInfo);
            }

            Log.Error($"GetElevated({info} returns null. ai={ai}");
            return(null);
        }
        public static bool Prefix(ref NetAI __instance, ref float __result)
        {
            float laneOffset  = 0;
            float startOffset = 0;
            float endOffset   = 0;
            bool  IsCSURSLane = CSURUtil.IsCSURSLane(__instance.m_info, ref laneOffset, ref startOffset, ref endOffset);

            if (CSURUtil.IsCSUROffset(__instance.m_info))
            {
                if (!IsCSURSLane)
                {
                    __result = (__instance.m_info.m_halfWidth - __instance.m_info.m_pavementWidth) / 2f;
                }
                else
                {
                    float laneNum = CSURUtil.CountCSURSVehicleLanes(__instance.m_info) + CSURUtil.CountCSURSOtherLanes(__instance.m_info);
                    __result = (laneNum * 3.75f / 2f);
                }
                return(false);
            }
            return(true);
        }
        internal static bool Prefix(ushort segmentID, ref NetSegment data, int index, ref TerrainModify.Surface surface, ref TerrainModify.Heights heights, ref TerrainModify.Edges edges, ref float left, ref float right, ref float leftStartY, ref float rightStartY, ref float leftEndY, ref float rightEndY, ref bool __result, NetAI __instance)
        {
            var net = __instance.m_info.GetMetaData();

            if (net is null)
            {
#if DEBUGQUAYROADS
                Log.Debug("No AR data found for: \n segmentId: " + segmentID + "name: " + data.Info.name);
#endif
                return(true);
            }

            ProfileSection[] profile = net.QuayRoadsProfile;
            if (profile is null)
            {
                return(true);
            }
            Log.Debug("modifying mask for segment " + segmentID.ToString() + ", section " + index);
            bool invert = (data.m_flags & NetSegment.Flags.Invert) != 0;
            return(ModifyMaskCommon.ModifyMask(profile, invert, index, ref surface, ref heights, ref edges, ref left, ref right, ref leftStartY, ref rightStartY, ref leftEndY, ref rightEndY, ref __result));
        }
        internal static bool Prefix(ushort nodeID, ref NetNode data, ushort segment1, ushort segment2, int index, ref TerrainModify.Surface surface, ref TerrainModify.Heights heights, ref TerrainModify.Edges edges, ref float left, ref float right, ref float leftY, ref float rightY, ref bool __result, NetAI __instance)
        {
            var net = __instance.m_info.GetMetaData();

            if (net is null)
            {
                return(true);
            }

            ProfileSection[] profile = net.QuayRoadsProfile;
            if (profile is null)
            {
                return(true);
            }

            Log.Debug("modifying mask for node " + nodeID.ToString() + ", section " + index);
            NetManager netManager    = Singleton <NetManager> .instance;
            bool       isStartNode   = netManager.m_segments.m_buffer[segment1].m_startNode == nodeID;
            bool       segmentInvert = (netManager.m_segments.m_buffer[segment1].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None;
            bool       invert        = isStartNode ^ segmentInvert;
            float      leftStartY    = leftY;
            float      rightStartY   = rightY;
            float      leftEndY      = leftY;
            float      rightEndY     = rightY;
            bool       result        = ModifyMaskCommon.ModifyMask(profile, invert, index, ref surface, ref heights, ref edges, ref left, ref right, ref leftStartY, ref rightStartY, ref leftEndY, ref rightEndY, ref __result);

            if (isStartNode)
            {
                leftY  = leftStartY;
                rightY = rightStartY;
            }
            else
            {
                leftY  = leftEndY;
                rightY = rightEndY;
            }
            return(result);
        }