From 21775c36ab07dfeade0c433978bb8bd4a9bf3bc5 Mon Sep 17 00:00:00 2001 From: Katy Fox Date: Sun, 19 Dec 2021 12:35:34 -0500 Subject: [PATCH] Custom rolling stock job generation - closes #25 --- CCL_GameScripts/TrainCarSetup.cs | 4 + DVCustomCarLoader/CCLSettings.cs | 25 ++++++ DVCustomCarLoader/CarTypeInjector.cs | 91 ++++++++++++++++++++-- DVCustomCarLoader/CustomCar.cs | 9 +++ DVCustomCarLoader/CustomCarManager.cs | 22 ------ DVCustomCarLoader/DVCustomCarLoader.csproj | 1 + DVCustomCarLoader/Main.cs | 16 ++++ 7 files changed, 141 insertions(+), 27 deletions(-) create mode 100644 DVCustomCarLoader/CCLSettings.cs diff --git a/CCL_GameScripts/TrainCarSetup.cs b/CCL_GameScripts/TrainCarSetup.cs index 88da79f5..d7a5b5b9 100644 --- a/CCL_GameScripts/TrainCarSetup.cs +++ b/CCL_GameScripts/TrainCarSetup.cs @@ -43,9 +43,13 @@ private void BringUpLocoSetup() [Header("Basic")] public string Identifier = "My New Car"; public BaseTrainCarType BaseCarType; + public bool ReplaceBaseType = false; public BaseCargoContainerType CargoClass = BaseCargoContainerType.None; public GameObject InteriorPrefab; + public Sprite BookletSprite = null; + + public float FullDamagePrice = 10000f; [Header("Bogie Replacement")] public Transform FrontBogie; diff --git a/DVCustomCarLoader/CCLSettings.cs b/DVCustomCarLoader/CCLSettings.cs new file mode 100644 index 00000000..2b4146d3 --- /dev/null +++ b/DVCustomCarLoader/CCLSettings.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityModManagerNet; + +namespace DVCustomCarLoader +{ + public class CCLSettings : UnityModManager.ModSettings, IDrawable + { + [Draw("Prefer custom cars to default cars when generating jobs")] + public bool PreferCustomCarsForJobs = false; + + public void OnChange() + { + + } + + public override void Save(UnityModManager.ModEntry modEntry) + { + Save(this, modEntry); + } + } +} diff --git a/DVCustomCarLoader/CarTypeInjector.cs b/DVCustomCarLoader/CarTypeInjector.cs index f068460b..5292d188 100644 --- a/DVCustomCarLoader/CarTypeInjector.cs +++ b/DVCustomCarLoader/CarTypeInjector.cs @@ -6,6 +6,7 @@ using CCL_GameScripts; using CCL_GameScripts.Effects; using DV.Logic.Job; +using DV.RenderTextureSystem.BookletRender; using DVCustomCarLoader.LocoComponents; using DVCustomCarLoader.LocoComponents.DieselElectric; using HarmonyLib; @@ -26,8 +27,13 @@ public static class CarTypeInjector private static readonly Dictionary carTypeToCustomCar = new Dictionary(); public static bool TryGetCarTypeById( string id, out TrainCarType type ) => idToCarType.TryGetValue(id.ToLower(), out type); + public static TrainCarType CarTypeById(string id) => idToCarType[id]; + public static bool TryGetCustomCarByType( TrainCarType carType, out CustomCar car ) => carTypeToCustomCar.TryGetValue(carType, out car); + public static CustomCar CustomCarByType(TrainCarType carType) => carTypeToCustomCar[carType]; + public static bool TryGetCustomCarById( string id, out CustomCar car ) => idToCustomCar.TryGetValue(id.ToLower(), out car); + public static CustomCar CustomCarById(string id) => idToCustomCar[id]; public static bool IsCustomTypeRegistered( TrainCarType carType ) => carTypeToCustomCar.ContainsKey(carType); public static bool IsCustomTypeRegistered( string identifier ) => idToCarType.ContainsKey(identifier); @@ -37,7 +43,9 @@ public static class CarTypeInjector // Reflected fields private static readonly HashSet locomotivesMap; private static readonly HashSet multipleUnitLocos; - private static readonly Dictionary CarTypeToContainerType; + private static Dictionary CarTypeToContainerType => CargoTypes.CarTypeToContainerType; + private static readonly Dictionary carTypeToFullDamagePrice; + private static Dictionary trainCarTypeToLength; static CarTypeInjector() { @@ -53,11 +61,28 @@ static CarTypeInjector() Main.Error("Failed to get CarTypes.multipleUnitLocos"); } - CarTypeToContainerType = AccessTools.Field(typeof(CargoTypes), nameof(CargoTypes.CarTypeToContainerType))?.GetValue(null) - as Dictionary; - if( CarTypeToContainerType == null ) + carTypeToFullDamagePrice = AccessTools.Field(typeof(ResourceTypes), "carTypeToFullDamagePrice")?.GetValue(null) + as Dictionary; + if (carTypeToFullDamagePrice == null) { - Main.Error("Failed to get CargoTypes.CarTypeToContainerType"); + Main.Error("Failed to get ResourceTypes.carTypeToFullDamagePrice"); + } + } + + public static void InjectYardTracksOrganizer(YardTracksOrganizer yto) + { + trainCarTypeToLength = AccessTools.Field(typeof(YardTracksOrganizer), "trainCarTypeToLength")?.GetValue(yto) + as Dictionary; + + if (trainCarTypeToLength == null) + { + Main.Error("Failed to get YardTracksOrganizer.trainCarTypeToLength"); + return; + } + + foreach (CustomCar car in CustomCarManager.CustomCarTypes) + { + trainCarTypeToLength.Add(car.CarType, car.InterCouplerDistance); } } @@ -116,6 +141,21 @@ private static void InjectCarTypesData( CustomCar car ) } CarTypeToContainerType.Add(car.CarType, car.CargoClass); + carTypeToFullDamagePrice.Add(car.CarType, car.FullDamagePrice); + + // setup booklet sprite + if (car.BookletSprite) + { + IconsSpriteMap.carTypeToSpriteIcon.Add(car.CarType, car.BookletSprite); + } + else + { + if (IconsSpriteMap.carTypeToSpriteIcon.TryGetValue(car.BaseCarType, out var baseSprite)) + { + car.BookletSprite = baseSprite; + IconsSpriteMap.carTypeToSpriteIcon.Add(car.CarType, baseSprite); + } + } } #region Audio Pooling @@ -222,6 +262,8 @@ public static void InjectLocoAudioToPool( CustomCar car, TrainComponentPool comp #endregion } + #region Car Types Patches + [HarmonyPatch(typeof(CarTypes), nameof(CarTypes.GetCarPrefab))] public static class CarTypes_GetCarPrefab_Patch { @@ -315,6 +357,36 @@ public static bool IsDieselLocomotive( TrainCarType carType, ref bool __result ) } } + #endregion + + [HarmonyPatch(typeof(CargoTypes), nameof(CargoTypes.GetTrainCarTypesThatAreSpecificContainerType))] + public static class CargoTypes_GetCarsByContainer_Patch + { + public static void Postfix(ref List __result) + { + if (Main.Settings.PreferCustomCarsForJobs) + { + // override all base types + if (__result.Any(CarTypeInjector.IsInCustomRange)) + { + __result = __result.Where(CarTypeInjector.IsInCustomRange).ToList(); + } + } + else + { + // only override individual cars + var overridden = __result + .Where(CarTypeInjector.IsInCustomRange) + .Select(CarTypeInjector.CustomCarByType) + .Where(car => car.ReplaceBaseType) + .Select(car => car.BaseCarType) + .ToHashSet(); + + __result = __result.Where(ct => !overridden.Contains(ct)).ToList(); + } + } + } + [HarmonyPatch(typeof(TrainComponentPool), "Awake")] public static class TrainComponentPool_Awake_Patch { @@ -328,4 +400,13 @@ public static void Prefix( TrainComponentPool __instance ) } } } + + [HarmonyPatch(typeof(YardTracksOrganizer), "Awake")] + public static class YardTracksOrganizer_Awake_Patch + { + public static void Postfix(YardTracksOrganizer __instance) + { + CarTypeInjector.InjectYardTracksOrganizer(__instance); + } + } } diff --git a/DVCustomCarLoader/CustomCar.cs b/DVCustomCarLoader/CustomCar.cs index fee008aa..77e6f984 100644 --- a/DVCustomCarLoader/CustomCar.cs +++ b/DVCustomCarLoader/CustomCar.cs @@ -25,6 +25,7 @@ public class CustomCar /// The underlying type of this car. /// public TrainCarType BaseCarType = TrainCarType.FlatbedEmpty; + public bool ReplaceBaseType { get; protected set; } = false; /// /// The base prefab that will be duplicated from. @@ -48,6 +49,9 @@ public class CustomCar public LocoRequiredLicense RequiredLicense { get; protected set; } = LocoRequiredLicense.None; public CargoContainerType CargoClass { get; protected set; } = CargoContainerType.None; + public Sprite BookletSprite { get; set; } = null; + public float FullDamagePrice { get; protected set; } = 10000f; + public bool FinalizePrefab() { Main.ModEntry.Logger.Log($"Augmenting prefab for {identifier}"); @@ -295,6 +299,11 @@ public bool FinalizePrefab() // setup traincar properties CargoClass = (CargoContainerType)carSetup.CargoClass; + BookletSprite = carSetup.BookletSprite; + FullDamagePrice = carSetup.FullDamagePrice; + ReplaceBaseType = carSetup.ReplaceBaseType; + + Main.Log($"Cargo class: {CargoClass}, Damage price: {FullDamagePrice}"); if( !carSetup.OverridePhysics ) { diff --git a/DVCustomCarLoader/CustomCarManager.cs b/DVCustomCarLoader/CustomCarManager.cs index dd8c02a9..4b0b28e1 100644 --- a/DVCustomCarLoader/CustomCarManager.cs +++ b/DVCustomCarLoader/CustomCarManager.cs @@ -9,28 +9,6 @@ namespace DVCustomCarLoader public static class CustomCarManager { public static List CustomCarTypes = new List(); - - //private static readonly Dictionary SpawnedCustomCarIds = new Dictionary(); - - //public static bool IsRegisteredCustomCar( TrainCar trainCar ) - //{ - // return SpawnedCustomCarIds.ContainsKey(trainCar); - //} - - //public static bool TryGetCustomCarId( TrainCar trainCar, out string id ) - //{ - // return SpawnedCustomCarIds.TryGetValue(trainCar, out id); - //} - - //public static void RegisterSpawnedCar( TrainCar car, string identifier ) - //{ - // SpawnedCustomCarIds[car] = identifier; - //} - - //public static void DeregisterCar( TrainCar car ) - //{ - // SpawnedCustomCarIds.Remove(car); - //} public static void Setup() { diff --git a/DVCustomCarLoader/DVCustomCarLoader.csproj b/DVCustomCarLoader/DVCustomCarLoader.csproj index 865e2065..ff01e7cf 100644 --- a/DVCustomCarLoader/DVCustomCarLoader.csproj +++ b/DVCustomCarLoader/DVCustomCarLoader.csproj @@ -77,6 +77,7 @@ + diff --git a/DVCustomCarLoader/Main.cs b/DVCustomCarLoader/Main.cs index 2d2eb070..b0099ad1 100644 --- a/DVCustomCarLoader/Main.cs +++ b/DVCustomCarLoader/Main.cs @@ -12,11 +12,17 @@ public static class Main public static UnityModManager.ModEntry ModEntry; public static bool Enabled; + public static CCLSettings Settings { get; private set; } + public static bool Load(UnityModManager.ModEntry modEntry) { Enabled = modEntry.Enabled; ModEntry = modEntry; + Settings = UnityModManager.ModSettings.Load(ModEntry); + ModEntry.OnGUI = DrawGUI; + ModEntry.OnSaveGUI = SaveGUI; + Harmony harmony = null; try @@ -49,6 +55,16 @@ public static bool Load(UnityModManager.ModEntry modEntry) return true; } + static void DrawGUI(UnityModManager.ModEntry entry) + { + Settings.Draw(entry); + } + + static void SaveGUI(UnityModManager.ModEntry entry) + { + Settings.Save(entry); + } + #region Logging public static void Log( string msg ) => ModEntry.Logger.Log(msg);