/// <summary> /// Set up prop types of vehicle props generated by Elektrix's TVP mod. Need the TVP Patch mod /// </summary> public void SetVehiclePropType(Dictionary <PropInfo, VehicleInfo> propVehicleInfoTable, PropInfo info) { propType = Asset.PropType.PropsUnsortedVehicle; if (!propVehicleInfoTable.ContainsKey(info)) { return; } PrefabAI ai = propVehicleInfoTable[info].GetAI(); if (ai == null) { return; } Type aiType = ai.GetType(); if (IsMotorVehicle(aiType)) { propType = Asset.PropType.PropsMoterVehicle; } else if (IsRailwayVehicle(aiType)) { propType = Asset.PropType.PropsRailwayVehicle; } else if (IsAircraft(aiType)) { propType = Asset.PropType.PropsAircraft; } else if (IsWatercraft(aiType)) { propType = Asset.PropType.PropsWaterCraft; } }
private static void GetGeneratedRoadName(NetSegment segment, PrefabAI ai, ushort district, out string genName) { string filename = AdrController.CurrentConfig.GetConfigForDistrict(district).RoadConfig?.NamesFile ?? ""; if (string.IsNullOrEmpty(filename) || !AdrController.LoadedLocalesRoadName.ContainsKey(filename)) { filename = AdrController.CurrentConfig.GetConfigForDistrict(0).RoadConfig?.NamesFile; if (string.IsNullOrEmpty(filename) || !AdrController.LoadedLocalesRoadName.ContainsKey(filename)) { filename = null; } } Randomizer randomizer = new Randomizer(segment.m_nameSeed); if (filename != null) { int range = AdrController.LoadedLocalesRoadName[filename]?.Length ?? 0; if (range == 0) { genName = null; return; } genName = AdrController.LoadedLocalesRoadName[filename][randomizer.Int32((uint)range)]; } else { genName = m_roadBaseAiGenerateName.Invoke(ai, new object[] { randomizer })?.ToString(); } }
public void SetPrefab(VehicleInfo prefab) { if ((UnityEngine.Object)prefab == (UnityEngine.Object)null) { return; } PrefabAI ai = prefab.GetAI(); if ((UnityEngine.Object)ai == (UnityEngine.Object)null) { return; } FieldInfo field = ai.GetType().GetField("m_transportInfo"); if (field == null) { return; } TransportInfo.TransportType transportType = (field.GetValue((object)ai) as TransportInfo).m_transportType; if (this._firstShow) { this.FirstShowInit(transportType, prefab); } else { this.SetTransportType(transportType, prefab); } }
public static TransportSystemDefinition from(PrefabAI buildingAI) { DepotAI depotAI = buildingAI as DepotAI; if (depotAI == null) { return(null); } return(from(depotAI.m_transportInfo)); }
public static IBasicBuildingAIOverrides getBuildingOverrideExtension(BuildingInfo info) { PrefabAI targetAi = info.GetAI(); Type targetTypeAi = targetAi.GetType(); if (subtypes == null) { subtypes = new Dictionary <Type, Type>(); var subclasses = SVMUtils.GetSubtypesRecursive(typeof(BasicBuildingAIOverrides <,>), typeof(SVMBuildingAIOverrideUtils)); SVMUtils.doLog("GetOverride pré - subclasses:\r\n\t{0}", string.Join("\r\n\t", subclasses?.Select(x => x.ToString())?.ToArray() ?? new string[0])); foreach (Type t in subclasses) { try { subtypes[t.BaseType.GetGenericArguments()[1]] = t; } catch (Exception e) { SVMUtils.doErrorLog("ERROR ADDING SUBTYPE {0}!\r\n{1}", t, subclasses); } } SVMUtils.doLog("GetOverride - Classes:\r\n\t{0}", string.Join("\r\n\t", subtypes?.Select(x => x.Key.ToString() + "=>" + x.Value.ToString())?.ToArray() ?? new string[0])); } Type targetClass = null; IBasicBuildingAIOverrides value = null; if (!subtypes.ContainsKey(targetTypeAi)) { foreach (var clazz in subtypes.Keys) { if (clazz.IsAssignableFrom(targetTypeAi)) { value = (IBasicBuildingAIOverrides)SVMUtils.GetPrivateStaticField("instance", subtypes[clazz]); //SVMUtils.doLog("GetOverride - clazz = {0}; value = {1}", clazz, value); if (value.AcceptsAI(targetAi)) { targetClass = subtypes[clazz]; break; } } } SVMUtils.doLog("GetOverride - targetClass = {0} ({1})", targetClass, targetTypeAi); if (targetClass == null) { return(null); } } else { targetClass = subtypes[targetTypeAi]; value = (IBasicBuildingAIOverrides)SVMUtils.GetPrivateStaticField("instance", targetClass); } //SVMUtils.doLog("GetOverride - value = {0}", value); return((IBasicBuildingAIOverrides)value); }
public static string GetLocalizedTooltip(Asset asset, PrefabInfo prefab, string title) { MilestoneInfo unlockMilestone = prefab.GetUnlockMilestone(); string text = TooltipHelper.Format(new string[] { LocaleFormatter.Title, title, LocaleFormatter.Sprite, (!string.IsNullOrEmpty(prefab.m_InfoTooltipThumbnail)) ? prefab.m_InfoTooltipThumbnail : prefab.name, LocaleFormatter.Text, (asset.findIt2Description + Asset.GetLocalizedDescription(prefab)), LocaleFormatter.Locked, (!ToolsModifierControl.IsUnlocked(unlockMilestone)).ToString() }); ToolsModifierControl.GetUnlockingInfo(unlockMilestone, out string unlockDesc, out string currentValue, out string targetValue, out string progress, out string locked); string addTooltip = TooltipHelper.Format(new string[] { LocaleFormatter.LockedInfo, locked, LocaleFormatter.UnlockDesc, unlockDesc, LocaleFormatter.UnlockPopulationProgressText, progress, LocaleFormatter.UnlockPopulationTarget, targetValue, LocaleFormatter.UnlockPopulationCurrent, currentValue }); text = TooltipHelper.Append(text, addTooltip); PrefabAI aI = prefab.GetAI(); if (aI != null) { text = TooltipHelper.Append(text, aI.GetLocalizedTooltip()); } if (prefab is PropInfo || prefab is TreeInfo) { text = TooltipHelper.Append(text, TooltipHelper.Format(new string[] { LocaleFormatter.Cost, LocaleFormatter.FormatCost(prefab.GetConstructionCost(), false) })); } return(text); }
public static List <ushort> getAllDepotsFromCity() { List <ushort> saida = new List <ushort>(); var bm = Singleton <BuildingManager> .instance; var buildings = bm.GetServiceBuildings(ItemClass.Service.PublicTransport); foreach (ushort i in buildings) { PrefabAI prefAI = bm.m_buildings.m_buffer[i].Info.GetAI(); if (prefAI is DepotAI buildingAI && buildingAI.m_maxVehicleCount > 0) { saida.Add(i); } } return(saida); }
public static void TryCopyAttributes(PrefabAI src, PrefabAI dst, bool safe = true) { var oldAIFields = src.GetType() .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); var newAIFields = dst.GetType() .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); var newAIFieldDic = new Dictionary <string, FieldInfo>(newAIFields.Length); foreach (var field in newAIFields) { newAIFieldDic.Add(field.Name, field); } foreach (var fieldInfo in oldAIFields) { // do not copy attributes marked NonSerialized bool copyField = !fieldInfo.IsDefined(typeof(NonSerializedAttribute), true); if (safe && !fieldInfo.IsDefined(typeof(CustomizablePropertyAttribute), true)) { copyField = false; } if (copyField) { FieldInfo newAIField; newAIFieldDic.TryGetValue(fieldInfo.Name, out newAIField); try { if (newAIField != null && newAIField.GetType().Equals(fieldInfo.GetType())) { newAIField.SetValue(dst, fieldInfo.GetValue(src)); } } catch (NullReferenceException) { } } } }
public override void RefreshLines() { var tsd = Singleton <T> .instance.GetTSD(); bool hasPrefix = TLMLineUtils.hasPrefix(ref tsd); int count = 0; foreach (ushort buildingID in TLMDepotAI.getAllDepotsFromCity()) { PrefabAI prefabAI = Singleton <BuildingManager> .instance.m_buildings.m_buffer[buildingID].Info.GetAI(); if (prefabAI is ShelterAI && tsd.isShelterAiDepot()) { AddToList(buildingID, false, ref count); } else if (!tsd.isShelterAiDepot() && prefabAI is DepotAI ai) { var tiArray = new TransportInfo[] { ai.m_transportInfo, ai.m_secondaryTransportInfo }; foreach (TransportInfo info in tiArray) { if (tsd.isFromSystem(info) && (!hasPrefix || m_prefixFilter.selectedIndex == 0 || TLMDepotAI.getPrefixesServedByDepot(buildingID, info == ai.m_secondaryTransportInfo).Contains((uint)(m_prefixFilter.selectedIndex - 1)))) { AddToList(buildingID, info == ai.m_secondaryTransportInfo, ref count); } } } } RemoveExtraLines(count); switch (m_LastSortCriterion) { case DepotSortCriterion.NAME: OnNameSort(); break; case DepotSortCriterion.DISTRICT: OnDistrictSort(); break; } isUpdated = true; }
public override bool AcceptsAI(PrefabAI ai) => ai.GetType() == typeof(DepotAI);
public override bool AcceptsAI(PrefabAI ai) => typeof(DepotAI).IsAssignableFrom(ai.GetType());
/// <summary> /// Copies all attributes that share the same name and type from one AI object to another /// </summary> /// <param name="oldAI">Source AI instance</param> /// <param name="newAI">Destination AI instance</param> private void TryCopyAttributes(PrefabAI oldAI, PrefabAI newAI) { var oldAIFields = oldAI.GetType() .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); var newAIFields = newAI.GetType() .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); var newAIFieldDic = new Dictionary<String, FieldInfo>(newAIFields.Length); foreach (var field in newAIFields) { newAIFieldDic.Add(field.Name, field); } foreach (var fieldInfo in oldAIFields) { if (fieldInfo.IsDefined(typeof (CustomizablePropertyAttribute), true)) { FieldInfo newAIField; newAIFieldDic.TryGetValue(fieldInfo.Name, out newAIField); try { if (newAIField.GetType().Equals(fieldInfo.GetType())) { newAIField.SetValue(newAI, fieldInfo.GetValue(oldAI)); } } catch (NullReferenceException) { } } } }
public virtual bool AcceptsAI(PrefabAI ai) => true;
public bool AllowVehicleType(VehicleInfo.VehicleType veh, PrefabAI ai) => AllowVehicleType(veh, (U)ai);
private static string DefaultPrefix(NetInfo info, PrefabAI ai) { string text = null; if ((info.m_vehicleTypes & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None) { if (ai is RoadTunnelAI roadTunnel) { if ((!roadTunnel.m_highwayRules || info.m_forwardVehicleLaneCount + info.m_backwardVehicleLaneCount >= 2)) { text = "TUNNEL_NAME_PATTERN"; } } if (ai is RoadAI roadAi) { if (roadAi.m_enableZoning) { if ((info.m_setVehicleFlags & Vehicle.Flags.OnGravel) != 0) { text = "ROAD_NAME_PATTERN"; } else if (info.m_halfWidth >= 12f) { text = "AVENUE_NAME_PATTERN"; } else { text = "STREET_NAME_PATTERN"; } } else if (roadAi.m_highwayRules) { if (info.m_hasForwardVehicleLanes && info.m_hasBackwardVehicleLanes) { text = "ROAD_NAME_PATTERN"; } else if (info.m_forwardVehicleLaneCount >= 2 || info.m_backwardVehicleLaneCount >= 2) { text = "HIGHWAY_NAME_PATTERN"; } } } if (ai is DamAI) { if ((info.m_vehicleTypes & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None) { text = "ROAD_NAME_PATTERN"; } } if (ai is RoadBridgeAI bridgeAi) { if ((info.m_vehicleTypes & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None && (!bridgeAi.m_highwayRules || info.m_forwardVehicleLaneCount + info.m_backwardVehicleLaneCount >= 2)) { text = "BRIDGE_NAME_PATTERN"; } } } return(text); }
public static bool GenerateSegmentNameInternal(ushort segmentID, ref string __result, ref List <ushort> usedQueue, bool removePrefix) { LogUtils.DoLog($"[START {segmentID}]" + __result); if ((NetManager.instance.m_segments.m_buffer[segmentID].m_flags & NetSegment.Flags.CustomName) != 0) { if (usedQueue.Count == 0) { return(true); } else { InstanceID id = default; id.NetSegment = segmentID; __result = Singleton <InstanceManager> .instance.GetName(id); return(false); } } NetSegment segment = NetManager.instance.m_segments.m_buffer[segmentID]; NetInfo info = segment.Info; PrefabAI ai = info.GetAI(); string format = null; Randomizer randomizer = new Randomizer(segment.m_nameSeed); ushort district = (ushort)(DistrictManager.instance.GetDistrict(segment.m_middlePosition) & 0xFF); Xml.AdrDistrictConfig districtConfig = AdrController.CurrentConfig.GetConfigForDistrict(district); Xml.AdrDistrictConfig cityConfig = AdrController.CurrentConfig.GetConfigForDistrict(0); if ((info.m_vehicleTypes & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None) { string filenamePrefix = districtConfig.RoadConfig?.QualifierFile ?? ""; ; if ((filenamePrefix == null || !AdrController.LoadedLocalesRoadPrefix.ContainsKey(filenamePrefix)) && district > 0) { filenamePrefix = cityConfig.RoadConfig?.QualifierFile; } if (filenamePrefix != null && AdrController.LoadedLocalesRoadPrefix.ContainsKey(filenamePrefix)) { LocaleStruct.RoadPrefixFileIndexer currentPrefixFile = AdrController.LoadedLocalesRoadPrefix[filenamePrefix]; format = currentPrefixFile.GetPrefix(ai, info.m_forwardVehicleLaneCount == 0 || info.m_backwardVehicleLaneCount == 0, info.m_forwardVehicleLaneCount == info.m_backwardVehicleLaneCount, info.m_halfWidth * 2, (byte)(info.m_forwardVehicleLaneCount + info.m_backwardVehicleLaneCount), randomizer, segmentID); } LogUtils.DoLog("selectedPrefix = {0}", format); if (format == null) { string key = DefaultPrefix(info, ai); uint rangeFormat = Locale.Count(key); format = Locale.Get(key, randomizer.Int32(rangeFormat)); } } if (format == null) { return(true); } if (removePrefix) { format = Regex.Replace(format, "(?!\\{)(\\w+|\\.)(?!\\})", ""); if (format.IsNullOrWhiteSpace()) { return(true); } } string genName = ""; string sourceRoad = ""; string targetRoad = ""; string sourceKm = ""; string sourceKmWithDecimal = ""; string sourceDistrict = ""; string targetDistrict = ""; string direction = ""; if (format.Contains("{0}")) { GetGeneratedRoadName(segment, ai, district, out genName); if (genName == null) { return(true); } } ushort sourceSeg = 0; ushort targetSeg = 0; if (format.Contains("{1}") || format.Contains("{2}") || format.Contains("{3}") || format.Contains("{4}") || format.Contains("{7}")) { SegmentUtils.GetSegmentRoadEdges(segmentID, true, true, true, out ComparableRoad startRef, out ComparableRoad endRef, out _); sourceSeg = startRef.segmentReference; targetSeg = endRef.segmentReference; if (format.Contains("{1}")) { if (!usedQueue.Contains(sourceSeg)) { usedQueue.Add(sourceSeg); GenerateSegmentNameInternal(sourceSeg, ref sourceRoad, ref usedQueue, false); } } if (format.Contains("{2}")) { if (!usedQueue.Contains(targetSeg)) { usedQueue.Add(targetSeg); GenerateSegmentNameInternal(targetSeg, ref targetRoad, ref usedQueue, false); } } if (format.Contains("{3}") || format.Contains("{4}")) { float km = GetNumberAt(startRef.segmentReference, NetManager.instance.m_segments.m_buffer[startRef.segmentReference].m_startNode == startRef.nodeReference) / 1000f; sourceKm = km.ToString("0"); sourceKmWithDecimal = km.ToString("0.0"); } if (format.Contains("{7}"))//direction { int cardinalDirection = SegmentUtils.GetCardinalDirection(startRef, endRef); direction = Locale.Get("K45_CARDINAL_POINT_SHORT", cardinalDirection.ToString()); } } if (format.Contains("{5}") || format.Contains("{6}")) { GetSegmentRoadEdges(segmentID, false, false, false, out ComparableRoad startRef, out ComparableRoad endRef, out _); if (format.Contains("{5}"))//source district { sourceDistrict = GetDistrictAt(startRef); } if (format.Contains("{6}"))//target district { targetDistrict = GetDistrictAt(endRef); } } if (AddressesMod.DebugMode) { __result = $"[{segmentID}] " + StringUtils.SafeFormat(format, genName, sourceSeg, targetSeg, sourceKm, sourceKmWithDecimal, sourceDistrict, targetDistrict, direction)?.Trim(); } else { __result = StringUtils.SafeFormat(format, genName, sourceRoad, targetRoad, sourceKm, sourceKmWithDecimal, sourceDistrict, targetDistrict, direction)?.Trim(); } LogUtils.DoLog($"[END {segmentID}]" + __result); return(false); }
public string GetPrefix(PrefabAI ai, bool isOneWay, bool isSymmetric, float width, byte lanes, Randomizer rand, ushort segmentId, ushort seedId) { Highway highway = Highway.ANY; RoadType type = RoadType.NONE; if (ai is RoadBaseAI baseAi) { if (baseAi is DamAI) { type = RoadType.DAM; } else if (baseAi is RoadBridgeAI) { type = RoadType.BRIDGE; } else if (baseAi.IsUnderground()) { type = RoadType.TUNNEL; } else { type = RoadType.GROUND; } highway = baseAi.m_highwayRules ? Highway.TRUE : Highway.FALSE; } if (type == RoadType.NONE) { LogUtils.DoLog($"AI NAO IDENTIFICADA: {ai}"); return(null); } OneWay wayVal = isOneWay ? OneWay.TRUE : OneWay.FALSE; Symmetry symVal = isSymmetric ? Symmetry.TRUE : Symmetry.FALSE; LinkingType linking = LinkingType.NO_LINKING; SeedConfiguration seedConfiguration = (AdrNameSeedDataXml.Instance.NameSeedConfigs.TryGetValue(seedId, out AdrNameSeedConfig seedConf) && !(seedConf.HighwayParent is null) ? SeedConfiguration.HAS_HIGHWAY_TYPE : SeedConfiguration.NO_HIGHWAY_TYPE) | ((seedConf?.ForcedName).IsNullOrWhiteSpace()? SeedConfiguration.NO_FORCED_NAME : SeedConfiguration.HAS_FORCED_NAME); bool hasStart = true; bool hasEnd = true; if (wayVal == OneWay.TRUE && lanes <= 2) { SegmentUtils.GetSegmentRoadEdges(segmentId, true, true, true, out ComparableRoad startRef, out ComparableRoad endRef, out _); LogUtils.DoLog($"OneWay s={startRef}; e= {endRef}"); if (startRef.segmentReference == 0 || endRef.segmentReference == 0) { hasStart = startRef.segmentReference != 0; hasEnd = endRef.segmentReference != 0; } else if ((NetManager.instance.m_segments.m_buffer[startRef.segmentReference].Info.GetAI() is RoadBaseAI baseAiSource && baseAiSource.m_highwayRules) || (NetManager.instance.m_segments.m_buffer[endRef.segmentReference].Info.GetAI() is RoadBaseAI baseAiTarget && baseAiTarget.m_highwayRules)) { switch (startRef.CompareTo(endRef)) { case 1: linking = LinkingType.FROM_BIG; break; case 0: linking = LinkingType.SAME_SIZE; break; case -1: linking = LinkingType.FROM_SMALL; break; } } } List <RoadPrefixFileItem> filterResult = m_prefixes.Where(x => (x.roadType & type) == type && (x.oneWay & wayVal) == wayVal && (x.symmetry & symVal) == symVal && (x.highway & highway) == highway && (wayVal == OneWay.FALSE || ((x.linking & linking) == linking)) && (hasStart || !x.requireSource) && (hasEnd || !x.requireTarget) && x.minWidth <= width + 0.99f && width + 0.99f < x.maxWidth && x.minLanes <= lanes && lanes < x.maxLanes && (x.seedConfig & seedConfiguration) == seedConfiguration ).ToList(); if (filterResult.Count == 0 && linking != LinkingType.NO_LINKING) { filterResult = m_prefixes.Where(x => (x.roadType & type) == type && (x.oneWay & wayVal) == wayVal && (x.symmetry & symVal) == symVal && (x.highway & highway) == highway && (wayVal == OneWay.FALSE || ((x.linking & LinkingType.NO_LINKING) == LinkingType.NO_LINKING)) && (hasStart || !x.requireSource) && (hasEnd || !x.requireTarget) && x.minWidth <= width + 0.99f && width + 0.99f < x.maxWidth && x.minLanes <= lanes && lanes < x.maxLanes && (x.seedConfig & seedConfiguration) == seedConfiguration ).ToList(); } LogUtils.DoLog($"Results for: {type} O:{wayVal} S:{symVal} H:{highway} W:{width} L:{lanes} Lk:{linking} Hs:{hasStart} He:{hasEnd} Sc:{seedConfiguration} = {filterResult?.Count}"); if (filterResult?.Count == 0) { return(null); } return(filterResult[rand.Int32((uint)(filterResult.Count))].name); }