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 SunhavenMods.Shared; using UnityEngine; using UnityEngine.SceneManagement; using Wish; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("FasterRaces")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.4.2.0")] [assembly: AssemblyInformationalVersion("1.4.2+5c08b5aa5d0be9c4b93df77f697dc55d5ac97088")] [assembly: AssemblyProduct("FasterRaces")] [assembly: AssemblyTitle("FasterRaces")] [assembly: AssemblyVersion("1.4.2.0")] [module: RefSafetyRules(11)] 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; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SunhavenMods.Shared { public static class ConfigFileHelper { public static ConfigFile CreateNamedConfig(string pluginGuid, string configFileName, Action logWarning = null) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown string text = Path.Combine(Paths.ConfigPath, configFileName); string text2 = Path.Combine(Paths.ConfigPath, pluginGuid + ".cfg"); try { if (!File.Exists(text) && File.Exists(text2)) { File.Copy(text2, text); } } catch (Exception ex) { logWarning?.Invoke("[Config] Migration to " + configFileName + " failed: " + ex.Message); } return new ConfigFile(text, true); } public static bool ReplacePluginConfig(BaseUnityPlugin plugin, ConfigFile newConfig, Action logWarning = null) { if ((Object)(object)plugin == (Object)null || newConfig == null) { return false; } try { Type typeFromHandle = typeof(BaseUnityPlugin); PropertyInfo property = typeFromHandle.GetProperty("Config", BindingFlags.Instance | BindingFlags.Public); if (property != null && property.CanWrite) { property.SetValue(plugin, newConfig, null); return true; } FieldInfo field = typeFromHandle.GetField("k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(plugin, newConfig); return true; } FieldInfo[] fields = typeFromHandle.GetFields(BindingFlags.Instance | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.FieldType == typeof(ConfigFile)) { fieldInfo.SetValue(plugin, newConfig); return true; } } } catch (Exception ex) { logWarning?.Invoke("[Config] ReplacePluginConfig failed: " + ex.Message); } return false; } } } namespace FasterRaces { [BepInPlugin("com.azraelgodking.fasterraces", "Faster Races", "1.4.2")] public class Plugin : BaseUnityPlugin { public static class SpeedPatch { private static PropertyInfo _subRaceProp; private static bool _subRaceChecked; private static bool _loggedRaceResolveFailure; [HarmonyPriority(300)] public static void Postfix(StatType stat, ref float __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)stat == 6 && EnableMod != null && EnableMod.Value) { float num = Mathf.Clamp(GetEffectiveSpeedBonus(GetCurrentRaceName()), 0f, 300f); if (!(num <= 0f)) { __result *= 1f + num / 100f; } } } private static string GetCurrentRaceName() { try { Player instance = Player.Instance; if ((Object)(object)instance == (Object)null) { return null; } if (!_subRaceChecked) { _subRaceChecked = true; _subRaceProp = ((object)instance).GetType().GetProperty("SubRace", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } return (_subRaceProp?.GetValue(instance))?.ToString(); } catch (Exception ex) { if (!_loggedRaceResolveFailure) { _loggedRaceResolveFailure = true; ManualLogSource log = Log; if (log != null) { log.LogDebug((object)("[FasterRaces] GetCurrentRaceName failed: " + ex.Message)); } } return null; } } } internal static ConfigEntry EnableMod; internal static ConfigEntry SpeedBonusPercent; private const float MinSpeedBonusPercent = 0f; private const float MaxSpeedBonusPercent = 300f; internal static readonly Dictionary> RaceSpeedOverrides = new Dictionary>(); private static readonly string[] KnownRaces = new string[8] { "Human", "Elf", "Angel", "Demon", "FireElemental", "WaterElemental", "MagmaElemental", "Shade" }; private Harmony _harmony; private bool _applicationQuitting; public static ManualLogSource Log { get; private set; } public static bool IsSpeedBonusActive { get { if (EnableMod == null || !EnableMod.Value) { return false; } return ((SpeedBonusPercent != null) ? SpeedBonusPercent.Value : 0f) > 0f; } } private void Awake() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ConfigFile val = CreateNamedConfig(); ConfigFileHelper.ReplacePluginConfig((BaseUnityPlugin)(object)this, val, (Action)Log.LogWarning); EnableMod = val.Bind("General", "Enabled", true, "Enable Faster Races movement speed bonus. When enabled, Haven's Birthright will not apply its own movement speed bonuses to avoid double speed."); SpeedBonusPercent = val.Bind("General", "SpeedBonusPercent", 25f, new ConfigDescription("Global percentage bonus to movement speed (e.g. 25 = +25%). Used for any race that does not have a per-race override set.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 300f), Array.Empty())); string[] knownRaces = KnownRaces; foreach (string text in knownRaces) { ConfigEntry value = val.Bind("PerRace", text + "SpeedBonusPercent", -1f, new ConfigDescription("Speed bonus % for " + text + ". Set to -1 to use the global SpeedBonusPercent.", (AcceptableValueBase)(object)new AcceptableValueRange(-1f, 300f), Array.Empty())); RaceSpeedOverrides[text] = value; } _harmony = new Harmony("com.azraelgodking.fasterraces"); MethodInfo methodInfo = AccessTools.Method(typeof(Player), "GetStat", new Type[1] { typeof(StatType) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(SpeedPatch), "Postfix", (Type[])null, (Type[])null); if (methodInfo != null && methodInfo2 != null) { _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Patched Player.GetStat for movement speed"); } else { if (methodInfo == null) { Log.LogWarning((object)"[Reflect] Player.GetStat(StatType) not found - speed bonus inactive. Check game version."); } if (methodInfo2 == null) { Log.LogWarning((object)"[Reflect] SpeedPatch.Postfix not found - internal error."); } } Log.LogInfo((object)string.Format("{0} v{1} loaded. Global speed bonus: {2}%", "Faster Races", "1.4.2", SpeedBonusPercent.Value)); } internal static float GetEffectiveSpeedBonus(string raceName) { if (!string.IsNullOrEmpty(raceName) && RaceSpeedOverrides.TryGetValue(raceName, out ConfigEntry value) && value.Value >= 0f) { return value.Value; } return SpeedBonusPercent?.Value ?? 0f; } private static ConfigFile CreateNamedConfig() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown string text = Path.Combine(Paths.ConfigPath, "FasterRaces.cfg"); string text2 = Path.Combine(Paths.ConfigPath, "com.azraelgodking.fasterraces.cfg"); try { if (!File.Exists(text) && File.Exists(text2)) { File.Copy(text2, text); } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[Config] Migration to FasterRaces.cfg failed: " + ex.Message)); } } return new ConfigFile(text, true); } private void OnApplicationQuit() { _applicationQuitting = true; } private void OnDestroy() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); string text = ((Scene)(ref activeScene)).name ?? string.Empty; string text2 = text.ToLowerInvariant(); if (_applicationQuitting || !Application.isPlaying || text2.Contains("menu") || text2.Contains("title")) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[Lifecycle] Plugin OnDestroy during expected teardown (scene: " + text + ")")); } } else { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[Lifecycle] Plugin OnDestroy outside expected teardown (scene: " + text + ")")); } } Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } public static class PluginInfo { public const string PLUGIN_GUID = "com.azraelgodking.fasterraces"; public const string PLUGIN_NAME = "Faster Races"; public const string PLUGIN_VERSION = "1.4.2"; } }