diff --git a/.gitignore b/.gitignore index 81978f3..5318f27 100644 --- a/.gitignore +++ b/.gitignore @@ -398,3 +398,9 @@ FodyWeavers.xsd # .nfs files are created when an open file is removed but is still being accessed .nfs* + +# ====================================================== + +*.unitypackage +assetbundles/*.manifest +assetbundles/assetbundles \ No newline at end of file diff --git a/LICENSE b/LICENSE index f8ba749..70fa0b9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Derail Valley Modding +Copyright (c) 2023 ÆUGH Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 456d4f5..f8a512d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ -

Dumb S282 Tweaks

-

This is stupid

+# S282 Tweaks -## License -

- Source code is distributed under the MIT license. -

+Smoke deflectors and a streamlined boiler for the S282. + +todo screenshot + +## Credits + +AEUGH: Streamlined boiler, Witte & Wagner smoke deflectors, code +Tostiman: code +Cypress: Chinese smoke deflectors diff --git a/assetbundles/chinesesmokedeflectors b/assetbundles/chinesesmokedeflectors new file mode 100644 index 0000000..1971c91 Binary files /dev/null and b/assetbundles/chinesesmokedeflectors differ diff --git a/assets/fullcab b/assetbundles/fullcab similarity index 100% rename from assets/fullcab rename to assetbundles/fullcab diff --git a/assets/streamline b/assetbundles/streamline similarity index 100% rename from assets/streamline rename to assetbundles/streamline diff --git a/assets/wagnersmokedeflectors b/assetbundles/wagnersmokedeflectors similarity index 100% rename from assets/wagnersmokedeflectors rename to assetbundles/wagnersmokedeflectors diff --git a/assets/wittesmokedeflectors b/assetbundles/wittesmokedeflectors similarity index 100% rename from assets/wittesmokedeflectors rename to assetbundles/wittesmokedeflectors diff --git a/dumb282tweaks/CarPatch.cs b/dumb282tweaks/CarPatch.cs index d73d584..68ac36b 100644 --- a/dumb282tweaks/CarPatch.cs +++ b/dumb282tweaks/CarPatch.cs @@ -10,63 +10,98 @@ namespace dumb282tweaks; class CarPatch { static void Postfix(ref TrainCar __instance) { - if(__instance != null && __instance.carType == TrainCarType.LocoSteamHeavy) + if (__instance == null || __instance.carType != TrainCarType.LocoSteamHeavy) { - string bodyPath = "LocoS282A_Body/Static_LOD0/s282_locomotive_body"; - Transform s282Body = __instance.transform.Find(bodyPath); - if (s282Body == null) + return; + } + + string bodyPath = "LocoS282A_Body/Static_LOD0/s282_locomotive_body"; + Transform s282Body = __instance.transform.Find(bodyPath); + if (s282Body == null) + { + Error($"Couldn't find S282 body on '{__instance.transform.gameObject.name}' -> {bodyPath}"); + return; + } + + Material s282Mat = s282Body.GetComponent().material; + + // Smoke Deflector + Log($"Applying {MySettings.smokeDeflectorType.ToString()}"); + + switch(MySettings.smokeDeflectorType) { + case Settings.SmokeDeflectorType.Witte: { - Error($"Couldn't find S282 body on '{__instance.transform.gameObject.name}' -> {bodyPath}"); - return; + GameObject witteSmokeDeflector = Object.Instantiate(witteSmokeDeflectorsPrefab, __instance.transform); + witteSmokeDeflector.transform.localPosition = new Vector3(0.0f, 2.1f, 5f); + witteSmokeDeflector.transform.localRotation = Quaternion.identity; + + foreach (var aMeshRenderer in witteSmokeDeflector.GetComponentsInChildren()) + { + aMeshRenderer.material = s282Mat; + } + + break; } - - Material s282Mat = s282Body.GetComponent().material; - - // Smoke Deflector - switch(Main.Settings.smokeDeflectorType) { - case Settings.SmokeDeflectorType.Witte: - Log("witte"); - - GameObject witteSmokeDeflector = Object.Instantiate(witteSmokeDeflectorsLoad, __instance.transform); - witteSmokeDeflector.transform.localPosition = new Vector3(0.0f, 2.1f, 5f); - witteSmokeDeflector.transform.localRotation = Quaternion.identity; - - foreach (var aMeshRenderer in witteSmokeDeflector.GetComponentsInChildren()) - { - aMeshRenderer.material = s282Mat; - } - - break; - case Settings.SmokeDeflectorType.Wagner: - Log("witten't"); - - GameObject wagnerSmokeDeflector = Object.Instantiate(wagnerSmokeDeflectorsLoad, __instance.transform); - wagnerSmokeDeflector.transform.localPosition = new Vector3(0.0f, 2.1f, 5f); - wagnerSmokeDeflector.transform.localRotation = Quaternion.identity; - - foreach (var aMeshRenderer in wagnerSmokeDeflector.GetComponentsInChildren()) - { - aMeshRenderer.material = s282Mat; - } - - break; - } - - // Boiler - switch (Main.Settings.boilerType) + case Settings.SmokeDeflectorType.Wagner: { - case Settings.BoilerType.Streamlined: - GameObject streamlinedBoiler = Object.Instantiate(streamlinedBoilerLoad, __instance.transform); - streamlinedBoiler.transform.localPosition = new Vector3(0.0f, 2.15f, 5.1f); - streamlinedBoiler.transform.localRotation = Quaternion.identity; + GameObject wagnerSmokeDeflector = Object.Instantiate(wagnerSmokeDeflectorsPrefab, __instance.transform); + wagnerSmokeDeflector.transform.localPosition = new Vector3(0.0f, 2.1f, 5f); + wagnerSmokeDeflector.transform.localRotation = Quaternion.identity; - foreach (var aMeshRenderer in streamlinedBoiler.GetComponentsInChildren()) - { - aMeshRenderer.material = s282Mat; - } + foreach (var aMeshRenderer in wagnerSmokeDeflector.GetComponentsInChildren()) + { + aMeshRenderer.material = s282Mat; + } - break; + break; } + case Settings.SmokeDeflectorType.Chinese: + ApplyChineseSmokeDeflector(ref __instance, s282Body); + break; + } + + // Boiler + Log($"Applying {MySettings.boilerType.ToString()}"); + + switch (MySettings.boilerType) + { + case Settings.BoilerType.Streamlined: + GameObject streamlinedBoiler = Object.Instantiate(streamlinedBoilerPrefab, __instance.transform); + streamlinedBoiler.transform.localPosition = new Vector3(0.0f, 2.15f, 5.1f); + streamlinedBoiler.transform.localRotation = Quaternion.identity; + + foreach (var aMeshRenderer in streamlinedBoiler.GetComponentsInChildren()) + { + aMeshRenderer.material = s282Mat; + } + + break; } } + + private static void ApplyChineseSmokeDeflector(ref TrainCar locomotive, Transform body) + { + //hide smoke box door + var smokeboxDoorPath = "LocoS282A_Body/Static_LOD0/s282_locomotive_smokebox_door"; + Transform smokeBoxDoor = locomotive.transform.Find(smokeboxDoorPath); + if (smokeBoxDoor == null) + { + Error($"Couldn't find S282 smoke box door on '{locomotive.transform.gameObject.name}' -> {smokeboxDoorPath}"); + return; + } + smokeBoxDoor.gameObject.SetActive(false); + + //show deflector and stuff + GameObject chineseSmokeDeflector = Object.Instantiate(chineseSmokeDeflectorsPrefab, body); + chineseSmokeDeflector.transform.localPosition = smokeBoxDoor.localPosition; + + //todo apply S282 material? + // foreach (var aMeshRenderer in chineseSmokeDeflector.GetComponentsInChildren()) + // { + // if (aMeshRenderer.material.name == "S282") //todo + // { + // aMeshRenderer.material = s282Mat; + // } + // } + } } diff --git a/dumb282tweaks/Main.cs b/dumb282tweaks/Main.cs index 2fba697..64a3b39 100644 --- a/dumb282tweaks/Main.cs +++ b/dumb282tweaks/Main.cs @@ -4,99 +4,72 @@ using System.Reflection; using HarmonyLib; using UnityModManagerNet; using UnityEngine; -using System.Diagnostics.CodeAnalysis; -namespace dumb282tweaks; +namespace dumb282tweaks +{ + [EnableReloading] + public static class Main + { + public static UnityModManager.ModEntry MyModEntry { get; private set; } + public static Settings MySettings { get; private set; } -public static class Main { - // Variables - public static UnityModManager.ModEntry Instance { get; private set; } - public static dumb282tweaksSettings Settings { get; private set; } + public static GameObject wagnerSmokeDeflectorsPrefab; + public static GameObject witteSmokeDeflectorsPrefab; + public static GameObject chineseSmokeDeflectorsPrefab; - // public static readonly string[] cabTypeTexts = new[] { - // "Default", - // "German" - // }; - public static readonly string[] smokeDeflectorTypeTexts = new[] { - "None", - "Witte", - "Wagner" - }; - public static readonly string[] boilerTypeTexts = new[] { - "Default", - "Streamlined" - }; - // public static readonly string[] smokeStackTypeTexts = new[] { - // "Default", - // "Short", - // }; + public static GameObject streamlinedBoilerPrefab; - public static GameObject wagnerSmokeDeflectorsLoad; - public static GameObject witteSmokeDeflectorsLoad; - public static GameObject streamlinedBoilerLoad; + private static bool Load(UnityModManager.ModEntry modEntry) + { + Harmony harmony = null; - // Load - private static bool Load(UnityModManager.ModEntry modEntry) { - Harmony? harmony = null; + try + { + MyModEntry = modEntry; + MySettings = UnityModManager.ModSettings.Load(MyModEntry); - try { - Instance = modEntry; - Settings = UnityModManager.ModSettings.Load(Instance); + MyModEntry.OnGUI = entry => MySettings.Draw(entry); + MyModEntry.OnSaveGUI = entry => MySettings.Save(entry); - Instance.OnGUI = OnGUI; - Instance.OnSaveGUI = OnSaveGUI; + string assetPath = Path.Combine(MyModEntry.Path, "assetbundles\\"); - harmony = new Harmony(Instance.Info.Id); - harmony.PatchAll(Assembly.GetExecutingAssembly()); + wagnerSmokeDeflectorsPrefab = AssetBundle.LoadFromFile(Path.Combine(assetPath, "wagnersmokedeflectors")) + .LoadAsset("Assets/WagnerSmokeDeflectors.prefab"); + witteSmokeDeflectorsPrefab = AssetBundle.LoadFromFile(Path.Combine(assetPath, "wittesmokedeflectors")) + .LoadAsset("Assets/WitteSmokeDeflectors.prefab"); + chineseSmokeDeflectorsPrefab = AssetBundle.LoadFromFile(Path.Combine(assetPath, "chinesesmokedeflectors")) + .LoadAsset("Assets/Prefab/LocoS282A_Smokebox.prefab"); - string assetPath = Path.Combine(Instance.Path, "assets\\"); + streamlinedBoilerPrefab = AssetBundle.LoadFromFile(Path.Combine(assetPath, "streamline")) + .LoadAsset("Assets/Streamline.prefab"); - wagnerSmokeDeflectorsLoad = AssetBundle.LoadFromFile(Path.Combine(assetPath, "wagnersmokedeflectors")).LoadAsset("Assets/WagnerSmokeDeflectors.prefab"); - witteSmokeDeflectorsLoad = AssetBundle.LoadFromFile(Path.Combine(assetPath, "wittesmokedeflectors")).LoadAsset("Assets/WitteSmokeDeflectors.prefab"); - streamlinedBoilerLoad = AssetBundle.LoadFromFile(Path.Combine(assetPath, "streamline")).LoadAsset("Assets/Streamline.prefab"); + harmony = new Harmony(MyModEntry.Info.Id); + harmony.PatchAll(Assembly.GetExecutingAssembly()); + } + catch (Exception ex) + { + MyModEntry.Logger.LogException($"Failed to load {MyModEntry.Info.DisplayName}:", ex); + harmony?.UnpatchAll(MyModEntry.Info.Id); + return false; + } - } catch(Exception ex) { - Instance.Logger.LogException($"Failed to load {Instance.Info.DisplayName}:", ex); - harmony?.UnpatchAll(Instance.Info.Id); - return false; + return true; } - return true; - } + // Logger Commands + public static void Log(string message) + { + MyModEntry.Logger.Log(message); + } - // GUI Rendering - static void OnGUI(UnityModManager.ModEntry modEntry) { - GUILayout.BeginVertical(); + public static void Warning(string message) + { + MyModEntry.Logger.Warning(message); + } - GUILayout.Label("These settings are applied on train spawn, meaning rejoining the game will refresh all 282 locos to the settings specified here, but if you don't unload the train it will keep whatever settings were there previously. This is a temporary solution until I have a proper GUI implemented."); - GUILayout.Label("Also, reloading a save will currently break things and the tweaks won't load. This isn't good."); - - GUILayout.Space(2f); - - //todo this is not implemented - // GUILayout.Label("Cab Type"); - // Settings.cabType = (Settings.CabType) GUILayout.SelectionGrid((int) Settings.cabType, cabTypeTexts, 1, "toggle"); - - GUILayout.Label("Smoke Deflector Type"); - Settings.smokeDeflectorType = (Settings.SmokeDeflectorType) GUILayout.SelectionGrid((int) Settings.smokeDeflectorType, smokeDeflectorTypeTexts, 1, "toggle"); - - GUILayout.Label("Boiler Type"); - Settings.boilerType = (Settings.BoilerType) GUILayout.SelectionGrid((int) Settings.boilerType, boilerTypeTexts, 1, "toggle"); - - GUILayout.EndVertical(); - } - static void OnSaveGUI(UnityModManager.ModEntry modEntry) { - Settings.Save(modEntry); - } - - // Logger Commands - public static void Log(string message) { - Instance.Logger.Log(message); - } - public static void Warning(string message) { - Instance.Logger.Warning(message); - } - public static void Error(string message) { - Instance.Logger.Error(message); + public static void Error(string message) + { + MyModEntry.Logger.Error(message); + } } } diff --git a/dumb282tweaks/Settings.cs b/dumb282tweaks/Settings.cs index b46b151..5e2c03b 100644 --- a/dumb282tweaks/Settings.cs +++ b/dumb282tweaks/Settings.cs @@ -1,39 +1,69 @@ +using System; using System.ComponentModel; +using UnityEngine; using UnityModManagerNet; -using static dumb282tweaks.Settings; -namespace dumb282tweaks; +namespace dumb282tweaks +{ -public static class Settings { - public enum CabType { - [Description("Default 282 Cab")] - Default, - [Description("German Cab")] - German - } - public enum BoilerType { - [Description("Default Boiler")] - Default, - [Description("Streamlined Boiler")] - Streamlined, - } - public enum SmokeDeflectorType { - [Description("No Smoke Deflectors")] - None, - [Description("Witte Smoke Deflectors")] - Witte, - [Description("Wagner Smoke Deflectors")] - Wagner, + public class Settings : UnityModManager.ModSettings + { + // public enum CabType + // { + // [Description("Default 282 Cab")] Default, + // [Description("German Cab")] German + // } + + public enum BoilerType + { + [Description("Default Boiler")] Default, + [Description("Streamlined Boiler")] Streamlined, + } + + public enum SmokeDeflectorType + { + [Description("No smoke deflectors")] + None, + + [Description("Witte smoke deflectors")] + Witte, + + [Description("Wagner smoke deflectors")] + Wagner, + + [Description("Chinese smoke deflectors and more")] + Chinese, + } + + // public CabType cabType = CabType.Default; + public SmokeDeflectorType smokeDeflectorType = SmokeDeflectorType.Wagner; + public BoilerType boilerType = BoilerType.Default; + + public void Draw(UnityModManager.ModEntry modEntry) + { + GUILayout.BeginVertical(); + + GUILayout.Label("These settings are applied on train spawn, meaning rejoining the game will refresh all 282 locos to the settings specified here, but if you don't unload the train it will keep whatever settings were there previously. This is a temporary solution until I have a proper GUI implemented."); + GUILayout.Label("Also, reloading a save will currently break things and the tweaks won't load. This isn't good."); + + GUILayout.Space(2f); + + //todo this is not implemented + // GUILayout.Label("Cab Type"); + // Settings.cabType = (Settings.CabType) GUILayout.SelectionGrid((int) Settings.cabType, cabTypeTexts, 1, "toggle"); + + GUILayout.Label("Smoke Deflector Type"); + smokeDeflectorType = (SmokeDeflectorType) GUILayout.SelectionGrid((int) smokeDeflectorType, Enum.GetNames(typeof(SmokeDeflectorType)), 1, "toggle"); + + GUILayout.Label("Boiler Type"); + boilerType = (BoilerType) GUILayout.SelectionGrid((int) boilerType, Enum.GetNames(typeof(BoilerType)), 1, "toggle"); + + GUILayout.EndVertical(); + } + + public override void Save(UnityModManager.ModEntry modEntry) + { + Save(this, modEntry); + } } } - -public class dumb282tweaksSettings : UnityModManager.ModSettings { - // public CabType cabType = CabType.Default; - public SmokeDeflectorType smokeDeflectorType = SmokeDeflectorType.Wagner; - public BoilerType boilerType = BoilerType.Default; - - public override void Save(UnityModManager.ModEntry modEntry) { - Save(this, modEntry); - } -} - diff --git a/package.ps1 b/package.ps1 index bdf7568..623f5c5 100644 --- a/package.ps1 +++ b/package.ps1 @@ -4,7 +4,7 @@ param ( ) Set-Location "$PSScriptRoot" -$FilesToInclude = "info.json","build/*","LICENSE","assets" +$FilesToInclude = "info.json","build/*","LICENSE","assetbundles" $modInfo = Get-Content -Raw -Path "info.json" | ConvertFrom-Json $modId = $modInfo.Id @@ -20,7 +20,7 @@ $ZipOutDir = "$ZipWorkDir/$modId" New-Item "$ZipOutDir" -ItemType Directory -Force Copy-Item -Force -Path $FilesToInclude -Destination "$ZipOutDir" -Copy-Item -Force -Path "assets/*" -Destination "$ZipOutDir/assets" +Copy-Item -Force -Path "assetbundles/*" -Destination "$ZipOutDir/assetbundles" if (!$NoArchive) {