using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Xml.Serialization; using BepInEx; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("RandomizerMod")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("RandomizerMod")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("c5450fe0-edcf-483f-b9ea-4b1ef9d36da7")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace OutwardRandomizerMod; [Serializable] public class ValueRange { public float Min; public float Max; public float Chance; public ValueRange() { } public ValueRange(float min, float max, float chance) { Min = min; Max = max; Chance = chance; } internal float ChangeValue(float value) { float num = Random.Range(Min, Max); return value * num; } internal float GetValue() { return Random.Range(Min, Max); } } [Serializable] public class Config { public float DecreaseChanceForAdd = 0.05f; public List Weight = new List(); public List Durability = new List(); public List ColdProtectionModify = new List(); public List ColdProtectionAdd = new List(); public List HeatProtectionModify = new List(); public List HeatProtectionAdd = new List(); public List ImpactResistanceModify = new List(); public List ImpactResistanceAdd = new List(); public List ManaUseModifierModify = new List(); public List ManaUseModifierAdd = new List(); public List PouchCapacityBonusModify = new List(); public List PouchCapacityBonusAdd = new List(); public List StaminaUsePenaltyModify = new List(); public List StaminaUsePenaltyAdd = new List(); public List MovementPenaltyModify = new List(); public List MovementPenaltyAdd = new List(); public List DamageAttackModify = new List(); public List DamageAttackAdd = new List(); public List DamageResistanceModify = new List(); public List DamageResistanceAdd = new List(); public List StamCost = new List(); public List Impact = new List(); public List AttackSpeed = new List(); public List Damage = new List(); public List BagCapacity = new List(); public int MinNumberOfDropsInc; public int MaxNumberOfDropsInc; } public class ItemSaveData { public class DamageSaveData { public Types Type { get; set; } public float Damage { get; set; } } public class AttackSaveData { public float StamCost { get; set; } public float Knockback { get; set; } public float AttackSpeed { get; set; } public List Damage { get; set; } = new List(); } public int ItemID { get; set; } public string UID { get; set; } public string Name { get; set; } public string Type { get; set; } public string SubType { get; set; } public float Weight { get; set; } public int MaxDurability { get; set; } public List DamageResistance { get; set; } = new List(); public float ImpactResistance { get; set; } public float HeatProtection { get; set; } public float ColdProtection { get; set; } public float MovementPenalty { get; set; } public float StaminaUsePenalty { get; set; } public float ManaUseModifier { get; set; } public List DamageAttack { get; set; } = new List(); public float PouchCapacityBonus { get; set; } public List BaseDamage { get; set; } = new List(); public float StamCost { get; set; } public float Impact { get; set; } public float AttackSpeed { get; set; } public List Attacks { get; set; } = new List(); public float ContainerCapacity { get; set; } [XmlIgnore] public bool IsNew { get; set; } } public class ItemsSaveObject { public List Items { get; set; } = new List(); } [BepInPlugin("com.myname.randomizermod", "Randomizer Mod", "1.0.0")] public class RandomizerPlugin : BaseUnityPlugin { public const string GUID = "com.myname.randomizermod"; public const string NAME = "Randomizer Mod"; public const string VERSION = "1.0.0"; public string pluginFolderPath; public string filePath; public static ItemsSaveObject _itemsSaveData = new ItemsSaveObject(); public static Config _config; internal void Awake() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) Debug.LogError((object)"Initializing Randomizer Mod 1.0.0!"); pluginFolderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); filePath = Path.Combine(pluginFolderPath, "randomitems.xml"); LoadConfig(); new Harmony("com.myname.randomizermod").PatchAll(); } private void LoadConfig() { if (!File.Exists(filePath)) { _config = new Config(); SaveConfig(); Debug.LogError((object)"Read File Good1"); return; } try { using (StreamReader textReader = new StreamReader(filePath)) { _config = (Config)new XmlSerializer(typeof(Config)).Deserialize(textReader); } Debug.LogError((object)"read file good2"); } catch (Exception ex) { Debug.LogError((object)"file bad"); LogException(ex); } } private void SaveConfig() { try { using FileStream stream = new FileStream(filePath, FileMode.Create); using StreamWriter textWriter = new StreamWriter(stream, Encoding.GetEncoding("UTF-8")); new XmlSerializer(typeof(Config)).Serialize(textWriter, _config); } catch (Exception ex) { LogException(ex); } } public static void LogException(Exception ex) { Debug.LogError((object)ex); } public static void Log(string message) { Debug.Log((object)("RandomizeItems: " + message)); } public static FieldInfo GetField(string name) { return typeof(T).GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } public static float GetValue(float value, List modify, List add, ref float decreaseChance) { if ((double)value != 0.0 && modify != null && modify.Any()) { foreach (ValueRange item in modify.OrderBy((ValueRange o) => o.Chance)) { float num = Random.Range(0f, 1f); if ((double)item.Chance >= (double)num) { return item.ChangeValue(value); } } } else if (add != null && add.Any()) { foreach (ValueRange item2 in add.OrderBy((ValueRange o) => o.Chance)) { float num2 = Random.Range(0f, 1f); if ((double)item2.Chance - (double)decreaseChance >= (double)num2) { decreaseChance += _config.DecreaseChanceForAdd; return item2.GetValue(); } } } return value; } public static void LoadItemsData(string path) { Log("Loading saved items"); Stopwatch stopwatch = Stopwatch.StartNew(); try { using StreamReader streamReader = new StreamReader(path); using GZipStream stream = new GZipStream(streamReader.BaseStream, CompressionMode.Decompress); using StreamReader textReader = new StreamReader(stream); _itemsSaveData = (ItemsSaveObject)new XmlSerializer(typeof(ItemsSaveObject)).Deserialize(textReader); } catch (Exception ex) { _itemsSaveData = new ItemsSaveObject(); LogException(ex); } stopwatch.Stop(); } public static void SaveItemsData(string path) { Log("Saving items data."); Stopwatch stopwatch = Stopwatch.StartNew(); try { using FileStream stream = new FileStream(path, FileMode.Create); using GZipStream stream2 = new GZipStream(stream, CompressionMode.Compress); using StreamWriter textWriter = new StreamWriter(stream2, Encoding.GetEncoding("UTF-8")); new XmlSerializer(typeof(ItemsSaveObject)).Serialize(textWriter, _itemsSaveData); } catch (Exception ex) { LogException(ex); } Log($"Saved {_itemsSaveData.Items.Count} items. Elapsed: {stopwatch.Elapsed}"); } } [HarmonyPatch(typeof(SaveManager), "ChooseCharacterSaveInstance")] public class SaveManager_ChooseCharacterSaveInstance { [HarmonyPrefix] public static void ChooseCharacterSaveInstance(UID _charSaveID, int _instanceIndex, SaveManager __instance) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) CharacterSaveInstanceHolder val = ((DictionaryExt)RandomizerPlugin.GetField("m_charSaves").GetValue(__instance))[UID.op_Implicit(_charSaveID)]; string text = Path.Combine(((List)RandomizerPlugin.GetField("m_tempSaveInstances").GetValue(val))[0].SavePath, "randomitems.data"); MonoBehaviour.print((object)val); MonoBehaviour.print((object)text); if (File.Exists(text)) { RandomizerPlugin.LoadItemsData(text); } } } [HarmonyPatch(typeof(DropTable), "GenerateDrop")] public class DropTable_GenerateDrop { [HarmonyPrefix] public static void GenerateDrop(ItemContainer _dropContainer, DropTable __instance) { __instance.MinNumberOfDrops += RandomizerPlugin._config.MinNumberOfDropsInc; __instance.MaxNumberOfDrops += RandomizerPlugin._config.MaxNumberOfDropsInc; } } [HarmonyPatch(typeof(Character), "DodgeInput", new Type[] { typeof(Vector3) })] public class Character_DodgeInput { [HarmonyPrefix] public static bool DodgeInput(Vector3 _direction, Character __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.OwnerPlayerSys == (Object)null) && __instance.IsLocalPlayer && (bool)RandomizerPlugin.GetField("m_currentlyChargingAttack").GetValue(__instance)) { RandomizerPlugin.Log("DodgeInput: Dodge ignored to save bow"); return false; } return true; } } [HarmonyPatch(typeof(ItemStats), "OnInit")] public class ItemStats_OnInit { [HarmonyPrefix] public static void OnInit(Item _linkedItem) { try { if (_linkedItem is MeleeWeapon || _linkedItem is ProjectileWeapon || _linkedItem is Bag || _linkedItem is Armor) { ModifyItem(_linkedItem.Stats, _linkedItem); } } catch (Exception ex) { RandomizerPlugin.LogException(ex); } } private static void ModifyItem(ItemStats self, Item linkedItem) { ItemSaveData itemSaveData = RandomizerPlugin._itemsSaveData.Items.FirstOrDefault((ItemSaveData f) => f.UID == linkedItem.UID); if (itemSaveData == null) { ItemSaveData itemSaveData2 = new ItemSaveData(); itemSaveData2.UID = linkedItem.UID; itemSaveData2.ItemID = linkedItem.ItemID; itemSaveData2.Name = linkedItem.Name; itemSaveData2.Type = ((object)linkedItem).GetType().ToString(); ItemSaveData itemSaveData3 = itemSaveData2; Item obj = linkedItem; Weapon val = (Weapon)(object)((obj is Weapon) ? obj : null); itemSaveData3.SubType = (((Object)(object)val != (Object)null) ? ((object)(WeaponType)(ref val.Type)).ToString() : "None"); itemSaveData2.IsNew = true; itemSaveData = itemSaveData2; } ItemSaveData itemSaveData4 = itemSaveData; float decreaseChance = 0f; Item obj2 = linkedItem; Bag val2 = (Bag)(object)((obj2 is Bag) ? obj2 : null); if ((Object)(object)val2 != (Object)null && itemSaveData4.IsNew) { itemSaveData4.ContainerCapacity = Mathf.Ceil(RandomizerPlugin.GetValue(val2.BagCapacity, RandomizerPlugin._config.BagCapacity, null, ref decreaseChance)); } WeaponStats val3 = (WeaponStats)(object)((self is WeaponStats) ? self : null); if ((Object)(object)val3 == (Object)null) { EquipmentStats val4 = (EquipmentStats)(object)((self is EquipmentStats) ? self : null); if ((Object)(object)val4 != (Object)null) { ModifyEquipmentStats(val4, itemSaveData4, ref decreaseChance); UpdateSaveData(itemSaveData4); } } else { ModifyWeaponStats(val3, itemSaveData4, ref decreaseChance); ModifyEquipmentStats((EquipmentStats)(object)val3, itemSaveData4, ref decreaseChance); UpdateSaveData(itemSaveData4); } } private static void ModifyWeaponStats(WeaponStats weaponStats, ItemSaveData saveData, ref float decreaseChance) { //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if (saveData.IsNew) { saveData.StamCost = Mathf.Ceil(RandomizerPlugin.GetValue(weaponStats.StamCost, RandomizerPlugin._config.StamCost, null, ref decreaseChance)); saveData.Impact = Mathf.Ceil(RandomizerPlugin.GetValue(weaponStats.Impact, RandomizerPlugin._config.Impact, null, ref decreaseChance)); saveData.AttackSpeed = (float)Math.Round(RandomizerPlugin.GetValue(weaponStats.AttackSpeed, RandomizerPlugin._config.AttackSpeed, null, ref decreaseChance), 2); saveData.BaseDamage = new List(); for (int i = 0; i < weaponStats.BaseDamage.List.Count; i++) { DamageType val = weaponStats.BaseDamage.List[i]; saveData.BaseDamage.Add(new ItemSaveData.DamageSaveData { Type = val.Type, Damage = (float)Math.Round(RandomizerPlugin.GetValue(val.Damage, RandomizerPlugin._config.Damage, null, ref decreaseChance)) }); } saveData.Attacks = new List(); for (int j = 0; j < weaponStats.Attacks.Length; j++) { AttackData val2 = weaponStats.Attacks[j]; ItemSaveData.AttackSaveData attackSaveData = new ItemSaveData.AttackSaveData { StamCost = Mathf.Ceil(RandomizerPlugin.GetValue(val2.StamCost, RandomizerPlugin._config.StamCost, null, ref decreaseChance)), Knockback = Mathf.Ceil(RandomizerPlugin.GetValue(val2.Knockback, RandomizerPlugin._config.Impact, null, ref decreaseChance)), AttackSpeed = (float)Math.Round(RandomizerPlugin.GetValue(val2.AttackSpeed, RandomizerPlugin._config.AttackSpeed, null, ref decreaseChance), 2), Damage = new List() }; for (int k = 0; k < val2.Damage.Count; k++) { float value = val2.Damage[k]; attackSaveData.Damage.Add(Mathf.Ceil(RandomizerPlugin.GetValue(value, RandomizerPlugin._config.Damage, null, ref decreaseChance))); } saveData.Attacks.Add(attackSaveData); } } weaponStats.StamCost = saveData.StamCost; weaponStats.Impact = saveData.Impact; weaponStats.AttackSpeed = saveData.AttackSpeed; weaponStats.BaseDamage = new DamageList(((IEnumerable)saveData.BaseDamage).Select((Func)((ItemSaveData.DamageSaveData s) => new DamageType { Type = s.Type, Damage = s.Damage })).ToArray()); weaponStats.Attacks = ((IEnumerable)saveData.Attacks).Select((Func)((ItemSaveData.AttackSaveData s) => new AttackData { StamCost = s.StamCost, AttackSpeed = s.AttackSpeed, Damage = s.Damage, Knockback = s.Knockback })).ToArray(); } private static void UpdateSaveData(ItemSaveData saveData) { if (!RandomizerPlugin._itemsSaveData.Items.Any((ItemSaveData a) => a.UID == saveData.UID)) { RandomizerPlugin._itemsSaveData.Items.Add(saveData); saveData.IsNew = false; } } private static void ModifyEquipmentStats(EquipmentStats stats, ItemSaveData saveData, ref float decreaseChance) { if (saveData.IsNew) { saveData.Weight = Mathf.Ceil(RandomizerPlugin.GetValue((float)RandomizerPlugin.GetField("m_rawWeight").GetValue(stats), RandomizerPlugin._config.Weight, null, ref decreaseChance)); saveData.MaxDurability = (int)RandomizerPlugin.GetValue(((ItemStats)stats).MaxDurability, RandomizerPlugin._config.Durability, null, ref decreaseChance); saveData.ColdProtection = Mathf.Ceil(RandomizerPlugin.GetValue((float)RandomizerPlugin.GetField("m_coldProtection").GetValue(stats), RandomizerPlugin._config.ColdProtectionModify, RandomizerPlugin._config.ColdProtectionAdd, ref decreaseChance)); saveData.HeatProtection = Mathf.Ceil(RandomizerPlugin.GetValue((float)RandomizerPlugin.GetField("m_heatProtection").GetValue(stats), RandomizerPlugin._config.HeatProtectionModify, RandomizerPlugin._config.HeatProtectionAdd, ref decreaseChance)); saveData.ImpactResistance = Mathf.Ceil(RandomizerPlugin.GetValue((float)RandomizerPlugin.GetField("m_impactResistance").GetValue(stats), RandomizerPlugin._config.ImpactResistanceModify, RandomizerPlugin._config.ImpactResistanceAdd, ref decreaseChance)); saveData.ManaUseModifier = Mathf.Ceil(RandomizerPlugin.GetValue((float)RandomizerPlugin.GetField("m_manaUseModifier").GetValue(stats), RandomizerPlugin._config.ManaUseModifierModify, RandomizerPlugin._config.ManaUseModifierAdd, ref decreaseChance)); saveData.PouchCapacityBonus = Mathf.Ceil(RandomizerPlugin.GetValue((float)RandomizerPlugin.GetField("m_pouchCapacityBonus").GetValue(stats), RandomizerPlugin._config.PouchCapacityBonusModify, RandomizerPlugin._config.PouchCapacityBonusAdd, ref decreaseChance)); saveData.StaminaUsePenalty = Mathf.Ceil(RandomizerPlugin.GetValue((float)RandomizerPlugin.GetField("m_staminaUsePenalty").GetValue(stats), RandomizerPlugin._config.StaminaUsePenaltyModify, RandomizerPlugin._config.StaminaUsePenaltyAdd, ref decreaseChance)); saveData.MovementPenalty = Mathf.Ceil(RandomizerPlugin.GetValue((float)RandomizerPlugin.GetField("m_movementPenalty").GetValue(stats), RandomizerPlugin._config.MovementPenaltyModify, RandomizerPlugin._config.MovementPenaltyAdd, ref decreaseChance)); float[] array = (float[])RandomizerPlugin.GetField("m_damageAttack").GetValue(stats); saveData.DamageAttack = new List(); for (int i = 0; i < array.Length; i++) { if (i > 5) { saveData.DamageAttack.Add(array[i]); } else { saveData.DamageAttack.Add(Mathf.Ceil(RandomizerPlugin.GetValue(array[i], RandomizerPlugin._config.DamageAttackModify, RandomizerPlugin._config.DamageAttackAdd, ref decreaseChance))); } } float[] array2 = (float[])RandomizerPlugin.GetField("m_damageResistance").GetValue(stats); saveData.DamageResistance = new List(); for (int j = 0; j < array2.Length; j++) { if (j > 5) { saveData.DamageResistance.Add(array2[j]); } else { saveData.DamageResistance.Add(Mathf.Ceil(RandomizerPlugin.GetValue(array2[j], RandomizerPlugin._config.DamageResistanceModify, RandomizerPlugin._config.DamageResistanceAdd, ref decreaseChance))); } } } RandomizerPlugin.GetField("m_rawWeight").SetValue(stats, saveData.Weight); RandomizerPlugin.GetField("m_baseMaxDurability").SetValue(stats, saveData.MaxDurability); if ((saveData.Type == "MeleeWeapon" && saveData.SubType == "Shield") || saveData.Type == "Bag" || saveData.Type == "Armor") { RandomizerPlugin.GetField("m_coldProtection").SetValue(stats, saveData.ColdProtection); RandomizerPlugin.GetField("m_heatProtection").SetValue(stats, saveData.HeatProtection); RandomizerPlugin.GetField("m_impactResistance").SetValue(stats, saveData.ImpactResistance); RandomizerPlugin.GetField("m_pouchCapacityBonus").SetValue(stats, saveData.PouchCapacityBonus); RandomizerPlugin.GetField("m_damageResistance").SetValue(stats, saveData.DamageResistance.ToArray()); RandomizerPlugin.GetField("m_damageAttack").SetValue(stats, saveData.DamageAttack.ToArray()); RandomizerPlugin.GetField("m_manaUseModifier").SetValue(stats, saveData.ManaUseModifier); RandomizerPlugin.GetField("m_staminaUsePenalty").SetValue(stats, saveData.StaminaUsePenalty); RandomizerPlugin.GetField("m_movementPenalty").SetValue(stats, saveData.MovementPenalty); } } } [HarmonyPatch(typeof(Bag), "BaseInit")] public class Bag_BaseInit { [HarmonyPostfix] public static void BaseInit(Bag __instance) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown ItemContainerStatic val = (ItemContainerStatic)RandomizerPlugin.GetField("m_container").GetValue(__instance); ItemSaveData itemSaveData = RandomizerPlugin._itemsSaveData.Items.FirstOrDefault((ItemSaveData f) => f.UID == ((Item)__instance).UID); if ((Object)(object)val != (Object)null && itemSaveData != null) { RandomizerPlugin.GetField("m_baseContainerCapacity").SetValue(val, itemSaveData.ContainerCapacity); } } } [HarmonyPatch(typeof(SaveInstance), "Save")] public class SaveInstance_Save { [HarmonyPostfix] public static bool Save(bool __result, SaveInstance __instance) { RandomizerPlugin.SaveItemsData(Path.Combine(__instance.SavePath, "randomitems.data")); return __result; } }