using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using DM; using HarmonyLib; using Landfall.TABS; using Landfall.TABS.UnitEditor; using Landfall.TABS.Workshop; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("ConfigurableWeaponData")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ConfigurableWeaponData")] [assembly: AssemblyTitle("ConfigurableWeaponData")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ConfigurableWeaponData { public static class EditorState { [Serializable] public class StoreDto { public Dictionary> Weapons; public Dictionary Summons; } public static readonly Dictionary> Pending = new Dictionary>(); public static bool SuppressRemoveClear; public static readonly Dictionary Summons = new Dictionary(); private static readonly Dictionary BattleCache = new Dictionary(); public static int GetSummon(string key) { if (!Summons.TryGetValue(key, out var value)) { return 0; } return value; } public static void SetSummon(string key, int guid) { if (guid == 0) { Summons.Remove(key); } else { Summons[key] = guid; } } public static UnitBlueprint ResolveBlueprint(int guid) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (guid == 0) { return null; } try { DatabaseID val = default(DatabaseID); ((DatabaseID)(ref val))..ctor(guid); UnitBlueprint val2 = ContentDatabase.Instance().GetUnitBlueprint(val); if ((Object)(object)val2 == (Object)null) { val2 = ContentDatabase.Instance().GetUserUnitBlueprintByExactName(guid.ToString()); } return val2; } catch { return null; } } public static UnitBlueprint ResolveLiveOrSaved(int guid) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) try { UnitEditorManager val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null) { object? obj = typeof(UnitEditorManager).GetField("loadedUnit", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(val); UnitBlueprint val2 = (UnitBlueprint)((obj is UnitBlueprint) ? obj : null); if ((Object)(object)val2 != (Object)null && val2.Entity != null && val2.Entity.GUID.m_ID == guid) { object? obj2 = typeof(UnitEditorManager).GetMethod("GetBlueprint", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(val, null); UnitBlueprint val3 = (UnitBlueprint)((obj2 is UnitBlueprint) ? obj2 : null); if ((Object)(object)val3 != (Object)null) { return val3; } } } } catch { } return ResolveBlueprint(guid); } public static string ResolveUnitName(int guid) { UnitBlueprint val = ResolveBlueprint(guid); if ((Object)(object)val == (Object)null) { return guid.ToString(); } try { if (val.Entity != null && !string.IsNullOrEmpty(val.Entity.Name)) { return val.Entity.Name; } } catch { } return ((Object)val).name; } public static string KeyFor(bool right, int weaponGuid) { return (right ? "Right" : "Left") + "/" + weaponGuid; } public static bool TryGet(string key, string paramKey, out float value) { value = 0f; if (Pending.TryGetValue(key, out var value2)) { return value2.TryGetValue(paramKey, out value); } return false; } public static void Set(string key, string paramKey, float value) { if (!Pending.TryGetValue(key, out var value2)) { value2 = new Dictionary(); Pending[key] = value2; } value2[paramKey] = value; Debug.Log((object)$"[CWD] Pending[{key}][{paramKey}] = {value} (count={Pending.Count})"); } public static void ClearForKey(string key) { if (Pending.Remove(key)) { Debug.Log((object)$"[CWD] Pending removed {key} (count={Pending.Count})"); } } public static void ClearAll() { if (Pending.Count > 0) { Debug.LogWarning((object)("[CWD] Pending CLEARED!\n" + Environment.StackTrace)); } Pending.Clear(); } public static void LoadFromJson(int unitGuid) { ClearAll(); Summons.Clear(); StoreDto storeDto = ReadJson(unitGuid); if (storeDto == null) { return; } if (storeDto.Weapons != null) { foreach (KeyValuePair> weapon in storeDto.Weapons) { Pending[weapon.Key] = weapon.Value; } } if (storeDto.Summons != null) { foreach (KeyValuePair summon in storeDto.Summons) { Summons[summon.Key] = summon.Value; } } Debug.Log((object)$"[CWD] Loaded {Pending.Count} weapons, {Summons.Count} summons from json for unit {unitGuid}"); } public static void SaveToJson(int unitGuid) { string path = PathFor(unitGuid); try { Directory.CreateDirectory(Plugin.StoreDir); string text = JsonConvert.SerializeObject((object)new StoreDto { Weapons = Pending, Summons = Summons }, (Formatting)1); File.WriteAllText(path, text); Debug.Log((object)("[CWD] Wrote " + text.Replace("\n", " ").Replace("\r", " "))); } catch (Exception ex) { Debug.LogWarning((object)("[CWD] Save failed: " + ex.Message)); } } public static void DeleteJson(int unitGuid) { try { string path = PathFor(unitGuid); if (File.Exists(path)) { File.Delete(path); } DropBattleCache(unitGuid); } catch (Exception ex) { Debug.LogWarning((object)("[CWD] Delete failed: " + ex.Message)); } } public static void PruneDefaults() { List list = new List(); foreach (KeyValuePair> item in Pending) { List list2 = new List(); foreach (KeyValuePair item2 in item.Value) { float? num = ParamRegistry.DefaultFor(item2.Key); if (num.HasValue && Mathf.Abs(item2.Value - num.Value) < 0.0001f) { list2.Add(item2.Key); } } foreach (string item3 in list2) { item.Value.Remove(item3); } if (item.Value.Count == 0) { list.Add(item.Key); } } foreach (string item4 in list) { Pending.Remove(item4); } if (list.Count > 0) { Debug.Log((object)$"[CWD] Pruned {list.Count} default weapons (count={Pending.Count})"); } } public static IReadOnlyDictionary ForBattleUnit(int unitGuid, string key) { if (unitGuid == 0) { return null; } if (!BattleCache.TryGetValue(unitGuid, out var value)) { value = ReadJson(unitGuid); if (value == null) { value = new StoreDto(); } BattleCache[unitGuid] = value; } if (value.Weapons == null || !value.Weapons.TryGetValue(key, out var value2)) { return null; } return value2; } public static int ForBattleSummon(int unitGuid, string key) { if (unitGuid == 0) { return 0; } if (!BattleCache.TryGetValue(unitGuid, out var value)) { value = ReadJson(unitGuid); if (value == null) { value = new StoreDto(); } BattleCache[unitGuid] = value; } if (value.Summons == null || !value.Summons.TryGetValue(key, out var value2)) { return 0; } return value2; } public static void DropBattleCache(int unitGuid) { BattleCache.Remove(unitGuid); } public static string PathFor(int unitGuid) { return Path.Combine(Plugin.StoreDir, unitGuid + ".json"); } private static StoreDto ReadJson(int unitGuid) { string path = PathFor(unitGuid); if (!File.Exists(path)) { return null; } try { string text = File.ReadAllText(path); StoreDto storeDto = JsonConvert.DeserializeObject(text); if (storeDto == null) { return null; } if (storeDto.Weapons == null && storeDto.Summons == null) { Dictionary> dictionary = JsonConvert.DeserializeObject>>(text); if (dictionary != null) { storeDto.Weapons = dictionary; } } return storeDto; } catch (Exception ex) { Debug.LogWarning((object)("[CWD] Load failed: " + ex.Message)); return null; } } } public static class ProjectileValues { private static readonly ConditionalWeakTable> Table = new ConditionalWeakTable>(); public static void Set(RangeWeapon weapon, Dictionary values) { if (!((Object)(object)weapon == (Object)null) && values != null) { Table.Remove(weapon); Table.Add(weapon, values); } } public static Dictionary Get(RangeWeapon weapon) { if ((Object)(object)weapon == (Object)null) { return null; } if (!Table.TryGetValue(weapon, out var value)) { return null; } return value; } } public static class HarmonyPatches { public class CWDScaleMonitor : MonoBehaviour { private Vector3 _start; private float _t; public void Init() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) _start = ((Component)this).transform.localScale; } private void Update() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) _t += Time.deltaTime; if (((Component)this).transform.localScale != _start) { Debug.Log((object)$"[CWD] scale changed on '{((Object)this).name}': {_start} -> {((Component)this).transform.localScale}"); _start = ((Component)this).transform.localScale; } if (_t > 5f) { Object.Destroy((Object)(object)this); } } } [HarmonyPatch(typeof(UnitBlueprint), "SetWeapon")] public static class SetWeaponPatch { private static void Postfix(UnitBlueprint __instance, Weapon __result, GameObject weaponObject, HandType handType) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__result == (Object)null || (Object)(object)weaponObject == (Object)null) { return; } CharacterItem component = weaponObject.GetComponent(); if ((Object)(object)component == (Object)null || component.Entity == null) { return; } int iD = component.Entity.GUID.m_ID; if (iD == 0) { return; } string text = EditorState.KeyFor((int)handType == 0, iD); Dictionary dictionary = null; int num = 0; UnitEditorManager val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null) { dictionary = (EditorState.Pending.TryGetValue(text, out var value) ? value : null); } else { try { num = __instance.Entity.GUID.m_ID; } catch { } dictionary = EditorState.ForBattleUnit(num, text) as Dictionary; } RangeWeapon val2 = (RangeWeapon)(object)((__result is RangeWeapon) ? __result : null); MeleeWeapon val3 = (MeleeWeapon)(object)((__result is MeleeWeapon) ? __result : null); if (dictionary != null && dictionary.Count > 0) { if ((Object)(object)val2 != (Object)null) { WeaponApplier.ApplyWeapon((Component)(object)val2, dictionary); } else if ((Object)(object)val3 != (Object)null) { WeaponApplier.ApplyWeapon((Component)(object)val3, dictionary); } else if ((Object)(object)__result != (Object)null) { WeaponApplier.ApplyWeapon((Component)(object)__result, dictionary); } Debug.Log((object)$"[CWD] SetWeapon applied {dictionary.Count} values for {text}; scale={((Component)__result).transform.localScale}"); } else if (EditorState.Pending.Count > 0) { Debug.LogWarning((object)("[CWD] SetWeapon: no values for " + text + "; pending keys: " + string.Join(", ", EditorState.Pending.Keys))); } if ((Object)(object)val2 != (Object)null) { ApplySummon(val2, text, (!((Object)(object)val != (Object)null)) ? num : 0); } if ((Object)(object)val == (Object)null) { ((Component)__result).gameObject.AddComponent().Init(); } if (!((Object)(object)val2 != (Object)null)) { return; } Dictionary dictionary2 = new Dictionary(); foreach (ParamDef item in ParamRegistry.For(WeaponTypeKind.Ranged, ParamTarget.Projectile)) { if (dictionary.TryGetValue(item.Key, out var value2)) { dictionary2[item.Key] = value2; } } if (dictionary2.Count > 0) { ProjectileValues.Set(val2, dictionary2); } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] SetWeapon patch: " + ex.Message)); } } } [HarmonyPatch(typeof(RangeWeapon), "SetProjectileStats")] public static class SetProjectileStatsPatch { private static bool Prefix(RangeWeapon __instance, GameObject spawnedObject) { try { if ((Object)(object)spawnedObject != (Object)null && (Object)(object)spawnedObject.GetComponent() != (Object)null) { return false; } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] SetProjectileStats prefix: " + ex.Message)); } return true; } private static void Postfix(RangeWeapon __instance, GameObject spawnedObject) { try { if (!((Object)(object)spawnedObject == (Object)null) && !((Object)(object)spawnedObject.GetComponent() != (Object)null)) { Dictionary dictionary = ProjectileValues.Get(__instance); if (dictionary != null) { WeaponApplier.ApplyProjectile(spawnedObject, dictionary); } } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] SetProjectileStats patch: " + ex.Message)); } } } [HarmonyPatch(typeof(CustomUnitHandler), "SaveUnit")] public static class SaveUnitPatch { private static void Postfix(UnitBlueprint unitBlueprint) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)unitBlueprint == (Object)null) && unitBlueprint.Entity != null) { DatabaseID gUID = unitBlueprint.Entity.GUID; if (!((DatabaseID)(ref gUID)).IsDefaultID()) { EditorState.PruneDefaults(); EditorState.SaveToJson(gUID.m_ID); EditorState.DropBattleCache(gUID.m_ID); Debug.Log((object)$"[CWD] SaveUnit postfix: persisted {EditorState.Pending.Count} weapons for guid {gUID.m_ID}"); } } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] SaveUnit patch: " + ex.Message)); } } } [HarmonyPatch(typeof(ContentDatabase), "RemoveUserUnitBlueprintAndEmptyFactionsCreated")] public static class RemoveUnitPatch { private static void Postfix(DatabaseID id) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) try { if (!((DatabaseID)(ref id)).IsDefaultID()) { EditorState.DeleteJson(id.m_ID); Debug.Log((object)$"[CWD] Removed weapon data for deleted unit {id.m_ID}"); } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] RemoveUnit patch: " + ex.Message)); } } } [HarmonyPatch(typeof(UnitEditorManager), "LoadUnit")] public static class LoadUnitPatch { private static void Postfix(UnitEditorManager __instance, UnitBlueprint blueprint) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)blueprint == (Object)null) && blueprint.Entity != null) { int iD = blueprint.Entity.GUID.m_ID; EditorState.LoadFromJson(iD); EditorState.DropBattleCache(iD); EditorState.SaveToJson(iD); if ((Object)(object)__instance != (Object)null && !UnitEditorManager.isTestingUnit) { __instance.RespawnWeapons(); } Debug.Log((object)$"[CWD] LoadUnit: loaded + auto-saved + respawned for {iD} (entries={EditorState.Pending.Count})"); } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] LoadUnit patch: " + ex.Message)); } } } [HarmonyPatch(typeof(UnitEditorManager), "RespawnWeapons")] public static class RespawnWeaponsPatch { private static void Prefix() { EditorState.SuppressRemoveClear = true; } private static void Postfix() { EditorState.SuppressRemoveClear = false; } } [HarmonyPatch(typeof(UnitEditorManager), "RemoveWeapon", new Type[] { typeof(EquipedWeaponWrapper) })] public static class RemoveWeaponPatch { private static void Postfix(EquipedWeaponWrapper weapon) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) try { if (weapon == null || EditorState.SuppressRemoveClear) { return; } int num = 0; try { CharacterItem prop = ((EquipedWrapper)weapon).prop; if ((Object)(object)prop != (Object)null && prop.Entity != null) { num = prop.Entity.GUID.m_ID; } } catch { } if (num != 0) { EditorState.ClearForKey(EditorState.KeyFor(weapon.isRightHanded, num)); } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] RemoveWeapon patch: " + ex.Message)); } } } [HarmonyPatch(typeof(UnitEditorStatCell), "UpdateValue")] public static class StatCellUpdatePatch { private static void Postfix(UnitEditorStatCell __instance) { try { object? obj = typeof(UnitEditorStatCell).GetField("stat", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance); StatsWrapper val = (StatsWrapper)((obj is StatsWrapper) ? obj : null); if (val != null && UIPatcher.IsOurs(val)) { UIPatcher.OnValueEdited(val, __instance); } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] StatCellUpdate patch: " + ex.Message)); } } } [HarmonyPatch(typeof(UnitEditorEquipedClothing), "Setup")] public static class EquipedClothingSetupPatch { private static void Postfix(UnitEditorEquipedClothing __instance, EquipedWrapper equiped) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown try { if (equiped != null && (int)equiped.GetWrapperType() == 1) { UIPatcher.HandleWeaponPage(__instance, (EquipedWeaponWrapper)equiped); } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] EquipedClothing.Setup patch: " + ex.Message)); } } } [HarmonyPatch(typeof(UnitEditorManager), "SetRider", new Type[] { typeof(UnitBlueprint) })] public static class SetRiderPatch { private static bool Prefix(UnitEditorManager __instance, UnitBlueprint m_unit) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) try { if (!UIPatcher.SummonPickMode) { return true; } UIPatcher.SummonPickMode = false; if ((Object)(object)m_unit == (Object)null) { return false; } int guid = 0; try { guid = m_unit.Entity.GUID.m_ID; } catch { } UIPatcher.OnSummonPicked(__instance, guid); return false; } catch (Exception ex) { UIPatcher.SummonPickMode = false; Debug.LogWarning((object)("[CWD] SetRider patch: " + ex.Message)); return true; } } } [HarmonyPatch(typeof(UnitEditorManager), "EquipProjectile")] public static class EquipProjectilePatch { private static void Postfix(ProjectileEntity projectileEntity, bool isMainHand) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)projectileEntity == (Object)null) { return; } EquipedWeaponWrapper val = UIPatcher.LastWeapon(); if (val != null && val.isRightHanded == isMainHand) { int num = 0; try { num = ((EquipedWrapper)val).prop.Entity.GUID.m_ID; } catch { } if (num != 0) { EditorState.SetSummon(EditorState.KeyFor(isMainHand, num), 0); Debug.Log((object)"[CWD] projectile picked, summon cleared"); } } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] EquipProjectile patch: " + ex.Message)); } } } [HarmonyPatch(typeof(UnitEditorListSelectScreen), "Back")] public static class ListBackPatch { private static void Postfix() { if (UIPatcher.SummonPickMode) { UIPatcher.SummonPickMode = false; Debug.Log((object)"[CWD] summon picker cancelled"); } } } [HarmonyPatch(typeof(UnitEditorSubMenu), "Open")] public static class SubMenuOpenPatch { private static void Postfix(UnitEditorSubMenu __instance) { try { UnitEditorEquipedClothing componentInParent = ((Component)__instance).GetComponentInParent(); if (!((Object)(object)componentInParent == (Object)null)) { EquipedWeaponWrapper val = UIPatcher.LastWeapon(); if (val != null && !((Object)(object)((EquipedWrapper)val).prop == (Object)null)) { UIPatcher.RefreshPage(componentInParent, val); } } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] SubMenuOpen patch: " + ex.Message)); } } } public static void Apply() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) new Harmony("com.configurable.weapondata").PatchAll(); Debug.Log((object)"[CWD] Harmony patches applied (SetWeapon covers editor + battle)"); } public static void ApplySummon(RangeWeapon rw, string key, int battleUnitGuid) { try { int num = ((battleUnitGuid != 0) ? EditorState.ForBattleSummon(battleUnitGuid, key) : EditorState.GetSummon(key)); if (num != 0) { UnitBlueprint val = ((battleUnitGuid != 0) ? EditorState.ResolveBlueprint(num) : EditorState.ResolveLiveOrSaved(num)); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)$"[CWD] summon blueprint not found: {num}"); return; } rw.unitToSpawn = val; rw.ObjectToSpawn = null; Debug.Log((object)$"[CWD] weapon {key} summons unit {num}"); } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] summon apply: " + ex.Message)); } } } public enum WeaponTypeKind { Ranged, Melee } public enum ParamTarget { Weapon, Projectile } public enum ComponentKind { Weapon, RangeWeapon, MeleeWeapon, MoveTransform, Collision, Compensation, Scale } public class ParamDef { public string Key; public string DisplayName; public string Description; public WeaponTypeKind Kind; public ParamTarget Target; public ComponentKind On; public string FieldName; public float Min; public float Max; public float Default; public bool IsMultiplier; public bool IsInt; public int Axis = -1; public FieldInfo Field; } public static class ParamRegistry { public static readonly List All = new List(); private static void Add(ParamDef p) { All.Add(p); } public static void Init(ConfigFile cfg) { Add(new ParamDef { Key = "Range", DisplayName = "Range", Description = "Max attack range (m).", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Weapon, On = ComponentKind.Weapon, FieldName = "maxRange", Min = 0.1f, Max = 200f, Default = 10f }); Add(new ParamDef { Key = "MaxAngle", DisplayName = "Attack Angle", Description = "Max firing angle (deg).", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Weapon, On = ComponentKind.Weapon, FieldName = "maxAngle", Min = 0.1f, Max = 360f, Default = 360f }); Add(new ParamDef { Key = "Cooldown", DisplayName = "Cooldown", Description = "Time between attacks (s).", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Weapon, On = ComponentKind.Weapon, FieldName = "internalCooldown", Min = 0.05f, Max = 20f, Default = 1f }); Add(new ParamDef { Key = "MinRandom", DisplayName = "Random Min", Description = "Random cooldown lower bound (multiplier).", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Weapon, On = ComponentKind.RangeWeapon, FieldName = "minRandom", Min = 0.01f, Max = 5f, Default = 0.8f, IsMultiplier = true }); Add(new ParamDef { Key = "MaxRandom", DisplayName = "Random Max", Description = "Random cooldown upper bound (multiplier).", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Weapon, On = ComponentKind.RangeWeapon, FieldName = "maxRandom", Min = 0.01f, Max = 5f, Default = 1.2f, IsMultiplier = true }); Add(new ParamDef { Key = "Spread", DisplayName = "Spread", Description = "Inaccuracy (deg).", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Weapon, On = ComponentKind.RangeWeapon, FieldName = "spread", Min = 0f, Max = 90f, Default = 0f }); Add(new ParamDef { Key = "Reload", DisplayName = "Reload Time", Description = "Reload duration (s).", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Weapon, On = ComponentKind.RangeWeapon, FieldName = "reloadTime", Min = 0f, Max = 60f, Default = 0f }); Add(new ParamDef { Key = "ProjCount", DisplayName = "Proj Count", Description = "Projectiles fired per shot.", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Weapon, On = ComponentKind.RangeWeapon, FieldName = "numberOfObjects", Min = 1f, Max = 30f, Default = 1f, IsInt = true }); Add(new ParamDef { Key = "MagSize", DisplayName = "Mag Size", Description = "Shots before reload.", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Weapon, On = ComponentKind.RangeWeapon, FieldName = "magSize", Min = 1f, Max = 100f, Default = 1f, IsInt = true }); Add(new ParamDef { Key = "FireForce", DisplayName = "Proj Force", Description = "Launch force applied to the projectile.", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Weapon, On = ComponentKind.RangeWeapon, FieldName = "force", Min = 0f, Max = 5000f, Default = 1000f }); Add(new ParamDef { Key = "DelayPerSpawn", DisplayName = "Multi-shot Delay", Description = "Delay between each projectile in a burst (s).", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Weapon, On = ComponentKind.RangeWeapon, FieldName = "delayPerSpawn", Min = 0f, Max = 5f, Default = 0.02f }); Add(new ParamDef { Key = "Recoil", DisplayName = "Recoil", Description = "Weapon recoil impulse.", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Weapon, On = ComponentKind.RangeWeapon, FieldName = "shootRecoil", Min = 0f, Max = 100f, Default = 5f }); Add(new ParamDef { Key = "TorsoRecoil", DisplayName = "Torso Recoil", Description = "Recoil applied to the torso.", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Weapon, On = ComponentKind.RangeWeapon, FieldName = "torsoRecoil", Min = 0f, Max = 100f, Default = 5f }); AddScale(WeaponTypeKind.Ranged, ParamTarget.Weapon, "Size", "Weapon size multiplier (X/Y/Z axes)."); Add(new ParamDef { Key = "ProjDamage", DisplayName = "Proj Damage", Description = "Projectile impact damage.", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Projectile, On = ComponentKind.Collision, FieldName = "damage", Min = 0f, Max = 10000f, Default = 80f }); Add(new ParamDef { Key = "ProjImpact", DisplayName = "Proj Impact", Description = "Projectile impact force multiplier.", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Projectile, On = ComponentKind.Collision, FieldName = "impactMultiplier", Min = 0f, Max = 20f, Default = 1f, IsMultiplier = true }); Add(new ParamDef { Key = "ProjTeamDmg", DisplayName = "Proj Team Damage", Description = "Damage dealt to friendly units (fraction).", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Projectile, On = ComponentKind.Collision, FieldName = "teamDamage", Min = 0f, Max = 1f, Default = 0.1f }); Add(new ParamDef { Key = "ProjSpeed", DisplayName = "Proj Speed", Description = "Projectile launch speed (m/s).", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Projectile, On = ComponentKind.MoveTransform, FieldName = "selfImpulse.z", Min = 0f, Max = 500f, Default = 30f }); Add(new ParamDef { Key = "ProjGravity", DisplayName = "Proj Gravity", Description = "Projectile gravity (m/s^2).", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Projectile, On = ComponentKind.MoveTransform, FieldName = "gravity", Min = 0f, Max = 100f, Default = 15f }); Add(new ParamDef { Key = "ProjDrag", DisplayName = "Proj Drag", Description = "Projectile air drag.", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Projectile, On = ComponentKind.MoveTransform, FieldName = "drag", Min = 0f, Max = 10f, Default = 0f }); Add(new ParamDef { Key = "ProjVelSpread", DisplayName = "Proj Vel Spread", Description = "Random projectile speed variance.", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Projectile, On = ComponentKind.MoveTransform, FieldName = "randomVelocitySpread", Min = 0f, Max = 50f, Default = 0f }); Add(new ParamDef { Key = "ProjAim", DisplayName = "Proj Aim Assist", Description = "Projectile homing strength toward the target.", Kind = WeaponTypeKind.Ranged, Target = ParamTarget.Projectile, On = ComponentKind.Compensation, FieldName = "forwardCompensation", Min = 0f, Max = 5f, Default = 0f }); AddScale(WeaponTypeKind.Ranged, ParamTarget.Projectile, "ProjSize", "Projectile size multiplier (X/Y/Z axes)."); Add(new ParamDef { Key = "MeleeRange", DisplayName = "Range", Description = "Max melee range (m).", Kind = WeaponTypeKind.Melee, Target = ParamTarget.Weapon, On = ComponentKind.Weapon, FieldName = "maxRange", Min = 0.1f, Max = 50f, Default = 2f }); Add(new ParamDef { Key = "MeleeAngle", DisplayName = "Swing Angle", Description = "Max swing angle (deg).", Kind = WeaponTypeKind.Melee, Target = ParamTarget.Weapon, On = ComponentKind.Weapon, FieldName = "maxAngle", Min = 1f, Max = 360f, Default = 360f }); Add(new ParamDef { Key = "MeleeCooldown", DisplayName = "Cooldown", Description = "Time between swings (s).", Kind = WeaponTypeKind.Melee, Target = ParamTarget.Weapon, On = ComponentKind.Weapon, FieldName = "internalCooldown", Min = 0.05f, Max = 20f, Default = 1f }); Add(new ParamDef { Key = "MeleeForce", DisplayName = "Curve Force", Description = "Swing impulse magnitude.", Kind = WeaponTypeKind.Melee, Target = ParamTarget.Weapon, On = ComponentKind.MeleeWeapon, FieldName = "curveForce", Min = 0f, Max = 5000f, Default = 100f }); Add(new ParamDef { Key = "MeleeDamage", DisplayName = "Damage", Description = "Melee hit damage.", Kind = WeaponTypeKind.Melee, Target = ParamTarget.Weapon, On = ComponentKind.Collision, FieldName = "damage", Min = 0f, Max = 10000f, Default = 80f }); Add(new ParamDef { Key = "MeleeImpact", DisplayName = "Impact", Description = "Melee impact force multiplier.", Kind = WeaponTypeKind.Melee, Target = ParamTarget.Weapon, On = ComponentKind.Collision, FieldName = "impactMultiplier", Min = 0f, Max = 20f, Default = 1f, IsMultiplier = true }); Add(new ParamDef { Key = "ParryPower", DisplayName = "Parry Power", Description = "Force needed to parry this weapon.", Kind = WeaponTypeKind.Melee, Target = ParamTarget.Weapon, On = ComponentKind.MeleeWeapon, FieldName = "requiredPowerToParry", Min = 0f, Max = 1000f, Default = 100f }); AddScale(WeaponTypeKind.Melee, ParamTarget.Weapon, "Size", "Weapon size multiplier (X/Y/Z axes)."); ResolveFields(); WriteConfigEntries(cfg); } private static void AddScale(WeaponTypeKind kind, ParamTarget target, string prefix, string desc) { Add(new ParamDef { Key = prefix + "X", DisplayName = prefix + " X", Description = desc, Kind = kind, Target = target, On = ComponentKind.Scale, Min = 0.1f, Max = 10f, Default = 1f, IsMultiplier = true, Axis = 0 }); Add(new ParamDef { Key = prefix + "Y", DisplayName = prefix + " Y", Description = desc, Kind = kind, Target = target, On = ComponentKind.Scale, Min = 0.1f, Max = 10f, Default = 1f, IsMultiplier = true, Axis = 1 }); Add(new ParamDef { Key = prefix + "Z", DisplayName = prefix + " Z", Description = desc, Kind = kind, Target = target, On = ComponentKind.Scale, Min = 0.1f, Max = 10f, Default = 1f, IsMultiplier = true, Axis = 2 }); } private static void ResolveFields() { foreach (ParamDef item in All) { if (item.On != ComponentKind.Scale) { Type type = item.On switch { ComponentKind.Weapon => typeof(Weapon), ComponentKind.RangeWeapon => typeof(RangeWeapon), ComponentKind.MeleeWeapon => typeof(MeleeWeapon), ComponentKind.MoveTransform => typeof(MoveTransform), ComponentKind.Collision => typeof(CollisionWeapon), ComponentKind.Compensation => typeof(Compensation), _ => null, }; if (!(type == null)) { string name = (item.FieldName.Contains(".") ? item.FieldName.Split(new char[1] { '.' })[0] : item.FieldName); item.Field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } } } private static void WriteConfigEntries(ConfigFile cfg) { foreach (ParamDef item in All) { _ = cfg.Bind("Parameters." + item.Kind.ToString() + "." + item.Target, item.Key, item.Default, $"Min={item.Min} Max={item.Max} Default={item.Default}. Listed params are editable in the unit editor's weapon Data tab.").Value; } cfg.Save(); } public static IEnumerable For(WeaponTypeKind kind) { foreach (ParamDef item in All) { if (item.Kind == kind) { yield return item; } } } public static IEnumerable For(WeaponTypeKind kind, ParamTarget target) { foreach (ParamDef item in All) { if (item.Kind == kind && item.Target == target) { yield return item; } } } public static float? DefaultFor(string key) { foreach (ParamDef item in All) { if (item.Key == key) { return item.Default; } } return null; } public static float ReadActual(Component weaponRoot, ParamDef p, GameObject projectileOverride = null) { try { if (p.On == ComponentKind.Scale) { return 1f; } if (p.Field == null) { return p.Default; } Component val3; if (p.Target == ParamTarget.Projectile) { GameObject val = projectileOverride; if ((Object)(object)val == (Object)null) { RangeWeapon val2 = (RangeWeapon)(((object)((weaponRoot is RangeWeapon) ? weaponRoot : null)) ?? ((object)weaponRoot.GetComponent())); val = (((Object)(object)val2 != (Object)null) ? val2.ObjectToSpawn : null); } if ((Object)(object)val == (Object)null) { return p.Default; } val3 = val.GetComponentInChildren(p.Field.DeclaringType); } else { val3 = ResolveOnWeapon(weaponRoot, p.On); } if ((Object)(object)val3 == (Object)null) { return p.Default; } object value = p.Field.GetValue(val3); if (value is float result) { return result; } if (p.IsInt && value is int num) { return num; } return p.Default; } catch { return p.Default; } } private static Component ResolveOnWeapon(Component weapon, ComponentKind on) { return (Component)(on switch { ComponentKind.Weapon => weapon.GetComponent(), ComponentKind.RangeWeapon => weapon.GetComponent(), ComponentKind.MeleeWeapon => weapon.GetComponent(), ComponentKind.Collision => weapon.GetComponentInChildren(), ComponentKind.Compensation => weapon.GetComponentInChildren(), _ => null, }); } } [BepInPlugin("com.configurable.weapondata", "ConfigurableWeaponData", "1.4.4")] public class Plugin : BaseUnityPlugin { public const string GUID = "com.configurable.weapondata"; public const string NAME = "ConfigurableWeaponData"; public const string VERSION = "1.4.4"; public static Plugin Instance; public static ConfigFile Cfg; public static string StoreDir; public void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown Instance = this; Cfg = new ConfigFile(Path.Combine(Paths.ConfigPath, "configurableweapondata.cfg"), false); ParamRegistry.Init(Cfg); StoreDir = Path.Combine(Paths.PluginPath, "ConfigurableWeaponData", "weapons"); Directory.CreateDirectory(StoreDir); HarmonyPatches.Apply(); ((BaseUnityPlugin)this).Logger.LogMessage((object)("ConfigurableWeaponData 1.4.4 loaded. Store: " + StoreDir)); } } public static class UIPatcher { public class CWDInputRow : MonoBehaviour, IPointerDownHandler, IEventSystemHandler { public string rowKey; public ParamDef param; public TextMeshProUGUI valueText; public TMP_InputField inputField; private Coroutine _debounce; private string _pending; private float _lastApplied = float.NaN; public void SetInitialApplied(float v) { _lastApplied = v; } public void OnPointerDown(PointerEventData eventData) { try { if ((Object)(object)inputField != (Object)null) { ((Selectable)inputField).interactable = true; if ((Object)(object)EventSystem.current != (Object)null) { EventSystem.current.SetSelectedGameObject(((Component)inputField).gameObject); } inputField.ActivateInputField(); ((Selectable)inputField).Select(); Debug.Log((object)("[CWD] Input activated on row '" + param.Key + "'")); } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] input activate: " + ex.Message)); } } public void OnValueChanged(string newValue) { try { _pending = newValue; if (_debounce != null) { ((MonoBehaviour)this).StopCoroutine(_debounce); } _debounce = ((MonoBehaviour)this).StartCoroutine(DebounceApply()); } catch (Exception ex) { Debug.LogWarning((object)("[CWD] value changed: " + ex.Message)); } } private IEnumerator DebounceApply() { yield return (object)new WaitForSeconds(0.4f); _debounce = null; ApplyText(_pending); } public void OnEndEdit(string newValue) { try { if (_debounce != null) { ((MonoBehaviour)this).StopCoroutine(_debounce); _debounce = null; } ApplyText(newValue); if (float.TryParse((newValue != null) ? newValue.Trim().TrimEnd('x', 'X').Trim() : "", NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && (Object)(object)valueText != (Object)null) { ((TMP_Text)valueText).text = Format(param, result); } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] end edit: " + ex.Message)); } } private void ApplyText(string s) { if (s == null) { return; } if (float.TryParse(s.Trim().TrimEnd('x', 'X').Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { if (float.IsNaN(_lastApplied) || !Mathf.Approximately(_lastApplied, result)) { _lastApplied = result; EditorState.Set(rowKey, param.Key, result); UnitEditorManager val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null && !UnitEditorManager.isTestingUnit) { val.RespawnWeapons(); } Debug.Log((object)$"[CWD] applied {param.Key} = {result}"); } } else { Debug.LogWarning((object)("[CWD] parse failed: '" + s + "'")); } } } [CompilerGenerated] private static class <>O { public static UnityAction <0>__OnSaveClicked; public static UnityAction <1>__OpenSummonPicker; } private const string Tag = "[CWD]"; private static WeaponTypeKind _kind; private static string _key; private static Component _weaponProp; private static GameObject _projOverride; private static EquipedWeaponWrapper _lastWeapon; private static GameObject _scroll; private static readonly List _rows = new List(); public static bool SummonPickMode; private static Font _font; public static EquipedWeaponWrapper LastWeapon() { return _lastWeapon; } public static void RefreshPage(UnitEditorEquipedClothing page, EquipedWeaponWrapper weapon) { if ((Object)(object)_scroll != (Object)null) { KickEventSystem(); } else { HandleWeaponPage(page, weapon); } } private static void KickEventSystem() { try { if ((Object)(object)EventSystem.current != (Object)null) { EventSystem.current.SetSelectedGameObject((GameObject)null); } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] eventsystem kick: " + ex.Message)); } } public static bool IsOurs(StatsWrapper sw) { if (sw != null && sw.name != null) { return sw.name.StartsWith("[CWD]"); } return false; } public static void HandleWeaponPage(UnitEditorEquipedClothing page, EquipedWeaponWrapper weapon) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) WeaponTypeKind kind; if ((Object)(object)((Component)((EquipedWrapper)weapon).prop).GetComponent() != (Object)null) { kind = WeaponTypeKind.Ranged; } else { if (!((Object)(object)((Component)((EquipedWrapper)weapon).prop).GetComponent() != (Object)null)) { return; } kind = WeaponTypeKind.Melee; } int num = 0; try { num = ((EquipedWrapper)weapon).prop.Entity.GUID.m_ID; } catch { } if (num == 0) { return; } _kind = kind; _key = EditorState.KeyFor(weapon.isRightHanded, num); _weaponProp = (Component)(object)((EquipedWrapper)weapon).prop; _projOverride = null; try { UnitEditorManager val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null) { ProjectileEntity projectile = val.GetProjectile(weapon); if ((Object)(object)projectile != (Object)null) { _projOverride = ((Component)projectile).gameObject; } } } catch { } _lastWeapon = weapon; ((MonoBehaviour)Plugin.Instance).StartCoroutine(DelayedInject(page)); } private static IEnumerator DelayedInject(UnitEditorEquipedClothing page) { yield return null; yield return null; if ((Object)(object)page == (Object)null) { yield break; } try { Inject(page); } catch (Exception ex) { Debug.LogWarning((object)("[CWD] Inject failed: " + ex.Message)); } } public static void OpenSummonPicker() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) try { UnitEditorManager val = Object.FindObjectOfType(); if (!((Object)(object)val == (Object)null)) { UnitEditorUIManager unitEditorUIManager = val.unitEditorUIManager; if (!((Object)(object)unitEditorUIManager == (Object)null)) { SummonPickMode = true; UnitBlueprint[] array = ContentDatabase.Instance().GetUserUnitBlueprintsByIdExcluded(val.GetCurrentID()).ToArray(); ((MonoBehaviour)Plugin.Instance).StartCoroutine(unitEditorUIManager.listSelectScreen.Setup(array)); unitEditorUIManager.NavigateToPage("VOICESELECT"); ((MonoBehaviour)Plugin.Instance).StartCoroutine(FixHeaderLater()); Debug.Log((object)"[CWD] summon picker opened"); } } } catch (Exception ex) { SummonPickMode = false; Debug.LogWarning((object)("[CWD] summon picker: " + ex.Message)); } } private static IEnumerator FixHeaderLater() { yield return null; yield return null; try { if (SummonPickMode) { UnitEditorListSelectScreen val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null && (Object)(object)val.header != (Object)null) { val.header.Localized = false; val.header.LocaleID = "Select Summon Unit"; } } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] header fix: " + ex.Message)); } } public static void OnSummonPicked(UnitEditorManager mgr, int guid) { try { EditorState.SetSummon(_key, guid); if (_lastWeapon != null) { try { mgr.EquipProjectile((ProjectileEntity)null, _lastWeapon.isRightHanded); } catch { } } if (!UnitEditorManager.isTestingUnit) { mgr.RespawnWeapons(); } UnitEditorUIManager unitEditorUIManager = mgr.unitEditorUIManager; if ((Object)(object)unitEditorUIManager != (Object)null) { unitEditorUIManager.NavigateToPage("EQUIPEDCLOTHING"); if (_lastWeapon != null) { unitEditorUIManager.SetupEquipedWeapon(_lastWeapon); } } Debug.Log((object)$"[CWD] summon picked: {guid}"); } catch (Exception ex) { Debug.LogWarning((object)("[CWD] summon picked: " + ex.Message)); } } private static void DumpDiagnostics(UnitEditorEquipedClothing page, Transform container) { try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"[CWD] EventSystem: current={(Object)(object)EventSystem.current != (Object)null}, module={(Object)(object)EventSystem.current != (Object)null && (Object)(object)EventSystem.current.currentInputModule != (Object)null}"); Canvas componentInParent = ((Component)page).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { GraphicRaycaster component = ((Component)componentInParent).GetComponent(); stringBuilder.AppendLine($"[CWD] Canvas '{((Object)componentInParent).name}' raycaster={(Object)(object)component != (Object)null}, sortingOrder={componentInParent.sortingOrder}"); } DumpNode(stringBuilder, ((Component)page).transform, "", 0, 6); Debug.Log((object)stringBuilder.ToString()); } catch (Exception ex) { Debug.LogWarning((object)("[CWD] diagnostics: " + ex.Message)); } } private static void DumpNode(StringBuilder sb, Transform t, string indent, int depth, int maxDepth) { if (!((Object)(object)t == (Object)null) && depth <= maxDepth) { GameObject gameObject = ((Component)t).gameObject; CanvasGroup component = gameObject.GetComponent(); Image component2 = gameObject.GetComponent(); string text = ""; if ((Object)(object)component != (Object)null) { text = $" [CG a={component.alpha} i={component.interactable} b={component.blocksRaycasts}]"; } if ((Object)(object)component2 != (Object)null) { text += $" [Img rt={((Graphic)component2).raycastTarget}]"; } sb.AppendLine($"{indent}{((Object)gameObject).name} active={gameObject.activeInHierarchy}{text}"); for (int i = 0; i < t.childCount; i++) { DumpNode(sb, t.GetChild(i), indent + " ", depth + 1, maxDepth); } } } private static void Inject(UnitEditorEquipedClothing page) { //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Expected O, but got Unknown //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Expected O, but got Unknown //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) for (int num = _rows.Count - 1; num >= 0; num--) { if ((Object)(object)_rows[num] != (Object)null) { Object.Destroy((Object)(object)_rows[num]); } } _rows.Clear(); if ((Object)(object)_scroll != (Object)null) { Object.Destroy((Object)(object)_scroll); _scroll = null; } object? value = F_ProjectileStat().GetValue(page); GameObject val = (GameObject)((value is GameObject) ? value : null); Transform val2 = null; if ((Object)(object)val != (Object)null) { val2 = val.transform.parent; } if ((Object)(object)val2 == (Object)null) { object? value2 = F_TABSContentParent().GetValue(page); GameObject val3 = (GameObject)((value2 is GameObject) ? value2 : null); if ((Object)(object)val3 != (Object)null) { val2 = val3.transform; } } if ((Object)(object)val2 == (Object)null) { val2 = ((Component)page).transform; } for (int i = 0; i < val2.childCount; i++) { GameObject gameObject = ((Component)val2.GetChild(i)).gameObject; if (!((Object)(object)val != (Object)null) || !((Object)(object)gameObject == (Object)(object)val)) { gameObject.SetActive(false); } } GameObject val4 = (_scroll = new GameObject("CWDScroll", new Type[5] { typeof(RectTransform), typeof(Image), typeof(ScrollRect), typeof(RectMask2D), typeof(LayoutElement) })); val4.transform.SetParent(val2, false); LayoutElement component = val4.GetComponent(); component.minHeight = 300f; component.preferredHeight = 340f; component.flexibleHeight = 1f; Image component2 = val4.GetComponent(); ((Graphic)component2).color = new Color(0f, 0f, 0f, 0.02f); ((Graphic)component2).raycastTarget = true; ScrollRect component3 = val4.GetComponent(); GameObject val5 = new GameObject("Content", new Type[3] { typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(ContentSizeFitter) }); val5.transform.SetParent(val4.transform, false); VerticalLayoutGroup component4 = val5.GetComponent(); ((HorizontalOrVerticalLayoutGroup)component4).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)component4).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)component4).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)component4).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)component4).spacing = 2f; ((LayoutGroup)component4).padding = new RectOffset(2, 2, 2, 2); val5.GetComponent().verticalFit = (FitMode)2; RectTransform component5 = val5.GetComponent(); component5.anchorMin = new Vector2(0f, 1f); component5.anchorMax = new Vector2(1f, 1f); component5.pivot = new Vector2(0.5f, 1f); component3.content = component5; component3.viewport = val4.GetComponent(); component3.horizontal = false; component3.vertical = true; component3.movementType = (MovementType)2; component3.scrollSensitivity = 25f; component3.inertia = true; int num2 = 0; foreach (ParamDef item2 in ParamRegistry.For(_kind)) { float v = item2.Default; if (EditorState.TryGet(_key, item2.Key, out var value3)) { v = value3; } else if ((Object)(object)_weaponProp != (Object)null) { v = ParamRegistry.ReadActual(_weaponProp, item2, _projOverride); } GameObject item = MakeRow(val5.transform, item2, v); _rows.Add(item); num2++; } if (_kind == WeaponTypeKind.Ranged) { _rows.Add(MakeSummonButtonRow(val5.transform)); if ((Object)(object)val != (Object)null) { val.SetActive(EditorState.GetSummon(_key) == 0); } } if ((Object)(object)val != (Object)null) { val.transform.SetAsLastSibling(); } _rows.Add(MakeSaveRow(val2)); Debug.Log((object)$"[CWD] CustomRows: {num2} rows under '{((Object)val2).name}'"); try { if ((Object)(object)EventSystem.current != (Object)null) { EventSystem.current.SetSelectedGameObject((GameObject)null); } } catch (Exception ex) { Debug.LogWarning((object)("[CWD] eventsystem kick: " + ex.Message)); } DumpDiagnostics(page, val2); } private static GameObject MakeSaveRow(Transform parent) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown Resources val = default(Resources); GameObject val2 = new GameObject("CWD_Save", new Type[2] { typeof(RectTransform), typeof(LayoutElement) }); val2.transform.SetParent(parent, false); val2.transform.SetAsLastSibling(); LayoutElement component = val2.GetComponent(); component.minHeight = 40f; component.preferredHeight = 40f; GameObject obj = DefaultControls.CreateButton(val); ((Object)obj).name = "SaveButton"; obj.transform.SetParent(val2.transform, false); RectTransform component2 = obj.GetComponent(); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.offsetMin = Vector2.zero; component2.offsetMax = Vector2.zero; Button component3 = obj.GetComponent