using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Brumdail")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.3.0")]
[assembly: AssemblyInformationalVersion("1.1.3+f6361625ce7ba05912464b947482405d6a6f1291")]
[assembly: AssemblyProduct("ErenshorQoL")]
[assembly: AssemblyTitle("ErenshorQoL")]
[assembly: AssemblyVersion("1.1.3.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace ErenshorQoL
{
[BepInPlugin("Brumdail.ErenshorQoLMod", "Erenshor Quality of Life Mods", "1.1.3")]
[BepInProcess("Erenshor.exe")]
public class ErenshorQoLMod : BaseUnityPlugin
{
public enum Toggle
{
Off,
On
}
internal class AcceptableShortcuts : AcceptableValueBase
{
public AcceptableShortcuts()
: base(typeof(KeyboardShortcut))
{
}
public override object Clamp(object value)
{
return value;
}
public override bool IsValid(object value)
{
return true;
}
public override string ToDescriptionString()
{
return "# Acceptable values: " + string.Join(", ", UnityInput.Current.SupportedKeyCodes);
}
}
public class AutoPet
{
public static void AutoSendPet(string activatedFrom)
{
bool flag = (Object)(object)GameData.PlayerControl.Myself.MyCharmedNPC != (Object)null;
bool flag2 = (Object)(object)GameData.PlayerControl.CurrentTarget != (Object)null;
NPC myCharmedNPC = GameData.PlayerControl.Myself.MyCharmedNPC;
Character currentTarget = GameData.PlayerControl.CurrentTarget;
bool flag3 = false;
if (flag2 && flag)
{
flag3 = true;
}
if (flag && flag2 && flag3 && ((Object)(object)myCharmedNPC.CurrentAggroTarget == (Object)null || (Object)(object)myCharmedNPC.CurrentAggroTarget != (Object)(object)currentTarget) && flag2)
{
myCharmedNPC.CurrentAggroTarget = currentTarget;
}
}
public static void AutoBackoffPet(string activatedFrom)
{
if ((Object)(object)GameData.PlayerControl.Myself.MyCharmedNPC != (Object)null && (Object)(object)GameData.PlayerControl.Myself.MyCharmedNPC.CurrentAggroTarget != (Object)null)
{
GameData.PlayerControl.Myself.MyCharmedNPC.CurrentAggroTarget = null;
UpdateSocialLog.LogAdd(GameData.PlayerControl.Myself.MyCharmedNPC.NPCName.ToString() + " says: backing off...");
}
}
}
public class AutoAttack
{
public static void EnableAutoAttack(string activatedFrom)
{
bool flag = false;
if (flag)
{
UpdateSocialLog.LogAdd("Auto-Attack On " + activatedFrom + " - GameData.Autoattacking is: {GameData.Autoattacking}", "lightblue");
}
if (GameData.Autoattacking)
{
return;
}
PlayerCombat component = ((Component)GameData.PlayerControl.Myself).GetComponent<PlayerCombat>();
if ((Object)(object)component != (Object)null)
{
MethodInfo methodInfo = AccessTools.Method(typeof(PlayerCombat), "ToggleAttack", (Type[])null, (Type[])null);
if (methodInfo != null)
{
methodInfo.Invoke(component, null);
}
if (flag)
{
UpdateSocialLog.LogAdd("Activeated Auto-Attack On " + activatedFrom + " - GameData.Autoattacking is: {GameData.Autoattacking}", "orange");
}
}
}
}
public class AutoGroupCommand
{
public static void AutoCommandAttack(string activatedFrom)
{
}
}
[HarmonyPatch(typeof(Character))]
[HarmonyPatch("DoDeath")]
[HarmonyPriority(50000)]
[HarmonyAfter(new string[] { "Brumdail.ErenshorREL" })]
private class AutoLoot
{
private static void Postfix(Character __instance)
{
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
if (AutoLootToggle.Value != Toggle.On || !((Object)(object)__instance != (Object)null) || !__instance.isNPC || !((Object)(object)__instance.MyNPC != (Object)null))
{
return;
}
bool flag = false;
float num = 30f;
num = AutoLootDistance.Value;
if (num < 0f)
{
num = 0f;
}
if (!(Vector3.Distance(((Component)GameData.PlayerControl).transform.position, ((Component)__instance.MyNPC).transform.position) < num))
{
return;
}
LootTable component = ((Component)__instance.MyNPC).GetComponent<LootTable>();
if ((Object)(object)component != (Object)null)
{
if (flag)
{
UpdateSocialLog.LogAdd("LootTable: " + ((object)component).ToString());
}
component.LoadLootTable();
if (flag)
{
UpdateSocialLog.LogAdd("LoadedLootTable: " + ((object)component).ToString());
}
GameData.LootWindow.LootAll();
}
}
}
[HarmonyPatch(typeof(TypeText))]
[HarmonyPatch("CheckCommands")]
private class QoLCommands
{
private static bool Prefix()
{
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_0391: Unknown result type (might be due to invalid IL or missing references)
if (QoLCommandsToggle.Value == Toggle.On)
{
bool flag = true;
bool flag2 = false;
bool flag3 = true;
bool flag4 = false;
bool flag5 = true;
if (GameData.TextInput.typed.text.Length >= 9 && GameData.TextInput.typed.text.Substring(0, 9).ToLower() == "/autoloot")
{
if (AutoLootToggle.Value == Toggle.Off)
{
AutoLootToggle.Value = Toggle.On;
}
else if (AutoLootToggle.Value == Toggle.On)
{
AutoLootToggle.Value = Toggle.Off;
}
UpdateSocialLog.LogAdd("AutoLoot: " + AutoLootToggle.Value, "orange");
GameData.TextInput.typed.text = "";
GameData.TextInput.CDFrames = 10f;
GameData.TextInput.InputBox.SetActive(false);
GameData.PlayerTyping = false;
return false;
}
if (GameData.TextInput.typed.text.Length >= 5 && flag && GameData.TextInput.typed.text.Substring(0, 5).ToLower() == "/bank")
{
GameData.BankUI.OpenBank(((Component)GameData.PlayerControl).transform.position);
GameData.TextInput.typed.text = "";
GameData.TextInput.CDFrames = 10f;
GameData.TextInput.InputBox.SetActive(false);
GameData.PlayerTyping = false;
return false;
}
if (GameData.TextInput.typed.text.Length >= 7 && flag2)
{
if (GameData.TextInput.typed.text.Substring(0, 7).ToLower() == "/vendor" && (Object)(object)GameData.PlayerControl.CurrentTarget != (Object)null && GameData.PlayerControl.CurrentTarget.isNPC)
{
Character currentTarget = GameData.PlayerControl.CurrentTarget;
if (!currentTarget.isVendor)
{
currentTarget.isVendor = true;
}
if ((Object)(object)((Component)currentTarget).GetComponent<VendorInventory>() == (Object)null)
{
List<Item> itemsForSale = ((Component)currentTarget).GetComponent<VendorInventory>().ItemsForSale;
Object obj = Resources.Load("Bread");
itemsForSale.Add((Item)(object)((obj is Item) ? obj : null));
List<Item> itemsForSale2 = ((Component)currentTarget).GetComponent<VendorInventory>().ItemsForSale;
Object obj2 = Resources.Load("Water");
itemsForSale2.Add((Item)(object)((obj2 is Item) ? obj2 : null));
for (int i = 0; i <= 11; i++)
{
if (i >= ((Component)currentTarget).GetComponent<VendorInventory>().ItemsForSale.Count)
{
List<Item> itemsForSale3 = ((Component)currentTarget).GetComponent<VendorInventory>().ItemsForSale;
Object obj3 = Resources.Load("Empty");
itemsForSale3.Add((Item)(object)((obj3 is Item) ? obj3 : null));
}
}
UpdateSocialLog.LogAdd("Vendor setup for: " + ((Object)currentTarget).name, "yellow");
GameData.TextInput.typed.text = "";
GameData.TextInput.CDFrames = 10f;
GameData.TextInput.InputBox.SetActive(false);
GameData.PlayerTyping = false;
return false;
}
}
else
{
UpdateSocialLog.LogAdd("/vendor command requires an NPC target", "yellow");
}
}
if (GameData.TextInput.typed.text.Length >= 8 && flag3 && !GameData.GM.DemoBuild && GameData.TextInput.typed.text.Substring(0, 8).ToLower() == "/auction")
{
GameData.AHUI.OpenAuctionHouse(((Component)GameData.PlayerControl).transform.position);
GameData.TextInput.typed.text = "";
GameData.TextInput.CDFrames = 10f;
GameData.TextInput.InputBox.SetActive(false);
GameData.PlayerTyping = false;
return false;
}
if (GameData.TextInput.typed.text.Length >= 9 && flag4 && GameData.TextInput.typed.text.Substring(0, 9).ToLower() == "/allscene")
{
return false;
}
if (GameData.TextInput.typed.text.Length >= 5 && flag5 && GameData.TextInput.typed.text.Substring(0, 5).ToLower() == "/help")
{
UpdateSocialLog.LogAdd("QoL Modded commands: ", "lightblue");
UpdateSocialLog.LogAdd("/autoloot - Toggles the feature to automatically Loot All items from the nearest corpse each time a creature dies.", "lightblue");
UpdateSocialLog.LogAdd("/bank - Opens the bank window", "lightblue");
UpdateSocialLog.LogAdd("/auction - Opens the auction hall window", "lightblue");
UpdateSocialLog.LogAdd("\nGM commands: *most not available in the demo build", "orange");
UpdateSocialLog.LogAdd("/iamadev - Enable Dev Controls", "orange");
UpdateSocialLog.LogAdd("/allitem - List all items", "orange");
UpdateSocialLog.LogAdd("/additem 11823624 - Add item (use /allitem to get item codes)", "orange");
UpdateSocialLog.LogAdd("/hpscale 1.0 (multiplier) - NPC HP scale modifier. You must zone to activate this modifier", "orange");
UpdateSocialLog.LogAdd("/loadset 35 (level 1-35) - Sets targetted SimPlayer to level and gear for level", "orange");
UpdateSocialLog.LogAdd("/livenpc - List living NPCs in zone", "orange");
UpdateSocialLog.LogAdd("/levelup - Maxes target's Earned XP", "orange");
UpdateSocialLog.LogAdd("/simlocs - Report sim zone population", "orange");
UpdateSocialLog.LogAdd("/fastdev - Increases player RunSpeed to 24", "orange");
UpdateSocialLog.LogAdd("/raining - Changes atmosphere to raining", "orange");
UpdateSocialLog.LogAdd("/thunder - Changes atmosphere to thunderstorm", "orange");
UpdateSocialLog.LogAdd("/bluesky - Changes atmosphere to blue sky", "orange");
UpdateSocialLog.LogAdd("/dosunny - Toggles sun", "orange");
UpdateSocialLog.LogAdd("/gamepad - Gamepad Control Enabled (experimental)", "orange");
UpdateSocialLog.LogAdd("/devkill - Kill current target", "orange");
UpdateSocialLog.LogAdd("/preview - Enable Demonstration Mode (CAUTION: Save Files will be overwritten!!)", "red");
UpdateSocialLog.LogAdd("/invisme - Toggle Dev Invis", "orange");
UpdateSocialLog.LogAdd("/toscene Stowaway - Teleport to the named scene", "orange");
UpdateSocialLog.LogAdd("/droneme - Toggle Drone Mode", "orange");
UpdateSocialLog.LogAdd("/debugap - List NPCs attacking the player", "orange");
UpdateSocialLog.LogAdd("/spychar - List information about the target", "orange");
UpdateSocialLog.LogAdd("/nodechk - List Nodes in the current zone", "orange");
UpdateSocialLog.LogAdd("/faction 5 - Modify player's faction standing of the target's faction. Use negative numbers to decrease faction.", "orange");
UpdateSocialLog.LogAdd("/yousolo - Removes SimPlayer from group", "orange");
UpdateSocialLog.LogAdd("/allgrps - List group data", "orange");
UpdateSocialLog.LogAdd("/portsim SimName - Teleport specified SimPlayer to player", "orange");
UpdateSocialLog.LogAdd("\nPlayers commands:", "yellow");
UpdateSocialLog.LogAdd("/players - Get a list of players in zone", "yellow");
UpdateSocialLog.LogAdd("/time - Get the current game time", "yellow");
UpdateSocialLog.LogAdd("/whisper PlayerName Msg - Send a private message", "yellow");
UpdateSocialLog.LogAdd("/group - Send a message to your group (wait, attack, guard, etc)", "yellow");
UpdateSocialLog.LogAdd("/dance - boogie down.", "yellow");
UpdateSocialLog.LogAdd("/keyring - List held keys", "yellow");
UpdateSocialLog.LogAdd("/all players || /all pla - List all players in Erenshor", "yellow");
UpdateSocialLog.LogAdd("/shout - Message the entire zone", "yellow");
UpdateSocialLog.LogAdd("/friend - Target SimPlayer is a FRIEND of this character. Their progress will be loosely tied to this character's progress.", "yellow");
UpdateSocialLog.LogAdd("/time 1, /time10, /time25, /time50 - Set TimeScale multiplier", "yellow");
UpdateSocialLog.LogAdd("Hotkeys:", "yellow");
UpdateSocialLog.LogAdd("o - options", "yellow");
UpdateSocialLog.LogAdd("i - inventory", "yellow");
UpdateSocialLog.LogAdd("b - skill book", "yellow");
UpdateSocialLog.LogAdd("b - spell book", "yellow");
UpdateSocialLog.LogAdd("c - consider opponent", "yellow");
UpdateSocialLog.LogAdd("h - greet your target", "yellow");
UpdateSocialLog.LogAdd("q - autoattack toggle", "yellow");
UpdateSocialLog.LogAdd("escape (hold) - exit to menu", "yellow");
GameData.TextInput.typed.text = "";
GameData.TextInput.CDFrames = 10f;
GameData.TextInput.InputBox.SetActive(false);
GameData.PlayerTyping = false;
return false;
}
}
return true;
}
}
[HarmonyPatch(typeof(UseSkill))]
[HarmonyPatch("DoSkill")]
private class AutoOnSkill
{
private static void Prefix()
{
if (AutoPetToggle.Value == Toggle.On && AutoPetOnSkillToggle.Value == Toggle.On)
{
AutoPet.AutoSendPet("Skill");
}
if (AutoAttackToggle.Value == Toggle.On && AutoAttackOnSkillToggle.Value == Toggle.On)
{
AutoAttack.EnableAutoAttack("Skill");
}
}
}
[HarmonyPatch(typeof(PlayerCombat))]
[HarmonyPatch("ToggleAttack")]
private class AutoOnAutoattack
{
private static void Postfix()
{
if (AutoPetToggle.Value == Toggle.On)
{
if (AutoPetOnSkillToggle.Value == Toggle.On && GameData.Autoattacking)
{
AutoPet.AutoSendPet("AutoAttack");
}
if (AutoPetOnSkillToggle.Value == Toggle.On && !GameData.Autoattacking)
{
AutoPet.AutoBackoffPet("AutoAttack");
}
}
}
}
[HarmonyPatch(typeof(AuctionHouseUI))]
[HarmonyPatch("OpenListItem")]
private class AutoPriceYourItem
{
private static void Postfix(AuctionHouseUI __instance)
{
if (AutoPriceItem.Value == Toggle.On)
{
int num = 0;
num = GameData.SlotToBeListed.MyItem.ItemValue * 6 - 1;
GameData.AHUI.ListPrice.text = $"{num}";
}
}
}
internal const string ModName = "ErenshorQoLMod";
internal const string ModVersion = "1.1.3";
internal const string ModDescription = "Erenshor Quality of Life Mods";
internal const string Author = "Brumdail";
private const string ModGUID = "Brumdail.ErenshorQoLMod";
private static string ConfigFileName = "Brumdail.ErenshorQoLMod.cfg";
private static string ConfigFileFullPath = Paths.ConfigPath + Path.DirectorySeparatorChar + ConfigFileName;
internal static ErenshorQoLMod context = null;
private readonly Harmony harmony = new Harmony("Brumdail.ErenshorQoLMod");
public static readonly ManualLogSource ErenshorQoLLogger = Logger.CreateLogSource("ErenshorQoLMod");
internal static ConfigEntry<Toggle> AutoLootToggle = null;
internal static ConfigEntry<float> AutoLootDistance = null;
internal static ConfigEntry<Toggle> QoLCommandsToggle = null;
internal static ConfigEntry<Toggle> AutoAttackToggle = null;
internal static ConfigEntry<Toggle> AutoAttackOnSkillToggle = null;
internal static ConfigEntry<Toggle> AutoAttackOnSpellToggle = null;
internal static ConfigEntry<Toggle> AutoAttackOnGroupAttackToggle = null;
internal static ConfigEntry<Toggle> AutoAttackOnPetAttackToggle = null;
internal static ConfigEntry<Toggle> AutoPetToggle = null;
internal static ConfigEntry<Toggle> AutoPetOnSkillToggle = null;
internal static ConfigEntry<Toggle> AutoPetOnSpellToggle = null;
internal static ConfigEntry<Toggle> AutoPetOnGroupAttackToggle = null;
internal static ConfigEntry<Toggle> AutoPetOnAutoAttackToggle = null;
internal static ConfigEntry<Toggle> AutoGroupAttackToggle = null;
internal static ConfigEntry<Toggle> AutoGroupAttackOnSkillToggle = null;
internal static ConfigEntry<Toggle> AutoGroupAttackOnSpellToggle = null;
internal static ConfigEntry<Toggle> AutoGroupAttackOnPetAttackToggle = null;
internal static ConfigEntry<Toggle> AutoGroupAttackOnAutoAttackToggle = null;
internal static ConfigEntry<Toggle> AutoPriceItem = null;
internal static bool _configApplied;
private void Awake()
{
context = this;
Utilities.GenerateConfigs();
harmony.PatchAll();
SetupWatcher();
}
private void OnDestroy()
{
((BaseUnityPlugin)this).Config.Save();
}
private void Update()
{
((BaseUnityPlugin)this).Config.Save();
}
private void SetupWatcher()
{
FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
fileSystemWatcher.Changed += ReadConfigValues;
fileSystemWatcher.Created += ReadConfigValues;
fileSystemWatcher.Renamed += ReadConfigValues;
fileSystemWatcher.IncludeSubdirectories = true;
fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
fileSystemWatcher.EnableRaisingEvents = true;
}
private void ReadConfigValues(object sender, FileSystemEventArgs e)
{
if (!File.Exists(ConfigFileFullPath))
{
return;
}
try
{
ErenshorQoLLogger.LogDebug((object)"ReadConfigValues called");
((BaseUnityPlugin)this).Config.Reload();
}
catch
{
ErenshorQoLLogger.LogError((object)("There was an issue loading your " + ConfigFileName));
ErenshorQoLLogger.LogError((object)"Please check your config entries for spelling and format!");
}
}
internal ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description)
{
return ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, description);
}
internal ConfigEntry<T> config<T>(string group, string name, T value, string description)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
return ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
}
}
public class Utilities
{
internal static void ApplyConfig()
{
ErenshorQoLMod._configApplied = true;
}
internal static void GenerateConfigs()
{
ErenshorQoLMod.AutoLootToggle = ErenshorQoLMod.context.config("1 - AutoLoot", "Enable AutoLoot", ErenshorQoLMod.Toggle.On, "This file is automatically generated by the Erenshor Quality of Life Mods plugin and is used to configure various mod features. You can revert to the defaults if you experience issues.\nEnable automatic looting within the LootDistance?");
ErenshorQoLMod.AutoLootDistance = ErenshorQoLMod.context.config("1 - AutoLoot", "Auto Loot Distance", 30f, "Distance to automatically loot items from defeated enemies. Acceptable Range <float> 5-10000");
ErenshorQoLMod.QoLCommandsToggle = ErenshorQoLMod.context.config("2 - QoL Commands", "Enable QoL Commands", ErenshorQoLMod.Toggle.On, "Enable additional Quality of Life commands like /bank, /sell, /auction, updated /help etc.");
ErenshorQoLMod.AutoAttackToggle = ErenshorQoLMod.context.config("3 - Auto Attack", "Enable Auto Attack", ErenshorQoLMod.Toggle.On, "Enable automatically turning on auto-attack.");
ErenshorQoLMod.AutoAttackOnSkillToggle = ErenshorQoLMod.context.config("3 - Auto Attack", "Auto Attack on Skill Use", ErenshorQoLMod.Toggle.On, "Automatically start attacking when a skill is used.");
ErenshorQoLMod.AutoPetToggle = ErenshorQoLMod.context.config("4 - Auto Pet", "Enable Auto Pet Command", ErenshorQoLMod.Toggle.On, "Enable automatically commanding the pet to attack.");
ErenshorQoLMod.AutoPetOnSkillToggle = ErenshorQoLMod.context.config("4 - Auto Pet", "Auto Pet Command on Skill Use", ErenshorQoLMod.Toggle.On, "Automatically command the pet to attack when a skill is used.");
ErenshorQoLMod.AutoPetOnAutoAttackToggle = ErenshorQoLMod.context.config("4 - Auto Pet", "Auto Pet Command on Auto Attack", ErenshorQoLMod.Toggle.On, "Automatically command the pet to attack when auto-attack is enabled.");
ErenshorQoLMod.AutoPriceItem = ErenshorQoLMod.context.config("6 - Auto Price Item", "Auto Set AH Item Price", ErenshorQoLMod.Toggle.On, "Automatically start with the highest sellable auction house price when adding an item.");
}
}
}