using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BattleImprove.Components; using BattleImprove.Components.QOL; using BattleImprove.Patcher.QOL; using BattleImprove.Patcher.TakeHitPatcher; using BattleImprove.Transpiler; using BattleImprove.UI.InGame; using BattleImprove.Utils; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using PerfectRandom.Sulfur.Core; using PerfectRandom.Sulfur.Core.DevTools; using PerfectRandom.Sulfur.Core.Input; using PerfectRandom.Sulfur.Core.Items; using PerfectRandom.Sulfur.Core.LevelGeneration; using PerfectRandom.Sulfur.Core.Stats; using PerfectRandom.Sulfur.Core.UI; using PerfectRandom.Sulfur.Core.Units; using PerfectRandom.Sulfur.Core.Weapons; using PerfectRandom.Sulfur.Core.World; using PerfectRandom.Sulfur.Gameplay; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.UI; using UrGUI.UWindow; [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("BattleImprove")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.5.2.0")] [assembly: AssemblyInformationalVersion("1.5.2+bf2254015cace9fa9b1a39241aa22aed4b60ebef")] [assembly: AssemblyProduct("Battle Improvements")] [assembly: AssemblyTitle("BattleImprove")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.5.2.0")] [module: UnverifiableCode] [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; } } } public class HitSoundEffect : PluginInstance { public AudioClip[] hitClose; public AudioClip[] hitFar; public AudioClip[] hitCrit; public void PlayHitSound(Vector3 position, bool isCrit, bool isFar = false, float volume = 1f) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (isCrit) { AudioSource.PlayClipAtPoint(hitCrit[Random.Range(0, hitCrit.Length)], position, volume); } else if (isFar) { AudioSource.PlayClipAtPoint(hitFar[Random.Range(0, hitFar.Length)], position, volume); } else { AudioSource.PlayClipAtPoint(hitClose[Random.Range(0, hitClose.Length)], position, volume); } } } public class BF5MessageController : MessageController { public KillStreakController headshotStreak; public KillStreakController killStreak; protected override GameObject GetDamageInfo(string type, int damage, GameObject placeholder) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) GameObject damageInfo = base.GetDamageInfo(type, damage, placeholder); damageInfo.transform.localPosition = new Vector3(0f, 0f, 0f); damageInfo.GetComponent().pivot = new Vector2(0.5f, 0.5f); TMP_Text component = damageInfo.GetComponent(); component.alignment = (TextAlignmentOptions)514; component.fontSize = 15f; return damageInfo; } public override void OnEnemyKill(string enemyName, string weaponName, string exp, bool isHeadShot, bool isFar = false) { base.OnEnemyKill(enemyName, weaponName, exp, isHeadShot, isFar); if (isHeadShot) { headshotStreak.AddKillStreak(); } else { killStreak.AddKillStreak(); } headshotStreak.ResetTimer(); killStreak.ResetTimer(); } } public class DamageSource : MonoBehaviour { public string damageType; public int damage; public TMP_Text message; private float timer; private GameObject placeholder; private void Start() { timer = 0f; message = ((Component)this).GetComponent(); } private void Update() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.position = Vector3.MoveTowards(((Component)this).transform.position, placeholder.transform.position, 200f * Time.deltaTime); timer += Time.deltaTime; if (timer > 5f) { Object.Destroy((Object)(object)placeholder); Object.Destroy((Object)(object)((Component)this).gameObject); } } public void InitMessage(string type, int damage, GameObject placeholder) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.localPosition = new Vector3(0f, 0f, 0f); ((Component)this).transform.position = placeholder.transform.position; damageType = type; this.damage = damage; message.text = damageType + " " + damage; this.placeholder = placeholder; Reset(); } public void Reset() { timer = 0f; message.text = damageType + " " + damage; } } public class KillStreakController : MonoBehaviour { public GameObject FirstStreak; public TMP_Text streakCounter; public GameObject iconPrefab; public GameObject container; private float timer; private int streakCount; private void Start() { streakCounter.text = ""; timer = 0f; } private void Update() { if (!Object.op_Implicit((Object)(object)FirstStreak)) { return; } timer += Time.deltaTime; if (timer > 6f) { StreakIcon[] componentsInChildren = container.GetComponentsInChildren(); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].Fade(); } timer = 0f; streakCount = 0; streakCounter.text = ""; } } public void ResetTimer() { timer = 0f; } public void AddKillStreak() { GameObject placeholder = GetPlaceholder(); LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)this).GetComponent()); GameObject val = Object.Instantiate(iconPrefab, container.transform, false); val.GetComponent().InitStrekIcon(placeholder, this); streakCount++; if (!Object.op_Implicit((Object)(object)FirstStreak)) { FirstStreak = val; } if (streakCount % 5 == 0) { ((Component)streakCounter).gameObject.SetActive(true); StreakIcon[] componentsInChildren = container.GetComponentsInChildren(); foreach (StreakIcon streakIcon in componentsInChildren) { if ((Object)(object)((Component)streakIcon).gameObject != (Object)(object)FirstStreak && !streakIcon.NeedDestroyWhenOnPosition) { streakIcon.TargetPosition = FirstStreak; streakIcon.NeedDestroyWhenOnPosition = true; } } streakCounter.text = "×" + streakCount; } timer = 0f; } protected virtual GameObject GetPlaceholder() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown GameObject val = new GameObject("Placeholder", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(((Component)this).transform); val.transform.SetAsFirstSibling(); val.GetComponent().sizeDelta = new Vector2(25f, 25f); return val; } } public class MessageController : PluginInstance { private GameObject banner; private TMP_Text tmpEnemyName; private TMP_Text tmpWeaponName; private TMP_Text tmpExp; private Animator bannerAnim; private bool isShowing; public AudioClip killSound; public AudioClip headShotKillSound; private AudioSource audioSource; private GameObject gameobjectTotalDamage; private TMP_Text tmpTotalDamage; private float timer; private int totalDamage; private int currentDamage; private GameObject damageInfoPlaceholder; private GameObject damageInfoContainer; private GameObject firstMessage; public GameObject damageSourcePrefab; internal PluginData.AttackFeedback data; protected override void Awake() { isShowing = false; InitBanner(); InitDamageInfo(); ResetDamageCounter(); base.Awake(); } protected virtual GameObject InitDamageInfo() { GameObject gameObject = ((Component)((Component)this).transform.Find("Damage")).gameObject; gameobjectTotalDamage = ((Component)gameObject.transform.Find("Total")).gameObject; tmpTotalDamage = gameobjectTotalDamage.GetComponent(); damageInfoPlaceholder = ((Component)gameObject.transform.Find("Placeholder")).gameObject; damageInfoContainer = ((Component)gameObject.transform.Find("Container")).gameObject; return gameObject; } protected virtual GameObject InitBanner() { banner = ((Component)((Component)this).transform.Find("Banner")).gameObject; tmpEnemyName = ((Component)FindChild(banner.transform, "Enemy")).GetComponent(); tmpWeaponName = ((Component)FindChild(banner.transform, "Weapon")).GetComponent(); tmpExp = ((Component)FindChild(banner.transform, "Exp")).GetComponent(); bannerAnim = banner.GetComponent(); audioSource = banner.GetComponent(); return banner; } protected virtual void Start() { data = DataManager.AttackFeedbackData; } protected void Update() { UpdateTotalDamage(); if (isShowing && (timer += Time.deltaTime) > 5f) { ResetDamageCounter(); HideMessage(); } } public virtual void OnEnemyKill(string enemyName, string weaponName, string exp, bool isHeadShot, bool isFar = false) { if (!TmpFontFixer.Resolved) { TmpFontFixer.Apply(((Component)this).gameObject); } tmpEnemyName.text = enemyName; tmpWeaponName.text = weaponName; tmpExp.text = exp; ((MonoBehaviour)this).StartCoroutine(ShowMessage()); PlayKillAudio(isHeadShot, isFar); } public void OnEnemyHit(string type, int damage) { if (!TmpFontFixer.Resolved) { TmpFontFixer.Apply(((Component)this).gameObject); } gameobjectTotalDamage.SetActive(true); totalDamage += damage; if ((Object)(object)firstMessage != (Object)null && (Object)(object)damageInfoContainer != (Object)null) { DamageSource[] componentsInChildren = damageInfoContainer.GetComponentsInChildren(); foreach (DamageSource damageSource in componentsInChildren) { if (damageSource.damageType == type) { damageSource.damage += damage; damageSource.Reset(); return; } } } AddDamageInfo(type, damage); } private static Transform FindChild(Transform parent, string name) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown foreach (Transform item in parent) { Transform val = item; if (((Object)val).name == name) { return val; } Transform val2 = FindChild(val, name); if ((Object)(object)val2 != (Object)null) { return val2; } } return null; } public void HideMessage() { isShowing = false; bannerAnim.SetTrigger("Fade"); } private void ResetDamageCounter() { gameobjectTotalDamage.SetActive(false); totalDamage = 0; currentDamage = 0; timer = 0f; } private IEnumerator ShowMessage() { if (!isShowing) { isShowing = true; bannerAnim.SetTrigger("Pop"); } yield return (object)new WaitForEndOfFrame(); Transform transform = banner.transform; LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((transform is RectTransform) ? transform : null)); } private void UpdateTotalDamage() { if (currentDamage < totalDamage) { timer = 0f; int num = Mathf.Max(1, (totalDamage - currentDamage) / 100); currentDamage += num; tmpTotalDamage.text = currentDamage.ToString(); } } protected virtual GameObject AddDamageInfo(string type, int damage) { GameObject placeholder = GetPlaceholder(); LayoutRebuilder.ForceRebuildLayoutImmediate(damageInfoPlaceholder.GetComponent()); firstMessage = GetDamageInfo(type, damage, placeholder); return firstMessage; } protected virtual GameObject GetPlaceholder() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown GameObject val = new GameObject("Placeholder", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(damageInfoPlaceholder.transform); val.transform.SetAsFirstSibling(); val.GetComponent().sizeDelta = new Vector2(25f, 25f); return val; } protected virtual GameObject GetDamageInfo(string type, int damage, GameObject placeholder) { GameObject obj = Object.Instantiate(damageSourcePrefab, damageInfoContainer.transform); TmpFontFixer.Apply(obj); obj.GetComponent().InitMessage(type, damage, placeholder); return obj; } protected virtual void PlayKillAudio(bool isHeadShot, bool isFar) { audioSource.PlayOneShot(isFar ? headShotKillSound : killSound, data.messageVolume); } } public class StreakIcon : MonoBehaviour { private Animator animator; private KillStreakController controller; private GameObject targetPosition; private bool needDestroyWhenOnPosition; public GameObject TargetPosition { get { if (!((Object)(object)targetPosition == (Object)null)) { return targetPosition; } return controller.FirstStreak; } set { if (Object.op_Implicit((Object)(object)targetPosition)) { Object.Destroy((Object)(object)targetPosition); } targetPosition = value; } } public bool NeedDestroyWhenOnPosition { get { return needDestroyWhenOnPosition; } set { if (value) { needDestroyWhenOnPosition = value; ((MonoBehaviour)this).StartCoroutine(DestroyWhenOnPosition()); } } } private void Start() { animator = ((Component)this).GetComponent(); } private void Update() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)TargetPosition)) { ((Component)this).transform.position = Vector3.MoveTowards(((Component)this).transform.position, TargetPosition.transform.position, 200f * Time.deltaTime); } } public void InitStrekIcon(GameObject placeholder, KillStreakController controller) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.localPosition = new Vector3(0f, 0f, 0f); ((Component)this).transform.position = placeholder.transform.position; targetPosition = placeholder; needDestroyWhenOnPosition = false; this.controller = controller; } public void Destroy(float delay = 0f) { Object.Destroy((Object)(object)targetPosition.gameObject, delay); Object.Destroy((Object)(object)((Component)this).gameObject, delay); } private IEnumerator DestroyWhenOnPosition() { while (((Component)this).transform.position != targetPosition.transform.position) { yield return (object)new WaitForEndOfFrame(); } Object.Destroy((Object)(object)((Component)this).gameObject); } public void Fade() { animator.SetTrigger("Fade"); Destroy(0.25f); } } public class xCrossHair : PluginInstance { public Animator crossHairAnim; private PluginData.AttackFeedback data; private Image[] images; private void Start() { data = DataManager.AttackFeedbackData; images = ((Component)this).GetComponentsInChildren(); } public void StartTrigger(string type) { if (!(type == "Hit")) { if (type == "Kill") { KillTrigger(); } } else { HitTrigger(); } } private void HitTrigger() { crossHairAnim.SetTrigger("Hit"); SetHitColor(); } private void KillTrigger() { crossHairAnim.SetTrigger("Kill"); SetKillColor(); } private void SetHitColor() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) Image[] array = images; for (int i = 0; i < array.Length; i++) { ((Graphic)array[i]).color = data.hitColor; } } private void SetKillColor() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) Image[] array = images; for (int i = 0; i < array.Length; i++) { ((Graphic)array[i]).color = data.killColor; } } } public class LootDropVFX : MonoBehaviour { public ParticleSystem[] systems; private GameObject parentObject; private bool isScaling; private void Start() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.localPosition = new Vector3(0f, 0.1f, 0f); ((Component)this).transform.localScale = new Vector3(1f, 1f, 1f); ParticleSystem[] array = systems; foreach (ParticleSystem obj in array) { _ = parentObject.transform.localScale; ((Component)obj).transform.localScale = new Vector3(0.4f, 0.4f, 0.4f); } isScaling = true; ((MonoBehaviour)this).StartCoroutine(StopScale()); } private void Update() { bool mouseButton = InputCompat.GetMouseButton(1); ParticleSystem[] array = systems; for (int i = 0; i < array.Length; i++) { ((Component)array[i]).gameObject.SetActive(!mouseButton); } _ = isScaling; } private IEnumerator StopScale() { yield return (object)new WaitForSeconds(3f); isScaling = false; } public void SetParent(GameObject parent) { parentObject = parent; } } namespace BattleImprove { [BepInPlugin("BattleImprove", "Battle Improvements", "1.5.2")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; internal static Harmony Harmony; internal static LocalizationManager i18n; private static bool debugMode; internal static GameObject PluginGameObject; internal static GameObject IndicatorGameObject; internal static bool NeedUpdate => UpdateChecker.CheckForUpdate(); public void Awake() { ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Plugin BattleImprove 1.5.2 is loading!"); Config.InitConfig(((BaseUnityPlugin)this).Config); Patching(); ((MonoBehaviour)this).StartCoroutine(PrefabManager.LoadAssetBundle()); Logger.LogInfo((object)"Plugin BattleImprove is loaded!"); ((MonoBehaviour)this).StartCoroutine(InitPluginGameobject()); } private IEnumerator InitPluginGameobject() { while (!SulfurSave.Imp.initialized || !PrefabManager.IsLoaded) { LoggingInfo("Waiting for game to load..."); yield return (object)new WaitForSeconds(1f); } LoggingInfo("Starting plugin initialization..."); LoggingInfo("Loading localization..."); i18n = new LocalizationManager(); i18n.LoadLocalization(Application.systemLanguage); LoggingInfo("Initializing plugin gameobject..."); GameObject val = GameObject.Find("CmPlugin"); if ((Object)(object)val == (Object)null) { PluginGameObject = new GameObject("CmPlugin"); Object.DontDestroyOnLoad((Object)(object)PluginGameObject); } else { PluginGameObject = val; } LoggingInfo("Loading plugin data..."); DataManager.SetUpData(); LoggingInfo("Loading plugin prefab..."); PrefabManager.LoadAttackFeedbackPrefab(); LoggingInfo("Loading other gameobject..."); PluginGameObject.AddComponent(); GameObject val2 = new GameObject("Menu"); val2.transform.parent = PluginGameObject.transform; val2.AddComponent(); } private void OnDestroy() { Harmony.UnpatchSelf(); } private void Patching() { LoggingInfo("Patching...", needDebug: true); Harmony = Harmony.CreateAndPatchAll(typeof(AttackFeedbackPatch), (string)null); Harmony.PatchAll(typeof(DataManager)); if (Config.EnableExpShare.Value) { Harmony.PatchAll(typeof(ExpSharePatch)); } if (Config.EnableHealthBar.Value) { Harmony.PatchAll(typeof(HealthBarPatch)); } if (Config.EnableLoopDropVFX.Value) { Harmony.PatchAll(typeof(LootDropPatch)); } if (Config.EnableDeadUnitCollision.Value) { Harmony.PatchAll(typeof(RemoveDeadBodyCollisionTranspiler)); } if (Config.EnableDeadProtection.Value) { Harmony.PatchAll(typeof(DeadProtection)); } if (Config.ReverseMouseScroll.Value) { Harmony.PatchAll(typeof(MouseScrollTranspiler)); } if (Config.EnableSoundFeedback.Value) { Harmony.PatchAll(typeof(SoundPatch)); } if (Config.EnableDamageMessage.Value) { Harmony.PatchAll(typeof(DamageInfoPatch)); Harmony.PatchAll(typeof(KillMessagePatch)); } if (Config.EnableXCrossHair.Value) { Harmony.PatchAll(typeof(CrossHairPatch)); } LoggingInfo("Patching complete!"); } public static void LoggingInfo(string info, bool needDebug = false) { if (needDebug) { if (debugMode) { Logger.LogInfo((object)("Debug info: " + info)); } } else { Logger.LogInfo((object)info); } } } public class Config { internal static ConfigEntry EnableHealthBar; internal static ConfigEntry EnableExpShare; internal static ConfigEntry EnableSoundFeedback; internal static ConfigEntry EnableDeadUnitCollision; internal static ConfigEntry EnableXCrossHair; internal static ConfigEntry EnableDamageMessage; internal static ConfigEntry EnableLoopDropVFX; internal static ConfigEntry EnableDeadProtection; internal static ConfigEntry ReverseMouseScroll; internal static ConfigEntry Proportion; public static void InitConfig(ConfigFile cfg) { Plugin.LoggingInfo("Loading Config..."); ToggleConfigInit(cfg); ExpShareConfigInit(cfg); OtherConfigInit(cfg); Plugin.LoggingInfo("Config Loaded."); } private static void ToggleConfigInit(ConfigFile cfg) { EnableExpShare = cfg.Bind("Toggle/开关", "EnableExpShare", true, "Enable experience share/是否开启经验共享"); EnableHealthBar = cfg.Bind("Toggle/开关", "EnableHealthBar", true, "Enable health bar/是否开启血条"); EnableXCrossHair = cfg.Bind("Toggle/开关", "EnableHitFeedback", true, "Enable xCrossHair feedback/是否开启击中准心反馈"); EnableSoundFeedback = cfg.Bind("Toggle/开关", "EnableSoundFeedback", true, "Enable hit sound feedback on enemies/是否开启敌人受击声音反馈"); EnableDamageMessage = cfg.Bind("Toggle/开关", "EnableDamageMessage", true, "Enable damage and kill message/是否开启伤害与击杀信息"); EnableDeadUnitCollision = cfg.Bind("Toggle/开关", "EnableDeadUnitCollision", true, "Allowing bullets to pass through deadbody/是否使子弹能穿过尸体"); EnableLoopDropVFX = cfg.Bind("Toggle/开关", "EnableLoopDropVFX", true, "Enable loot drop VFX/是否开启掉落特效"); EnableDeadProtection = cfg.Bind("Toggle/开关", "EnableDeadProtection", true, "Enable dead protection/是否开启死亡保护"); } private static void ExpShareConfigInit(ConfigFile cfg) { Proportion = cfg.Bind("ExpShare/经验共享", "Proportion", 0.5f, "The proportion of experience shared to second weapon/共享给第二把武器的经验比例"); } private static void OtherConfigInit(ConfigFile cfg) { ReverseMouseScroll = cfg.Bind("Other/其他", "ReverseMouseScroll", true, "Reverse mouse scroll direction/反转鼠标滚轮方向"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "BattleImprove"; public const string PLUGIN_NAME = "Battle Improvements"; public const string PLUGIN_VERSION = "1.5.2"; } } namespace BattleImprove.Utils { [HarmonyPatch] public static class DataManager { public static PluginData.Version VersionData; public static PluginData.AttackFeedback AttackFeedbackData; public static PluginData.DeadProtection DeadProtectionData; public static Dictionary KillMessageStyle = new Dictionary { { 0, "Battlefield 1" }, { 1, "Battlefield 5" } }; public static void SetUpData() { SaveManager.LoadSaveFile(); } public static void SaveAllData() { SaveVersionData(); SaveAttackMessageData(); SaveDeadProtectionData(); } public static void SaveVersionData(bool reset = false) { SaveManager.SaveVersionData(); } public static void SaveAttackMessageData(bool reset = false) { SaveManager.SaveAttackMessageData(); } public static void SaveDeadProtectionData(bool reset = false) { if (reset) { DeadProtectionData.opened = false; } if (DeadProtectionData.opened) { DeadProtectionData.weapons.Clear(); } SaveManager.SaveDeadProtectionData(); } [HarmonyPostfix] [HarmonyPatch(typeof(PauseMenu), "ExitAction")] [HarmonyPatch(typeof(GameManager), "PlayerDied")] private static void ExitActionPostfix() { SaveAllData(); } } public static class InputCompat { public static bool GetKeyDown(KeyCode keyCode) { //IL_000b: 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) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; if (current == null) { return false; } Key val = Map(keyCode); if ((int)val == 0) { return false; } KeyControl val2 = current[val]; if (val2 != null) { return ((ButtonControl)val2).wasPressedThisFrame; } return false; } public static bool GetMouseButton(int button) { Mouse current = Mouse.current; if (current == null) { return false; } return button switch { 0 => current.leftButton.isPressed, 1 => current.rightButton.isPressed, 2 => current.middleButton.isPressed, _ => false, }; } private static Key Map(KeyCode k) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Expected I4, but got Unknown //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Invalid comparison between Unknown and I4 //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Expected I4, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 if ((int)k <= 13) { if ((int)k == 8) { return (Key)65; } if ((int)k == 9) { return (Key)3; } if ((int)k == 13) { return (Key)2; } } else { switch (k - 27) { default: if ((int)k != 127) { switch (k - 256) { case 26: return (Key)94; case 27: return (Key)95; case 28: return (Key)96; case 29: return (Key)97; case 30: return (Key)98; case 31: return (Key)99; case 32: return (Key)100; case 33: return (Key)101; case 34: return (Key)102; case 35: return (Key)103; case 36: return (Key)104; case 37: return (Key)105; case 21: return (Key)70; case 22: return (Key)68; case 23: return (Key)69; case 24: return (Key)67; case 25: return (Key)66; case 17: return (Key)63; case 18: return (Key)64; case 20: return (Key)61; case 19: return (Key)62; case 45: return (Key)72; case 48: return (Key)51; case 47: return (Key)52; case 50: return (Key)55; case 49: return (Key)56; case 52: return (Key)53; case 51: return (Key)54; case 0: return (Key)84; case 1: return (Key)85; case 2: return (Key)86; case 3: return (Key)87; case 4: return (Key)88; case 5: return (Key)89; case 6: return (Key)90; case 7: return (Key)91; case 8: return (Key)92; case 9: return (Key)93; case 15: return (Key)77; case 14: return (Key)80; case 13: return (Key)81; case 12: return (Key)79; case 11: return (Key)78; case 10: return (Key)82; } break; } return (Key)71; case 70: return (Key)15; case 71: return (Key)16; case 72: return (Key)17; case 73: return (Key)18; case 74: return (Key)19; case 75: return (Key)20; case 76: return (Key)21; case 77: return (Key)22; case 78: return (Key)23; case 79: return (Key)24; case 80: return (Key)25; case 81: return (Key)26; case 82: return (Key)27; case 83: return (Key)28; case 84: return (Key)29; case 85: return (Key)30; case 86: return (Key)31; case 87: return (Key)32; case 88: return (Key)33; case 89: return (Key)34; case 90: return (Key)35; case 91: return (Key)36; case 92: return (Key)37; case 93: return (Key)38; case 94: return (Key)39; case 95: return (Key)40; case 21: return (Key)50; case 22: return (Key)41; case 23: return (Key)42; case 24: return (Key)43; case 25: return (Key)44; case 26: return (Key)45; case 27: return (Key)46; case 28: return (Key)47; case 29: return (Key)48; case 30: return (Key)49; case 5: return (Key)1; case 0: return (Key)60; case 18: return (Key)13; case 34: return (Key)14; case 64: return (Key)11; case 66: return (Key)12; case 65: return (Key)10; case 32: return (Key)6; case 12: return (Key)5; case 69: return (Key)4; case 17: return (Key)7; case 19: return (Key)8; case 20: return (Key)9; case 1: case 2: case 3: case 4: case 6: case 7: case 8: case 9: case 10: case 11: case 13: case 14: case 15: case 16: case 31: case 33: case 35: case 36: case 37: case 38: case 39: case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63: case 67: case 68: break; } } return (Key)0; } } public class LocalizationManager { public enum SupportedLanguages { English, ChineseSimplified } private static Dictionary localizationText = new Dictionary(); private static SystemLanguage currentLanguage; public unsafe void LoadLocalization(SystemLanguage language) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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) if (Enum.GetNames(typeof(SupportedLanguages)).Contains(((object)(*(SystemLanguage*)(&language))/*cast due to .constrained prefix*/).ToString())) { currentLanguage = language; } else { currentLanguage = (SystemLanguage)10; } localizationText.Clear(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = $"BattleImprove.Lang.{currentLanguage}.lang"; using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { Debug.LogError((object)("Failed to load localization file: " + text)); return; } using StreamReader streamReader = new StreamReader(stream); string[] array = streamReader.ReadToEnd().Split('\n'); foreach (string text2 in array) { if (!string.IsNullOrWhiteSpace(text2) && !text2.StartsWith("#")) { string[] array2 = text2.Split('=', 2); if (array2.Length == 2) { localizationText[array2[0].Trim()] = array2[1].Trim(); } } } } public string GetText(string key) { if (!localizationText.ContainsKey(key)) { return key; } return localizationText[key]; } } [Serializable] public class PluginData { public class Version : PluginData { public KeyCode menuKey = (KeyCode)282; public string version => "1.5.2"; } public class AttackFeedback : PluginData { public float indicatorVolume = 0.5f; public float indicatorDistance = 0.5f; public float indicatorDistanceFar = 0.5f; public float indicatorDistanceHeadShoot = 0.5f; public Color hitColor = Color.white; public Color killColor = Color.red; public int messageStyle; public float messageVolume = 0.5f; } public class DeadProtection : PluginData { public bool opened; public List weapons = new List(); public float weaponDurability = 0.3f; public float attachmentChance = 0.3f; public float enchantmentChance = 0.3f; public float barrelChance = 0.3f; } } public abstract class PluginInstance : MonoBehaviour where T : MonoBehaviour { public static T Instance; protected virtual void Awake() { Instance = (T)(object)((this is T) ? this : null); Plugin.LoggingInfo("PluginInstance<" + typeof(T).Name + "> initialized."); } protected virtual void OnDestroy() { Object.Destroy((Object)(object)((Component)this).gameObject); } } public static class PrefabManager { internal static AssetBundle AssetBundle; public static Dictionary Prefabs = new Dictionary(); public static bool IsLoaded; public static IEnumerator LoadAssetBundle() { IsLoaded = false; Plugin.LoggingInfo("Loading Asset Bundle...", needDebug: true); AssetBundle = AssetBundle.LoadFromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("BattleImprove.Assets.battle_improve")); if ((Object)(object)AssetBundle == (Object)null) { Plugin.LoggingInfo("Failed to load custom assets."); } else { AssetBundleRequest request = AssetBundle.LoadAssetAsync("AttackFeedback"); yield return request; Dictionary prefabs = Prefabs; Object asset = request.asset; prefabs.Add("AttackFeedback", (GameObject)(object)((asset is GameObject) ? asset : null)); foreach (string style in DataManager.KillMessageStyle.Values) { request = AssetBundle.LoadAssetAsync(style); yield return request; Dictionary prefabs2 = Prefabs; Object asset2 = request.asset; prefabs2.Add(style, (GameObject)(object)((asset2 is GameObject) ? asset2 : null)); } for (int i = 1; i <= 5; i++) { request = AssetBundle.LoadAssetAsync("LoopDropTier" + i); yield return request; Dictionary prefabs3 = Prefabs; string key = "LoopDropTier" + i; Object asset3 = request.asset; prefabs3.Add(key, (GameObject)(object)((asset3 is GameObject) ? asset3 : null)); } } Plugin.LoggingInfo("Asset Bundle loaded!", needDebug: true); IsLoaded = true; } public static GameObject LoadPrefab(string name, GameObject parent) { Plugin.LoggingInfo("Loading " + name + " Prefab...", needDebug: true); return Object.Instantiate(Prefabs[name], parent.transform, true); } internal static void LoadAttackFeedbackPrefab() { Plugin.IndicatorGameObject = LoadPrefab("AttackFeedback", Plugin.PluginGameObject); TmpFontFixer.Apply(Plugin.IndicatorGameObject); LoadKillMessageStyle(DataManager.KillMessageStyle[DataManager.AttackFeedbackData.messageStyle]); } internal static void LoadKillMessageStyle(string style = "Battlefield 1") { if ((Object)(object)PluginInstance.Instance != (Object)null) { Object.Destroy((Object)(object)((Component)PluginInstance.Instance).gameObject); } TmpFontFixer.Apply(LoadPrefab(style, Plugin.IndicatorGameObject)); } } public static class SaveManager { public const string SaveFileName = "BattleImproveSaveData"; public static void LoadSaveFile() { try { SulfurSaveBase imp = SulfurSave.Imp; if (((imp != null) ? imp.saveSettings : null) != null && ES3.KeyExists("CmPlugin", SulfurSave.Imp.saveSettings)) { TransferSaveData(); } } catch (Exception ex) { Plugin.LoggingInfo("Vanilla-save migration check skipped: " + ex.Message); } try { if (ES3.FileExists("BattleImproveSaveData")) { LoadAll(); return; } Plugin.LoggingInfo("Save data not found, creating new one..."); LoadDefaults(); Plugin.LoggingInfo("Save data created!"); } catch (Exception value) { Console.WriteLine(value); Plugin.LoggingInfo("Failed to load save data, creating new one..."); LoadDefaults(); } } private static void LoadAll() { LoadVersionData(); LoadAttackMessageData(); LoadDeadProtectionData(); } private static void LoadDeadProtectionData() { DataManager.DeadProtectionData = ES3.Load("DeadProtection", "BattleImproveSaveData", new PluginData.DeadProtection()); } private static void LoadAttackMessageData() { DataManager.AttackFeedbackData = ES3.Load("AttackFeedback", "BattleImproveSaveData", new PluginData.AttackFeedback()); } private static void LoadVersionData() { DataManager.VersionData = ES3.Load("Version", "BattleImproveSaveData", new PluginData.Version()); } public static void SaveAll() { SaveVersionData(); SaveAttackMessageData(); SaveDeadProtectionData(); } public static void SaveVersionData() { ES3.Save("Version", DataManager.VersionData, "BattleImproveSaveData"); } public static void SaveAttackMessageData() { ES3.Save("AttackFeedback", DataManager.AttackFeedbackData, "BattleImproveSaveData"); } public static void SaveDeadProtectionData(bool reset = false) { ES3.Save("DeadProtection", DataManager.DeadProtectionData, "BattleImproveSaveData"); } private static void TransferSaveData() { Plugin.LoggingInfo("Save data found in the vanilla save file, transfers it to the new file..."); Dictionary dictionary = SulfurSave.Imp.Load>("CmPlugin", new Dictionary()); ES3.DeleteKey("CmPlugin", SulfurSave.Imp.saveSettings); PluginData.Version version = dictionary["BattleImprove"] as PluginData.Version; Traverse.IterateFields((object)version, (Action)RoundUp); ES3.Save("BattleImprove", version, "BattleImproveSaveData"); PluginData.AttackFeedback attackFeedback = dictionary["AttackFeedback"] as PluginData.AttackFeedback; Traverse.IterateFields((object)attackFeedback, (Action)RoundUp); ES3.Save("AttackFeedback", attackFeedback, "BattleImproveSaveData"); PluginData.DeadProtection deadProtection = dictionary["DeadProtection"] as PluginData.DeadProtection; Traverse.IterateFields((object)deadProtection, (Action)RoundUp); ES3.Save("DeadProtection", deadProtection, "BattleImproveSaveData"); } private static void RoundUp(Traverse traverse) { if (traverse.GetValue() is float x) { traverse.SetValue((object)MathF.Round(x, 2)); } } private static void LoadDefaults() { ES3.Save("BattleImprove", new PluginData.Version(), "BattleImproveSaveData"); ES3.Save("AttackFeedback", new PluginData.AttackFeedback(), "BattleImproveSaveData"); ES3.Save("DeadProtection", new PluginData.DeadProtection(), "BattleImproveSaveData"); LoadAll(); } } public static class TmpFontFixer { private static TMP_FontAsset _gameFont; private static readonly char[] CjkProbe = new char[5] { '号', '击', '杀', '测', '的' }; public static bool Resolved { get; private set; } public static void Apply(GameObject root) { if ((Object)(object)root == (Object)null) { return; } TMP_FontAsset val = ResolveGameFont(); if ((Object)(object)val == (Object)null) { return; } TMP_Text[] componentsInChildren = root.GetComponentsInChildren(true); foreach (TMP_Text val2 in componentsInChildren) { try { if (!((Object)(object)val2.font == (Object)(object)val)) { val2.font = val; ((Graphic)val2).SetAllDirty(); } } catch (Exception ex) { Plugin.LoggingInfo("TmpFontFixer: failed on a text element: " + ex.Message); } } } private static TMP_FontAsset ResolveGameFont() { if (Resolved && (Object)(object)_gameFont != (Object)null) { return _gameFont; } TMP_Text[] array = Object.FindObjectsOfType(); foreach (TMP_Text val in array) { TMP_FontAsset f = (((Object)(object)val != (Object)null) ? val.font : null); if (IsUsable(f) && CoversCjk(f)) { return Lock(f); } } TMP_FontAsset[] array2 = Resources.FindObjectsOfTypeAll(); foreach (TMP_FontAsset f2 in array2) { if (IsUsable(f2) && CoversCjk(f2)) { return Lock(f2); } } if ((Object)(object)_gameFont == (Object)null) { array = Object.FindObjectsOfType(); foreach (TMP_Text val2 in array) { TMP_FontAsset val3 = (((Object)(object)val2 != (Object)null) ? val2.font : null); if (IsUsable(val3)) { _gameFont = val3; break; } } if ((Object)(object)_gameFont == (Object)null) { _gameFont = TMP_Settings.defaultFontAsset; } Plugin.LoggingInfo("TmpFontFixer: provisional font '" + Name(_gameFont) + "' (CJK not found yet, will retry).", needDebug: true); } return _gameFont; } private static TMP_FontAsset Lock(TMP_FontAsset f) { _gameFont = f; Resolved = true; Plugin.LoggingInfo("TmpFontFixer: locked game font '" + Name(f) + "'.", needDebug: true); return f; } private static bool IsUsable(TMP_FontAsset f) { if ((Object)(object)f != (Object)null && (Object)(object)((TMP_Asset)f).material != (Object)null) { return (Object)(object)f.atlasTexture != (Object)null; } return false; } private static bool CoversCjk(TMP_FontAsset f) { char[] cjkProbe = CjkProbe; foreach (char c in cjkProbe) { if (f.HasCharacter(c, false, false)) { return true; } } return false; } private static string Name(TMP_FontAsset f) { if (!((Object)(object)f != (Object)null)) { return ""; } return ((Object)f).name; } } public class UpdateChecker { private const string UPDATE_URL = "https://api.github.com/repos/CmmmmmmLau/SulFur_Battle_improvement/releases/latest"; public static bool CheckForUpdate() { using WebClient webClient = new WebClient(); webClient.Headers.Add("User-Agent", "UnityModUpdater"); try { string json = webClient.DownloadString("https://api.github.com/repos/CmmmmmmLau/SulFur_Battle_improvement/releases/latest"); string current = "1.5.2"; string text = ExtractVersionFromJson(json); if (CheckUpdate(current, text)) { Plugin.Logger.LogInfo((object)("New version available: " + text)); return true; } Plugin.Logger.LogInfo((object)"No new version available."); return false; } catch (WebException ex) { Plugin.Logger.LogError((object)("Failed to check for update: " + ex.Message)); return false; } } private static bool CheckUpdate(string current, string latest) { Version version = new Version(current); return new Version(latest) > version; } private static string ExtractVersionFromJson(string json) { int num = json.IndexOf("\"tag_name\":\"") + 12; int num2 = json.IndexOf("\",", num); return json.Substring(num, num2 - num).Replace("v", ""); } } } namespace BattleImprove.UI.InGame { public class WindowAttackFeedback : WindowBase { private PluginData.AttackFeedback data; private WLabel label; private string resourcePack { get { if (!((Object)(object)Plugin.IndicatorGameObject == (Object)null)) { return i18n.GetText("AttackFeedback.resource.loaded"); } return i18n.GetText("AttackFeedback.resource.missed"); } } protected override void Init() { //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) data = DataManager.AttackFeedbackData; window = UWindow.Begin("Attack Feedback", 200f, 10f, 22f, 5f, true, true, true); UWindow obj = window; obj.Width += 50f; StartPosition(310, 100); label = window.Label(i18n.GetText("AttackFeedback.resource") + ":" + resourcePack); window.Button("Reload", (Action)ReloadPrefab); window.Space(); window.Label(i18n.GetText("AttackFeedback.indicator")); window.Slider(i18n.GetText("AttackFeedback.volume"), (Action)SetIndicatorVolume, data.indicatorVolume, 0f, 1f, true, "0.##"); window.Slider(i18n.GetText("AttackFeedback.distance"), (Action)SetIndicatorDistance, data.indicatorDistance, 0f, 1f, true, "0.##"); window.Slider(i18n.GetText("AttackFeedback.distance.far"), (Action)SetIndicatorDistanceFar, data.indicatorDistanceFar, 0f, 1f, true, "0.##"); window.Slider(i18n.GetText("AttackFeedback.distance.headshot"), (Action)SetIndicatorDistanceHeadshoot, data.indicatorDistanceHeadShoot, 0f, 1f, true, "0.##"); window.Space(); window.Label(i18n.GetText("AttackFeedback.cross")); window.ColorPicker(i18n.GetText("AttackFeedback.hitcolor"), (Action)SetHitColor, data.hitColor); window.ColorPicker(i18n.GetText("AttackFeedback.killcolor"), (Action)SetChangeKillColor, data.killColor); window.Space(); window.Label(i18n.GetText("AttackFeedback.message")); window.DropDown(i18n.GetText("AttackFeedback.style"), (Action)SetKillMessageStyle, data.messageStyle, DataManager.KillMessageStyle); window.Slider(i18n.GetText("AttackFeedback.volume"), (Action)SetKillMessageVolume, data.messageVolume, 0f, 1f, true, "0.##"); window.Button(i18n.GetText("AttackFeedback.test"), (Action)TestKillMessage); window.Space(); base.Init(); } private void ReloadPrefab() { if ((Object)(object)Plugin.IndicatorGameObject == (Object)null) { PrefabManager.LoadAttackFeedbackPrefab(); } FieldInfo field = typeof(WLabel).GetField("DisplayedString", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(label, i18n.GetText("AttackFeedback.resource") + ":" + resourcePack); } } private void SetIndicatorVolume(float value) { data.indicatorVolume = MathF.Round(value, 2); } private void SetIndicatorDistance(float value) { data.indicatorDistance = MathF.Round(value, 2); } private void SetIndicatorDistanceFar(float value) { data.indicatorDistanceFar = MathF.Round(value, 2); } private void SetIndicatorDistanceHeadshoot(float value) { data.indicatorDistanceHeadShoot = MathF.Round(value, 2); } private void SetHitColor(Color color) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) data.hitColor = color; } private void SetChangeKillColor(Color color) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) data.killColor = color; } private void SetKillMessageStyle(int value) { data.messageStyle = value; PrefabManager.LoadKillMessageStyle(DataManager.KillMessageStyle[value]); } private void SetKillMessageVolume(float value) { data.messageVolume = MathF.Round(value, 2); } private void TestKillMessage() { PluginInstance.Instance.OnEnemyKill("Enemy Name#" + Random.Range(0, 10), "Weapon Name#" + Random.Range(0, 10), Random.Range(0, 10).ToString(), Random.Range(0, 10) < 5, Random.Range(0, 10) < 5); PluginInstance.Instance.OnEnemyHit("Bullet Damage Type#" + Random.Range(0, 10), Random.Range(0, 100)); } } public class WindowBase : MonoBehaviour { public UWindow window; internal MenuController controller; protected LocalizationManager i18n = Plugin.i18n; protected virtual void Start() { Init(); } public void Destroy() { Object.Destroy((Object)(object)this); } public virtual void Toggle() { window.IsDrawing = !window.IsDrawing; } internal WindowBase StartPosition(int x, int y) { window.X = x; window.Y = y; return this; } internal WindowBase SetController(MenuController controller) { this.controller = controller; return this; } protected virtual void Init() { window.Space(); window.Button("Close", (Action)Close); window.IsDrawing = false; } protected virtual void Close() { controller.SaveData(); window.IsDrawing = false; } } public class WindowDeadProtection : WindowBase { private PluginData.DeadProtection data; protected override void Init() { data = DataManager.DeadProtectionData; window = UWindow.Begin("Dead Protection", 200f, 10f, 22f, 5f, true, true, true); UWindow obj = window; obj.Width += 50f; StartPosition(310, 100); window.Label(i18n.GetText("DeadProtection.durability")); window.Slider("", (Action)OnDurabilityChange, data.weaponDurability, 0f, 1f, true, "0.##"); window.Label(i18n.GetText("DeadProtection.barrel")); window.Slider("", (Action)OnBarrelChange, data.barrelChance, 0f, 1f, true, "0.##"); window.Label(i18n.GetText("DeadProtection.attachment")); window.Slider("", (Action)OnAttachmentChange, data.attachmentChance, 0f, 1f, true, "0.##"); window.Label(i18n.GetText("DeadProtection.enchantment")); window.Slider("", (Action)OnEnchantmentChange, data.enchantmentChance, 0f, 1f, true, "0.##"); base.Init(); } private void OnDurabilityChange(float value) { data.weaponDurability = MathF.Round(value, 2); } private void OnAttachmentChange(float value) { data.attachmentChance = MathF.Round(value, 2); } private void OnEnchantmentChange(float value) { data.enchantmentChance = MathF.Round(value, 2); } private void OnBarrelChange(float value) { data.barrelChance = MathF.Round(value, 2); } } public class WindowHotkey : WindowBase { private WLabel label; private bool needInput; private KeyCode key; protected override void Init() { window = UWindow.Begin(i18n.GetText("Hotkey.title"), 200f, 10f, 22f, 5f, true, true, true); PluginData.Version versionData = DataManager.VersionData; label = window.Label(i18n.GetText("Hotkey.current") + " " + ((object)Unsafe.As(ref versionData.menuKey)/*cast due to .constrained prefix*/).ToString()); StartPosition(350, 350); base.Init(); } public override void Toggle() { base.Toggle(); needInput = window.IsDrawing; } private void Update() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (!needInput) { return; } Event current = Event.current; if (current.isKey) { key = current.keyCode; FieldInfo field = typeof(WLabel).GetField("DisplayedString", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(label, i18n.GetText("Hotkey.current") + " " + ((object)Unsafe.As(ref key)/*cast due to .constrained prefix*/).ToString()); } } } protected override void Close() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) DataManager.VersionData.menuKey = (KeyCode)(((int)key == 0) ? 282 : ((int)key)); DataManager.SaveAllData(); base.Close(); } } public class WindowMenu : WindowBase { protected override void Init() { window = UWindow.Begin("Battle Improvement", 200f, 10f, 22f, 5f, true, true, true); StartPosition(100, 100); window.Button(i18n.GetText("AttackFeedback"), (Action)delegate { OpenSubMenu("AttackFeedback"); }); window.Button(i18n.GetText("DeadProtection"), (Action)delegate { OpenSubMenu("DeadProtection"); }); window.Button(i18n.GetText("Settings"), (Action)delegate { OpenSubMenu("Setting"); }); base.Init(); } protected override void Close() { base.Close(); controller.CloseSubWindow(); controller.Pause(state: false); } private void OpenSubMenu(string name) { controller.OpenSubWindow(name); } } public class WindowSetting : WindowBase { protected override void Init() { window = UWindow.Begin(i18n.GetText("Settings"), 200f, 10f, 22f, 5f, true, true, true); UWindow obj = window; obj.Width += 50f; StartPosition(310, 100); window.Button(i18n.GetText("Reset"), (Action)Reset); window.Button(i18n.GetText("Hotkey"), (Action)ChangeMenuKey); base.Init(); } private void Reset() { controller.ResetWindow(); } private void ChangeMenuKey() { controller.OpenSubWindow("Hotkey", closeCurrent: false); } } public class WindowUpdateCheck : WindowBase { protected override void Start() { if (Plugin.NeedUpdate) { Init(); } else { Object.Destroy((Object)(object)this); } } protected override void Init() { window = UWindow.Begin("Update Check", 200f, 10f, 22f, 5f, true, true, true); StartPosition(0, 0); window.Space(); window.Label(Plugin.i18n.GetText("NeedUpdate")); window.Label(Plugin.i18n.GetText("NeedUpdate.Current") + "1.5.2"); window.Label(Plugin.i18n.GetText("NeedUpdate.Text")); base.Init(); window.IsDrawing = true; ((MonoBehaviour)this).StartCoroutine(AutoClose()); } private IEnumerator AutoClose() { yield return (object)new WaitForSeconds(5f); Close(); Destroy(); } } } namespace BattleImprove.Transpiler { public class MouseScrollTranspiler { [HarmonyTranspiler] [HarmonyPatch(typeof(InputReader), "SelectByScroll")] private static IEnumerable ProjectileTranspiler(IEnumerable instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((Func)((CodeInstruction i) => i.opcode == OpCodes.Ble_Un_S || i.opcode == OpCodes.Ble_Un), (string)null) }); if (val.IsValid) { val.Instruction.opcode = OpCodes.Bge_Un_S; Plugin.LoggingInfo("MouseScrollTranspiler: reversed scroll comparison branch.", needDebug: true); } else { Plugin.LoggingInfo("MouseScrollTranspiler: could not find scroll comparison branch to reverse."); } return val.InstructionEnumeration(); } } public class RemoveDeadBodyCollisionTranspiler { [HarmonyWrapSafe] [HarmonyPostfix] [HarmonyPatch(typeof(Npc), "Die")] private static void DisableCorpseCollider(Npc __instance) { if ((Object)(object)__instance.hitmeshCollider != (Object)null) { __instance.hitmeshCollider.enabled = false; Plugin.LoggingInfo("Disabled corpse hit collider so bullets pass through.", needDebug: true); } } } } namespace BattleImprove.Patcher.TakeHitPatcher { public class AttackFeedbackPatch { internal static Npc[] Enemies; internal static List KilledEnemies; [HarmonyWrapSafe] [HarmonyPostfix] [HarmonyPatch(typeof(InputReader), "LoadingContinue")] private static void ResetList() { Enemies = (from npc in StaticInstance.Instance.GetAllNpcs(false) where ((Unit)npc).IsHostileTo(StaticInstance.Instance.PlayerUnit) select npc).ToArray(); KilledEnemies = new List(); } protected static bool TargetCheck(DamageSourceData source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)source.sourceUnit != (Object)null) { return source.sourceUnit.isPlayer; } return false; } } [HarmonyWrapSafe] [HarmonyPatch(typeof(Npc), "ReceiveDamage", new Type[] { typeof(float), typeof(DamageTypes), typeof(DamageSourceData), typeof(Data), typeof(Vector3?) })] public class CrossHairPatch : AttackFeedbackPatch { private static void Prefix(Npc __instance, out bool __state) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 UnitState unitState = ((Unit)__instance).UnitState; bool flag = unitState - 1 <= 1; __state = flag; } private static void Postfix(Npc __instance, ref DamageSourceData source, bool __state) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)PluginInstance.Instance == (Object)null) && AttackFeedbackPatch.TargetCheck(source) && __state) { PlayHitAnimation((Unit)(object)__instance); } } private static void PlayHitAnimation(Unit unit) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 UnitState unitState = unit.UnitState; bool flag = unitState - 1 <= 1; bool flag2 = flag; if (Config.EnableXCrossHair.Value && flag2) { PluginInstance.Instance.StartTrigger("Hit"); } else { PluginInstance.Instance.StartTrigger("Kill"); } } } [HarmonyWrapSafe] [HarmonyPatch(typeof(Npc), "ReceiveDamage", new Type[] { typeof(float), typeof(DamageTypes), typeof(DamageSourceData), typeof(Data), typeof(Vector3?) })] public class DamageInfoPatch : AttackFeedbackPatch { private static void Prefix(Npc __instance, out float __state) { __state = ((Unit)__instance).GetCurrentHealth(); } private unsafe static void Postfix(Npc __instance, DamageTypes damageType, ref DamageSourceData source, float __state) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)PluginInstance.Instance == (Object)null || !AttackFeedbackPatch.TargetCheck(source) || !Config.EnableDamageMessage.Value) { return; } float num = __state - ((Unit)__instance).GetCurrentHealth(); if (num <= 0f) { return; } WeaponSO val = (((Object)(object)source.sourceWeapon != (Object)null) ? source.sourceWeapon.weaponDefinition : null); string text; if (source.melee && (Object)(object)val != (Object)null) { text = ((ItemDefinition)val).LocalizedDisplayName; } else { text = (((Object)(object)AssetAccess.GetAsset(damageType) != (Object)null) ? AssetAccess.GetAsset(damageType).shortLabel : ((object)(*(DamageTypes*)(&damageType))/*cast due to .constrained prefix*/).ToString()); if ((Object)(object)val != (Object)null) { CaliberType asset = AssetAccess.GetAsset(val.caliber); text = text + " " + (((Object)(object)asset != (Object)null) ? asset.label : ((object)Unsafe.As(ref val.caliber)/*cast due to .constrained prefix*/).ToString()) + " " + ((object)Unsafe.As(ref val.projectileType)/*cast due to .constrained prefix*/).ToString(); } } PluginInstance.Instance.OnEnemyHit(text, Convert.ToInt32(num)); } } [HarmonyWrapSafe] [HarmonyPatch(typeof(Npc), "ReceiveDamage", new Type[] { typeof(float), typeof(DamageTypes), typeof(DamageSourceData), typeof(Data), typeof(Vector3?) })] public class KillMessagePatch : AttackFeedbackPatch { private static void Postfix(Npc __instance, ref DamageSourceData source, Data hitbox, Vector3? hitPosition) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Invalid comparison between Unknown and I4 //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Invalid comparison between Unknown and I4 if (!((Object)(object)PluginInstance.Instance == (Object)null) && AttackFeedbackPatch.TargetCheck(source) && !IsAlive((Unit)(object)__instance)) { Vector3 val = (Vector3)(((??)hitPosition) ?? ((Component)__instance).transform.position); float num = Vector3.Distance(StaticInstance.Instance.PlayerUnit.EyesPosition, val); bool flag = (Object)(object)source.sourceWeapon != (Object)null; if (flag) { HoldableWeightClass holdableWeightClass = ((Holdable)source.sourceWeapon).holdableWeightClass; bool flag2 = holdableWeightClass - 3 <= 1; flag = flag2; } bool flag3 = flag; string sourceName = ((Unit)__instance).SourceName; string text = (((Object)(object)source.sourceWeapon != (Object)null) ? ((ItemDefinition)source.sourceWeapon.weaponDefinition).LocalizedDisplayName : ""); string text2 = Convert.ToString(((Unit)__instance).ExperienceOnKill); bool isHeadShot = (int)((ShapeId)(ref hitbox.shapeId)).part == 4; Plugin.LoggingInfo("KillMessage: " + sourceName + " " + text + " " + text2); PluginInstance.Instance.OnEnemyKill(sourceName, text, text2, isHeadShot, num > 20f && flag3); } } private static bool IsAlive(Unit unit) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) UnitState unitState = unit.UnitState; if (unitState - 1 <= 1) { return true; } if ((Object)(object)unit.LastDamagedBy.sourceUnit == (Object)null) { return true; } if (AttackFeedbackPatch.KilledEnemies.Contains(unit)) { return true; } AttackFeedbackPatch.KilledEnemies.Add(unit); return false; } } [HarmonyWrapSafe] [HarmonyPatch(typeof(Npc), "ReceiveDamage", new Type[] { typeof(float), typeof(DamageTypes), typeof(DamageSourceData), typeof(Data), typeof(Vector3?) })] public class SoundPatch { private static PluginData.AttackFeedback data; private static void Postfix(Npc __instance, DamageTypes damageType, ref DamageSourceData source, Data hitbox, Vector3? hitPosition) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Invalid comparison between Unknown and I4 //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Invalid comparison between Unknown and I4 //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)PluginInstance.Instance == (Object)null || (Object)(object)source.sourceUnit == (Object)null || !source.sourceUnit.isPlayer) { return; } if (data == null) { data = DataManager.AttackFeedbackData; } if ((int)((Unit)__instance).UnitState != 0 && AttackFeedbackPatch.Enemies != null && AttackFeedbackPatch.Enemies.Contains(__instance)) { Unit playerUnit = StaticInstance.Instance.PlayerUnit; Vector3 val = (Vector3)(((??)hitPosition) ?? ((Component)__instance).transform.position); float num = Vector3.Distance(playerUnit.EyesPosition, ((Component)__instance).transform.position); bool flag = (int)((ShapeId)(ref hitbox.shapeId)).part == 4; if ((int)damageType == 1 || flag) { Vector3 position = Vector3.LerpUnclamped(((Component)playerUnit).transform.position, val, data.indicatorDistanceHeadShoot); PluginInstance.Instance.PlayHitSound(position, isCrit: true, isFar: false, data.indicatorVolume); } else if (num < 20f) { Vector3 position2 = Vector3.LerpUnclamped(((Component)playerUnit).transform.position, val, data.indicatorDistance); PluginInstance.Instance.PlayHitSound(position2, isCrit: false, isFar: false, data.indicatorVolume); } else { Vector3 position3 = Vector3.LerpUnclamped(((Component)playerUnit).transform.position, val, data.indicatorDistanceFar); PluginInstance.Instance.PlayHitSound(position3, isCrit: false, isFar: true, data.indicatorVolume); } } } } } namespace BattleImprove.Patcher.QOL { public class DeadProtection { [HarmonyWrapSafe] [HarmonyPrefix] [HarmonyPatch(typeof(LootManager), "AddToChurchCollection")] private static void SavePlayerEquipment() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Invalid comparison between Unknown and I4 //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Expected O, but got Unknown Plugin.LoggingInfo("Player died, saving weapon! Quick!!!"); PluginData.DeadProtection deadProtectionData = DataManager.DeadProtectionData; List weapons = deadProtectionData.weapons; weapons.Clear(); foreach (InventoryItem item2 in ((Component)StaticInstance.Instance.PlayerUnit).GetComponent().EquippedHoldables.Select((KeyValuePair keyValuePair) => keyValuePair.Value)) { if ((int)item2.SlotType == 7) { ItemDefinition itemDefinition = item2.itemDefinition; WeaponSO val = (WeaponSO)(object)((itemDefinition is WeaponSO) ? itemDefinition : null); Plugin.LoggingInfo("Saved item: " + ((ItemDefinition)val).LocalizedDisplayName); Plugin.LoggingInfo("Durability Current: " + item2.DurabilityCurrent); item2.ModifyDurability((float)(-item2.DurabilityCurrent) * (1f - deadProtectionData.weaponDurability)); Plugin.LoggingInfo("Durability Modified: " + item2.DurabilityCurrent); Plugin.LoggingInfo("Grabbing item data..."); ItemId id = ((ItemDefinition)val).id; Vector2Int val2 = item2.gridPosition; int x = ((Vector2Int)(ref val2)).x; val2 = item2.gridPosition; int y = ((Vector2Int)(ref val2)).y; int quantity = item2.quantity; int currentAmmo = item2.currentAmmo; CaliberTypes currentCaliber = item2.CurrentCaliber; ItemAttributeCollectionData obj = item2.stats.SerializedAttributeData(); ItemId[] serializedAttachments = item2.GetSerializedAttachments(); ItemId[] serializedEnchantments = item2.GetSerializedEnchantments(); val2 = item2.InventorySize; int x2 = ((Vector2Int)(ref val2)).x; val2 = item2.InventorySize; InventoryData item = new InventoryData(id, x, y, quantity, currentAmmo, currentCaliber, obj, serializedAttachments, serializedEnchantments, 0, x2, ((Vector2Int)(ref val2)).y, false, false); Plugin.LoggingInfo("Saving item data..."); weapons.Add(item); } } DataManager.SaveDeadProtectionData(reset: true); } [HarmonyWrapSafe] [HarmonyPostfix] [HarmonyPatch(typeof(ChurchCollectionLootable), "Loot")] private static void ReturnPlayerEquipment(ChurchCollectionLootable __instance) { Plugin.LoggingInfo("Donation box opened, popping equipment back!"); Transform val = Traverse.Create((object)__instance).Field("lootSpawnTransform").GetValue(); if ((Object)(object)val == (Object)null) { val = ((Component)__instance).transform; } PluginData.DeadProtection deadProtectionData = DataManager.DeadProtectionData; PluginInstance.Instance.SpawnItems(deadProtectionData, val); } } public class ExpSharePatch { [HarmonyWrapSafe] [HarmonyPostfix] [HarmonyPatch(typeof(Npc), "GiveExperience")] private static void GiveExperiencePrePatch(Npc __instance) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) InventorySlot key = (InventorySlot)(((int)((Holdable)StaticInstance.Instance.PlayerUnit.lastUsedWeapon).inventorySlot == 4) ? 5 : 4); Dictionary equippedHoldables = ((Component)StaticInstance.Instance.PlayerUnit).GetComponent().EquippedHoldables; float num = ((Unit)__instance).ExperienceOnKill; float value = Config.Proportion.Value; if (equippedHoldables.ContainsKey(key)) { equippedHoldables[key].AddExperience(num * value); } } } public class HealthBarPatch { [HarmonyWrapSafe] [HarmonyPrefix] [HarmonyPatch(typeof(UnitDebugFrame), "Update")] private static bool UpdateHPBar(UnitDebugFrame __instance) { if (StaticInstance.Instance.shouldShow) { return true; } ((Component)__instance).transform.LookAt(((Component)StaticInstance.Instance.currentCamera).transform); HealthBar component = ((Component)__instance.owner).GetComponent(); if (component.UpdateValue()) { Traverse.Create((object)__instance).Method("UpdateValues", Array.Empty()).GetValue(); } if (__instance.owner.IsAlive) { return false; } ((Behaviour)component).enabled = false; ((Component)__instance).gameObject.SetActive(false); return false; } [HarmonyPostfix] [HarmonyPatch(typeof(Npc), "Start")] private static void AddDebugFrame(Npc __instance) { ((Component)__instance).gameObject.AddComponent(); } } public class LootDropPatch { [HarmonyWrapSafe] [HarmonyPostfix] [HarmonyPatch(typeof(Pickup), "SetupAndSpawn")] private static void SetupAndSpawnPostfix(Pickup __instance) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected I4, but got Unknown Plugin.LoggingInfo("LootParticle Postfix", needDebug: true); Plugin.LoggingInfo("LootParticle Hide Postfix", needDebug: true); LootDropVFX componentInChildren = ((Component)__instance).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { Object.Destroy((Object)(object)((Component)componentInChildren).gameObject); Plugin.LoggingInfo("LootParticle Destroyed", needDebug: true); } else { Plugin.LoggingInfo("LootParticle not found", needDebug: true); } Transform val = (((Object)(object)__instance.shadow != (Object)null) ? __instance.shadow : ((Component)__instance).transform.Find("Shadow")); if ((Object)(object)val == (Object)null) { Plugin.LoggingInfo("LootDropPatch: pickup has no shadow transform, skipping VFX parent."); return; } GameObject gameObject = ((Component)val).gameObject; ItemQuality itemQuality = __instance.ItemSO.itemQuality; ((GameObject)((int)itemQuality switch { 0 => PrefabManager.LoadPrefab("LoopDropTier1", ((Component)__instance).gameObject), 1 => PrefabManager.LoadPrefab("LoopDropTier2", ((Component)__instance).gameObject), 2 => PrefabManager.LoadPrefab("LoopDropTier3", ((Component)__instance).gameObject), 3 => PrefabManager.LoadPrefab("LoopDropTier4", ((Component)__instance).gameObject), 4 => PrefabManager.LoadPrefab("LoopDropTier5", ((Component)__instance).gameObject), _ => PrefabManager.LoadPrefab("LoopDropTier1", ((Component)__instance).gameObject), })).GetComponent().SetParent(gameObject); } } } namespace BattleImprove.Components { public class MenuController : PluginInstance { protected Dictionary windos = new Dictionary(); protected WindowBase currentWindow; protected WindowBase menu; protected KeyCode menuKey => DataManager.VersionData.menuKey; private void Start() { ((Component)this).gameObject.AddComponent().SetController(this); InitWindow(); } public void Update() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (InputCompat.GetKeyDown(menuKey)) { ToggleMenu(); } } public void ResetWindow() { ToggleMenu(); foreach (KeyValuePair windo in windos) { windo.Value.Destroy(); } windos.Clear(); InitWindow(); } private void InitWindow() { menu = ((Component)this).gameObject.AddComponent().SetController(this); windos.Add("Menu", menu); WindowBase value = ((Component)this).gameObject.AddComponent().SetController(this); windos.Add("AttackFeedback", value); WindowBase value2 = ((Component)this).gameObject.AddComponent().SetController(this); windos.Add("DeadProtection", value2); WindowBase value3 = ((Component)this).gameObject.AddComponent().SetController(this); windos.Add("Setting", value3); WindowBase value4 = ((Component)this).gameObject.AddComponent().SetController(this); windos.Add("Hotkey", value4); } public void ToggleMenu() { if ((Object)(object)menu.window.ActiveSkin == (Object)null) { UWindow.RestoreGlobalDefaultSkin(); } menu.Toggle(); if (menu.window.IsDrawing) { if ((Object)(object)currentWindow != (Object)null) { currentWindow.Toggle(); } Pause(state: true); } else { CloseSubWindow(); Pause(state: false); } SaveData(); } public void SaveData() { DataManager.SaveAllData(); } public void Pause(bool state) { GameManager instance = StaticInstance.Instance; if (!((Object)(object)instance == (Object)null)) { instance.ModifyCursorState((LockStatePadlock)4, state); instance.ModifyControllerLock((LockStatePadlock)4, state); } } public void OpenSubWindow(string name, bool closeCurrent = true) { if ((Object)(object)currentWindow != (Object)null && (Object)(object)currentWindow != (Object)(object)windos[name] && currentWindow.window.IsDrawing && closeCurrent) { currentWindow.Toggle(); } if (closeCurrent) { currentWindow = windos[name]; currentWindow.Toggle(); } else { windos[name].Toggle(); } } public void CloseSubWindow() { foreach (KeyValuePair windo in windos) { windo.Value.window.IsDrawing = false; } } } } namespace BattleImprove.Components.QOL { public class HealthBar : MonoBehaviour { private Camera camera; private bool isInitialized; private Npc npc; private float timer; private void Start() { npc = ((Component)this).gameObject.GetComponent(); if (((Unit)npc).IsProtectedNpc) { Object.Destroy((Object)(object)this); return; } isInitialized = false; ((MonoBehaviour)this).StartCoroutine(Initialize()); } private void Update() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (isInitialized && ((Unit)npc).IsAlive) { Vector3 eyesPosition = ((Unit)npc).EyesPosition; timer += Time.deltaTime; ((Component)((Unit)npc).debugFrame).gameObject.SetActive(CheckVisible(eyesPosition)); } } private IEnumerator Initialize() { yield return (object)new WaitForSeconds(3f); StaticInstance.Instance.AddDebugFrameToUnit((Unit)(object)npc); camera = StaticInstance.Instance.currentCamera; isInitialized = true; } private bool CheckVisible(Vector3 position) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //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) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) try { Vector3 val = camera.WorldToViewportPoint(position); int result; if (val.z > 0f) { float x = val.x; if (x > 0f && x < 1f) { float y = val.y; if (y > 0f && y < 1f) { result = ((Vector3.Distance(position, ((Component)camera).transform.position) < 15f) ? 1 : 0); goto IL_0068; } } } result = 0; goto IL_0068; IL_0068: return (byte)result != 0; } catch { Plugin.Logger.LogInfo((object)"Player camera lost, trying to find it again"); camera = StaticInstance.Instance.currentCamera; StaticInstance.Instance.AddDebugFrameToUnit((Unit)(object)npc); } return false; } public bool UpdateValue() { if (!(timer > 0.25f)) { return false; } timer = 0f; return true; } } public class LootSpawnHelper : PluginInstance { private PluginData.DeadProtection data; private void Start() { data = DataManager.DeadProtectionData; } public void SpawnItems(PluginData.DeadProtection keptItems, Transform transform) { ((MonoBehaviour)this).StartCoroutine(SpawnWeapon(keptItems.weapons, transform)); keptItems.opened = true; } private IEnumerator SpawnWeapon(List weapons, Transform transform) { foreach (InventoryData weapon in weapons) { ItemDefinition asset = AssetAccess.GetAsset(weapon.id); weapon.attachmentIds = RandomDeleteElement(weapon.attachmentIds, data.attachmentChance); weapon.enchantmentIds = RandomDeleteElement(weapon.enchantmentIds, data.enchantmentChance); if ((int)weapon.caliberId != 0 && Random.Range(0f, 1f) < data.barrelChance) { weapon.caliberId = (CaliberTypes)0; } Room currentRoom = StaticInstance.Instance.PlayerUnit.currentRoom; StaticInstance.Instance.SpawnPickup(new Vector3(transform.position.x, transform.position.y, transform.position.z + 0.08f), false, asset, currentRoom, weapon, (Container)null, 0.75f); yield return (object)new WaitForSeconds(1f); } } private unsafe ItemId[] RandomDeleteElement(ItemId[] array, float chance) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (array == null) { return null; } List list = new List(array); foreach (ItemId item in list.ToList()) { float num = Random.Range(0f, 1f); string[] obj = new string[6] { "Rolling for ", null, null, null, null, null }; ItemId val = item; obj[1] = ((object)(*(ItemId*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[2] = " with chance "; obj[3] = chance.ToString(); obj[4] = " got "; obj[5] = num.ToString(); Plugin.LoggingInfo(string.Concat(obj)); if (num < chance) { list.Remove(item); } } return list.ToArray(); } } }