Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CustomCrosshairV2 v0.1.2
src/RoR2CustomCrosshair/bin/Debug/netstandard2.1/RoR2CustomCrosshair.dll
Decompiled 7 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.Bandit2.Weapon; using EntityStates.Commando.CommandoWeapon; using EntityStates.Toolbot; using Microsoft.CodeAnalysis; using On.RoR2.UI; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.Skills; using RoR2.UI; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("RoR2CustomCrosshair")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+9a54713ad61bad5c325b1410f08b5cad2eda5494")] [assembly: AssemblyProduct("RoR2CustomCrosshair")] [assembly: AssemblyTitle("RoR2CustomCrosshair")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.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] [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] [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 RoR2CustomCrosshair { internal sealed class BanditSpreadSource : ISpreadSource { private sealed class Weapon { internal readonly string Name; internal readonly GenericBulletSpread Spread; internal readonly float FanDegrees; internal readonly bool HasFan; internal Weapon(string name, GenericBulletSpread spread, bool hasFan, float fanDegrees) { Name = name; Spread = spread; HasFan = hasFan; FanDegrees = fanDegrees; } internal float EnvelopeDegrees(float bloom) { float num = (HasFan ? (FanDegrees + bloom) : 0f); return Mathf.Max(num + Spread.HorizontalDegrees(bloom), Spread.VerticalDegrees(bloom)); } } private const string BanditBodyName = "Bandit2Body"; private BodyIndex _banditBodyIndex = (BodyIndex)(-1); private readonly Dictionary<Type, Weapon?> _weapons = new Dictionary<Type, Weapon>(); private SkillDef? _lastPrimarySkill; private Weapon? _lastWeapon; private CharacterBody? _loggedBody; private Weapon? _loggedWeapon; public bool LogSamples => false; public bool CanHandle(CharacterBody body) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0033: 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_0015: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 if ((int)_banditBodyIndex == -1) { _banditBodyIndex = BodyCatalog.FindBodyIndex("Bandit2Body"); if ((int)_banditBodyIndex == -1) { return false; } } return body.bodyIndex == _banditBodyIndex; } public bool TrySample(CharacterBody body, out SpreadSample sample) { sample = default(SpreadSample); Weapon weapon = CurrentPrimary(body); if (weapon == null || body.spreadBloomCurve == null) { return false; } float spreadBloomAngle = body.spreadBloomAngle; float bloom = body.spreadBloomCurve.Evaluate(0f); sample = new SpreadSample(weapon.EnvelopeDegrees(spreadBloomAngle), weapon.EnvelopeDegrees(bloom), spreadBloomAngle); LogWeaponOnce(body, weapon); return true; } private Weapon? CurrentPrimary(CharacterBody body) { GenericSkill val = (Object.op_Implicit((Object)(object)body.skillLocator) ? body.skillLocator.primary : null); SkillDef val2 = (Object.op_Implicit((Object)(object)val) ? val.skillDef : null); if ((Object)(object)val2 == (Object)null) { return null; } if ((Object)(object)val2 != (Object)(object)_lastPrimarySkill) { _lastPrimarySkill = val2; Type stateType = ((SerializableEntityStateType)(ref val2.activationState)).stateType; _lastWeapon = ((stateType != null) ? WeaponFor(stateType) : null); } return _lastWeapon; } private Weapon? WeaponFor(Type stateType) { if (_weapons.TryGetValue(stateType, out Weapon value)) { return value; } Weapon weapon = null; if (typeof(FireShotgun2).IsAssignableFrom(stateType)) { FireShotgun2 val = GenericBulletSpread.ReadState<FireShotgun2>(stateType); if (val != null) { bool hasFan = ((GenericBulletBaseState)val).bulletCount > 1; float fanDegrees = Mathf.Max(val.minFixedSpreadYaw, val.maxFixedSpreadYaw); weapon = new Weapon(stateType.Name, GenericBulletSpread.From((GenericBulletBaseState)(object)val), hasFan, fanDegrees); } } else if (typeof(Bandit2FireRifle).IsAssignableFrom(stateType)) { Bandit2FireRifle val2 = GenericBulletSpread.ReadState<Bandit2FireRifle>(stateType); if (val2 != null) { weapon = new Weapon(stateType.Name, GenericBulletSpread.From((GenericBulletBaseState)(object)val2), hasFan: false, 0f); } } _weapons[stateType] = weapon; return weapon; } private void LogWeaponOnce(CharacterBody body, Weapon weapon) { if (!((Object)(object)_loggedBody == (Object)(object)body) || _loggedWeapon != weapon) { _loggedBody = body; _loggedWeapon = weapon; AnimationCurve spreadBloomCurve = body.spreadBloomCurve; float num = spreadBloomCurve.Evaluate(0f); float num2 = spreadBloomCurve.Evaluate(1f); Plugin.Log.LogDebug((object)("[Spread] Bandit source active: primary '" + _lastPrimarySkill?.skillName + "' (" + weapon.Name + "), " + weapon.Spread.Describe() + ", fan " + (weapon.HasFan ? $"+/-{weapon.FanDegrees:0.###} deg + bloom" : "none") + "; " + $"bloom {num:0.###}..{num2:0.###} deg, decay {body.spreadBloomDecayTime:0.###} s " + $"(attack speed scales decay: {body.spreadBloomDecayWithAttackSpeed}); " + $"envelope {weapon.EnvelopeDegrees(num):0.###} deg at rest, {weapon.EnvelopeDegrees(num2):0.###} deg at full bloom.")); } } } internal sealed class CommandoSpreadSource : ISpreadSource { private const string CommandoBodyName = "CommandoBody"; private BodyIndex _commandoBodyIndex = (BodyIndex)(-1); private SkillDef? _lastPrimarySkill; private bool _lastPrimaryIsDoubleTap; private CharacterBody? _loggedBody; public bool LogSamples => false; public bool CanHandle(CharacterBody body) { return IsCommando(body); } public bool TrySample(CharacterBody body, out SpreadSample sample) { sample = default(SpreadSample); if (!IsCommando(body) || !PrimaryIsDoubleTap(body) || body.spreadBloomCurve == null) { return false; } sample = new SpreadSample(body.spreadBloomAngle, body.spreadBloomCurve.Evaluate(0f), body.spreadBloomAngle); LogBodyOnce(body); return true; } private bool IsCommando(CharacterBody body) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0033: 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_0015: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 if ((int)_commandoBodyIndex == -1) { _commandoBodyIndex = BodyCatalog.FindBodyIndex("CommandoBody"); if ((int)_commandoBodyIndex == -1) { return false; } } return body.bodyIndex == _commandoBodyIndex; } private bool PrimaryIsDoubleTap(CharacterBody body) { GenericSkill val = (Object.op_Implicit((Object)(object)body.skillLocator) ? body.skillLocator.primary : null); SkillDef val2 = (Object.op_Implicit((Object)(object)val) ? val.skillDef : null); if ((Object)(object)val2 == (Object)null) { return false; } if ((Object)(object)val2 != (Object)(object)_lastPrimarySkill) { _lastPrimarySkill = val2; Type stateType = ((SerializableEntityStateType)(ref val2.activationState)).stateType; _lastPrimaryIsDoubleTap = stateType != null && typeof(FirePistol2).IsAssignableFrom(stateType); } return _lastPrimaryIsDoubleTap; } private void LogBodyOnce(CharacterBody body) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00c2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_loggedBody == (Object)(object)body) { return; } _loggedBody = body; string text = "none"; GameObject defaultCrosshairPrefab = body.defaultCrosshairPrefab; CrosshairController val = default(CrosshairController); if (Object.op_Implicit((Object)(object)defaultCrosshairPrefab) && defaultCrosshairPrefab.TryGetComponent<CrosshairController>(ref val)) { text = $"{((Object)defaultCrosshairPrefab).name} maxSpreadAngle {val.maxSpreadAngle:0.###}"; SpritePosition[] spriteSpreadPositions = val.spriteSpreadPositions; if (spriteSpreadPositions != null && spriteSpreadPositions.Length > 0) { SpritePosition val2 = spriteSpreadPositions[0]; text += string.Format(", sprite '{0}' moves {1} -> {2}", Object.op_Implicit((Object)(object)val2.target) ? ((Object)val2.target).name : "?", val2.zeroPosition, val2.onePosition); } } AnimationCurve spreadBloomCurve = body.spreadBloomCurve; Plugin.Log.LogDebug((object)("[Spread] Commando source active: primary '" + _lastPrimarySkill?.skillName + "', " + $"spread {spreadBloomCurve.Evaluate(0f):0.###} deg at rest, {spreadBloomCurve.Evaluate(1f):0.###} deg at full bloom, " + $"decay time {body.spreadBloomDecayTime:0.###} s (scales with attack speed: {body.spreadBloomDecayWithAttackSpeed}), " + "vanilla crosshair: " + text + ".")); } } internal static class CrosshairConfig { private const int CurrentConfigVersion = 2; private const float SliderStep = 0.5f; internal static ConfigEntry<bool> Enabled; internal static BarsSettings InnerBars; internal static BarsSettings OuterBars; internal static CircleSettings Circle; internal static DotSettings CenterDot; internal static int Revision { get; private set; } internal static void Bind(ConfigFile config) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; Enabled = config.Bind<bool>("General", "Enabled", true, "Replace the ordinary crosshair of your own survivor with the custom crosshair."); InnerBars = new BarsSettings(config, "Inner Bars", new BarsDefaults { Enabled = true, Length = 8f, Thickness = 2f, Gap = 4f, GapMax = 64f, Fill = new Color32((byte)0, byte.MaxValue, (byte)0, byte.MaxValue) }); OuterBars = new BarsSettings(config, "Outer Bars", new BarsDefaults { Enabled = false, Length = 10f, Thickness = 2f, Gap = 14f, GapMax = 128f, Fill = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue) }); Circle = new CircleSettings(config, "Circle"); CenterDot = new DotSettings(config, "Center Dot"); MigrateFromVersion1(config); config.Save(); config.SaveOnConfigSet = saveOnConfigSet; config.SettingChanged += delegate { Revision++; }; } internal static void RegisterRiskOfOptions() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown ModSettingsManager.SetModDescription("Procedural crosshair with Inner Bars, Outer Bars, Circle and Center Dot layers. Sizes are pixels at 1920x1080 and scale with resolution."); Sprite val = ModIcon.Load(); if ((Object)(object)val != (Object)null) { ModSettingsManager.SetModIcon(val, "com.example.ror2customcrosshair", "RoR2 Custom Crosshair"); } ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(Enabled)); InnerBars.Register(); OuterBars.Register(); Circle.Register(); CenterDot.Register(); } private static void MigrateFromVersion1(ConfigFile config) { ConfigEntry<int> val = config.Bind<int>("Internal", "Config Version", 0, "Settings layout version, used for migration. Do not edit."); if (val.Value < 2) { BarsSettings innerBars = InnerBars; Move<float>(config, "Crosshair", "Length", innerBars.Length); Move<float>(config, "Crosshair", "Thickness", innerBars.Thickness); Move<float>(config, "Crosshair", "Gap", innerBars.Gap); Move<int>(config, "Crosshair Color", "Opacity", innerBars.Fill.Opacity); Move<int>(config, "Crosshair Color", "R", innerBars.Fill.Red); Move<int>(config, "Crosshair Color", "G", innerBars.Fill.Green); Move<int>(config, "Crosshair Color", "B", innerBars.Fill.Blue); Move<bool>(config, "Outline", "Enabled", innerBars.Outline.Enabled); Move<float>(config, "Outline", "Thickness", innerBars.Outline.Thickness); Move<int>(config, "Outline Color", "Opacity", innerBars.Outline.Color.Opacity); Move<int>(config, "Outline Color", "R", innerBars.Outline.Color.Red); Move<int>(config, "Outline Color", "G", innerBars.Outline.Color.Green); Move<int>(config, "Outline Color", "B", innerBars.Outline.Color.Blue); val.Value = 2; Plugin.Log.LogInfo((object)"Migrated crosshair settings to the layered layout (old values now under 'Inner Bars')."); } } private static void Move<T>(ConfigFile config, string oldSection, string oldKey, ConfigEntry<T> target) { ConfigEntry<T> val = config.Bind<T>(oldSection, oldKey, (T)((ConfigEntryBase)target).DefaultValue, (ConfigDescription)null); target.Value = val.Value; config.Remove(((ConfigEntryBase)val).Definition); } internal static ConfigEntry<float> BindFloat(ConfigFile config, string section, string key, float defaultValue, float min, float max, string description) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown return config.Bind<float>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>())); } internal static ConfigEntry<int> BindByte(ConfigFile config, string section, string key, int defaultValue) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown return config.Bind<int>(section, key, defaultValue, new ConfigDescription(key + " value from 0 to 255.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255), Array.Empty<object>())); } internal static void AddFloatOption(ConfigEntry<float> entry, float min, float max) { //IL_0002: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new StepSliderOption(entry, new StepSliderConfig { min = min, max = max, increment = 0.5f, FormatString = "{0:0.0}" })); } internal static void AddByteOption(ConfigEntry<int> entry) { //IL_0002: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new IntSliderOption(entry, new IntSliderConfig { min = 0, max = 255 })); } } internal sealed class ColorSettings { internal readonly ConfigEntry<int> Red; internal readonly ConfigEntry<int> Green; internal readonly ConfigEntry<int> Blue; internal readonly ConfigEntry<int> Opacity; internal Color Value => new Color((float)Red.Value / 255f, (float)Green.Value / 255f, (float)Blue.Value / 255f, (float)Opacity.Value / 255f); internal ColorSettings(ConfigFile config, string section, string keyPrefix, Color32 defaults) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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) //IL_0073: Unknown result type (might be due to invalid IL or missing references) Red = CrosshairConfig.BindByte(config, section, keyPrefix + "R", defaults.r); Green = CrosshairConfig.BindByte(config, section, keyPrefix + "G", defaults.g); Blue = CrosshairConfig.BindByte(config, section, keyPrefix + "B", defaults.b); Opacity = CrosshairConfig.BindByte(config, section, keyPrefix + "Opacity", defaults.a); } internal void Register() { CrosshairConfig.AddByteOption(Red); CrosshairConfig.AddByteOption(Green); CrosshairConfig.AddByteOption(Blue); CrosshairConfig.AddByteOption(Opacity); } } internal sealed class OutlineSettings { internal const float MaxThickness = 10f; internal readonly ConfigEntry<bool> Enabled; internal readonly ConfigEntry<float> Thickness; internal readonly ColorSettings Color; internal bool Visible => Enabled.Value && Thickness.Value > 0.001f; internal OutlineSettings(ConfigFile config, string section) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) Enabled = config.Bind<bool>(section, "Outline Enabled", true, "Draw a border around this layer."); Thickness = CrosshairConfig.BindFloat(config, section, "Outline Thickness", 1f, 0f, 10f, "Border width on each side, in pixels at 1920x1080."); Color = new ColorSettings(config, section, "Outline ", new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue)); } internal void Register() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(Enabled)); CrosshairConfig.AddFloatOption(Thickness, 0f, 10f); Color.Register(); } } internal struct BarsDefaults { internal bool Enabled; internal float Length; internal float Thickness; internal float Gap; internal float GapMax; internal Color32 Fill; } internal sealed class BarsSettings { internal const float MaxLength = 64f; internal const float MaxThickness = 20f; private readonly float _gapMax; internal readonly ConfigEntry<bool> Enabled; internal readonly ConfigEntry<CrosshairMode> Mode; internal readonly ConfigEntry<float> Length; internal readonly ConfigEntry<float> Thickness; internal readonly ConfigEntry<float> Gap; internal readonly ColorSettings Fill; internal readonly OutlineSettings Outline; internal BarsSettings(ConfigFile config, string section, BarsDefaults defaults) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) _gapMax = defaults.GapMax; Enabled = config.Bind<bool>(section, "Enabled", defaults.Enabled, "Show the " + section + "."); Mode = config.Bind<CrosshairMode>(section, "Mode", CrosshairMode.Static, "Static: fixed gap. Dynamic: gap will follow actual weapon spread (not implemented yet; currently same as Static)."); Length = CrosshairConfig.BindFloat(config, section, "Length", defaults.Length, 0.5f, 64f, "Length of each arm, in pixels at 1920x1080."); Thickness = CrosshairConfig.BindFloat(config, section, "Thickness", defaults.Thickness, 0.5f, 20f, "Thickness of each arm, in pixels at 1920x1080."); Gap = CrosshairConfig.BindFloat(config, section, "Gap", defaults.Gap, 0f, _gapMax, "Distance from screen center to the inner edge of each arm, in pixels at 1920x1080."); Fill = new ColorSettings(config, section, "", defaults.Fill); Outline = new OutlineSettings(config, section); } internal void Register() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(Enabled)); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)Mode)); CrosshairConfig.AddFloatOption(Length, 0.5f, 64f); CrosshairConfig.AddFloatOption(Thickness, 0.5f, 20f); CrosshairConfig.AddFloatOption(Gap, 0f, _gapMax); Fill.Register(); Outline.Register(); } } internal sealed class CircleSettings { internal const float MaxRadius = 128f; internal const float MaxThickness = 20f; internal readonly ConfigEntry<bool> Enabled; internal readonly ConfigEntry<CrosshairMode> Mode; internal readonly ConfigEntry<float> Radius; internal readonly ConfigEntry<float> Thickness; internal readonly ColorSettings Fill; internal readonly OutlineSettings Outline; internal CircleSettings(ConfigFile config, string section) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) Enabled = config.Bind<bool>(section, "Enabled", false, "Show the circle."); Mode = config.Bind<CrosshairMode>(section, "Mode", CrosshairMode.Static, "Static: fixed radius. Dynamic: radius will follow actual weapon spread (not implemented yet; currently same as Static)."); Radius = CrosshairConfig.BindFloat(config, section, "Radius", 16f, 0f, 128f, "Distance from screen center to the inner edge of the ring, in pixels at 1920x1080."); Thickness = CrosshairConfig.BindFloat(config, section, "Thickness", 2f, 0.5f, 20f, "Ring thickness, in pixels at 1920x1080."); Fill = new ColorSettings(config, section, "", new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue)); Outline = new OutlineSettings(config, section); } internal void Register() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(Enabled)); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)Mode)); CrosshairConfig.AddFloatOption(Radius, 0f, 128f); CrosshairConfig.AddFloatOption(Thickness, 0.5f, 20f); Fill.Register(); Outline.Register(); } } internal sealed class DotSettings { internal const float MaxSize = 20f; internal readonly ConfigEntry<bool> Enabled; internal readonly ConfigEntry<float> Size; internal readonly ColorSettings Fill; internal readonly OutlineSettings Outline; internal DotSettings(ConfigFile config, string section) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) Enabled = config.Bind<bool>(section, "Enabled", false, "Show the center dot."); Size = CrosshairConfig.BindFloat(config, section, "Size", 2f, 0.5f, 20f, "Diameter of the dot, in pixels at 1920x1080."); Fill = new ColorSettings(config, section, "", new Color32((byte)0, byte.MaxValue, (byte)0, byte.MaxValue)); Outline = new OutlineSettings(config, section); } internal void Register() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(Enabled)); CrosshairConfig.AddFloatOption(Size, 0.5f, 20f); Fill.Register(); Outline.Register(); } } internal static class CrosshairDisplayPolicy { private const string StandardCrosshairAddress = "RoR2/Base/UI/StandardCrosshair.prefab"; private const string GenericSprintCrosshairPath = "Prefabs/Crosshair/SprintingCrosshair"; private static readonly string[] StockPreservingAddresses = new string[3] { "RoR2/Base/Bandit2/Bandit2Crosshair.prefab", "RoR2/Base/Toolbot/ToolbotGrenadeLauncherCrosshair.prefab", "RoR2/Base/Toolbot/ToolbotDualWieldCrosshair.prefab" }; private static readonly (string Address, string? BodyName)[] CosmeticSkillCrosshairAddresses = new(string, string)[3] { ("RoR2/Base/Bandit2/Bandit2CrosshairPrepRevolver.prefab", null), ("RoR2/Base/Bandit2/Bandit2CrosshairPrepRevolverFire.prefab", null), ("RoR2/Base/UI/BadCrosshair.prefab", "ToolbotBody") }; private static Transform? _holder; private static GameObject? _standardTemplate; private static readonly Dictionary<GameObject, GameObject?> StockPreserving = new Dictionary<GameObject, GameObject>(); private static readonly Dictionary<GameObject, string?> CosmeticSkillCrosshairs = new Dictionary<GameObject, string>(); private static readonly Dictionary<string, BodyIndex> BodyIndices = new Dictionary<string, BodyIndex>(); private static GameObject? _genericSprintCrosshair; private static bool _genericSprintCrosshairLoaded; private static int _pendingLoads; internal static bool IsReady => _pendingLoads == 0 && (Object)(object)_standardTemplate != (Object)null; internal static void Initialize(Transform holder) { _holder = holder; _pendingLoads = 1 + StockPreservingAddresses.Length + CosmeticSkillCrosshairAddresses.Length; CrosshairPrefabFactory.LoadAsync("RoR2/Base/UI/StandardCrosshair.prefab", delegate(GameObject? standard) { _standardTemplate = Build(standard, (GameObject s) => CrosshairPrefabFactory.BuildStandard(s, holder)); if ((Object)(object)_standardTemplate != (Object)null) { Plugin.Log.LogInfo((object)"Crosshair template ready."); } else { Plugin.Log.LogError((object)"Crosshair template unavailable; vanilla crosshairs will be used."); } _pendingLoads--; }); string[] stockPreservingAddresses = StockPreservingAddresses; foreach (string address in stockPreservingAddresses) { CrosshairPrefabFactory.LoadAsync(address, delegate(GameObject? vanilla) { if ((Object)(object)vanilla != (Object)null) { GameObject val = Build(vanilla, (GameObject v) => CrosshairPrefabFactory.BuildStockPreserving(v, holder)); StockPreserving[vanilla] = val; if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)(((Object)vanilla).name + ": ammo displays could not be preserved; its vanilla crosshair will be kept.")); } } _pendingLoads--; }); } (string, string)[] cosmeticSkillCrosshairAddresses = CosmeticSkillCrosshairAddresses; for (int num2 = 0; num2 < cosmeticSkillCrosshairAddresses.Length; num2++) { var (address2, bodyName) = cosmeticSkillCrosshairAddresses[num2]; CrosshairPrefabFactory.LoadAsync(address2, delegate(GameObject? prefab) { if ((Object)(object)prefab != (Object)null) { CosmeticSkillCrosshairs[prefab] = bodyName; } _pendingLoads--; }); } } internal static void Shutdown() { _standardTemplate = null; StockPreserving.Clear(); CosmeticSkillCrosshairs.Clear(); BodyIndices.Clear(); _holder = null; } internal static GameObject? ChooseTemplate(CharacterBody body, GameObject picked) { if (!IsReady || !Object.op_Implicit((Object)(object)picked)) { return null; } if (StockPreserving.ContainsKey(picked) || IsOrdinaryCrosshair(body, picked) || IsActiveWeaponCrosshair(body, picked)) { return TemplateFor(picked); } if (IsGenericSprintCrosshair(body, picked) || IsCosmeticSkillCrosshair(body, picked)) { return TemplateFor(ActiveWeaponCrosshair(body) ?? body.defaultCrosshairPrefab); } return null; } private static GameObject? TemplateFor(GameObject? vanilla) { if ((Object)(object)vanilla != (Object)null && StockPreserving.TryGetValue(vanilla, out GameObject value)) { return value; } return _standardTemplate; } private static GameObject? ActiveWeaponCrosshair(CharacterBody body) { GenericSkill val = (Object.op_Implicit((Object)(object)body.skillLocator) ? body.skillLocator.primary : null); object result; if (Object.op_Implicit((Object)(object)val)) { SkillDef skillDef = val.skillDef; ToolbotWeaponSkillDef val2 = (ToolbotWeaponSkillDef)(object)((skillDef is ToolbotWeaponSkillDef) ? skillDef : null); if (val2 != null && Object.op_Implicit((Object)(object)val2.crosshairPrefab)) { result = val2.crosshairPrefab; goto IL_004a; } } result = null; goto IL_004a; IL_004a: return (GameObject?)result; } private static bool IsActiveWeaponCrosshair(CharacterBody body, GameObject picked) { GameObject val = ActiveWeaponCrosshair(body); return (Object)(object)val != (Object)null && (Object)(object)picked == (Object)(object)val; } private static bool IsCosmeticSkillCrosshair(CharacterBody body, GameObject picked) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Invalid comparison between Unknown and I4 //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (!CosmeticSkillCrosshairs.TryGetValue(picked, out string value)) { return false; } if (value == null) { return true; } if (!BodyIndices.TryGetValue(value, out var value2) || (int)value2 == -1) { value2 = BodyCatalog.FindBodyIndex(value); BodyIndices[value] = value2; } return (int)value2 != -1 && body.bodyIndex == value2; } private static GameObject? Build(GameObject? source, Func<GameObject, GameObject?> build) { if ((Object)(object)source == (Object)null || (Object)(object)_holder == (Object)null) { return null; } try { return build(source); } catch (Exception arg) { Plugin.Log.LogError((object)$"Could not build crosshair template from {((Object)source).name}: {arg}"); return null; } } private static bool IsOrdinaryCrosshair(CharacterBody body, GameObject picked) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Invalid comparison between Unknown and I4 if ((Object)(object)picked == (Object)(object)body.defaultCrosshairPrefab) { return true; } SkillCrosshairController val = default(SkillCrosshairController); if (((Component)body).TryGetComponent<SkillCrosshairController>(ref val) && val.options != null) { SkillDefCrosshairOptions[] options = val.options; foreach (SkillDefCrosshairOptions val2 in options) { if (val2 != null && (int)val2.priority < 1 && (Object)(object)val2.crosshairPrefab == (Object)(object)picked) { return true; } } } return false; } private static bool IsGenericSprintCrosshair(CharacterBody body, GameObject picked) { if (!body.isSprinting || !body.useSprintCrosshair || Object.op_Implicit((Object)(object)body.sprintCrosshairPrefabOverride)) { return false; } GameObject genericSprintCrosshair = GetGenericSprintCrosshair(); return (Object)(object)genericSprintCrosshair != (Object)null && (Object)(object)picked == (Object)(object)genericSprintCrosshair; } private static GameObject? GetGenericSprintCrosshair() { if (!_genericSprintCrosshairLoaded) { _genericSprintCrosshairLoaded = true; _genericSprintCrosshair = LegacyResourcesAPI.Load<GameObject>("Prefabs/Crosshair/SprintingCrosshair"); if ((Object)(object)_genericSprintCrosshair == (Object)null) { Plugin.Log.LogWarning((object)"Could not load 'Prefabs/Crosshair/SprintingCrosshair'; the vanilla sprint crosshair will be shown."); } } return _genericSprintCrosshair; } } internal readonly struct PixelFrame { internal readonly float ResolutionScale; internal readonly float PixelsPerUnit; internal readonly float CenterFraction; internal readonly Vector2 Center; internal readonly Vector2 OriginOffset; internal PixelFrame(float resolutionScale, float pixelsPerUnit, float centerFraction, Vector2 anchorScreen, Vector2 rootScreen) { //IL_0017: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0044: 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) ResolutionScale = resolutionScale; PixelsPerUnit = pixelsPerUnit; CenterFraction = centerFraction; Center = new Vector2(SnapToGrid(anchorScreen.x, centerFraction), SnapToGrid(anchorScreen.y, centerFraction)); OriginOffset = Center - rootScreen; } internal static float FractionFor(float logicalSize, float resolutionScale) { return (Mathf.Max(1, RoundPx(logicalSize * resolutionScale)) % 2 == 0) ? 0f : 0.5f; } internal int Width(float logical) { return Mathf.Max(1, RoundPx(logical * ResolutionScale)); } internal int CenteredSize(float logical) { float num = logical * ResolutionScale; if (CenterFraction == 0f) { return Mathf.Max(2, 2 * RoundPx(num * 0.5f)); } return Mathf.Max(1, 2 * (int)Mathf.Floor(num * 0.5f) + 1); } internal float EdgeDistance(float logical, float extraPixels = 0f) { float num = Mathf.Max(0f, Mathf.Max(0f, logical) * ResolutionScale + extraPixels); return Mathf.Floor(CenterFraction + num + 0.5f) - CenterFraction; } internal float ToLocal(float pixels) { return pixels / PixelsPerUnit; } internal void Place(RectTransform rect, Vector4 pixelRect) { //IL_0003: 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_0016: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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) Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor((pixelRect.x + pixelRect.z) * 0.5f, (pixelRect.y + pixelRect.w) * 0.5f); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(pixelRect.z - pixelRect.x, pixelRect.w - pixelRect.y); rect.anchoredPosition = (OriginOffset + val) / PixelsPerUnit; rect.sizeDelta = val2 / PixelsPerUnit; } internal static int RoundPx(float value) { return (int)Mathf.Floor(value + 0.5f); } private static float SnapToGrid(float value, float fraction) { return Mathf.Floor(value - fraction + 0.5f) + fraction; } } internal sealed class BorderedRect { private static readonly string[] SideNames = new string[4] { "Top", "Bottom", "Left", "Right" }; private readonly Image _fill; private readonly Image[] _strips = (Image[])(object)new Image[4]; private BorderedRect(Transform layer, string name) { _fill = Find(layer, "Fill" + name); for (int i = 0; i < 4; i++) { _strips[i] = Find(layer, "Outline" + name + SideNames[i]); } } internal static BorderedRect Bind(Transform layer, string name) { return new BorderedRect(layer, name); } internal static void BuildBorder(Transform layer, string name) { string[] sideNames = SideNames; foreach (string text in sideNames) { CrosshairPrefabFactory.CreateImage("Outline" + name + text, layer); } } internal static void BuildFill(Transform layer, string name) { CrosshairPrefabFactory.CreateImage("Fill" + name, layer); } internal void Apply(in PixelFrame frame, Vector4 r, Color fill, int border, Color borderColor) { //IL_0008: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: 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_00d1: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) Show(_fill, in frame, r, fill); if (border <= 0) { Image[] strips = _strips; foreach (Image val in strips) { ((Behaviour)val).enabled = false; } } else { float num = border; Show(_strips[0], in frame, new Vector4(r.x - num, r.w, r.z + num, r.w + num), borderColor); Show(_strips[1], in frame, new Vector4(r.x - num, r.y - num, r.z + num, r.y), borderColor); Show(_strips[2], in frame, new Vector4(r.x - num, r.y, r.x, r.w), borderColor); Show(_strips[3], in frame, new Vector4(r.z, r.y, r.z + num, r.w), borderColor); } } internal void Hide() { ((Behaviour)_fill).enabled = false; Image[] strips = _strips; foreach (Image val in strips) { ((Behaviour)val).enabled = false; } } private static void Show(Image image, in PixelFrame frame, Vector4 r, Color color) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) frame.Place(((Graphic)image).rectTransform, r); ((Graphic)image).color = color; ((Behaviour)image).enabled = true; } private static Image Find(Transform layer, string name) { return ((Component)layer.Find(name)).GetComponent<Image>(); } } internal sealed class BarsLayer { private static readonly string[] ArmNames = new string[4] { "Left", "Right", "Top", "Bottom" }; private readonly BarsSettings _settings; private readonly BorderedRect[] _arms = new BorderedRect[4]; internal bool Enabled => _settings.Enabled.Value; internal float Thickness => _settings.Thickness.Value; internal BarsLayer(Transform root, string layerName, BarsSettings settings) { _settings = settings; Transform layer = root.Find(layerName); for (int i = 0; i < 4; i++) { _arms[i] = BorderedRect.Bind(layer, ArmNames[i]); } } internal static void Build(Transform root, string layerName) { Transform layer = (Transform)(object)CrosshairPrefabFactory.CreateRect(layerName, root); string[] armNames = ArmNames; foreach (string name in armNames) { BorderedRect.BuildBorder(layer, name); } string[] armNames2 = ArmNames; foreach (string name2 in armNames2) { BorderedRect.BuildFill(layer, name2); } } internal void Apply(in PixelFrame frame, float dynamicOffset) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) if (!Enabled) { BorderedRect[] arms = _arms; foreach (BorderedRect borderedRect in arms) { borderedRect.Hide(); } return; } float extraPixels = ((_settings.Mode.Value == CrosshairMode.Dynamic) ? dynamicOffset : 0f); float num = (float)frame.CenteredSize(_settings.Thickness.Value) * 0.5f; float num2 = frame.EdgeDistance(_settings.Gap.Value, extraPixels); float num3 = num2 + (float)frame.Width(_settings.Length.Value); Color value = _settings.Fill.Value; Color value2 = _settings.Outline.Color.Value; int border = (_settings.Outline.Visible ? frame.Width(_settings.Outline.Thickness.Value) : 0); _arms[0].Apply(in frame, new Vector4(0f - num3, 0f - num, 0f - num2, num), value, border, value2); _arms[1].Apply(in frame, new Vector4(num2, 0f - num, num3, num), value, border, value2); _arms[2].Apply(in frame, new Vector4(0f - num, num2, num, num3), value, border, value2); _arms[3].Apply(in frame, new Vector4(0f - num, 0f - num3, num, 0f - num2), value, border, value2); } } internal sealed class RingPart { private const float SegmentPixels = 1.5f; private const int MinSegments = 24; private const int MaxSegments = 512; private readonly RingMesh _mesh; private readonly Image _image; private RingPart(Transform layer, string name) { _mesh = ((Component)layer.Find(name)).GetComponent<RingMesh>(); _image = _mesh.Image; } internal static RingPart Bind(Transform layer, string name) { return new RingPart(layer, name); } internal static void Build(Transform layer, string name) { CrosshairPrefabFactory.CreateImage(name, layer); ((Component)layer.Find(name)).gameObject.AddComponent<RingMesh>(); } internal void Apply(in PixelFrame frame, float inner, float outer, int border, Color fill, Color borderColor) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) float num = outer + (float)border + 1f; int segments = Mathf.Clamp(Mathf.CeilToInt(MathF.PI * 2f * (outer + (float)border) / 1.5f), 24, 512); frame.Place(((Graphic)_image).rectTransform, new Vector4(0f - num, 0f - num, num, num)); ((Graphic)_image).color = Color.white; _mesh.SetShape(frame.ToLocal(inner), frame.ToLocal(outer), frame.ToLocal(border), frame.ToLocal(1f), fill, borderColor, segments); ((Behaviour)_image).enabled = true; } internal void Hide() { ((Behaviour)_image).enabled = false; } } internal sealed class CenterDotLayer { private const string DotName = "Dot"; private readonly DotSettings _settings; private readonly RingPart _dot; internal bool Enabled => _settings.Enabled.Value; internal float Size => _settings.Size.Value; internal CenterDotLayer(Transform root, string layerName, DotSettings settings) { _settings = settings; _dot = RingPart.Bind(root.Find(layerName), "Dot"); } internal static void Build(Transform root, string layerName) { RingPart.Build((Transform)(object)CrosshairPrefabFactory.CreateRect(layerName, root), "Dot"); } internal void Apply(in PixelFrame frame) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) if (!Enabled) { _dot.Hide(); return; } float outer = (float)frame.CenteredSize(_settings.Size.Value) * 0.5f; int border = (_settings.Outline.Visible ? frame.Width(_settings.Outline.Thickness.Value) : 0); _dot.Apply(in frame, 0f, outer, border, _settings.Fill.Value, _settings.Outline.Color.Value); } } internal sealed class CircleLayer { private const string RingName = "Ring"; private readonly CircleSettings _settings; private readonly RingPart _ring; internal CircleLayer(Transform root, string layerName, CircleSettings settings) { _settings = settings; _ring = RingPart.Bind(root.Find(layerName), "Ring"); } internal static void Build(Transform root, string layerName) { RingPart.Build((Transform)(object)CrosshairPrefabFactory.CreateRect(layerName, root), "Ring"); } internal void Apply(in PixelFrame frame, float dynamicOffset) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) if (!_settings.Enabled.Value) { _ring.Hide(); return; } float extraPixels = ((_settings.Mode.Value == CrosshairMode.Dynamic) ? dynamicOffset : 0f); float num = frame.EdgeDistance(_settings.Radius.Value, extraPixels); float outer = num + (float)frame.Width(_settings.Thickness.Value); int border = (_settings.Outline.Visible ? frame.Width(_settings.Outline.Thickness.Value) : 0); _ring.Apply(in frame, num, outer, border, _settings.Fill.Value, _settings.Outline.Color.Value); } } internal enum CrosshairMode { Static, Dynamic } internal static class CrosshairPrefabFactory { internal const string ProceduralRootName = "ProceduralCrosshair"; internal const string CircleLayerName = "Circle"; internal const string OuterBarsLayerName = "OuterBars"; internal const string InnerBarsLayerName = "InnerBars"; internal const string CenterDotLayerName = "CenterDot"; internal static void LoadAsync(string address, Action<GameObject?> onLoaded) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) AsyncOperationHandle<GameObject> val = Addressables.LoadAssetAsync<GameObject>((object)address); val.Completed += delegate(AsyncOperationHandle<GameObject> op) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 if ((int)op.Status != 1 || (Object)(object)op.Result == (Object)null) { Plugin.Log.LogError((object)$"Could not load '{address}': {op.OperationException}"); onLoaded(null); } else { onLoaded(op.Result); } }; } internal static GameObject BuildStandard(GameObject standardCrosshair, Transform holder) { CrosshairController controller; GameObject val = Clone(standardCrosshair, holder, "RoR2CustomCrosshair", out controller); Plugin.Log.LogDebug((object)("StandardCrosshair components: " + string.Join(", ", from c in val.GetComponents<Component>() select ((object)c).GetType().Name))); controller.spriteSpreadPositions = Array.Empty<SpritePosition>(); controller.skillStockSpriteDisplays = Array.Empty<SkillStockSpriteDisplay>(); controller.remapSprites = Array.Empty<RawImage>(); HideVanillaVisuals(val, new HashSet<Transform>()); AddProceduralCrosshair(val); return val; } internal static GameObject? BuildStockPreserving(GameObject vanillaCrosshair, Transform holder) { //IL_0043: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) CrosshairController controller; GameObject val = Clone(vanillaCrosshair, holder, "RoR2CustomCrosshair_" + ((Object)vanillaCrosshair).name, out controller); Transform transform = val.transform; List<SkillStockSpriteDisplay> list = new List<SkillStockSpriteDisplay>(); SkillStockSpriteDisplay[] array = controller.skillStockSpriteDisplays ?? Array.Empty<SkillStockSpriteDisplay>(); foreach (SkillStockSpriteDisplay val2 in array) { if (Object.op_Implicit((Object)(object)val2.target) && !IsAtCenter(transform, val2.target.transform)) { list.Add(val2); } } if (list.Count == 0) { Object.Destroy((Object)(object)val); return null; } controller.spriteSpreadPositions = Array.Empty<SpritePosition>(); controller.remapSprites = Array.Empty<RawImage>(); controller.skillStockSpriteDisplays = list.ToArray(); HashSet<Transform> hashSet = new HashSet<Transform>(); foreach (SkillStockSpriteDisplay item in list) { Transform val3 = item.target.transform; while ((Object)(object)val3 != (Object)null && (Object)(object)val3 != (Object)(object)transform) { hashSet.Add(val3); val3 = val3.parent; } } HideVanillaVisuals(val, hashSet); AddProceduralCrosshair(val); Plugin.Log.LogDebug((object)(((Object)vanillaCrosshair).name + ": keeping vanilla stock displays " + string.Join(", ", list.Select((SkillStockSpriteDisplay d) => ((Object)d.target).name)) + "; spread artwork removed.")); return val; } private static GameObject Clone(GameObject source, Transform holder, string name, out CrosshairController controller) { GameObject val = Object.Instantiate<GameObject>(source, holder, false); ((Object)val).name = name; HudElement val2 = default(HudElement); if (!val.TryGetComponent<CrosshairController>(ref controller) || !val.TryGetComponent<HudElement>(ref val2)) { Object.Destroy((Object)(object)val); throw new InvalidOperationException(((Object)source).name + " no longer has CrosshairController + HudElement."); } return val; } private static bool IsAtCenter(Transform root, Transform target) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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) Vector3 val = root.InverseTransformPoint(target.position); return ((Vector3)(ref val)).sqrMagnitude < 1f; } private static void HideVanillaVisuals(GameObject template, HashSet<Transform> keep) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown foreach (Transform item in template.transform) { Transform val = item; if (!keep.Contains(val)) { ((Component)val).gameObject.SetActive(false); } } Graphic[] components = template.GetComponents<Graphic>(); foreach (Graphic val2 in components) { ((Behaviour)val2).enabled = false; } } private static void AddProceduralCrosshair(GameObject template) { RectTransform root = CreateRect("ProceduralCrosshair", template.transform); CircleLayer.Build((Transform)(object)root, "Circle"); BarsLayer.Build((Transform)(object)root, "OuterBars"); BarsLayer.Build((Transform)(object)root, "InnerBars"); CenterDotLayer.Build((Transform)(object)root, "CenterDot"); template.AddComponent<ProceduralCrosshairView>(); } internal static RectTransform CreateRect(string name, Transform parent) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) //IL_007f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(parent, false); val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = Vector2.zero; val2.sizeDelta = Vector2.zero; return val2; } internal static void CreateImage(string name, Transform parent) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) RectTransform val = CreateRect(name, parent); ((Component)val).gameObject.AddComponent<CanvasRenderer>(); Image val2 = ((Component)val).gameObject.AddComponent<Image>(); ((Graphic)val2).raycastTarget = false; ((MaskableGraphic)val2).maskable = false; ((Graphic)val2).color = Color.clear; ((Behaviour)val2).enabled = false; } } internal readonly struct SpreadSample { internal readonly float CurrentDegrees; internal readonly float RestingDegrees; internal readonly float BloomDegrees; internal SpreadSample(float currentDegrees, float restingDegrees, float bloomDegrees) { CurrentDegrees = currentDegrees; RestingDegrees = restingDegrees; BloomDegrees = bloomDegrees; } } internal interface ISpreadSource { bool LogSamples { get; } bool CanHandle(CharacterBody body); bool TrySample(CharacterBody body, out SpreadSample sample); } internal sealed class SpreadSourceResolver { private readonly ISpreadSource[] _sources; private CharacterBody? _body; private ISpreadSource? _source; internal SpreadSourceResolver(params ISpreadSource[] sources) { _sources = sources; } internal bool TrySample(CharacterBody body, out SpreadSample sample, out ISpreadSource? source) { if ((Object)(object)body != (Object)(object)_body) { _body = body; _source = null; ISpreadSource[] sources = _sources; foreach (ISpreadSource spreadSource in sources) { if (spreadSource.CanHandle(body)) { _source = spreadSource; break; } } } source = _source; sample = default(SpreadSample); return _source != null && _source.TrySample(body, out sample); } } internal static class SpreadProjection { internal static float HalfAngleToPixels(float halfAngleDegrees, Camera camera) { float num = camera.fieldOfView * 0.5f * (MathF.PI / 180f); if (num <= 0f || halfAngleDegrees <= 0f) { return 0f; } float num2 = Mathf.Min(halfAngleDegrees, 89f) * (MathF.PI / 180f); return Mathf.Tan(num2) / Mathf.Tan(num) * ((float)camera.pixelHeight * 0.5f); } } internal sealed class GenericBulletSpread { internal readonly int BulletCount; internal readonly float MaxSpread; internal readonly float YawScale; internal readonly float PitchScale; private GenericBulletSpread(GenericBulletBaseState state) { BulletCount = state.bulletCount; MaxSpread = state.maxSpread; YawScale = state.spreadYawScale; PitchScale = state.spreadPitchScale; } internal static T? ReadState<T>(Type stateType) where T : GenericBulletBaseState { try { EntityState obj = EntityStateCatalog.InstantiateState(stateType); return (T)(object)((obj is T) ? obj : null); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not read configuration of " + stateType.FullName + ": " + ex.Message)); return default(T); } } internal static GenericBulletSpread From(GenericBulletBaseState state) { return new GenericBulletSpread(state); } internal float HorizontalDegrees(float bloomDegrees) { return (MaxSpread + bloomDegrees) * YawScale; } internal float VerticalDegrees(float bloomDegrees) { return (MaxSpread + bloomDegrees) * PitchScale; } internal string Describe() { return $"{BulletCount} bullet(s), maxSpread {MaxSpread:0.###}, yaw x{YawScale:0.###}, pitch x{PitchScale:0.###}"; } } internal sealed class HudCrosshairDriver : MonoBehaviour { private static readonly ISpreadSource[] SpreadSources = new ISpreadSource[3] { new CommandoSpreadSource(), new BanditSpreadSource(), new ToolbotSpreadSource() }; private const float OffsetStepPixels = 0.25f; private const float SpreadLogInterval = 1f; private float _nextSpreadLogTime; private readonly SpreadSourceResolver _spreadResolver = new SpreadSourceResolver(SpreadSources); private CrosshairManager? _crosshairManager; private bool _replacing; internal static void Attach(HUD hud) { if (!Object.op_Implicit((Object)(object)((Component)hud).GetComponent<HudCrosshairDriver>())) { ((Component)hud).gameObject.AddComponent<HudCrosshairDriver>(); } } private void Awake() { _crosshairManager = ((Component)this).GetComponent<CrosshairManager>(); if (!Object.op_Implicit((Object)(object)_crosshairManager)) { Plugin.Log.LogWarning((object)("HUD '" + ((Object)this).name + "' has no CrosshairManager; custom crosshair unavailable.")); } } private void OnEnable() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)_crosshairManager)) { _crosshairManager.pickCrosshairGlobal += new PickCrosshairDelegate(OnPickCrosshair); } } private void OnDisable() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)_crosshairManager)) { _crosshairManager.pickCrosshairGlobal -= new PickCrosshairDelegate(OnPickCrosshair); } SetReplacing(replacing: false, null); } private void OnPickCrosshair(CrosshairManager manager, ref GameObject crosshairPrefab) { CharacterBody ownLiveBody = GetOwnLiveBody(manager); GameObject val = (((Object)(object)ownLiveBody != (Object)null && CrosshairConfig.Enabled.Value) ? CrosshairDisplayPolicy.ChooseTemplate(ownLiveBody, crosshairPrefab) : null); if ((Object)(object)val != (Object)null) { crosshairPrefab = val; } SetReplacing((Object)(object)val != (Object)null, ownLiveBody); } internal DynamicOffsets GetDynamicOffsets() { if (!_replacing || !Object.op_Implicit((Object)(object)_crosshairManager)) { return default(DynamicOffsets); } CameraRigController cameraRigController = _crosshairManager.cameraRigController; CharacterBody ownLiveBody = GetOwnLiveBody(_crosshairManager); Camera val = (Object.op_Implicit((Object)(object)cameraRigController) ? cameraRigController.sceneCam : null); if ((Object)(object)ownLiveBody == (Object)null || (Object)(object)val == (Object)null || !_spreadResolver.TrySample(ownLiveBody, out SpreadSample sample, out ISpreadSource source)) { return default(DynamicOffsets); } float num = SpreadProjection.HalfAngleToPixels(sample.CurrentDegrees, val); float num2 = SpreadProjection.HalfAngleToPixels(sample.RestingDegrees, val); float num3 = Mathf.Round(Mathf.Max(0f, num - num2) / 0.25f) * 0.25f; if (source.LogSamples) { LogSpreadSample(source, in sample, val, num, num3); } return new DynamicOffsets(num3, num3, num3); } private void LogSpreadSample(ISpreadSource source, in SpreadSample sample, Camera camera, float currentPixels, float offsetPixels) { if (!(offsetPixels <= 0f) && !(Time.unscaledTime < _nextSpreadLogTime)) { _nextSpreadLogTime = Time.unscaledTime + 1f; Plugin.Log.LogDebug((object)($"[Spread] {source.GetType().Name}: bloom {sample.BloomDegrees:0.###} deg -> spread {sample.CurrentDegrees:0.###} deg " + $"(rest {sample.RestingDegrees:0.###}), vertical FOV {camera.fieldOfView:0.#}, camera {camera.pixelWidth}x{camera.pixelHeight} -> " + $"cone radius {currentPixels:0.#} px, dynamic offset +{offsetPixels:0.##} px.")); } } private static CharacterBody? GetOwnLiveBody(CrosshairManager manager) { CameraRigController cameraRigController = manager.cameraRigController; if (!Object.op_Implicit((Object)(object)cameraRigController) || cameraRigController.hasOverride) { return null; } LocalUser localUserViewer = cameraRigController.localUserViewer; CharacterBody targetBody = cameraRigController.targetBody; if (localUserViewer == null || !Object.op_Implicit((Object)(object)targetBody) || (Object)(object)localUserViewer.cachedBodyObject != (Object)(object)((Component)targetBody).gameObject) { return null; } if (!Object.op_Implicit((Object)(object)targetBody.healthComponent) || !targetBody.healthComponent.alive) { return null; } return targetBody; } private void SetReplacing(bool replacing, CharacterBody? body) { if (replacing != _replacing) { _replacing = replacing; Plugin.Log.LogDebug((object)(replacing ? ("Custom crosshair active for " + body.GetDisplayName() + " (" + ((Object)body).name + ").") : "Custom crosshair released; vanilla crosshair logic in control.")); } } } internal static class ModIcon { private const string ResourceName = "RoR2CustomCrosshair.icon.png"; private static Sprite? _sprite; internal static Sprite? Load() { //IL_004a: 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) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_sprite != (Object)null) { return _sprite; } try { byte[] array = ReadResource(); if (array == null) { Plugin.Log.LogWarning((object)"Embedded resource 'RoR2CustomCrosshair.icon.png' not found; RiskOfOptions will show its default icon."); return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true) { name = "RoR2CustomCrosshairIcon", filterMode = (FilterMode)2, wrapMode = (TextureWrapMode)1 }; if (!ImageConversion.LoadImage(val, array, true)) { Object.Destroy((Object)(object)val); Plugin.Log.LogWarning((object)"Could not decode the embedded icon; RiskOfOptions will show its default icon."); return null; } Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); ((Object)val2).name = ((Object)val).name; ((Object)val).hideFlags = (HideFlags)32; ((Object)val2).hideFlags = (HideFlags)32; _sprite = val2; return _sprite; } catch (Exception arg) { Plugin.Log.LogWarning((object)$"Could not load the mod icon; RiskOfOptions will show its default icon. {arg}"); return null; } } private static byte[]? ReadResource() { using Stream stream = typeof(ModIcon).Assembly.GetManifestResourceStream("RoR2CustomCrosshair.icon.png"); if (stream == null) { return null; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } } [BepInPlugin("com.example.ror2customcrosshair", "RoR2 Custom Crosshair", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { [CompilerGenerated] private static class <>O { public static hook_Awake <0>__HUD_Awake; } public const string PluginGuid = "com.example.ror2customcrosshair"; public const string PluginName = "RoR2 Custom Crosshair"; public const string PluginVersion = "0.1.0"; private GameObject? _prefabHolder; internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; CrosshairConfig.Bind(((BaseUnityPlugin)this).Config); CrosshairConfig.RegisterRiskOfOptions(); _prefabHolder = new GameObject("RoR2CustomCrosshair_Templates"); _prefabHolder.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_prefabHolder); CrosshairDisplayPolicy.Initialize(_prefabHolder.transform); object obj = <>O.<0>__HUD_Awake; if (obj == null) { hook_Awake val = HUD_Awake; <>O.<0>__HUD_Awake = val; obj = (object)val; } HUD.Awake += (hook_Awake)obj; Log.LogInfo((object)"RoR2 Custom Crosshair 0.1.0 loaded."); } private static void HUD_Awake(orig_Awake orig, HUD self) { orig.Invoke(self); HudCrosshairDriver.Attach(self); } private void OnDestroy() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown object obj = <>O.<0>__HUD_Awake; if (obj == null) { hook_Awake val = HUD_Awake; <>O.<0>__HUD_Awake = val; obj = (object)val; } HUD.Awake -= (hook_Awake)obj; HudCrosshairDriver[] array = Object.FindObjectsOfType<HudCrosshairDriver>(); foreach (HudCrosshairDriver hudCrosshairDriver in array) { Object.Destroy((Object)(object)hudCrosshairDriver); } CrosshairDisplayPolicy.Shutdown(); if ((Object)(object)_prefabHolder != (Object)null) { Object.Destroy((Object)(object)_prefabHolder); } } } internal readonly struct DynamicOffsets : IEquatable<DynamicOffsets> { internal readonly float InnerBars; internal readonly float OuterBars; internal readonly float Circle; internal DynamicOffsets(float innerBars, float outerBars, float circle) { InnerBars = innerBars; OuterBars = outerBars; Circle = circle; } public bool Equals(DynamicOffsets other) { return InnerBars == other.InnerBars && OuterBars == other.OuterBars && Circle == other.Circle; } } internal sealed class ProceduralCrosshairView : MonoBehaviour { private const float ReferenceWidth = 1920f; private const float ReferenceHeight = 1080f; private static int _loggedScreenWidth = -1; private static int _loggedScreenHeight = -1; private static float _loggedPixelsPerUnit = -1f; private RectTransform _rect = null; private RectTransform _root = null; private CircleLayer _circle = null; private BarsLayer _outerBars = null; private BarsLayer _innerBars = null; private CenterDotLayer _centerDot = null; private Canvas? _canvas; private HudCrosshairDriver? _driver; private int _lastRevision = -1; private int _lastScreenWidth = -1; private int _lastScreenHeight = -1; private float _lastPixelsPerUnit = -1f; private Vector2 _lastRootScreen; private Vector2 _lastAnchorScreen; private DynamicOffsets _lastOffsets; private void Awake() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown _rect = (RectTransform)((Component)this).transform; _root = (RectTransform)((Component)this).transform.Find("ProceduralCrosshair"); _circle = new CircleLayer((Transform)(object)_root, "Circle", CrosshairConfig.Circle); _outerBars = new BarsLayer((Transform)(object)_root, "OuterBars", CrosshairConfig.OuterBars); _innerBars = new BarsLayer((Transform)(object)_root, "InnerBars", CrosshairConfig.InnerBars); _centerDot = new CenterDotLayer((Transform)(object)_root, "CenterDot", CrosshairConfig.CenterDot); Refresh(); } private void OnTransformParentChanged() { _canvas = null; _driver = null; } private void LateUpdate() { Refresh(); } private void Refresh() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0169: 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_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: 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_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: 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_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_canvas == (Object)null) { _canvas = ((Component)this).GetComponentInParent<Canvas>(); if ((Object)(object)_canvas == (Object)null) { return; } } Canvas rootCanvas = _canvas.rootCanvas; float pixelsPerUnit = GetPixelsPerUnit(rootCanvas); if (pixelsPerUnit <= 0f) { return; } Camera val = (((int)rootCanvas.renderMode == 0) ? null : rootCanvas.worldCamera); Vector2 val2 = RectTransformUtility.WorldToScreenPoint(val, ((Transform)_root).position); Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val, GetIntendedCenterWorld()); if ((Object)(object)_driver == (Object)null) { _driver = ((Component)this).GetComponentInParent<HudCrosshairDriver>(); } DynamicOffsets dynamicOffsets = (((Object)(object)_driver != (Object)null) ? _driver.GetDynamicOffsets() : default(DynamicOffsets)); if (_lastRevision == CrosshairConfig.Revision && _lastScreenWidth == Screen.width && _lastScreenHeight == Screen.height && Mathf.Approximately(_lastPixelsPerUnit, pixelsPerUnit)) { Vector2 val4 = _lastRootScreen - val2; if (((Vector2)(ref val4)).sqrMagnitude < 1E-06f) { val4 = _lastAnchorScreen - val3; if (((Vector2)(ref val4)).sqrMagnitude < 1E-06f && _lastOffsets.Equals(dynamicOffsets)) { return; } } } PixelFrame frame = CreateFrame(pixelsPerUnit, val3, val2); _circle.Apply(in frame, dynamicOffsets.Circle); _outerBars.Apply(in frame, dynamicOffsets.OuterBars); _innerBars.Apply(in frame, dynamicOffsets.InnerBars); _centerDot.Apply(in frame); LogLayoutOnce(rootCanvas, in frame, val2, val3); _lastRevision = CrosshairConfig.Revision; _lastScreenWidth = Screen.width; _lastScreenHeight = Screen.height; _lastPixelsPerUnit = pixelsPerUnit; _lastRootScreen = val2; _lastAnchorScreen = val3; _lastOffsets = dynamicOffsets; } private PixelFrame CreateFrame(float pixelsPerUnit, Vector2 anchorScreen, Vector2 rootScreen) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) float resolutionScale = Mathf.Min((float)Screen.width / 1920f, (float)Screen.height / 1080f); float centerFraction = (_innerBars.Enabled ? PixelFrame.FractionFor(_innerBars.Thickness, resolutionScale) : (_outerBars.Enabled ? PixelFrame.FractionFor(_outerBars.Thickness, resolutionScale) : (_centerDot.Enabled ? PixelFrame.FractionFor(_centerDot.Size, resolutionScale) : 0f))); return new PixelFrame(resolutionScale, pixelsPerUnit, centerFraction, anchorScreen, rootScreen); } private float GetPixelsPerUnit(Canvas rootCanvas) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) float x = ((Component)rootCanvas).transform.lossyScale.x; if (x <= 0f) { return 0f; } return rootCanvas.scaleFactor * (((Transform)_root).lossyScale.x / x); } private Vector3 GetIntendedCenterWorld() { //IL_002d: 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_003e: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0050: Unknown result type (might be due to invalid IL or missing references) Transform parent = ((Transform)_rect).parent; if ((Object)(object)parent == (Object)null) { return ((Transform)_root).position; } return ((Transform)_root).position - parent.TransformVector(Vector2.op_Implicit(_rect.anchoredPosition)); } private void LogLayoutOnce(Canvas rootCanvas, in PixelFrame frame, Vector2 rootScreen, Vector2 anchorScreen) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) if (_loggedScreenWidth != Screen.width || _loggedScreenHeight != Screen.height || !Mathf.Approximately(_loggedPixelsPerUnit, frame.PixelsPerUnit)) { _loggedScreenWidth = Screen.width; _loggedScreenHeight = Screen.height; _loggedPixelsPerUnit = frame.PixelsPerUnit; Plugin.Log.LogDebug((object)($"Crosshair layout: screen {Screen.width}x{Screen.height}, canvas {rootCanvas.renderMode} " + $"scaleFactor {rootCanvas.scaleFactor:0.###} pixelPerfect {rootCanvas.pixelPerfect}, " + $"px/unit {frame.PixelsPerUnit:0.###}, crosshair anchoredPosition {_rect.anchoredPosition}, " + $"root at {rootScreen.x:0.###},{rootScreen.y:0.###} px, anchor {anchorScreen.x:0.###},{anchorScreen.y:0.###} px, " + $"snapped center {frame.Center.x},{frame.Center.y}.")); } } } [RequireComponent(typeof(Image))] internal sealed class RingMesh : MonoBehaviour, IMeshModifier { private readonly struct Stop { internal readonly float Radius; internal readonly Color32 Color; internal Stop(float radius, Color32 color) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) Radius = radius; Color = color; } } private readonly struct Shape : IEquatable<Shape> { internal readonly float Inner; internal readonly float Outer; internal readonly float Border; internal readonly float Feather; internal readonly Color32 Fill; internal readonly Color32 BorderColor; internal readonly int Segments; internal Shape(float inner, float outer, float border, float feather, Color32 fill, Color32 borderColor, int segments) { //IL_001f: 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_0027: 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) Inner = inner; Outer = outer; Border = border; Feather = feather; Fill = fill; BorderColor = borderColor; Segments = segments; } public bool Equals(Shape o) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) return Inner == o.Inner && Outer == o.Outer && Border == o.Border && Feather == o.Feather && Segments == o.Segments && Same(Fill, o.Fill) && Same(BorderColor, o.BorderColor); } private static bool Same(Color32 a, Color32 b) { //IL_0000: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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) return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a; } } private readonly List<Stop> _stops = new List<Stop>(); private Shape _shape; private bool _hasShape; private Image? _image; internal Image Image => ((Object)(object)_image != (Object)null) ? _image : (_image = ((Component)this).GetComponent<Image>()); internal void SetShape(float inner, float outer, float border, float feather, Color fill, Color borderColor, int segments) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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) Shape shape = new Shape(inner, outer, border, feather, Color32.op_Implicit(fill), Color32.op_Implicit(borderColor), segments); if (!_hasShape || !shape.Equals(_shape)) { _shape = shape; _hasShape = true; ((Graphic)Image).SetVerticesDirty(); } } public void ModifyMesh(Mesh mesh) { } public void ModifyMesh(VertexHelper vh) { //IL_0083: 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_008c: Unknown result type (might be due to invalid IL or missing references) vh.Clear(); if (!_hasShape) { return; } BuildStops(_shape); int segments = _shape.Segments; float num = MathF.PI * 2f / (float)segments; Vector3 val = default(Vector3); for (int i = 0; i < _stops.Count; i++) { Stop stop = _stops[i]; for (int j = 0; j < segments; j++) { float num2 = (float)j * num; ((Vector3)(ref val))..ctor(Mathf.Cos(num2) * stop.Radius, Mathf.Sin(num2) * stop.Radius); vh.AddVert(val, stop.Color, Vector4.zero); } } for (int k = 0; k + 1 < _stops.Count; k++) { int num3 = k * segments; int num4 = (k + 1) * segments; for (int l = 0; l < segments; l++) { int num5 = (l + 1) % segments; vh.AddTriangle(num3 + l, num4 + l, num4 + num5); vh.AddTriangle(num3 + l, num4 + num5, num3 + num5); } } } private void BuildStops(Shape shape) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) _stops.Clear(); float num = shape.Feather * 0.5f; bool flag = shape.Border > 0f; List<float> list = new List<float>(4); List<Color32> list2 = new List<Color32>(3); if (flag && shape.Inner > 0f) { list.Add(Mathf.Max(0f, shape.Inner - shape.Border)); list2.Add(shape.BorderColor); } list.Add(shape.Inner); list2.Add(shape.Fill); list.Add(shape.Outer); if (flag) { list2.Add(shape.BorderColor); list.Add(shape.Outer + shape.Border); } for (int i = 0; i < list.Count; i++) { Color32 color = ((i == 0) ? Transparent(list2[0]) : list2[i - 1]); Color32 color2 = ((i == list.Count - 1) ? Transparent(list2[i - 1]) : list2[i]); if (i == 0 && list[0] <= 0f) { AddStop(0f, color2); continue; } AddStop(list[i] - num, color); AddStop(list[i] + num, color2); } } private void AddStop(float radius, Color32 color) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) float num = ((_stops.Count > 0) ? _stops[_stops.Count - 1].Radius : 0f); _stops.Add(new Stop(Mathf.Max(radius, num), color)); } private static Color32 Transparent(Color32 color) { //IL_0001: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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) return new Color32(color.r, color.g, color.b, (byte)0); } } internal sealed class ToolbotSpreadSource : ISpreadSource { private const string ToolbotBodyName = "ToolbotBody"; private BodyIndex _toolbotBodyIndex = (BodyIndex)(-1); private readonly Dictionary<SkillDef, bool> _isNailgun = new Dictionary<SkillDef, bool>(); private CharacterBody? _loggedBody; private SkillDef? _loggedPrimary; private SkillDef? _loggedOffhand; public bool LogSamples => true; public bool CanHandle(CharacterBody body) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0033: 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_0015: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 if ((int)_toolbotBodyIndex == -1) { _toolbotBodyIndex = BodyCatalog.FindBodyIndex("ToolbotBody"); if ((int)_toolbotBodyIndex == -1) { return false; } } return body.bodyIndex == _toolbotBodyIndex; } public bool TrySample(CharacterBody body, out SpreadSample sample) { sample = default(SpreadSample); SkillLocator skillLocator = body.skillLocator; if (!Object.op_Implicit((Object)(object)skillLocator)) { return false; } ToolbotWeaponSkillDef val = (ToolbotWeaponSkillDef)(Object.op_Implicit((Object)(object)skillLocator.primary) ? /*isinst with value type is only supported in some contexts*/: null); ToolbotWeaponSkillDef val2 = (ToolbotWeaponSkillDef)(Object.op_Implicit((Object)(object)skillLocator.secondary) ? /*isinst with value type is only supported in some contexts*/: null); LogWeaponsOnce(body, (SkillDef?)(object)val, (SkillDef?)(object)val2); if (!IsNailgun((SkillDef?)(object)val) && !IsNailgun((SkillDef?)(object)val2)) { return false; } if (body.spreadBloomCurve == null) { return false; } float num = NailgunEnvelopeScale(); float spreadBloomAngle = body.spreadBloomAngle; float num2 = body.spreadBloomCurve.Evaluate(0f); sample = new SpreadSample(spreadBloomAngle * num, num2 * num, spreadBloomAngle); return true; } private static float NailgunEnvelopeScale() { float spreadYawScale = BaseNailgunState.spreadYawScale; float spreadPitchScale = BaseNailgunState.spreadPitchScale; return Math.Max(1f, Math.Max(spreadYawScale * spreadYawScale, spreadPitchScale * spreadPitchScale)); } private bool IsNailgun(SkillDef? skill) { if ((Object)(object)skill == (Object)null) { return false; } if (!_isNailgun.TryGetValue(skill, out var value)) { Type stateType = ((SerializableEntityStateType)(ref skill.activationState)).stateType; value = stateType != null && typeof(FireNailgun).IsAssignableFrom(stateType); _isNailgun[skill] = value; } return value; } private void LogWeaponsOnce(CharacterBody body, SkillDef? primary, SkillDef? offhand) { if (!((Object)(object)_loggedBody == (Object)(object)body) || !((Object)(object)_loggedPrimary == (Object)(object)primary) || !((Object)(object)_loggedOffhand == (Object)(object)offhand)) { _loggedBody = body; _loggedPrimary = primary; _loggedOffhand = offhand; string arg = ((body.spreadBloomCurve != null) ? $"{body.spreadBloomCurve.Evaluate(0f):0.###}..{body.spreadBloomCurve.Evaluate(1f):0.###} deg" : "none"); Plugin.Log.LogDebug((object)("[Spread] MUL-T weapons: active " + Describe(primary) + (((Object)(object)offhand != (Object)null) ? (", Power Mode offhand " + Describe(offhand)) : "") + $"; body bloom curve {arg}, decay {body.spreadBloomDecayTime:0.###} s; " + $"nailgun envelope scale {NailgunEnvelopeScale():0.###}.")); } string Describe(SkillDef? skill) { return ((Object)(object)skill == (Object)null) ? "none" : ("'" + skill.skillName + "' (" + ((SerializableEntityStateType)(ref skill.activationState)).stateType?.Name + ", " + (IsNailgun(skill) ? "dynamic spread" : "no spread growth") + ")"); } } } }
src/RoR2CustomCrosshair/obj/Debug/netstandard2.1/RoR2CustomCrosshair.dll
Decompiled 7 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.Bandit2.Weapon; using EntityStates.Commando.CommandoWeapon; using EntityStates.Toolbot; using Microsoft.CodeAnalysis; using On.RoR2.UI; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.Skills; using RoR2.UI; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("RoR2CustomCrosshair")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+9a54713ad61bad5c325b1410f08b5cad2eda5494")] [assembly: AssemblyProduct("RoR2CustomCrosshair")] [assembly: AssemblyTitle("RoR2CustomCrosshair")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.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] [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] [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 RoR2CustomCrosshair { internal sealed class BanditSpreadSource : ISpreadSource { private sealed class Weapon { internal readonly string Name; internal readonly GenericBulletSpread Spread; internal readonly float FanDegrees; internal readonly bool HasFan; internal Weapon(string name, GenericBulletSpread spread, bool hasFan, float fanDegrees) { Name = name; Spread = spread; HasFan = hasFan; FanDegrees = fanDegrees; } internal float EnvelopeDegrees(float bloom) { float num = (HasFan ? (FanDegrees + bloom) : 0f); return Mathf.Max(num + Spread.HorizontalDegrees(bloom), Spread.VerticalDegrees(bloom)); } } private const string BanditBodyName = "Bandit2Body"; private BodyIndex _banditBodyIndex = (BodyIndex)(-1); private readonly Dictionary<Type, Weapon?> _weapons = new Dictionary<Type, Weapon>(); private SkillDef? _lastPrimarySkill; private Weapon? _lastWeapon; private CharacterBody? _loggedBody; private Weapon? _loggedWeapon; public bool LogSamples => false; public bool CanHandle(CharacterBody body) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0033: 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_0015: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 if ((int)_banditBodyIndex == -1) { _banditBodyIndex = BodyCatalog.FindBodyIndex("Bandit2Body"); if ((int)_banditBodyIndex == -1) { return false; } } return body.bodyIndex == _banditBodyIndex; } public bool TrySample(CharacterBody body, out SpreadSample sample) { sample = default(SpreadSample); Weapon weapon = CurrentPrimary(body); if (weapon == null || body.spreadBloomCurve == null) { return false; } float spreadBloomAngle = body.spreadBloomAngle; float bloom = body.spreadBloomCurve.Evaluate(0f); sample = new SpreadSample(weapon.EnvelopeDegrees(spreadBloomAngle), weapon.EnvelopeDegrees(bloom), spreadBloomAngle); LogWeaponOnce(body, weapon); return true; } private Weapon? CurrentPrimary(CharacterBody body) { GenericSkill val = (Object.op_Implicit((Object)(object)body.skillLocator) ? body.skillLocator.primary : null); SkillDef val2 = (Object.op_Implicit((Object)(object)val) ? val.skillDef : null); if ((Object)(object)val2 == (Object)null) { return null; } if ((Object)(object)val2 != (Object)(object)_lastPrimarySkill) { _lastPrimarySkill = val2; Type stateType = ((SerializableEntityStateType)(ref val2.activationState)).stateType; _lastWeapon = ((stateType != null) ? WeaponFor(stateType) : null); } return _lastWeapon; } private Weapon? WeaponFor(Type stateType) { if (_weapons.TryGetValue(stateType, out Weapon value)) { return value; } Weapon weapon = null; if (typeof(FireShotgun2).IsAssignableFrom(stateType)) { FireShotgun2 val = GenericBulletSpread.ReadState<FireShotgun2>(stateType); if (val != null) { bool hasFan = ((GenericBulletBaseState)val).bulletCount > 1; float fanDegrees = Mathf.Max(val.minFixedSpreadYaw, val.maxFixedSpreadYaw); weapon = new Weapon(stateType.Name, GenericBulletSpread.From((GenericBulletBaseState)(object)val), hasFan, fanDegrees); } } else if (typeof(Bandit2FireRifle).IsAssignableFrom(stateType)) { Bandit2FireRifle val2 = GenericBulletSpread.ReadState<Bandit2FireRifle>(stateType); if (val2 != null) { weapon = new Weapon(stateType.Name, GenericBulletSpread.From((GenericBulletBaseState)(object)val2), hasFan: false, 0f); } } _weapons[stateType] = weapon; return weapon; } private void LogWeaponOnce(CharacterBody body, Weapon weapon) { if (!((Object)(object)_loggedBody == (Object)(object)body) || _loggedWeapon != weapon) { _loggedBody = body; _loggedWeapon = weapon; AnimationCurve spreadBloomCurve = body.spreadBloomCurve; float num = spreadBloomCurve.Evaluate(0f); float num2 = spreadBloomCurve.Evaluate(1f); Plugin.Log.LogDebug((object)("[Spread] Bandit source active: primary '" + _lastPrimarySkill?.skillName + "' (" + weapon.Name + "), " + weapon.Spread.Describe() + ", fan " + (weapon.HasFan ? $"+/-{weapon.FanDegrees:0.###} deg + bloom" : "none") + "; " + $"bloom {num:0.###}..{num2:0.###} deg, decay {body.spreadBloomDecayTime:0.###} s " + $"(attack speed scales decay: {body.spreadBloomDecayWithAttackSpeed}); " + $"envelope {weapon.EnvelopeDegrees(num):0.###} deg at rest, {weapon.EnvelopeDegrees(num2):0.###} deg at full bloom.")); } } } internal sealed class CommandoSpreadSource : ISpreadSource { private const string CommandoBodyName = "CommandoBody"; private BodyIndex _commandoBodyIndex = (BodyIndex)(-1); private SkillDef? _lastPrimarySkill; private bool _lastPrimaryIsDoubleTap; private CharacterBody? _loggedBody; public bool LogSamples => false; public bool CanHandle(CharacterBody body) { return IsCommando(body); } public bool TrySample(CharacterBody body, out SpreadSample sample) { sample = default(SpreadSample); if (!IsCommando(body) || !PrimaryIsDoubleTap(body) || body.spreadBloomCurve == null) { return false; } sample = new SpreadSample(body.spreadBloomAngle, body.spreadBloomCurve.Evaluate(0f), body.spreadBloomAngle); LogBodyOnce(body); return true; } private bool IsCommando(CharacterBody body) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0033: 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_0015: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 if ((int)_commandoBodyIndex == -1) { _commandoBodyIndex = BodyCatalog.FindBodyIndex("CommandoBody"); if ((int)_commandoBodyIndex == -1) { return false; } } return body.bodyIndex == _commandoBodyIndex; } private bool PrimaryIsDoubleTap(CharacterBody body) { GenericSkill val = (Object.op_Implicit((Object)(object)body.skillLocator) ? body.skillLocator.primary : null); SkillDef val2 = (Object.op_Implicit((Object)(object)val) ? val.skillDef : null); if ((Object)(object)val2 == (Object)null) { return false; } if ((Object)(object)val2 != (Object)(object)_lastPrimarySkill) { _lastPrimarySkill = val2; Type stateType = ((SerializableEntityStateType)(ref val2.activationState)).stateType; _lastPrimaryIsDoubleTap = stateType != null && typeof(FirePistol2).IsAssignableFrom(stateType); } return _lastPrimaryIsDoubleTap; } private void LogBodyOnce(CharacterBody body) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00c2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_loggedBody == (Object)(object)body) { return; } _loggedBody = body; string text = "none"; GameObject defaultCrosshairPrefab = body.defaultCrosshairPrefab; CrosshairController val = default(CrosshairController); if (Object.op_Implicit((Object)(object)defaultCrosshairPrefab) && defaultCrosshairPrefab.TryGetComponent<CrosshairController>(ref val)) { text = $"{((Object)defaultCrosshairPrefab).name} maxSpreadAngle {val.maxSpreadAngle:0.###}"; SpritePosition[] spriteSpreadPositions = val.spriteSpreadPositions; if (spriteSpreadPositions != null && spriteSpreadPositions.Length > 0) { SpritePosition val2 = spriteSpreadPositions[0]; text += string.Format(", sprite '{0}' moves {1} -> {2}", Object.op_Implicit((Object)(object)val2.target) ? ((Object)val2.target).name : "?", val2.zeroPosition, val2.onePosition); } } AnimationCurve spreadBloomCurve = body.spreadBloomCurve; Plugin.Log.LogDebug((object)("[Spread] Commando source active: primary '" + _lastPrimarySkill?.skillName + "', " + $"spread {spreadBloomCurve.Evaluate(0f):0.###} deg at rest, {spreadBloomCurve.Evaluate(1f):0.###} deg at full bloom, " + $"decay time {body.spreadBloomDecayTime:0.###} s (scales with attack speed: {body.spreadBloomDecayWithAttackSpeed}), " + "vanilla crosshair: " + text + ".")); } } internal static class CrosshairConfig { private const int CurrentConfigVersion = 2; private const float SliderStep = 0.5f; internal static ConfigEntry<bool> Enabled; internal static BarsSettings InnerBars; internal static BarsSettings OuterBars; internal static CircleSettings Circle; internal static DotSettings CenterDot; internal static int Revision { get; private set; } internal static void Bind(ConfigFile config) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; Enabled = config.Bind<bool>("General", "Enabled", true, "Replace the ordinary crosshair of your own survivor with the custom crosshair."); InnerBars = new BarsSettings(config, "Inner Bars", new BarsDefaults { Enabled = true, Length = 8f, Thickness = 2f, Gap = 4f, GapMax = 64f, Fill = new Color32((byte)0, byte.MaxValue, (byte)0, byte.MaxValue) }); OuterBars = new BarsSettings(config, "Outer Bars", new BarsDefaults { Enabled = false, Length = 10f, Thickness = 2f, Gap = 14f, GapMax = 128f, Fill = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue) }); Circle = new CircleSettings(config, "Circle"); CenterDot = new DotSettings(config, "Center Dot"); MigrateFromVersion1(config); config.Save(); config.SaveOnConfigSet = saveOnConfigSet; config.SettingChanged += delegate { Revision++; }; } internal static void RegisterRiskOfOptions() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown ModSettingsManager.SetModDescription("Procedural crosshair with Inner Bars, Outer Bars, Circle and Center Dot layers. Sizes are pixels at 1920x1080 and scale with resolution."); Sprite val = ModIcon.Load(); if ((Object)(object)val != (Object)null) { ModSettingsManager.SetModIcon(val, "com.example.ror2customcrosshair", "RoR2 Custom Crosshair"); } ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(Enabled)); InnerBars.Register(); OuterBars.Register(); Circle.Register(); CenterDot.Register(); } private static void MigrateFromVersion1(ConfigFile config) { ConfigEntry<int> val = config.Bind<int>("Internal", "Config Version", 0, "Settings layout version, used for migration. Do not edit."); if (val.Value < 2) { BarsSettings innerBars = InnerBars; Move<float>(config, "Crosshair", "Length", innerBars.Length); Move<float>(config, "Crosshair", "Thickness", innerBars.Thickness); Move<float>(config, "Crosshair", "Gap", innerBars.Gap); Move<int>(config, "Crosshair Color", "Opacity", innerBars.Fill.Opacity); Move<int>(config, "Crosshair Color", "R", innerBars.Fill.Red); Move<int>(config, "Crosshair Color", "G", innerBars.Fill.Green); Move<int>(config, "Crosshair Color", "B", innerBars.Fill.Blue); Move<bool>(config, "Outline", "Enabled", innerBars.Outline.Enabled); Move<float>(config, "Outline", "Thickness", innerBars.Outline.Thickness); Move<int>(config, "Outline Color", "Opacity", innerBars.Outline.Color.Opacity); Move<int>(config, "Outline Color", "R", innerBars.Outline.Color.Red); Move<int>(config, "Outline Color", "G", innerBars.Outline.Color.Green); Move<int>(config, "Outline Color", "B", innerBars.Outline.Color.Blue); val.Value = 2; Plugin.Log.LogInfo((object)"Migrated crosshair settings to the layered layout (old values now under 'Inner Bars')."); } } private static void Move<T>(ConfigFile config, string oldSection, string oldKey, ConfigEntry<T> target) { ConfigEntry<T> val = config.Bind<T>(oldSection, oldKey, (T)((ConfigEntryBase)target).DefaultValue, (ConfigDescription)null); target.Value = val.Value; config.Remove(((ConfigEntryBase)val).Definition); } internal static ConfigEntry<float> BindFloat(ConfigFile config, string section, string key, float defaultValue, float min, float max, string description) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown return config.Bind<float>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>())); } internal static ConfigEntry<int> BindByte(ConfigFile config, string section, string key, int defaultValue) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown return config.Bind<int>(section, key, defaultValue, new ConfigDescription(key + " value from 0 to 255.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 255), Array.Empty<object>())); } internal static void AddFloatOption(ConfigEntry<float> entry, float min, float max) { //IL_0002: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new StepSliderOption(entry, new StepSliderConfig { min = min, max = max, increment = 0.5f, FormatString = "{0:0.0}" })); } internal static void AddByteOption(ConfigEntry<int> entry) { //IL_0002: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new IntSliderOption(entry, new IntSliderConfig { min = 0, max = 255 })); } } internal sealed class ColorSettings { internal readonly ConfigEntry<int> Red; internal readonly ConfigEntry<int> Green; internal readonly ConfigEntry<int> Blue; internal readonly ConfigEntry<int> Opacity; internal Color Value => new Color((float)Red.Value / 255f, (float)Green.Value / 255f, (float)Blue.Value / 255f, (float)Opacity.Value / 255f); internal ColorSettings(ConfigFile config, string section, string keyPrefix, Color32 defaults) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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) //IL_0073: Unknown result type (might be due to invalid IL or missing references) Red = CrosshairConfig.BindByte(config, section, keyPrefix + "R", defaults.r); Green = CrosshairConfig.BindByte(config, section, keyPrefix + "G", defaults.g); Blue = CrosshairConfig.BindByte(config, section, keyPrefix + "B", defaults.b); Opacity = CrosshairConfig.BindByte(config, section, keyPrefix + "Opacity", defaults.a); } internal void Register() { CrosshairConfig.AddByteOption(Red); CrosshairConfig.AddByteOption(Green); CrosshairConfig.AddByteOption(Blue); CrosshairConfig.AddByteOption(Opacity); } } internal sealed class OutlineSettings { internal const float MaxThickness = 10f; internal readonly ConfigEntry<bool> Enabled; internal readonly ConfigEntry<float> Thickness; internal readonly ColorSettings Color; internal bool Visible => Enabled.Value && Thickness.Value > 0.001f; internal OutlineSettings(ConfigFile config, string section) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) Enabled = config.Bind<bool>(section, "Outline Enabled", true, "Draw a border around this layer."); Thickness = CrosshairConfig.BindFloat(config, section, "Outline Thickness", 1f, 0f, 10f, "Border width on each side, in pixels at 1920x1080."); Color = new ColorSettings(config, section, "Outline ", new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue)); } internal void Register() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(Enabled)); CrosshairConfig.AddFloatOption(Thickness, 0f, 10f); Color.Register(); } } internal struct BarsDefaults { internal bool Enabled; internal float Length; internal float Thickness; internal float Gap; internal float GapMax; internal Color32 Fill; } internal sealed class BarsSettings { internal const float MaxLength = 64f; internal const float MaxThickness = 20f; private readonly float _gapMax; internal readonly ConfigEntry<bool> Enabled; internal readonly ConfigEntry<CrosshairMode> Mode; internal readonly ConfigEntry<float> Length; internal readonly ConfigEntry<float> Thickness; internal readonly ConfigEntry<float> Gap; internal readonly ColorSettings Fill; internal readonly OutlineSettings Outline; internal BarsSettings(ConfigFile config, string section, BarsDefaults defaults) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) _gapMax = defaults.GapMax; Enabled = config.Bind<bool>(section, "Enabled", defaults.Enabled, "Show the " + section + "."); Mode = config.Bind<CrosshairMode>(section, "Mode", CrosshairMode.Static, "Static: fixed gap. Dynamic: gap will follow actual weapon spread (not implemented yet; currently same as Static)."); Length = CrosshairConfig.BindFloat(config, section, "Length", defaults.Length, 0.5f, 64f, "Length of each arm, in pixels at 1920x1080."); Thickness = CrosshairConfig.BindFloat(config, section, "Thickness", defaults.Thickness, 0.5f, 20f, "Thickness of each arm, in pixels at 1920x1080."); Gap = CrosshairConfig.BindFloat(config, section, "Gap", defaults.Gap, 0f, _gapMax, "Distance from screen center to the inner edge of each arm, in pixels at 1920x1080."); Fill = new ColorSettings(config, section, "", defaults.Fill); Outline = new OutlineSettings(config, section); } internal void Register() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(Enabled)); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)Mode)); CrosshairConfig.AddFloatOption(Length, 0.5f, 64f); CrosshairConfig.AddFloatOption(Thickness, 0.5f, 20f); CrosshairConfig.AddFloatOption(Gap, 0f, _gapMax); Fill.Register(); Outline.Register(); } } internal sealed class CircleSettings { internal const float MaxRadius = 128f; internal const float MaxThickness = 20f; internal readonly ConfigEntry<bool> Enabled; internal readonly ConfigEntry<CrosshairMode> Mode; internal readonly ConfigEntry<float> Radius; internal readonly ConfigEntry<float> Thickness; internal readonly ColorSettings Fill; internal readonly OutlineSettings Outline; internal CircleSettings(ConfigFile config, string section) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) Enabled = config.Bind<bool>(section, "Enabled", false, "Show the circle."); Mode = config.Bind<CrosshairMode>(section, "Mode", CrosshairMode.Static, "Static: fixed radius. Dynamic: radius will follow actual weapon spread (not implemented yet; currently same as Static)."); Radius = CrosshairConfig.BindFloat(config, section, "Radius", 16f, 0f, 128f, "Distance from screen center to the inner edge of the ring, in pixels at 1920x1080."); Thickness = CrosshairConfig.BindFloat(config, section, "Thickness", 2f, 0.5f, 20f, "Ring thickness, in pixels at 1920x1080."); Fill = new ColorSettings(config, section, "", new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue)); Outline = new OutlineSettings(config, section); } internal void Register() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(Enabled)); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)Mode)); CrosshairConfig.AddFloatOption(Radius, 0f, 128f); CrosshairConfig.AddFloatOption(Thickness, 0.5f, 20f); Fill.Register(); Outline.Register(); } } internal sealed class DotSettings { internal const float MaxSize = 20f; internal readonly ConfigEntry<bool> Enabled; internal readonly ConfigEntry<float> Size; internal readonly ColorSettings Fill; internal readonly OutlineSettings Outline; internal DotSettings(ConfigFile config, string section) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) Enabled = config.Bind<bool>(section, "Enabled", false, "Show the center dot."); Size = CrosshairConfig.BindFloat(config, section, "Size", 2f, 0.5f, 20f, "Diameter of the dot, in pixels at 1920x1080."); Fill = new ColorSettings(config, section, "", new Color32((byte)0, byte.MaxValue, (byte)0, byte.MaxValue)); Outline = new OutlineSettings(config, section); } internal void Register() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(Enabled)); CrosshairConfig.AddFloatOption(Size, 0.5f, 20f); Fill.Register(); Outline.Register(); } } internal static class CrosshairDisplayPolicy { private const string StandardCrosshairAddress = "RoR2/Base/UI/StandardCrosshair.prefab"; private const string GenericSprintCrosshairPath = "Prefabs/Crosshair/SprintingCrosshair"; private static readonly string[] StockPreservingAddresses = new string[3] { "RoR2/Base/Bandit2/Bandit2Crosshair.prefab", "RoR2/Base/Toolbot/ToolbotGrenadeLauncherCrosshair.prefab", "RoR2/Base/Toolbot/ToolbotDualWieldCrosshair.prefab" }; private static readonly (string Address, string? BodyName)[] CosmeticSkillCrosshairAddresses = new(string, string)[3] { ("RoR2/Base/Bandit2/Bandit2CrosshairPrepRevolver.prefab", null), ("RoR2/Base/Bandit2/Bandit2CrosshairPrepRevolverFire.prefab", null), ("RoR2/Base/UI/BadCrosshair.prefab", "ToolbotBody") }; private static Transform? _holder; private static GameObject? _standardTemplate; private static readonly Dictionary<GameObject, GameObject?> StockPreserving = new Dictionary<GameObject, GameObject>(); private static readonly Dictionary<GameObject, string?> CosmeticSkillCrosshairs = new Dictionary<GameObject, string>(); private static readonly Dictionary<string, BodyIndex> BodyIndices = new Dictionary<string, BodyIndex>(); private static GameObject? _genericSprintCrosshair; private static bool _genericSprintCrosshairLoaded; private static int _pendingLoads; internal static bool IsReady => _pendingLoads == 0 && (Object)(object)_standardTemplate != (Object)null; internal static void Initialize(Transform holder) { _holder = holder; _pendingLoads = 1 + StockPreservingAddresses.Length + CosmeticSkillCrosshairAddresses.Length; CrosshairPrefabFactory.LoadAsync("RoR2/Base/UI/StandardCrosshair.prefab", delegate(GameObject? standard) { _standardTemplate = Build(standard, (GameObject s) => CrosshairPrefabFactory.BuildStandard(s, holder)); if ((Object)(object)_standardTemplate != (Object)null) { Plugin.Log.LogInfo((object)"Crosshair template ready."); } else { Plugin.Log.LogError((object)"Crosshair template unavailable; vanilla crosshairs will be used."); } _pendingLoads--; }); string[] stockPreservingAddresses = StockPreservingAddresses; foreach (string address in stockPreservingAddresses) { CrosshairPrefabFactory.LoadAsync(address, delegate(GameObject? vanilla) { if ((Object)(object)vanilla != (Object)null) { GameObject val = Build(vanilla, (GameObject v) => CrosshairPrefabFactory.BuildStockPreserving(v, holder)); StockPreserving[vanilla] = val; if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)(((Object)vanilla).name + ": ammo displays could not be preserved; its vanilla crosshair will be kept.")); } } _pendingLoads--; }); } (string, string)[] cosmeticSkillCrosshairAddresses = CosmeticSkillCrosshairAddresses; for (int num2 = 0; num2 < cosmeticSkillCrosshairAddresses.Length; num2++) { var (address2, bodyName) = cosmeticSkillCrosshairAddresses[num2]; CrosshairPrefabFactory.LoadAsync(address2, delegate(GameObject? prefab) { if ((Object)(object)prefab != (Object)null) { CosmeticSkillCrosshairs[prefab] = bodyName; } _pendingLoads--; }); } } internal static void Shutdown() { _standardTemplate = null; StockPreserving.Clear(); CosmeticSkillCrosshairs.Clear(); BodyIndices.Clear(); _holder = null; } internal static GameObject? ChooseTemplate(CharacterBody body, GameObject picked) { if (!IsReady || !Object.op_Implicit((Object)(object)picked)) { return null; } if (StockPreserving.ContainsKey(picked) || IsOrdinaryCrosshair(body, picked) || IsActiveWeaponCrosshair(body, picked)) { return TemplateFor(picked); } if (IsGenericSprintCrosshair(body, picked) || IsCosmeticSkillCrosshair(body, picked)) { return TemplateFor(ActiveWeaponCrosshair(body) ?? body.defaultCrosshairPrefab); } return null; } private static GameObject? TemplateFor(GameObject? vanilla) { if ((Object)(object)vanilla != (Object)null && StockPreserving.TryGetValue(vanilla, out GameObject value)) { return value; } return _standardTemplate; } private static GameObject? ActiveWeaponCrosshair(CharacterBody body) { GenericSkill val = (Object.op_Implicit((Object)(object)body.skillLocator) ? body.skillLocator.primary : null); object result; if (Object.op_Implicit((Object)(object)val)) { SkillDef skillDef = val.skillDef; ToolbotWeaponSkillDef val2 = (ToolbotWeaponSkillDef)(object)((skillDef is ToolbotWeaponSkillDef) ? skillDef : null); if (val2 != null && Object.op_Implicit((Object)(object)val2.crosshairPrefab)) { result = val2.crosshairPrefab; goto IL_004a; } } result = null; goto IL_004a; IL_004a: return (GameObject?)result; } private static bool IsActiveWeaponCrosshair(CharacterBody body, GameObject picked) { GameObject val = ActiveWeaponCrosshair(body); return (Object)(object)val != (Object)null && (Object)(object)picked == (Object)(object)val; } private static bool IsCosmeticSkillCrosshair(CharacterBody body, GameObject picked) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Invalid comparison between Unknown and I4 //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (!CosmeticSkillCrosshairs.TryGetValue(picked, out string value)) { return false; } if (value == null) { return true; } if (!BodyIndices.TryGetValue(value, out var value2) || (int)value2 == -1) { value2 = BodyCatalog.FindBodyIndex(value); BodyIndices[value] = value2; } return (int)value2 != -1 && body.bodyIndex == value2; } private static GameObject? Build(GameObject? source, Func<GameObject, GameObject?> build) { if ((Object)(object)source == (Object)null || (Object)(object)_holder == (Object)null) { return null; } try { return build(source); } catch (Exception arg) { Plugin.Log.LogError((object)$"Could not build crosshair template from {((Object)source).name}: {arg}"); return null; } } private static bool IsOrdinaryCrosshair(CharacterBody body, GameObject picked) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Invalid comparison between Unknown and I4 if ((Object)(object)picked == (Object)(object)body.defaultCrosshairPrefab) { return true; } SkillCrosshairController val = default(SkillCrosshairController); if (((Component)body).TryGetComponent<SkillCrosshairController>(ref val) && val.options != null) { SkillDefCrosshairOptions[] options = val.options; foreach (SkillDefCrosshairOptions val2 in options) { if (val2 != null && (int)val2.priority < 1 && (Object)(object)val2.crosshairPrefab == (Object)(object)picked) { return true; } } } return false; } private static bool IsGenericSprintCrosshair(CharacterBody body, GameObject picked) { if (!body.isSprinting || !body.useSprintCrosshair || Object.op_Implicit((Object)(object)body.sprintCrosshairPrefabOverride)) { return false; } GameObject genericSprintCrosshair = GetGenericSprintCrosshair(); return (Object)(object)genericSprintCrosshair != (Object)null && (Object)(object)picked == (Object)(object)genericSprintCrosshair; } private static GameObject? GetGenericSprintCrosshair() { if (!_genericSprintCrosshairLoaded) { _genericSprintCrosshairLoaded = true; _genericSprintCrosshair = LegacyResourcesAPI.Load<GameObject>("Prefabs/Crosshair/SprintingCrosshair"); if ((Object)(object)_genericSprintCrosshair == (Object)null) { Plugin.Log.LogWarning((object)"Could not load 'Prefabs/Crosshair/SprintingCrosshair'; the vanilla sprint crosshair will be shown."); } } return _genericSprintCrosshair; } } internal readonly struct PixelFrame { internal readonly float ResolutionScale; internal readonly float PixelsPerUnit; internal readonly float CenterFraction; internal readonly Vector2 Center; internal readonly Vector2 OriginOffset; internal PixelFrame(float resolutionScale, float pixelsPerUnit, float centerFraction, Vector2 anchorScreen, Vector2 rootScreen) { //IL_0017: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0044: 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) ResolutionScale = resolutionScale; PixelsPerUnit = pixelsPerUnit; CenterFraction = centerFraction; Center = new Vector2(SnapToGrid(anchorScreen.x, centerFraction), SnapToGrid(anchorScreen.y, centerFraction)); OriginOffset = Center - rootScreen; } internal static float FractionFor(float logicalSize, float resolutionScale) { return (Mathf.Max(1, RoundPx(logicalSize * resolutionScale)) % 2 == 0) ? 0f : 0.5f; } internal int Width(float logical) { return Mathf.Max(1, RoundPx(logical * ResolutionScale)); } internal int CenteredSize(float logical) { float num = logical * ResolutionScale; if (CenterFraction == 0f) { return Mathf.Max(2, 2 * RoundPx(num * 0.5f)); } return Mathf.Max(1, 2 * (int)Mathf.Floor(num * 0.5f) + 1); } internal float EdgeDistance(float logical, float extraPixels = 0f) { float num = Mathf.Max(0f, Mathf.Max(0f, logical) * ResolutionScale + extraPixels); return Mathf.Floor(CenterFraction + num + 0.5f) - CenterFraction; } internal float ToLocal(float pixels) { return pixels / PixelsPerUnit; } internal void Place(RectTransform rect, Vector4 pixelRect) { //IL_0003: 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_0016: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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) Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor((pixelRect.x + pixelRect.z) * 0.5f, (pixelRect.y + pixelRect.w) * 0.5f); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(pixelRect.z - pixelRect.x, pixelRect.w - pixelRect.y); rect.anchoredPosition = (OriginOffset + val) / PixelsPerUnit; rect.sizeDelta = val2 / PixelsPerUnit; } internal static int RoundPx(float value) { return (int)Mathf.Floor(value + 0.5f); } private static float SnapToGrid(float value, float fraction) { return Mathf.Floor(value - fraction + 0.5f) + fraction; } } internal sealed class BorderedRect { private static readonly string[] SideNames = new string[4] { "Top", "Bottom", "Left", "Right" }; private readonly Image _fill; private readonly Image[] _strips = (Image[])(object)new Image[4]; private BorderedRect(Transform layer, string name) { _fill = Find(layer, "Fill" + name); for (int i = 0; i < 4; i++) { _strips[i] = Find(layer, "Outline" + name + SideNames[i]); } } internal static BorderedRect Bind(Transform layer, string name) { return new BorderedRect(layer, name); } internal static void BuildBorder(Transform layer, string name) { string[] sideNames = SideNames; foreach (string text in sideNames) { CrosshairPrefabFactory.CreateImage("Outline" + name + text, layer); } } internal static void BuildFill(Transform layer, string name) { CrosshairPrefabFactory.CreateImage("Fill" + name, layer); } internal void Apply(in PixelFrame frame, Vector4 r, Color fill, int border, Color borderColor) { //IL_0008: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: 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_00d1: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) Show(_fill, in frame, r, fill); if (border <= 0) { Image[] strips = _strips; foreach (Image val in strips) { ((Behaviour)val).enabled = false; } } else { float num = border; Show(_strips[0], in frame, new Vector4(r.x - num, r.w, r.z + num, r.w + num), borderColor); Show(_strips[1], in frame, new Vector4(r.x - num, r.y - num, r.z + num, r.y), borderColor); Show(_strips[2], in frame, new Vector4(r.x - num, r.y, r.x, r.w), borderColor); Show(_strips[3], in frame, new Vector4(r.z, r.y, r.z + num, r.w), borderColor); } } internal void Hide() { ((Behaviour)_fill).enabled = false; Image[] strips = _strips; foreach (Image val in strips) { ((Behaviour)val).enabled = false; } } private static void Show(Image image, in PixelFrame frame, Vector4 r, Color color) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) frame.Place(((Graphic)image).rectTransform, r); ((Graphic)image).color = color; ((Behaviour)image).enabled = true; } private static Image Find(Transform layer, string name) { return ((Component)layer.Find(name)).GetComponent<Image>(); } } internal sealed class BarsLayer { private static readonly string[] ArmNames = new string[4] { "Left", "Right", "Top", "Bottom" }; private readonly BarsSettings _settings; private readonly BorderedRect[] _arms = new BorderedRect[4]; internal bool Enabled => _settings.Enabled.Value; internal float Thickness => _settings.Thickness.Value; internal BarsLayer(Transform root, string layerName, BarsSettings settings) { _settings = settings; Transform layer = root.Find(layerName); for (int i = 0; i < 4; i++) { _arms[i] = BorderedRect.Bind(layer, ArmNames[i]); } } internal static void Build(Transform root, string layerName) { Transform layer = (Transform)(object)CrosshairPrefabFactory.CreateRect(layerName, root); string[] armNames = ArmNames; foreach (string name in armNames) { BorderedRect.BuildBorder(layer, name); } string[] armNames2 = ArmNames; foreach (string name2 in armNames2) { BorderedRect.BuildFill(layer, name2); } } internal void Apply(in PixelFrame frame, float dynamicOffset) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) if (!Enabled) { BorderedRect[] arms = _arms; foreach (BorderedRect borderedRect in arms) { borderedRect.Hide(); } return; } float extraPixels = ((_settings.Mode.Value == CrosshairMode.Dynamic) ? dynamicOffset : 0f); float num = (float)frame.CenteredSize(_settings.Thickness.Value) * 0.5f; float num2 = frame.EdgeDistance(_settings.Gap.Value, extraPixels); float num3 = num2 + (float)frame.Width(_settings.Length.Value); Color value = _settings.Fill.Value; Color value2 = _settings.Outline.Color.Value; int border = (_settings.Outline.Visible ? frame.Width(_settings.Outline.Thickness.Value) : 0); _arms[0].Apply(in frame, new Vector4(0f - num3, 0f - num, 0f - num2, num), value, border, value2); _arms[1].Apply(in frame, new Vector4(num2, 0f - num, num3, num), value, border, value2); _arms[2].Apply(in frame, new Vector4(0f - num, num2, num, num3), value, border, value2); _arms[3].Apply(in frame, new Vector4(0f - num, 0f - num3, num, 0f - num2), value, border, value2); } } internal sealed class RingPart { private const float SegmentPixels = 1.5f; private const int MinSegments = 24; private const int MaxSegments = 512; private readonly RingMesh _mesh; private readonly Image _image; private RingPart(Transform layer, string name) { _mesh = ((Component)layer.Find(name)).GetComponent<RingMesh>(); _image = _mesh.Image; } internal static RingPart Bind(Transform layer, string name) { return new RingPart(layer, name); } internal static void Build(Transform layer, string name) { CrosshairPrefabFactory.CreateImage(name, layer); ((Component)layer.Find(name)).gameObject.AddComponent<RingMesh>(); } internal void Apply(in PixelFrame frame, float inner, float outer, int border, Color fill, Color borderColor) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) float num = outer + (float)border + 1f; int segments = Mathf.Clamp(Mathf.CeilToInt(MathF.PI * 2f * (outer + (float)border) / 1.5f), 24, 512); frame.Place(((Graphic)_image).rectTransform, new Vector4(0f - num, 0f - num, num, num)); ((Graphic)_image).color = Color.white; _mesh.SetShape(frame.ToLocal(inner), frame.ToLocal(outer), frame.ToLocal(border), frame.ToLocal(1f), fill, borderColor, segments); ((Behaviour)_image).enabled = true; } internal void Hide() { ((Behaviour)_image).enabled = false; } } internal sealed class CenterDotLayer { private const string DotName = "Dot"; private readonly DotSettings _settings; private readonly RingPart _dot; internal bool Enabled => _settings.Enabled.Value; internal float Size => _settings.Size.Value; internal CenterDotLayer(Transform root, string layerName, DotSettings settings) { _settings = settings; _dot = RingPart.Bind(root.Find(layerName), "Dot"); } internal static void Build(Transform root, string layerName) { RingPart.Build((Transform)(object)CrosshairPrefabFactory.CreateRect(layerName, root), "Dot"); } internal void Apply(in PixelFrame frame) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) if (!Enabled) { _dot.Hide(); return; } float outer = (float)frame.CenteredSize(_settings.Size.Value) * 0.5f; int border = (_settings.Outline.Visible ? frame.Width(_settings.Outline.Thickness.Value) : 0); _dot.Apply(in frame, 0f, outer, border, _settings.Fill.Value, _settings.Outline.Color.Value); } } internal sealed class CircleLayer { private const string RingName = "Ring"; private readonly CircleSettings _settings; private readonly RingPart _ring; internal CircleLayer(Transform root, string layerName, CircleSettings settings) { _settings = settings; _ring = RingPart.Bind(root.Find(layerName), "Ring"); } internal static void Build(Transform root, string layerName) { RingPart.Build((Transform)(object)CrosshairPrefabFactory.CreateRect(layerName, root), "Ring"); } internal void Apply(in PixelFrame frame, float dynamicOffset) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) if (!_settings.Enabled.Value) { _ring.Hide(); return; } float extraPixels = ((_settings.Mode.Value == CrosshairMode.Dynamic) ? dynamicOffset : 0f); float num = frame.EdgeDistance(_settings.Radius.Value, extraPixels); float outer = num + (float)frame.Width(_settings.Thickness.Value); int border = (_settings.Outline.Visible ? frame.Width(_settings.Outline.Thickness.Value) : 0); _ring.Apply(in frame, num, outer, border, _settings.Fill.Value, _settings.Outline.Color.Value); } } internal enum CrosshairMode { Static, Dynamic } internal static class CrosshairPrefabFactory { internal const string ProceduralRootName = "ProceduralCrosshair"; internal const string CircleLayerName = "Circle"; internal const string OuterBarsLayerName = "OuterBars"; internal const string InnerBarsLayerName = "InnerBars"; internal const string CenterDotLayerName = "CenterDot"; internal static void LoadAsync(string address, Action<GameObject?> onLoaded) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) AsyncOperationHandle<GameObject> val = Addressables.LoadAssetAsync<GameObject>((object)address); val.Completed += delegate(AsyncOperationHandle<GameObject> op) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 if ((int)op.Status != 1 || (Object)(object)op.Result == (Object)null) { Plugin.Log.LogError((object)$"Could not load '{address}': {op.OperationException}"); onLoaded(null); } else { onLoaded(op.Result); } }; } internal static GameObject BuildStandard(GameObject standardCrosshair, Transform holder) { CrosshairController controller; GameObject val = Clone(standardCrosshair, holder, "RoR2CustomCrosshair", out controller); Plugin.Log.LogDebug((object)("StandardCrosshair components: " + string.Join(", ", from c in val.GetComponents<Component>() select ((object)c).GetType().Name))); controller.spriteSpreadPositions = Array.Empty<SpritePosition>(); controller.skillStockSpriteDisplays = Array.Empty<SkillStockSpriteDisplay>(); controller.remapSprites = Array.Empty<RawImage>(); HideVanillaVisuals(val, new HashSet<Transform>()); AddProceduralCrosshair(val); return val; } internal static GameObject? BuildStockPreserving(GameObject vanillaCrosshair, Transform holder) { //IL_0043: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) CrosshairController controller; GameObject val = Clone(vanillaCrosshair, holder, "RoR2CustomCrosshair_" + ((Object)vanillaCrosshair).name, out controller); Transform transform = val.transform; List<SkillStockSpriteDisplay> list = new List<SkillStockSpriteDisplay>(); SkillStockSpriteDisplay[] array = controller.skillStockSpriteDisplays ?? Array.Empty<SkillStockSpriteDisplay>(); foreach (SkillStockSpriteDisplay val2 in array) { if (Object.op_Implicit((Object)(object)val2.target) && !IsAtCenter(transform, val2.target.transform)) { list.Add(val2); } } if (list.Count == 0) { Object.Destroy((Object)(object)val); return null; } controller.spriteSpreadPositions = Array.Empty<SpritePosition>(); controller.remapSprites = Array.Empty<RawImage>(); controller.skillStockSpriteDisplays = list.ToArray(); HashSet<Transform> hashSet = new HashSet<Transform>(); foreach (SkillStockSpriteDisplay item in list) { Transform val3 = item.target.transform; while ((Object)(object)val3 != (Object)null && (Object)(object)val3 != (Object)(object)transform) { hashSet.Add(val3); val3 = val3.parent; } } HideVanillaVisuals(val, hashSet); AddProceduralCrosshair(val); Plugin.Log.LogDebug((object)(((Object)vanillaCrosshair).name + ": keeping vanilla stock displays " + string.Join(", ", list.Select((SkillStockSpriteDisplay d) => ((Object)d.target).name)) + "; spread artwork removed.")); return val; } private static GameObject Clone(GameObject source, Transform holder, string name, out CrosshairController controller) { GameObject val = Object.Instantiate<GameObject>(source, holder, false); ((Object)val).name = name; HudElement val2 = default(HudElement); if (!val.TryGetComponent<CrosshairController>(ref controller) || !val.TryGetComponent<HudElement>(ref val2)) { Object.Destroy((Object)(object)val); throw new InvalidOperationException(((Object)source).name + " no longer has CrosshairController + HudElement."); } return val; } private static bool IsAtCenter(Transform root, Transform target) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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) Vector3 val = root.InverseTransformPoint(target.position); return ((Vector3)(ref val)).sqrMagnitude < 1f; } private static void HideVanillaVisuals(GameObject template, HashSet<Transform> keep) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown foreach (Transform item in template.transform) { Transform val = item; if (!keep.Contains(val)) { ((Component)val).gameObject.SetActive(false); } } Graphic[] components = template.GetComponents<Graphic>(); foreach (Graphic val2 in components) { ((Behaviour)val2).enabled = false; } } private static void AddProceduralCrosshair(GameObject template) { RectTransform root = CreateRect("ProceduralCrosshair", template.transform); CircleLayer.Build((Transform)(object)root, "Circle"); BarsLayer.Build((Transform)(object)root, "OuterBars"); BarsLayer.Build((Transform)(object)root, "InnerBars"); CenterDotLayer.Build((Transform)(object)root, "CenterDot"); template.AddComponent<ProceduralCrosshairView>(); } internal static RectTransform CreateRect(string name, Transform parent) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) //IL_007f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(parent, false); val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = Vector2.zero; val2.sizeDelta = Vector2.zero; return val2; } internal static void CreateImage(string name, Transform parent) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) RectTransform val = CreateRect(name, parent); ((Component)val).gameObject.AddComponent<CanvasRenderer>(); Image val2 = ((Component)val).gameObject.AddComponent<Image>(); ((Graphic)val2).raycastTarget = false; ((MaskableGraphic)val2).maskable = false; ((Graphic)val2).color = Color.clear; ((Behaviour)val2).enabled = false; } } internal readonly struct SpreadSample { internal readonly float CurrentDegrees; internal readonly float RestingDegrees; internal readonly float BloomDegrees; internal SpreadSample(float currentDegrees, float restingDegrees, float bloomDegrees) { CurrentDegrees = currentDegrees; RestingDegrees = restingDegrees; BloomDegrees = bloomDegrees; } } internal interface ISpreadSource { bool LogSamples { get; } bool CanHandle(CharacterBody body); bool TrySample(CharacterBody body, out SpreadSample sample); } internal sealed class SpreadSourceResolver { private readonly ISpreadSource[] _sources; private CharacterBody? _body; private ISpreadSource? _source; internal SpreadSourceResolver(params ISpreadSource[] sources) { _sources = sources; } internal bool TrySample(CharacterBody body, out SpreadSample sample, out ISpreadSource? source) { if ((Object)(object)body != (Object)(object)_body) { _body = body; _source = null; ISpreadSource[] sources = _sources; foreach (ISpreadSource spreadSource in sources) { if (spreadSource.CanHandle(body)) { _source = spreadSource; break; } } } source = _source; sample = default(SpreadSample); return _source != null && _source.TrySample(body, out sample); } } internal static class SpreadProjection { internal static float HalfAngleToPixels(float halfAngleDegrees, Camera camera) { float num = camera.fieldOfView * 0.5f * (MathF.PI / 180f); if (num <= 0f || halfAngleDegrees <= 0f) { return 0f; } float num2 = Mathf.Min(halfAngleDegrees, 89f) * (MathF.PI / 180f); return Mathf.Tan(num2) / Mathf.Tan(num) * ((float)camera.pixelHeight * 0.5f); } } internal sealed class GenericBulletSpread { internal readonly int BulletCount; internal readonly float MaxSpread; internal readonly float YawScale; internal readonly float PitchScale; private GenericBulletSpread(GenericBulletBaseState state) { BulletCount = state.bulletCount; MaxSpread = state.maxSpread; YawScale = state.spreadYawScale; PitchScale = state.spreadPitchScale; } internal static T? ReadState<T>(Type stateType) where T : GenericBulletBaseState { try { EntityState obj = EntityStateCatalog.InstantiateState(stateType); return (T)(object)((obj is T) ? obj : null); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not read configuration of " + stateType.FullName + ": " + ex.Message)); return default(T); } } internal static GenericBulletSpread From(GenericBulletBaseState state) { return new GenericBulletSpread(state); } internal float HorizontalDegrees(float bloomDegrees) { return (MaxSpread + bloomDegrees) * YawScale; } internal float VerticalDegrees(float bloomDegrees) { return (MaxSpread + bloomDegrees) * PitchScale; } internal string Describe() { return $"{BulletCount} bullet(s), maxSpread {MaxSpread:0.###}, yaw x{YawScale:0.###}, pitch x{PitchScale:0.###}"; } } internal sealed class HudCrosshairDriver : MonoBehaviour { private static readonly ISpreadSource[] SpreadSources = new ISpreadSource[3] { new CommandoSpreadSource(), new BanditSpreadSource(), new ToolbotSpreadSource() }; private const float OffsetStepPixels = 0.25f; private const float SpreadLogInterval = 1f; private float _nextSpreadLogTime; private readonly SpreadSourceResolver _spreadResolver = new SpreadSourceResolver(SpreadSources); private CrosshairManager? _crosshairManager; private bool _replacing; internal static void Attach(HUD hud) { if (!Object.op_Implicit((Object)(object)((Component)hud).GetComponent<HudCrosshairDriver>())) { ((Component)hud).gameObject.AddComponent<HudCrosshairDriver>(); } } private void Awake() { _crosshairManager = ((Component)this).GetComponent<CrosshairManager>(); if (!Object.op_Implicit((Object)(object)_crosshairManager)) { Plugin.Log.LogWarning((object)("HUD '" + ((Object)this).name + "' has no CrosshairManager; custom crosshair unavailable.")); } } private void OnEnable() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)_crosshairManager)) { _crosshairManager.pickCrosshairGlobal += new PickCrosshairDelegate(OnPickCrosshair); } } private void OnDisable() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)_crosshairManager)) { _crosshairManager.pickCrosshairGlobal -= new PickCrosshairDelegate(OnPickCrosshair); } SetReplacing(replacing: false, null); } private void OnPickCrosshair(CrosshairManager manager, ref GameObject crosshairPrefab) { CharacterBody ownLiveBody = GetOwnLiveBody(manager); GameObject val = (((Object)(object)ownLiveBody != (Object)null && CrosshairConfig.Enabled.Value) ? CrosshairDisplayPolicy.ChooseTemplate(ownLiveBody, crosshairPrefab) : null); if ((Object)(object)val != (Object)null) { crosshairPrefab = val; } SetReplacing((Object)(object)val != (Object)null, ownLiveBody); } internal DynamicOffsets GetDynamicOffsets() { if (!_replacing || !Object.op_Implicit((Object)(object)_crosshairManager)) { return default(DynamicOffsets); } CameraRigController cameraRigController = _crosshairManager.cameraRigController; CharacterBody ownLiveBody = GetOwnLiveBody(_crosshairManager); Camera val = (Object.op_Implicit((Object)(object)cameraRigController) ? cameraRigController.sceneCam : null); if ((Object)(object)ownLiveBody == (Object)null || (Object)(object)val == (Object)null || !_spreadResolver.TrySample(ownLiveBody, out SpreadSample sample, out ISpreadSource source)) { return default(DynamicOffsets); } float num = SpreadProjection.HalfAngleToPixels(sample.CurrentDegrees, val); float num2 = SpreadProjection.HalfAngleToPixels(sample.RestingDegrees, val); float num3 = Mathf.Round(Mathf.Max(0f, num - num2) / 0.25f) * 0.25f; if (source.LogSamples) { LogSpreadSample(source, in sample, val, num, num3); } return new DynamicOffsets(num3, num3, num3); } private void LogSpreadSample(ISpreadSource source, in SpreadSample sample, Camera camera, float currentPixels, float offsetPixels) { if (!(offsetPixels <= 0f) && !(Time.unscaledTime < _nextSpreadLogTime)) { _nextSpreadLogTime = Time.unscaledTime + 1f; Plugin.Log.LogDebug((object)($"[Spread] {source.GetType().Name}: bloom {sample.BloomDegrees:0.###} deg -> spread {sample.CurrentDegrees:0.###} deg " + $"(rest {sample.RestingDegrees:0.###}), vertical FOV {camera.fieldOfView:0.#}, camera {camera.pixelWidth}x{camera.pixelHeight} -> " + $"cone radius {currentPixels:0.#} px, dynamic offset +{offsetPixels:0.##} px.")); } } private static CharacterBody? GetOwnLiveBody(CrosshairManager manager) { CameraRigController cameraRigController = manager.cameraRigController; if (!Object.op_Implicit((Object)(object)cameraRigController) || cameraRigController.hasOverride) { return null; } LocalUser localUserViewer = cameraRigController.localUserViewer; CharacterBody targetBody = cameraRigController.targetBody; if (localUserViewer == null || !Object.op_Implicit((Object)(object)targetBody) || (Object)(object)localUserViewer.cachedBodyObject != (Object)(object)((Component)targetBody).gameObject) { return null; } if (!Object.op_Implicit((Object)(object)targetBody.healthComponent) || !targetBody.healthComponent.alive) { return null; } return targetBody; } private void SetReplacing(bool replacing, CharacterBody? body) { if (replacing != _replacing) { _replacing = replacing; Plugin.Log.LogDebug((object)(replacing ? ("Custom crosshair active for " + body.GetDisplayName() + " (" + ((Object)body).name + ").") : "Custom crosshair released; vanilla crosshair logic in control.")); } } } internal static class ModIcon { private const string ResourceName = "RoR2CustomCrosshair.icon.png"; private static Sprite? _sprite; internal static Sprite? Load() { //IL_004a: 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) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_sprite != (Object)null) { return _sprite; } try { byte[] array = ReadResource(); if (array == null) { Plugin.Log.LogWarning((object)"Embedded resource 'RoR2CustomCrosshair.icon.png' not found; RiskOfOptions will show its default icon."); return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true) { name = "RoR2CustomCrosshairIcon", filterMode = (FilterMode)2, wrapMode = (TextureWrapMode)1 }; if (!ImageConversion.LoadImage(val, array, true)) { Object.Destroy((Object)(object)val); Plugin.Log.LogWarning((object)"Could not decode the embedded icon; RiskOfOptions will show its default icon."); return null; } Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); ((Object)val2).name = ((Object)val).name; ((Object)val).hideFlags = (HideFlags)32; ((Object)val2).hideFlags = (HideFlags)32; _sprite = val2; return _sprite; } catch (Exception arg) { Plugin.Log.LogWarning((object)$"Could not load the mod icon; RiskOfOptions will show its default icon. {arg}"); return null; } } private static byte[]? ReadResource() { using Stream stream = typeof(ModIcon).Assembly.GetManifestResourceStream("RoR2CustomCrosshair.icon.png"); if (stream == null) { return null; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } } [BepInPlugin("com.example.ror2customcrosshair", "RoR2 Custom Crosshair", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { [CompilerGenerated] private static class <>O { public static hook_Awake <0>__HUD_Awake; } public const string PluginGuid = "com.example.ror2customcrosshair"; public const string PluginName = "RoR2 Custom Crosshair"; public const string PluginVersion = "0.1.0"; private GameObject? _prefabHolder; internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; CrosshairConfig.Bind(((BaseUnityPlugin)this).Config); CrosshairConfig.RegisterRiskOfOptions(); _prefabHolder = new GameObject("RoR2CustomCrosshair_Templates"); _prefabHolder.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_prefabHolder); CrosshairDisplayPolicy.Initialize(_prefabHolder.transform); object obj = <>O.<0>__HUD_Awake; if (obj == null) { hook_Awake val = HUD_Awake; <>O.<0>__HUD_Awake = val; obj = (object)val; } HUD.Awake += (hook_Awake)obj; Log.LogInfo((object)"RoR2 Custom Crosshair 0.1.0 loaded."); } private static void HUD_Awake(orig_Awake orig, HUD self) { orig.Invoke(self); HudCrosshairDriver.Attach(self); } private void OnDestroy() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown object obj = <>O.<0>__HUD_Awake; if (obj == null) { hook_Awake val = HUD_Awake; <>O.<0>__HUD_Awake = val; obj = (object)val; } HUD.Awake -= (hook_Awake)obj; HudCrosshairDriver[] array = Object.FindObjectsOfType<HudCrosshairDriver>(); foreach (HudCrosshairDriver hudCrosshairDriver in array) { Object.Destroy((Object)(object)hudCrosshairDriver); } CrosshairDisplayPolicy.Shutdown(); if ((Object)(object)_prefabHolder != (Object)null) { Object.Destroy((Object)(object)_prefabHolder); } } } internal readonly struct DynamicOffsets : IEquatable<DynamicOffsets> { internal readonly float InnerBars; internal readonly float OuterBars; internal readonly float Circle; internal DynamicOffsets(float innerBars, float outerBars, float circle) { InnerBars = innerBars; OuterBars = outerBars; Circle = circle; } public bool Equals(DynamicOffsets other) { return InnerBars == other.InnerBars && OuterBars == other.OuterBars && Circle == other.Circle; } } internal sealed class ProceduralCrosshairView : MonoBehaviour { private const float ReferenceWidth = 1920f; private const float ReferenceHeight = 1080f; private static int _loggedScreenWidth = -1; private static int _loggedScreenHeight = -1; private static float _loggedPixelsPerUnit = -1f; private RectTransform _rect = null; private RectTransform _root = null; private CircleLayer _circle = null; private BarsLayer _outerBars = null; private BarsLayer _innerBars = null; private CenterDotLayer _centerDot = null; private Canvas? _canvas; private HudCrosshairDriver? _driver; private int _lastRevision = -1; private int _lastScreenWidth = -1; private int _lastScreenHeight = -1; private float _lastPixelsPerUnit = -1f; private Vector2 _lastRootScreen; private Vector2 _lastAnchorScreen; private DynamicOffsets _lastOffsets; private void Awake() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown _rect = (RectTransform)((Component)this).transform; _root = (RectTransform)((Component)this).transform.Find("ProceduralCrosshair"); _circle = new CircleLayer((Transform)(object)_root, "Circle", CrosshairConfig.Circle); _outerBars = new BarsLayer((Transform)(object)_root, "OuterBars", CrosshairConfig.OuterBars); _innerBars = new BarsLayer((Transform)(object)_root, "InnerBars", CrosshairConfig.InnerBars); _centerDot = new CenterDotLayer((Transform)(object)_root, "CenterDot", CrosshairConfig.CenterDot); Refresh(); } private void OnTransformParentChanged() { _canvas = null; _driver = null; } private void LateUpdate() { Refresh(); } private void Refresh() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0169: 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_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: 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_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: 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_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_canvas == (Object)null) { _canvas = ((Component)this).GetComponentInParent<Canvas>(); if ((Object)(object)_canvas == (Object)null) { return; } } Canvas rootCanvas = _canvas.rootCanvas; float pixelsPerUnit = GetPixelsPerUnit(rootCanvas); if (pixelsPerUnit <= 0f) { return; } Camera val = (((int)rootCanvas.renderMode == 0) ? null : rootCanvas.worldCamera); Vector2 val2 = RectTransformUtility.WorldToScreenPoint(val, ((Transform)_root).position); Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val, GetIntendedCenterWorld()); if ((Object)(object)_driver == (Object)null) { _driver = ((Component)this).GetComponentInParent<HudCrosshairDriver>(); } DynamicOffsets dynamicOffsets = (((Object)(object)_driver != (Object)null) ? _driver.GetDynamicOffsets() : default(DynamicOffsets)); if (_lastRevision == CrosshairConfig.Revision && _lastScreenWidth == Screen.width && _lastScreenHeight == Screen.height && Mathf.Approximately(_lastPixelsPerUnit, pixelsPerUnit)) { Vector2 val4 = _lastRootScreen - val2; if (((Vector2)(ref val4)).sqrMagnitude < 1E-06f) { val4 = _lastAnchorScreen - val3; if (((Vector2)(ref val4)).sqrMagnitude < 1E-06f && _lastOffsets.Equals(dynamicOffsets)) { return; } } } PixelFrame frame = CreateFrame(pixelsPerUnit, val3, val2); _circle.Apply(in frame, dynamicOffsets.Circle); _outerBars.Apply(in frame, dynamicOffsets.OuterBars); _innerBars.Apply(in frame, dynamicOffsets.InnerBars); _centerDot.Apply(in frame); LogLayoutOnce(rootCanvas, in frame, val2, val3); _lastRevision = CrosshairConfig.Revision; _lastScreenWidth = Screen.width; _lastScreenHeight = Screen.height; _lastPixelsPerUnit = pixelsPerUnit; _lastRootScreen = val2; _lastAnchorScreen = val3; _lastOffsets = dynamicOffsets; } private PixelFrame CreateFrame(float pixelsPerUnit, Vector2 anchorScreen, Vector2 rootScreen) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) float resolutionScale = Mathf.Min((float)Screen.width / 1920f, (float)Screen.height / 1080f); float centerFraction = (_innerBars.Enabled ? PixelFrame.FractionFor(_innerBars.Thickness, resolutionScale) : (_outerBars.Enabled ? PixelFrame.FractionFor(_outerBars.Thickness, resolutionScale) : (_centerDot.Enabled ? PixelFrame.FractionFor(_centerDot.Size, resolutionScale) : 0f))); return new PixelFrame(resolutionScale, pixelsPerUnit, centerFraction, anchorScreen, rootScreen); } private float GetPixelsPerUnit(Canvas rootCanvas) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) float x = ((Component)rootCanvas).transform.lossyScale.x; if (x <= 0f) { return 0f; } return rootCanvas.scaleFactor * (((Transform)_root).lossyScale.x / x); } private Vector3 GetIntendedCenterWorld() { //IL_002d: 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_003e: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0050: Unknown result type (might be due to invalid IL or missing references) Transform parent = ((Transform)_rect).parent; if ((Object)(object)parent == (Object)null) { return ((Transform)_root).position; } return ((Transform)_root).position - parent.TransformVector(Vector2.op_Implicit(_rect.anchoredPosition)); } private void LogLayoutOnce(Canvas rootCanvas, in PixelFrame frame, Vector2 rootScreen, Vector2 anchorScreen) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) if (_loggedScreenWidth != Screen.width || _loggedScreenHeight != Screen.height || !Mathf.Approximately(_loggedPixelsPerUnit, frame.PixelsPerUnit)) { _loggedScreenWidth = Screen.width; _loggedScreenHeight = Screen.height; _loggedPixelsPerUnit = frame.PixelsPerUnit; Plugin.Log.LogDebug((object)($"Crosshair layout: screen {Screen.width}x{Screen.height}, canvas {rootCanvas.renderMode} " + $"scaleFactor {rootCanvas.scaleFactor:0.###} pixelPerfect {rootCanvas.pixelPerfect}, " + $"px/unit {frame.PixelsPerUnit:0.###}, crosshair anchoredPosition {_rect.anchoredPosition}, " + $"root at {rootScreen.x:0.###},{rootScreen.y:0.###} px, anchor {anchorScreen.x:0.###},{anchorScreen.y:0.###} px, " + $"snapped center {frame.Center.x},{frame.Center.y}.")); } } } [RequireComponent(typeof(Image))] internal sealed class RingMesh : MonoBehaviour, IMeshModifier { private readonly struct Stop { internal readonly float Radius; internal readonly Color32 Color; internal Stop(float radius, Color32 color) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) Radius = radius; Color = color; } } private readonly struct Shape : IEquatable<Shape> { internal readonly float Inner; internal readonly float Outer; internal readonly float Border; internal readonly float Feather; internal readonly Color32 Fill; internal readonly Color32 BorderColor; internal readonly int Segments; internal Shape(float inner, float outer, float border, float feather, Color32 fill, Color32 borderColor, int segments) { //IL_001f: 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_0027: 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) Inner = inner; Outer = outer; Border = border; Feather = feather; Fill = fill; BorderColor = borderColor; Segments = segments; } public bool Equals(Shape o) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) return Inner == o.Inner && Outer == o.Outer && Border == o.Border && Feather == o.Feather && Segments == o.Segments && Same(Fill, o.Fill) && Same(BorderColor, o.BorderColor); } private static bool Same(Color32 a, Color32 b) { //IL_0000: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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) return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a; } } private readonly List<Stop> _stops = new List<Stop>(); private Shape _shape; private bool _hasShape; private Image? _image; internal Image Image => ((Object)(object)_image != (Object)null) ? _image : (_image = ((Component)this).GetComponent<Image>()); internal void SetShape(float inner, float outer, float border, float feather, Color fill, Color borderColor, int segments) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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) Shape shape = new Shape(inner, outer, border, feather, Color32.op_Implicit(fill), Color32.op_Implicit(borderColor), segments); if (!_hasShape || !shape.Equals(_shape)) { _shape = shape; _hasShape = true; ((Graphic)Image).SetVerticesDirty(); } } public void ModifyMesh(Mesh mesh) { } public void ModifyMesh(VertexHelper vh) { //IL_0083: 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_008c: Unknown result type (might be due to invalid IL or missing references) vh.Clear(); if (!_hasShape) { return; } BuildStops(_shape); int segments = _shape.Segments; float num = MathF.PI * 2f / (float)segments; Vector3 val = default(Vector3); for (int i = 0; i < _stops.Count; i++) { Stop stop = _stops[i]; for (int j = 0; j < segments; j++) { float num2 = (float)j * num; ((Vector3)(ref val))..ctor(Mathf.Cos(num2) * stop.Radius, Mathf.Sin(num2) * stop.Radius); vh.AddVert(val, stop.Color, Vector4.zero); } } for (int k = 0; k + 1 < _stops.Count; k++) { int num3 = k * segments; int num4 = (k + 1) * segments; for (int l = 0; l < segments; l++) { int num5 = (l + 1) % segments; vh.AddTriangle(num3 + l, num4 + l, num4 + num5); vh.AddTriangle(num3 + l, num4 + num5, num3 + num5); } } } private void BuildStops(Shape shape) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) _stops.Clear(); float num = shape.Feather * 0.5f; bool flag = shape.Border > 0f; List<float> list = new List<float>(4); List<Color32> list2 = new List<Color32>(3); if (flag && shape.Inner > 0f) { list.Add(Mathf.Max(0f, shape.Inner - shape.Border)); list2.Add(shape.BorderColor); } list.Add(shape.Inner); list2.Add(shape.Fill); list.Add(shape.Outer); if (flag) { list2.Add(shape.BorderColor); list.Add(shape.Outer + shape.Border); } for (int i = 0; i < list.Count; i++) { Color32 color = ((i == 0) ? Transparent(list2[0]) : list2[i - 1]); Color32 color2 = ((i == list.Count - 1) ? Transparent(list2[i - 1]) : list2[i]); if (i == 0 && list[0] <= 0f) { AddStop(0f, color2); continue; } AddStop(list[i] - num, color); AddStop(list[i] + num, color2); } } private void AddStop(float radius, Color32 color) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) float num = ((_stops.Count > 0) ? _stops[_stops.Count - 1].Radius : 0f); _stops.Add(new Stop(Mathf.Max(radius, num), color)); } private static Color32 Transparent(Color32 color) { //IL_0001: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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) return new Color32(color.r, color.g, color.b, (byte)0); } } internal sealed class ToolbotSpreadSource : ISpreadSource { private const string ToolbotBodyName = "ToolbotBody"; private BodyIndex _toolbotBodyIndex = (BodyIndex)(-1); private readonly Dictionary<SkillDef, bool> _isNailgun = new Dictionary<SkillDef, bool>(); private CharacterBody? _loggedBody; private SkillDef? _loggedPrimary; private SkillDef? _loggedOffhand; public bool LogSamples => true; public bool CanHandle(CharacterBody body) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0033: 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_0015: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 if ((int)_toolbotBodyIndex == -1) { _toolbotBodyIndex = BodyCatalog.FindBodyIndex("ToolbotBody"); if ((int)_toolbotBodyIndex == -1) { return false; } } return body.bodyIndex == _toolbotBodyIndex; } public bool TrySample(CharacterBody body, out SpreadSample sample) { sample = default(SpreadSample); SkillLocator skillLocator = body.skillLocator; if (!Object.op_Implicit((Object)(object)skillLocator)) { return false; } ToolbotWeaponSkillDef val = (ToolbotWeaponSkillDef)(Object.op_Implicit((Object)(object)skillLocator.primary) ? /*isinst with value type is only supported in some contexts*/: null); ToolbotWeaponSkillDef val2 = (ToolbotWeaponSkillDef)(Object.op_Implicit((Object)(object)skillLocator.secondary) ? /*isinst with value type is only supported in some contexts*/: null); LogWeaponsOnce(body, (SkillDef?)(object)val, (SkillDef?)(object)val2); if (!IsNailgun((SkillDef?)(object)val) && !IsNailgun((SkillDef?)(object)val2)) { return false; } if (body.spreadBloomCurve == null) { return false; } float num = NailgunEnvelopeScale(); float spreadBloomAngle = body.spreadBloomAngle; float num2 = body.spreadBloomCurve.Evaluate(0f); sample = new SpreadSample(spreadBloomAngle * num, num2 * num, spreadBloomAngle); return true; } private static float NailgunEnvelopeScale() { float spreadYawScale = BaseNailgunState.spreadYawScale; float spreadPitchScale = BaseNailgunState.spreadPitchScale; return Math.Max(1f, Math.Max(spreadYawScale * spreadYawScale, spreadPitchScale * spreadPitchScale)); } private bool IsNailgun(SkillDef? skill) { if ((Object)(object)skill == (Object)null) { return false; } if (!_isNailgun.TryGetValue(skill, out var value)) { Type stateType = ((SerializableEntityStateType)(ref skill.activationState)).stateType; value = stateType != null && typeof(FireNailgun).IsAssignableFrom(stateType); _isNailgun[skill] = value; } return value; } private void LogWeaponsOnce(CharacterBody body, SkillDef? primary, SkillDef? offhand) { if (!((Object)(object)_loggedBody == (Object)(object)body) || !((Object)(object)_loggedPrimary == (Object)(object)primary) || !((Object)(object)_loggedOffhand == (Object)(object)offhand)) { _loggedBody = body; _loggedPrimary = primary; _loggedOffhand = offhand; string arg = ((body.spreadBloomCurve != null) ? $"{body.spreadBloomCurve.Evaluate(0f):0.###}..{body.spreadBloomCurve.Evaluate(1f):0.###} deg" : "none"); Plugin.Log.LogDebug((object)("[Spread] MUL-T weapons: active " + Describe(primary) + (((Object)(object)offhand != (Object)null) ? (", Power Mode offhand " + Describe(offhand)) : "") + $"; body bloom curve {arg}, decay {body.spreadBloomDecayTime:0.###} s; " + $"nailgun envelope scale {NailgunEnvelopeScale():0.###}.")); } string Describe(SkillDef? skill) { return ((Object)(object)skill == (Object)null) ? "none" : ("'" + skill.skillName + "' (" + ((SerializableEntityStateType)(ref skill.activationState)).stateType?.Name + ", " + (IsNailgun(skill) ? "dynamic spread" : "no spread growth") + ")"); } } } }