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 RepoRPG v1.0.38
RepoRPG.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using MenuLib; using MenuLib.MonoBehaviors; using MenuLib.Structs; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.AI; using UnityEngine.Audio; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("RepoRPG")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.38.0")] [assembly: AssemblyInformationalVersion("1.0.38")] [assembly: AssemblyProduct("RepoRPG")] [assembly: AssemblyTitle("RepoRPG")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.38.0")] [module: UnverifiableCode] [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 RepoRPG { internal sealed class RpgRuntime : MonoBehaviour { private sealed class BetMark { public int Actor; public float Mult; public float Remaining; public float Armed; public float At; public string Text = ""; public Transform? Target; public float LookedUp; } private struct TimedBuff { public float Speed; public float Grip; public float Guard; public float Until; public string Source; } private enum PullPhase { Travel, Cling, Kick } private sealed class Pull { public readonly List<Vector3> Points = new List<Vector3>(); public int Index; public float Start; public float LastProgressAt; public float Speed; public float FeetOffset; public float Timeout; public Vector3 Anchor; public float BestDist = float.MaxValue; public int HealthAtStart; public HookAim Kind; public PullPhase Phase; public Vector3 Face; public Vector3 Hand; public float ClingSeconds; public float ClingUntil; public float ClingStart; public float Drain; public float KickUntil; public Vector3 KickDir; public bool CanMantle; public Vector3 MantleTop; public Vector3 MantleLip; public void Reset() { //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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_0055: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_005e: 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_0064: 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) //IL_0066: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) Points.Clear(); Index = 0; Start = (LastProgressAt = (Speed = (FeetOffset = (Timeout = 0f)))); Anchor = (Face = (Hand = (KickDir = (MantleTop = (MantleLip = Vector3.zero))))); BestDist = float.MaxValue; HealthAtStart = 0; Kind = HookAim.None; Phase = PullPhase.Travel; ClingSeconds = (ClingUntil = (ClingStart = (Drain = (KickUntil = 0f)))); CanMantle = false; } } private enum HookAim { None, Item, Ledge, Floor, Wall, Ceiling, Invalid } private struct RoomMark { public Vector3 Pos; public int Monsters; public int Loot; public float Until; } private struct Ping { public Vector3 Pos; public string Name; public float Until; } private struct Glint { public Transform T; public Vector3 Center; public float Radius; public float Until; public float Phase; } private struct Threat { public EnemyHealth Eh; public string Text; public Color Col; } private sealed class CtRequest { public byte What; public string Uid = ""; public float SentAt; public int Tries; public Action Resend; } private sealed class PendingBuy { public string Label = ""; public string Item = ""; public Action OnPaid; public float SentAt; public int Cost; public bool Retried; } public struct Aura { public float Guard; public float GuardRadius; public float Stabilize; public float StabilizeRadius; public float Link; public float LinkRadius; public float Inspire; public float InspireRadius; public float InspireSpeed; public float InspireGrip; public float At; public int Actor; } private sealed class WorldMark { public string Id = ""; public Vector3 Pos; public string Text = ""; public Color Color; public float Until; } private sealed class PartDrop { public Vector3 Pos; public int[] Counts = new int[4]; public float Until; public float AskedAt = -99f; public bool Taken; } internal enum Recipe { Reroll, Raise, Upgrade, Legendary } private sealed class PendingSalvage { public string Uid = ""; public string Name = ""; public int Rarity; public float SentAt; public bool Retried; public bool Bulk; } private sealed class CallOut { public int Actor; public string Name = ""; public Vector3 Pos; public float Until; } private enum DialogChoice { Confirm, Discard, Cancel } private sealed class HudBlock { public readonly List<(string text, Color color)> Lines = new List<(string, Color)>(); public GUIStyle? Style; public string Shape = ""; public float StyleFor = -1f; public GUIStyle? Base; } private enum Rebind { None, KeyMenu, KeyAbility, KeyConfirm, KeyBack, KeyTabL, KeyTabR, KeySecondary, KeyAttrConfirm, KeyAttrReset, KeyHum, KeyHandOff, KeyMimicSwap, KeyCartFollow, KeySalvage, KeyCallOut, KeyHighlights, PadMenu, PadAbility, PadConfirm, PadBack, PadTabL, PadTabR, PadSecondary, PadAttrConfirm, PadAttrReset, PadHum, PadHandOff, PadMimicSwap, PadCartFollow, PadSalvage, PadCallOut, PadHighlights } private enum GKind { Head, Text, Bullet, Tip, Note, Term, Goto, Walk, Filter, ClassRow, Row, Space } private sealed class GItem { public GKind Kind; public string Text = ""; public string Text2 = ""; public string Arg = ""; public Color Color = Color.white; public float H; } public enum HealKind : byte { OverTime, Instant, Revive } private struct FocusItem { public int Key; public Rect Screen; public int ScrollId; public Rect Local; } private enum NavDevice { Mouse, Keyboard, Pad } private sealed class InFlight { public int Id; public float SentAt; public string Payload = ""; public string ClassId = ""; public bool Retried; } private enum HostChecks { Unknown, Yes, No } private enum DialogKind { Leave, PlayAs, Salvage, Compare, Craft, HostApply, Purchase } public enum PopupKind { Xp, Level, Loot, Contract, Perk, Other, Currency } private sealed class Popup { public bool Active; public PopupKind Kind; public string Key = ""; public string Label = ""; public string Text = ""; public Color Color; public int Amount; public int Count; public double Total; public float Start; public float End; public float Y = -1f; public long Seq; public bool Fading; } private enum UndoKind : byte { Talent, Attribute } private sealed class Tracked { public ValuableObject Obj; public Renderer[] Rends = Array.Empty<Renderer>(); public MeshFilter?[] Filters = Array.Empty<MeshFilter>(); public Color Col; public float Value; public float Until; public string Tag = ""; public Bounds B; public bool HasB; public bool Own; public PhysGrabObject? Pgo; public Component? Det; } private sealed class PoolItem { public ValuableObject Obj; public PhysGrabObject? Pgo; public Component? Det; public float Value; } private sealed class AbilityNums { public float Cd; public float Cdr; public float Power; public float HealPower; public float Dur; public float Radius; public float Scale = 1f; public int Charges; public bool CdrCapped; public readonly List<(string label, float value)> Acts = new List<(string, float)>(); public readonly List<string> Riders = new List<string>(); } private sealed class Mate { public int Actor; public int Hp; public int Max = 100; public bool Down; public string Name = ""; public string BarText = ""; public string ListText = ""; public float CriticalSince = -1f; public float LastCriticalPop = -99f; public PlayerAvatar? Avatar; } internal enum UiSound { Hover, Click, Confirm, Back, Error, Tick } private int _supplyLeft = -1; private int _supplyCharges; private int _supplyPrice = -1; private int _betLeft = -1; private int _betUses; private int _limitsLevel = -1; private readonly Dictionary<int, BetMark> _betMarks = new Dictionary<int, BetMark>(); private readonly List<int> _betGone = new List<int>(); private float _classStatsSendAt; private readonly Dictionary<string, float> _classStatsBuf = new Dictionary<string, float>(); private readonly Dictionary<string, float> _setStatsBuf = new Dictionary<string, float>(); private float _sentGrab = -9f; private float _sentThrow = -9f; private float _nextGripCheck; private readonly List<TimedBuff> _buffs = new List<TimedBuff>(); private readonly List<(Stat stat, float value, float until)> _selfDyn = new List<(Stat, float, float)>(); private float _pendingHealthPct; private float _pendingHealthAt; private float _inspire; private float _lastInspireSent = -99f; private float _nextInspireSend; private float _nextNearCheck; private bool _talking; private bool _monsterNear; private static readonly Lazy<Func<object?>> VoiceInstance = new Lazy<Func<object>>(delegate { Type type = AccessTools.TypeByName("PlayerVoiceChat"); FieldInfo f = ((type == null) ? null : AccessTools.Field(type, "instance")); return delegate { try { return f?.GetValue(null); } catch { return (object?)null; } }; }); private float _pactEnd; private float _pactDrain; private float _drainAcc; private float _lastBloodWeapon; private float _nextCartLook; private PhysGrabCart[] _cartsNear = Array.Empty<PhysGrabCart>(); private (float speed, float grip) _inspireFromAllies; private float _nextAudienceCheck; private bool _audience; private bool _whisperTalk; private float _nextVoiceDraw; private bool _inspireWasFull; private float _rallyRefund; private readonly string[] _copies = new string[2] { "", "" }; private readonly string[] _copyFrom = new string[2] { "", "" }; private int _copySlot; private int _copyCandidate = -1; private float _copyTimer; private float _nextCopyLook; private readonly (int charges, float cdEnd)[] _slotState = new(int, float)[2] { (1, 0f), (1, 0f) }; private float _lastCopyLook = -1f; private bool _freshUsed; private float _gambleCheckAt; private float _bloodAcc; private bool _inActive; private bool _refundAfterUse; private string _cartState = ""; private float _windReadyAt; private KeyCode _queuedClassKey; private bool _cartFollowOn = true; private readonly List<(string, Color)> _headLines = new List<(string, Color)>(); private float _headLinesAt = -9f; private int _headLinesSig; private Pull? _pull; private int _hookChain; private readonly Pull _aimPlan = new Pull(); private static readonly Collider[] HookOverlap = (Collider[])(object)new Collider[16]; private static readonly RaycastHit[] HookHits = (RaycastHit[])(object)new RaycastHit[16]; private static readonly Vector3[] FloorProbes = (Vector3[])(object)new Vector3[5] { Vector3.zero, Vector3.forward * 0.25f, Vector3.back * 0.25f, Vector3.left * 0.25f, Vector3.right * 0.25f }; private const float WallStandoff = 0.45f; private const float CeilingDrop = 2.05f; private const float MantleReach = 1.5f; private static readonly RaycastHit[] AimHits = (RaycastHit[])(object)new RaycastHit[24]; private static readonly HashSet<string> ThirdWaveActions = new HashSet<string> { "Bypass", "Echo", "Mend", "Rummage", "Policy", "Watchpost", "Overclock", "Pacify", "Hook", "Flare" }; private HookAim _hookTextAim = (HookAim)(-1); private int _hookTextDist = -1; private string _hookTextWhy = ""; private string _hookTextCling = ""; private string _hookText = ""; private HookAim _hookAim; private string _hookAimWhy = ""; private float _hookAimDist; private float _nextHookAim; private bool _reachTarget; private float _rummageStart; private float _rummageEnd; private float _rummageCount; private Vector3 _rummagePos; private float _nextThrow; private bool _voiceThrown; private float _bypassSeconds = 8f; private readonly List<RoomMark> _roomMarks = new List<RoomMark>(); private readonly List<Ping> _pings = new List<Ping>(); private readonly List<Glint> _glints = new List<Glint>(); private readonly List<Threat> _threats = new List<Threat>(); private float _nextThreat; private float _thickSkinUntil; private float _patchUpUntil; private float _patchUpPct; private float _secondBreathUntil; private float _firmUntil; private float _rhythmAt; private float _nextAttrTick; private float _airVy; private int _clearHeadLevel = -1; private int _secondBreathLevel = -1; private int _featherLevel = -1; private HashSet<string>? _attrKnownActive; private string _attrKnownFor = "~"; private readonly Dictionary<string, float> _attrFlash = new Dictionary<string, float>(); private bool _classWindowOpen; private bool _classPickDropped; private bool _classlessToldThisLevel; private float _nextClassWindowCheck; private readonly Dictionary<int, CtRequest> _ctRequests = new Dictionary<int, CtRequest>(); private int _ctNextReq = new Random().Next(1, 1073741824); private float _ctNextTick; private readonly List<float> _ctKillTimes = new List<float>(); private readonly HashSet<string> _ctCopied = new HashSet<string>(); private Vector3 _ctLastPos; private bool _ctHavePos; private readonly Dictionary<string, float> _ctFlash = new Dictionary<string, float>(); private readonly Dictionary<string, float> _ctClaimRetry = new Dictionary<string, float>(); private readonly HashSet<string> _ctRefused = new HashSet<string>(); private readonly HashSet<int> _ctScanned = new HashSet<int>(); private float _ctJugAcc; private string _ctModulePick = ""; private static readonly Color CtGood = new Color(0.55f, 1f, 0.55f); private static readonly Color CtBad = new Color(1f, 0.45f, 0.4f); private static readonly Color CtGold = new Color(1f, 0.8f, 0.35f); private readonly Queue<(string key, float amount, int a, int b)> _ctEvQueue = new Queue<(string, float, int, int)>(); private bool _ctInEv; private const int CtEvBurstLimit = 64; private readonly HashSet<string> _ctPaid = new HashSet<string>(); private bool _selfHurt; private bool _fallHandled; private int _neverDieLevel = -1; private RunSave? _deathSavesTagged; private float _sprintStart = -1f; private float _nextHoldCheck; private float _nextVigil; private float _airImpulseVy; private float _prevVy; private bool _holdingValuable; private bool _gearWasSprinting; private bool _featherFree; private int _vigilLevel = -1; private int _freeFirstLevel = -1; private int _bellLevel = -1; private readonly Dictionary<string, float> _gearFlash = new Dictionary<string, float>(); private int _chargedLevel = -1; private static readonly int[] ModuleRandomCost = new int[4] { 2, 1, 0, 0 }; private static readonly int[] ModuleChosenCost = new int[4] { 0, 0, 1, 0 }; public const int LoadoutCount = 3; private float _ljShieldUntil; private bool _ljJoining; private float _ljSince; private float _ljNextAsk; private int _ljAsks; private bool _ljToldSlow; private readonly Dictionary<string, float> _perkFlash = new Dictionary<string, float>(); private readonly Dictionary<string, float> _tagFlash = new Dictionary<string, float>(); private float _perkRevealAt = -99f; private int _perkRevealKey; private int _encoreCount; private int _ghostLevel = -1; private float _nextPerkTick; private float _sprintSampled; private bool _teamNear; private readonly Dictionary<int, int> _angelUsed = new Dictionary<int, int>(); private readonly RunStore _store = new RunStore(); private float _waitForHostSince = -1f; private float _levelStartTime; private float _nextCombatSend; private float _settingsDirtyAt; private int _extractionsThisLevel; private readonly StatSheet _stats = new StatSheet(); private bool _statsDirty = true; private PlayerHealth? _hpFilledFor; internal static bool KillHit; private readonly TrackedField _maxHealth = new TrackedField(typeof(PlayerHealth), "maxHealth", TrackedField.Mode.Rebase, HealthReady); private readonly TrackedField _move = new TrackedField(typeof(PlayerController), "MoveSpeed", TrackedField.Mode.Additive, PcReady, PcOverridden, (object pc) => Game.Get(pc, "playerOriginalMoveSpeed", 0f)); private readonly TrackedField _sprint = new TrackedField(typeof(PlayerController), "SprintSpeed", TrackedField.Mode.Additive, PcReady, PcOverridden, (object pc) => Game.Get(pc, "playerOriginalSprintSpeed", 0f)); private readonly TrackedField _crouch = new TrackedField(typeof(PlayerController), "CrouchSpeed", TrackedField.Mode.Additive, PcReady, PcOverridden, (object pc) => Game.Get(pc, "playerOriginalCrouchSpeed", 0f)); private readonly TrackedField _jumpForce = new TrackedField(typeof(PlayerController), "JumpForce", TrackedField.Mode.Additive, PcReady); private readonly TrackedField _jumpExtra = new TrackedField(typeof(PlayerController), "JumpExtra", TrackedField.Mode.Rebase, PcReady); private readonly TrackedField _energyMax = new TrackedField(typeof(PlayerController), "EnergyStart", TrackedField.Mode.Additive, PcReady); private readonly TrackedField _grabStrength = new TrackedField(typeof(PhysGrabber), "grabStrength"); private readonly TrackedField _grabRange = new TrackedField(typeof(PhysGrabber), "grabRange"); private readonly TrackedField _throw = new TrackedField(typeof(PhysGrabber), "throwStrength"); private float _cooldownEnd; private int _charges = 1; private float _buffEnd; private float _hotEnd; private float _hotPerSecond; private float _hotAcc; private float _scanEnd; private float _scanRadius; private int _scanCount; private float _invulnUntil; private float _lastDamageTime = -999f; private float _regenAcc; private int _lastSeenHp = -1; private float _nextAuraPulse; private readonly Dictionary<int, float> _allyHealAcc = new Dictionary<int, float>(); private float _teamXpDedupeUntil; private Net.TeamXp _lastTeamXp; private float _nextSense; private int _senseCount; private float _senseNearest; private float _nextScan; private readonly List<(Vector3 pos, float value, float dist)> _scanHits = new List<(Vector3, float, float)>(); private string _askKey = ""; private float _askSince; private float _askNext; private string _gotKey = ""; private RunSave? _gotData; private string _fellBackKey = ""; private bool _reloadFromHost; private float _bulwarkReadyAt; private bool _specialistPending; private int _mirrorLevel = -1; private int _crescendoLevel = -1; private static readonly HashSet<string> HostActions = new HashSet<string> { "RallyCry", "Reboot", "CartOverdrive", "ZeroGField", "DecoyBeacon", "BreachCharge", "Resupply", "DoubleOrNothing", "Bypass", "Echo", "Mend", "Policy", "Watchpost", "Pacify", "Flare" }; private int _lastCharged; private readonly Dictionary<int, PendingBuy> _pendingBuys = new Dictionary<int, PendingBuy>(); private readonly Dictionary<int, PendingBuy> _lateBuys = new Dictionary<int, PendingBuy>(); private int _nextBuyId = new Random().Next(1, 1073741824); private float _nextPerkReport; private bool _shopRotatedScene; private float _nextShopTick; private float _nextCartBuy; private float _medPatchLevel = -1f; private string _vendorLine = ShopX.VendorBrowse[0]; private float _vendorLineAt; private readonly List<(string label, string key, int price, Action buy)> _cart = new List<(string, string, int, Action)>(); private readonly Queue<Action> _cartQueue = new Queue<Action>(); private readonly Dictionary<string, float> _shopFlash = new Dictionary<string, float>(); private string _purchaseTitle = ""; private string _purchaseBody = ""; private Action? _purchaseAction; private static readonly int[] PartsUpCost = new int[4] { 0, 2, 0, 0 }; private int _momentum; private int _frenzy; private float _momentumNext; private float _lastSprint; private float _frenzyEnd; private float _shadowstepEnd; private float _scar; private bool _wasSprinting; private float _lastDynWeapon; private readonly Dictionary<int, Aura> _auras = new Dictionary<int, Aura>(); private bool _auraSentNonZero; private float _nextAuraLook; private float _guardedBy; private float _linkRegen; private int _guardActor = -1; private float _guardPct; private const float FrenzySeconds = 15f; private const float ShadowstepSeconds = 3f; private float _lastDodgeRefund = -9f; private float _rallyEnd; private float _saveHealAt; private int _saveHeal; private float _stDiagAt; private float _stDiagStartE = -1f; private float _stDiagStartT; private float _stDiagFrames; private string _banner = ""; private Color _bannerColor = Color.white; private float _bannerUntil; private string _bossShown = ""; private readonly List<WorldMark> _worldMarks = new List<WorldMark>(); private readonly Dictionary<int, PartDrop> _partDrops = new Dictionary<int, PartDrop>(); private float _nextPartCheck; private string _craftUid = ""; private string _craftTarget = ""; private int _craftLine; private Recipe? _craftPick; private readonly Dictionary<ConfigEntryBase, object> _hostPending = new Dictionary<ConfigEntryBase, object>(); private Vector2 _hostScroll; private readonly HashSet<string> _hostOpen = new HashSet<string>(); private string _presetName = ""; private bool _namingPreset; private string _hostToast = ""; private float _settingsWaitSince = -1f; private float _nextSettingsAsk; private bool _settingsTimeoutSaid; private string _hostHead = ""; private float _hostHeadAt = -10f; private float _hostHeadW = -1f; private float _hostHeadH; private const int ScrollHost = 10; private readonly Dictionary<int, PendingSalvage> _pendingSalvage = new Dictionary<int, PendingSalvage>(); private int _salvageSeq = new Random().Next(1, 1073741824); private GearItem? _salvageAsk; private List<GearItem>? _salvageAskBulk; private TeamContractDef? _tcDef; private int _tcState = -1; private int _tcTarget; private int _tcYes; private int _tcVotes; private int _tcLevel = -1; private float _tcScale = 1f; private float _tcVoteEnd; private int[] _tcParticipants = Array.Empty<int>(); private int[] _tcYesBy = Array.Empty<int>(); private int[] _tcNoBy = Array.Empty<int>(); private bool _tcBoardVote; private bool _tcVoted; private bool _tcRewarded; private float _tcHoldStart = -1f; private int _notTodaySaves; private bool _notTodayUsed; private readonly List<CallOut> _callOuts = new List<CallOut>(); private readonly HashSet<int> _callOutSeen = new HashSet<int>(); private readonly Dictionary<int, float> _callOutLast = new Dictionary<int, float>(); private int _callOutsThisDeath; private float _nextCallOut; private readonly List<SynergyDef> _synActive = new List<SynergyDef>(); private readonly List<(string text, Color a, Color b)> _synLines = new List<(string, Color, Color)>(); private string _synSig = ""; private float _synNext; private List<TeamPlay.Entry>? _card; private List<TeamPlay.Entry>? _cardWaiting; private float _cardWaitingSecs; private int _cardCountedLevel = -1; private float _cardUntil; private float _cardShownAt; private float _cardSecs; private float _cardKeyDownAt = -1f; private bool _cardPaused; private string _cardPrompt = ""; private string _cardPromptKey = ""; private int _accountPage; private int _unlockFilter; private Vector2 _accountScroll; private const int ScrollAccount = 11; private float _summaryAt = 0.5f; private string _summarySent = ""; private int _summaryPlayers; private Dictionary<string, int>? _attrInFlight; private int _attrRequestId = new Random().Next(1, 1073741824); private float _attrSentAt; private string _attrRunKey = ""; private bool _attrLateOk; private bool _attrRetried; private bool _dialogOpen; private bool _inDialog; private bool _dialogFocusSet; private Action? _dialogAfter; private int _dialogReturnFocus; private Vector2 _attrSideScroll; private const int ScrollAttrSide = 13; private int _attrCacheKey = int.MinValue; private readonly HashSet<string> _attrActiveNow = new HashSet<string>(); private readonly HashSet<string> _attrActiveAfter = new HashSet<string>(); private readonly List<string> _attrTotalLines = new List<string>(); private string _attrTitleNow = ""; private string _attrTitleAfter = ""; private int _attrSideKey = int.MinValue; private int _attrSideLayoutKey = int.MinValue; private string _sHead = ""; private string _sNow = ""; private string _sAfter = ""; private string _sNext = ""; private readonly List<(string full, string brief)> _sMiles = new List<(string, string)>(); private readonly List<(string full, string brief)> _sPairs = new List<(string, string)>(); private readonly List<(string full, string brief)> _sTotals = new List<(string, string)>(); private int _sFont; private int _sHeadFont; private bool _sTwoCol; private bool _sBrief; private float _sChartH; private int _attrDetailCache = int.MinValue; private Texture2D? _radarTex; private int _radarKey = int.MinValue; private Rect _radarRect; private bool _hudForce; private string _hudTraceClass = "-"; private bool _menuOpen; private int _menuClosedFrame = -10; private Texture2D? _cursorTex; private CursorLockMode _cursorLockBefore; private bool _cursorVisibleBefore = true; private ClassDef? _viewClass; private Vector2 _classScroll; private Vector2 _treeScroll; private readonly List<(string text, Color color, float until)> _toasts = new List<(string, Color, float)>(); private bool _abilityKeyQueued; private readonly HashSet<KeyCode> _held = new HashSet<KeyCode>(); private bool _stylesReady; private GUIStyle _title; private GUIStyle _h2; private GUIStyle _body; private GUIStyle _small; private GUIStyle _btn; private GUIStyle _tabStyle; private GUIStyle _smallRight; private GUIStyle _hud; private GUIStyle _toast; private GUIStyle _promptStyle; private GUIStyle _smallLine; private GUIStyle _smallCenter; private GUIStyle _bodyB; private GUIStyle _bodyCenterB; private GUIStyle _h2Center; private Texture2D _texPanel; private Texture2D _texDim; private Texture2D _texNode; private Texture2D _texNodeOn; private Texture2D _texNodeLocked; private Texture2D _texBar; private Texture2D _texBarBg; private const float VW = 1600f; private const float VH = 900f; private readonly Dictionary<KeyCode, float> _keyDownAt = new Dictionary<KeyCode, float>(); private static readonly Lazy<Func<bool>> ChatOpen = new Lazy<Func<bool>>(delegate { Type type = AccessTools.TypeByName("ChatManager"); FieldInfo inst = ((type == null) ? null : AccessTools.Field(type, "instance")); FieldInfo active = ((type == null) ? null : AccessTools.Field(type, "chatActive")); return (inst == null || active == null) ? ((Func<bool>)(() => false)) : ((Func<bool>)delegate { try { object value = inst.GetValue(null); bool flag = default(bool); int num; if (value != null) { object value2 = active.GetValue(value); if (value2 is bool) { flag = (bool)value2; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } }); }); private static Type? _esType; private static bool _esLooked; private readonly List<Behaviour> _esDisabled = new List<Behaviour>(); private float _esNextScan; private static FieldInfo? _mbHovering; private static MethodInfo? _mbHoverEnd; private static PropertyInfo? _mehHovering; private float _hudTopY = -1f; private float _menuOpenedAt; private Rect _menuWin; private float _lastUiScale = -1f; private float _lastGrow = -1f; private float _builtFontMul = -1f; private int _builtStyle = -1; private bool _lastFit; public const float MinTextPx = 14f; private const float SmallestFont = 15f; private float _fontMul = 1f; private float _lastFontMul = -1f; private readonly List<(string, Color)> _hudLeft = new List<(string, Color)>(); private float _nextHudBuild; private bool _hudRebuild; private readonly List<(string, Color)> _hudLeftNext = new List<(string, Color)>(); private string _classBlockDiag = ""; private int _classBlockRebuilds; private readonly Dictionary<PassiveDef, string> _passiveHead = new Dictionary<PassiveDef, string>(); private static readonly string[] GroupOrder = new string[6] { "Combat", "Support", "Control", "Utility", "Mobility", "Economy" }; private List<(string name, List<ClassDef> list)>? _classGroups; private int _classGroupsCount = -1; private readonly Dictionary<NodeDef, string> _nodeText = new Dictionary<NodeDef, string>(); private int _paletteApplied = -1; private bool _contrastChecked; private float _contentBottom; private static int _instances; private readonly HudBlock _contractsBlock = new HudBlock(); private readonly HudBlock _rightBlock = new HudBlock(); private string _contractSig = ""; private string _contractLevelKey = ""; private float _contractNextCheck; private float _contractLastHave = -99f; private float _contractsAlpha; private readonly StringBuilder _sigSb = new StringBuilder(256); private readonly List<(string, Color)> _teamLines = new List<(string, Color)>(); private float _teamLinesNext; private string _cDiagLast = ""; private int _cDiagFrame = -1; private int _cDiagDraws; private int _cDiagFontAt; private float _cDiagNextScan; private float _cDiagNextInstances; private string _overlapLast = ""; private Rect _cDiagPanelScreen; private readonly List<string> _overlapParts = new List<string>(); private readonly Vector3[] _hudCorners = (Vector3[])(object)new Vector3[4]; private int _ctSection; private Vector2 _ctScroll; private const int ScrollCtBoard = 18; private const int ScrollCtActive = 19; private const int ScrollCtChains = 20; private const int ScrollCtHistory = 21; private const int ScrollCtGivers = 22; private const int ScrollCtModules = 23; private static readonly string[] CtSections = new string[5] { "Board", "Active", "Chains", "History", "Givers" }; private Rebind _rebind; private float _rebindStarted; private bool _padCaptureArmed; private readonly HashSet<string> _padCapture = new HashSet<string>(); private float _controlsContentH = 1600f; private Vector2 _controlsScroll; private readonly List<float> _flowW = new List<float>(); private readonly List<Rect> _flowR = new List<Rect>(); private List<string>? _treeCheck; private int _debugPage; private int _dbgClass; private int _dbgStat; private readonly Dictionary<string, float> _dbgCustom = new Dictionary<string, float>(); private string _gearFilter = ""; private int _gearRarityF = -1; private int _gearKindF; private int _gearSort; private string _gearQuery = ""; private static readonly string[] GearSorts = new string[4] { "Rarity", "Slot", "Newest", "Attunement" }; private static readonly string[] GearKinds = new string[6] { "All kinds", "Set pieces", "Uniques", "New", "Behavior", "Attuned" }; private string _gearCompare = ""; private string _gearCompareNext = ""; private string _gearSel = ""; private int _gearSig = int.MinValue; private readonly List<GearItem> _gearItems = new List<GearItem>(); private readonly Dictionary<string, string> _gearRowText = new Dictionary<string, string>(); private readonly Dictionary<string, string[]> _rowLabels = new Dictionary<string, string[]>(); private readonly Dictionary<string, string> _inspectText = new Dictionary<string, string>(); private readonly float[] _gearTotals = new float[StatInfo.Count]; private readonly float[] _gearAfter = new float[StatInfo.Count]; private string _gearSideText = ""; private int _modPick = -1; private int _craftModChoice; private float _gearRevealAt = -99f; private int _gearNewCount; private Vector2 _gearInspectScroll; private Vector2 _gearSideScroll; private const int ScrollGearInspect = 14; private const int ScrollGearSide = 15; private static readonly Dictionary<string, string> SlotDescFallback = new Dictionary<string, string> { ["weapon"] = "Your hits: damage, stuns, bleeds, throws.", ["plating"] = "Survival: health, armour, healing, dodging.", ["servos"] = "Movement: speed, jumps and stamina.", ["core"] = "Your ability: cooldown, power, area, XP." }; private const int ScrollGuideCats = 9; private Vector2 _helpScroll; private Vector2 _guideCatScroll; private string _guideTopic = ""; private string _guideQuery = ""; private int _guideRole; private bool _guideWalk; private int _guideStep; private static int _cfgVersion; private static bool _cfgHooked; private readonly List<GItem> _gItems = new List<GItem>(); private string _gKey = ""; private float _gTotalH; private float _gNextStats; private List<GuideTopic>? _gVisible; private string _gVisibleKey = "~"; private static readonly Regex GuideToken = new Regex("\\{([a-z]+):([^{}]*)\\}", RegexOptions.Compiled); private Dictionary<string, ConfigEntryBase>? _cfgCache; private static readonly Color HealGreen = new Color(0.42f, 0.95f, 0.52f); private int _healSampleHp = -1; private int _healCount; private float _healNextSample; private float _healLastAt = -99f; private float _healGlow; private Rect _healthUiRect; private float _nextHealthUiLook; private Component? _healthUi; private const string HudChars = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~·•→★×–—…‘’“”"; private readonly HashSet<char> _hudExtra = new HashSet<char>(); private string _hudExtraText = ""; private readonly HashSet<(int, FontStyle)> _hudSizes = new HashSet<(int, FontStyle)>(); private bool _prewarmDirty = true; private bool _inHud; private bool _fontHooked; private bool _hudHadClass; private Font? _prewarmedFont; private float _noPlayerSince = -1f; private float _hudBadSince = -1f; private int _diagFontRebuilds; private int _diagHides; private int _diagHolds; private int _diagReloads; private int _diagThemeAt = -1; private float _diagNext; private readonly Dictionary<string, string> _digitShape = new Dictionary<string, string>(); private readonly StringBuilder _shapeSb = new StringBuilder(64); private const float PadIn = 12f; private const float GapLine = 4f; private const float GapItem = 8f; private const float GapSection = 16f; private readonly Dictionary<GUIStyle, float> _lineH = new Dictionary<GUIStyle, float>(); private readonly Dictionary<(GUIStyle, string, int), float> _textHCache = new Dictionary<(GUIStyle, string, int), float>(); private readonly Dictionary<(GUIStyle, string), float> _textWCache = new Dictionary<(GUIStyle, string), float>(); private readonly Dictionary<(GUIStyle, int, int, bool), (GUIStyle, float, int)> _fitLines = new Dictionary<(GUIStyle, int, int, bool), (GUIStyle, float, int)>(); private int _layoutVersion; private string _hintKey = ""; private string _hintLabel = ""; private string _hintGlyph = ""; private bool _hintDot; private float _hintW; private float _nextHintDotCheck; private float _nextHintPageCheck; private bool _hintPageOk = true; private string _bannerShown = ""; private float _bannerW; private float _bannerH; private float _bannerMul; private static bool _transitioning; private static float _transitionAt = -99f; private static bool _sceneLoadedSinceTransition; private bool _discardedNotice; private bool _blockedNoticeShown; private readonly List<FocusItem> _focusItems = new List<FocusItem>(); private readonly List<FocusItem> _focusBuilding = new List<FocusItem>(); private readonly HashSet<int> _focusKeysThisPass = new HashSet<int>(); private readonly Dictionary<int, float> _scrollViewHeights = new Dictionary<int, float>(); private readonly Dictionary<int, Rect> _scrollViewScreen = new Dictionary<int, Rect>(); private float _tabRowBottom; private int _focusKey; private bool _padMode; private NavDevice _device; private NavDevice _promptDevice = NavDevice.Keyboard; private bool _padActivate; private int _currentScrollId; private float _navRepeatAt; private Vector2 _lastMouse; private float _menuHoldStart = -1f; private bool _menuHoldFired; private int _lastHoverKey; private Rect _lastFocusScreen; private bool _hasLastFocus; private readonly Dictionary<int, int> _tabFocus = new Dictionary<int, int>(); private readonly int[] _tabKeys = new int[16]; private readonly HashSet<KeyCode> _kbPressed = new HashSet<KeyCode>(); private bool _kbShift; private int _adjustKey; private Action? _adjDec; private Action? _adjInc; private Action? _adjConfirm; private int _secondaryKey; private string _secondaryLabel = ""; private Action? _secondaryAction; private const int ScrollClasses = 1; private const int ScrollTree = 2; private const int ScrollGear = 3; private const int ScrollPerks = 4; private const int ScrollControls = 5; private const int ScrollShop = 6; private const int ScrollAttributes = 7; private const int ScrollHelp = 8; private static readonly KeyCode[] NavKeysUp = (KeyCode[])(object)new KeyCode[2] { (KeyCode)119, (KeyCode)273 }; private static readonly KeyCode[] NavKeysDown = (KeyCode[])(object)new KeyCode[2] { (KeyCode)115, (KeyCode)274 }; private static readonly KeyCode[] NavKeysLeft = (KeyCode[])(object)new KeyCode[2] { (KeyCode)97, (KeyCode)276 }; private static readonly KeyCode[] NavKeysRight = (KeyCode[])(object)new KeyCode[2] { (KeyCode)100, (KeyCode)275 }; private readonly List<(string[] glyphs, string label)> _prompts = new List<(string[], string)>(); private float _promptStripH = 44f; private const float PromptGap = 22f; private const float PromptGapTight = 10f; private const float PromptPad = 22f; private readonly Dictionary<string, int> _talentPending = new Dictionary<string, int>(); private string _talentPendingClass = ""; private readonly Dictionary<int, string> _perkPending = new Dictionary<int, string>(); private readonly Dictionary<byte, InFlight> _commits = new Dictionary<byte, InFlight>(); private int _commitSeq = new Random().Next(1, 1073741824); private readonly Dictionary<int, (byte type, InFlight f)> _lateCommits = new Dictionary<int, (byte, InFlight)>(); private HostChecks _hostChecks; private ClassDef? _playAsTarget; private DialogKind _dialogKind; private int _perkView = -1; private int _perkSort; private int _perkRarityF = -1; private int _perkTagF = -1; private int _perkOwnF; private string _perkQuery = ""; private Vector2 _perkSideScroll; private string _banishArmed = ""; private float _banishArmedUntil; private const int ScrollPerkSide = 12; private static readonly string[] PerkViewNames = new string[3] { "PICK", "OWNED", "ALL PERKS" }; private static readonly string[] PerkSortNames = new string[3] { "Rarity", "Tag", "When picked" }; private static readonly string[] PerkOwnNames = new string[4] { "Everything", "Owned", "Not owned", "Banished" }; private readonly List<PerkDef> _ownedList = new List<PerkDef>(); private readonly List<PerkDef> _allList = new List<PerkDef>(); private (int, int, int, int, int) _ownedKey = (-1, 0, 0, 0, 0); private (int, int, int, int, int, int, string) _allKey = (-1, 0, 0, 0, 0, 0, "~"); private const string SilhouetteText = "<color=#9a9ca0>Not discovered yet. A Legendary perk shows here once it has been offered to you.</color>"; private const int PoolSize = 8; private readonly Popup[] _popups = CreatePool(); private long _popupSeq; private float _xpPulseUntil; private static readonly Color PopXp = new Color(0.62f, 0.86f, 1f); private static readonly Color PopLevel = new Color(1f, 0.85f, 0.3f); private static readonly Color PopContract = new Color(0.95f, 0.83f, 0.55f); private static readonly Color PopPerk = new Color(1f, 0.7f, 0.12f); private static readonly Color PopOther = new Color(0.86f, 0.87f, 0.89f); private readonly List<Popup> _drawOrder = new List<Popup>(8); private float _blockedTopPx = -1f; private float _nextBlockScan; private readonly List<CanvasRenderer> _crs = new List<CanvasRenderer>(256); private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4]; private static readonly string[] RoleFilters = new string[7] { "All", "Combat", "Support", "Control", "Utility", "Mobility", "Economy" }; private int _roleFilter; private string _classQuery = ""; private bool _searching; private List<(string name, List<ClassDef> list)>? _visibleGroups; private string _visibleKey = ""; private readonly Dictionary<string, string> _classSummary = new Dictionary<string, string>(); private ClassDef? _comparePick; private ClassDef? _compareA; private ClassDef? _compareB; private readonly Dictionary<string, string> _synLineCache = new Dictionary<string, string>(); private readonly Dictionary<(NodeDef, int), string> _nodeValueText = new Dictionary<(NodeDef, int), string>(); private float _tabSwitchedAt = -9f; private bool _tabMemoryRestored; private readonly List<(UndoKind kind, string id)> _undo = new List<(UndoKind, string)>(); private readonly HashSet<string> _seenGear = new HashSet<string>(); private readonly HashSet<string> _newThisView = new HashSet<string>(); private int _seenContractLevel = int.MinValue; private string _seenRunKey = ""; private int _seenBoardLevel = int.MinValue; private int _tab; private static readonly string[] TabsBase = new string[10] { "Class", "Attributes", "Gear", "Perks", "Contracts", "Shop", "Account", "Settings", "Host", "Guide" }; private static readonly string[] TabsDebug = new string[11] { "Class", "Attributes", "Gear", "Perks", "Contracts", "Shop", "Account", "Settings", "Host", "Guide", "Debug" }; private Vector2 _gearScroll; private Vector2 _perkScroll; private readonly List<(string text, Color color)> _eliteLines = new List<(string, Color)>(); private float _nextEliteHud; private int _heldUpgradeId = int.MinValue; private float _heldUpgradeRefresh; private readonly List<(string, Color)> _heldUpgradeLines = new List<(string, Color)>(); private Vector2 _attrScroll; private AttributeDef? _attrFocus; private readonly Dictionary<string, int> _attrPending = new Dictionary<string, int>(); private static readonly string[] AttrCategories = new string[3] { "Combat", "Physical", "Utility" }; private (string, int, int) _attrDetailKey = ("", -1, -1); private readonly Dictionary<string, string> _attrDetail = new Dictionary<string, string>(); private readonly Dictionary<string, string> _perkFx = new Dictionary<string, string>(); private Vector2 _shopScroll; private string _svcTarget = ""; private int _svcLine = -1; private float _shopContentH = 820f; private readonly List<(string, Color)> _hudRight = new List<(string, Color)>(); private readonly List<PoolItem> _scanPool = new List<PoolItem>(); private int _scanWant; private float _scanTill; private float _cartCheckAt; private float _cartListAt; private bool _scanSharing; private PhysGrabCart[] _carts = Array.Empty<PhysGrabCart>(); private HashSet<int> _inCarts = new HashSet<int>(); private HashSet<int> _inCartsNext = new HashSet<int>(); private readonly List<int> _shareIds = new List<int>(); private readonly List<Tracked> _tracked = new List<Tracked>(); private Material? _outlineMat; private MaterialPropertyBlock? _outlineMpb; private Texture2D? _texTri; private Texture2D? _texDiamond; private float _scanHudAt; private bool _scanCopied; private readonly List<Rect> _keepClear = new List<Rect>(); private Rect _contractsRect; private Rect _rightRect; private GUIStyle? _scanStyle; private GUIStyle? _scanStyleFrom; private int _shopSection; private int _shopSel = -1; private Vector2 _shopGridScroll; private Vector2 _shopInspectScroll; private const int ScrollShopGrid = 16; private const int ScrollShopInspect = 17; private static readonly string[] ShopSections = new string[8] { "Featured", "Gear", "Modules", "Consumables", "Services", "Crates", "Buyback", "Wishlist" }; private int _effectsSplit; private float _effectsLeftH; private float _effectsRightH; private bool _effectsTwoCols; private Vector2 _effectsScroll; private const int ScrollEffects = 24; private string _effectsSig = ""; private readonly List<(string text, GUIStyle style, float h)> _effectsLines = new List<(string, GUIStyle, float)>(); private float _effectsH; private int _statsVersion; private static readonly Dictionary<Stat, string> Caps = new Dictionary<Stat, string> { { Stat.DodgeChance, "MaxDodgeChance" }, { Stat.CooldownReduction, "MaxCooldownReduction" }, { Stat.DamageTaken, "MaxDamageReduction" }, { Stat.HeldItemProtection, "MaxHeldItemProtection" }, { Stat.AppraiseValue, "MaxAppraiseBonus" }, { Stat.AppraiseRareBonus, "MaxAppraiseBonus" }, { Stat.GuardAura, "MaxShieldWall" }, { Stat.StabilizeAura, "MaxStabilize" }, { Stat.ScarTissueMax, "MaxScarTissue" }, { Stat.MarkDamage, "MaxMarkDamage" }, { Stat.NoiseReduction, "MaxNoiseReduction" }, { Stat.ScrapBonus, "MaxScrapBonus" }, { Stat.HealOnKill, "MaxHealOnKill" }, { Stat.HealthRegen, "MaxHealthRegen" }, { Stat.Lifesteal, "MaxLifesteal" }, { Stat.ExtractionHeal, "MaxExtractionHeal" }, { Stat.MoveSpeed, "MaxSpeedBonus" }, { Stat.SprintSpeed, "MaxSpeedBonus" }, { Stat.MaxStamina, "MaxStaminaBonus" }, { Stat.StaminaRegen, "MaxStaminaRegenBonus" }, { Stat.StaminaDrain, "MaxStaminaDrainReduction" }, { Stat.HoldingStaminaDrain, "MaxStaminaDrainReduction" } }; private static readonly Regex Num = new Regex("\\d+(\\.\\d+)?", RegexOptions.Compiled); private readonly Dictionary<int, Mate> _mates = new Dictionary<int, Mate>(); private readonly List<Mate> _mateOrder = new List<Mate>(); private float _matesAt = -99f; private float _mateAvatarsAt; private bool _mateOrderDirty; private Rect _triageRect; private float _triageDiagAt; private bool _triageDiagOn; private readonly List<string> _triageDiag = new List<string>(); private int _moreN = -1; private string _moreText = ""; private static readonly Color Good = new Color(0.45f, 1f, 0.4f); private static readonly Color Bad = new Color(1f, 0.38f, 0.32f); private Font? _font; private Texture2D _texWhite; private Texture2D _texAccent; private int _hoverId = -1; private int _hoverIdThisFrame = -1; private static readonly Regex ColorTags = new Regex("</?color[^>]*>", RegexOptions.Compiled); private readonly Dictionary<string, string> _shadowText = new Dictionary<string, string>(); private readonly Dictionary<(GUIStyle, int), GUIStyle> _sizedStyles = new Dictionary<(GUIStyle, int), GUIStyle>(); private readonly Dictionary<(GUIStyle, string, int, int), GUIStyle> _fitCache = new Dictionary<(GUIStyle, string, int, int), GUIStyle>(); private readonly GUIContent _measure = new GUIContent(); private bool _onFill; private readonly Dictionary<(Color, bool), Color> _readable = new Dictionary<(Color, bool), Color>(); private int _readableVersion = -1; private static readonly Regex SizeTag = new Regex("<size=(\\d+)>", RegexOptions.Compiled); private static readonly Regex ColorTag = new Regex("<color=#([0-9a-fA-F]{6})([0-9a-fA-F]{2})?>", RegexOptions.Compiled); private readonly Dictionary<string, string> _sizeTagCache = new Dictionary<string, string>(); private int _tagVersion = -1; private static MethodInfo? _clickMethod; private static MethodInfo? _hoverMethod; private static bool _soundLookupDone; private static FieldInfo? _mmInstance; private static readonly Dictionary<UiSound, object?[]?> SoundArgs = new Dictionary<UiSound, object[]>(); private static readonly Dictionary<UiSound, string[]> SoundNames = new Dictionary<UiSound, string[]> { [UiSound.Click] = new string[3] { "Action", "Click", "Confirm" }, [UiSound.Confirm] = new string[3] { "Confirm", "Buy", "Action" }, [UiSound.Back] = new string[4] { "Back", "Cancel", "Deny", "Action" }, [UiSound.Error] = new string[5] { "Deny", "Error", "Fail", "Back", "Action" }, [UiSound.Tick] = new string[3] { "Tick", "Move", "Action" } }; private bool LimitsKnown => _limitsLevel == RunInfo.LevelIndex; public string CurrentId => Current?.id ?? ""; private float SmallMass => Plugin.Cfg.GrapplerSmallMass.Value + Mathf.Clamp(ClassStat("grappler.heavy"), 0f, 10f); private bool FirmHold => _stats.Custom("attr.firm_hold") > 0f; private float RegenDelayCut => Mathf.Clamp(_stats.Custom("attr.resilient"), 0f, 3f); private RunSave CtRun => _store.Data; public bool ContractBoardOpen => Game.ClassSelectionOpen(); private int CtUsedSlots => CtRun.accepted.Count + PendingAccepts(); public int RerollPrice => ContractBoard.RerollPrice((CtRun.boardLevel == RunInfo.LevelIndex) ? CtRun.boardRerolls : 0); private int DeathSavesUsedThisLevel { get { RunSave data = _store.Data; int levelIndex = RunInfo.LevelIndex; if (data.deathSavesLevel != levelIndex) { bool flag = _deathSavesTagged == data && levelIndex > data.deathSavesLevel; if (data.deathSavesLevel != -1 && !flag) { data.deathSavesUsed = 0; } data.deathSavesLevel = levelIndex; } _deathSavesTagged = data; return data.deathSavesUsed; } } private int DeathSavesLeft { get { int num = Mathf.Max(0, Mathf.FloorToInt(_stats[Stat.DeathSaves]) + _notTodaySaves - DeathSavesUsedThisLevel); if (Difficulty.Hardcore) { num = Mathf.Min(num, Mathf.Max(0, Difficulty.SaveCost - DeathSavesUsedThisLevel)); } return num / Difficulty.SaveCost; } } public static bool LoadoutSwapAllowed { get { if (Game.InLevel()) { return Shop.OpenNow; } return true; } } public bool LateJoinShielded => Time.time < _ljShieldUntil; private float HealMoreMult => 1f + Mathf.Clamp(_stats.Custom("perk.heal_more"), 0f, 30f) / 100f; public int InventoryCap => Mathf.Max(4, Plugin.Cfg.InventorySize.Value - Mathf.RoundToInt(Mathf.Clamp(_stats.Custom("perk.hoarder"), 0f, 10f))); public static RpgRuntime? Instance { get; private set; } public RunSave Run => _store.Data; public ClassDef? Current { get; private set; } public ClassProgress? CurrentProgress { get; private set; } private TrackedField[] AllTracked => new TrackedField[10] { _maxHealth, _move, _sprint, _crouch, _jumpForce, _jumpExtra, _energyMax, _grabStrength, _grabRange, _throw }; public bool RunReady { get { if (_store.Loaded) { return _store.RunKey == RunInfo.Key; } return false; } } public float CooldownRemaining { get { if (_charges <= 0) { return Mathf.Max(0f, _cooldownEnd - Time.time); } return 0f; } } public int Charges => _charges; public int MaxCharges => 1 + Mathf.Max(0, Mathf.FloorToInt(_stats[Stat.AbilityCharges] + _stats.Custom(Current?.active.mods.charges))); public float BuffRemaining => Mathf.Max(0f, _buffEnd - Time.time); public float StaminaRegenBonus { get { if (Current != null) { return Mathf.Clamp((_stats[Stat.StaminaRegen] + _linkRegen) * Plugin.Cfg.StaminaRegenBonusScale.Value, 0f, Plugin.Cfg.MaxStaminaRegenBonus.Value); } return 0f; } } public float LevelElapsed => Time.time - _levelStartTime; public int ShopTier => ShopX.Tier(Account.Active("loyalty_card") ? Mathf.Max(_store.Data.shopRep, ShopX.TierAt[1]) : _store.Data.shopRep); private int[] Parts { get { RunSave data = _store.Data; if (data.parts == null || data.parts.Length < 4) { int[] array = new int[4]; if (data.parts != null) { Array.Copy(data.parts, array, data.parts.Length); } data.parts = array; } return data.parts; } } private bool CanEditHost { get { if (Game.IsMultiplayer()) { return Game.IsMaster(); } return true; } } public bool HostHasPending => _hostPending.Count > 0; public RunSave? HostRun => _store?.Data; private bool TeamVoting { get { if (_tcDef != null && _tcState == 0 && _tcLevel == RunInfo.LevelIndex) { if (!Game.InLevel()) { return Game.ClassSelectionOpen(); } return true; } return false; } } private bool GoldFrame { get { if (Account.Has("gold_frame")) { return Account.Data.goldFrame; } return false; } } private bool AttrHasPending => _attrPending.Count > 0; private bool AttrBusy => _attrInFlight != null; public static bool MenuOpen { get { if ((Object)(object)Instance != (Object)null) { if (!Instance._menuOpen) { return Time.frameCount <= Instance._menuClosedFrame + 2; } return true; } return false; } } public string MenuPrompt { get { //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) if (!Pad.Connected) { return ((object)Plugin.Cfg.MenuKey.Value/*cast due to .constrained prefix*/).ToString(); } return ((Plugin.Cfg.PadMenuHoldSeconds.Value > 0.01f) ? "HOLD " : "") + PadButtons(Plugin.Cfg.PadMenuButton.Value); } } public string AbilityPrompt { get { //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) if (!Pad.Connected) { return ((object)Plugin.Cfg.AbilityKey.Value/*cast due to .constrained prefix*/).ToString(); } return PadButtons(Plugin.Cfg.PadAbilityButton.Value); } } private float PmW => Mathf.Max(50f, TextW("> +", _btn) + 24f); public bool DebugAvailable { get { if (Plugin.Cfg.DebugTools.Value) { return Game.IsMaster(); } return false; } } private static HealFeedbackLevel HealLevel => Plugin.Cfg.HealFeedback.Value; private static bool HudDiag => Plugin.Cfg.HudDiagnostics.Value; private float HeaderH => LineH(_h2) + 6f; private float BtnH => Mathf.Max(36f, LineH(_btn) + 12f); private float GlyphRowH => Mathf.Max(24f, LineH(_tabStyle) + 6f); private float PendingBarH => BtnH + 8f + 4f; public static bool MenuBlocksGame { get { if (MenuOpen) { return !_transitioning; } return false; } } private float ScrollbarW { get { GUIStyle val = (((Object)(object)GUI.skin != (Object)null) ? GUI.skin.verticalScrollbar : null); if (val != null) { return Mathf.Max(16f, val.fixedWidth + (float)val.margin.horizontal); } return 16f; } } private float PromptRowH => 26f * _fontMul; private bool TalentsHavePending => _talentPending.Count > 0; private bool PerksHavePending => _perkPending.Count > 0; private bool TalentsBusy => _commits.ContainsKey(1); private bool PerksBusy => _commits.ContainsKey(2); private bool ClaimBusy => _commits.ContainsKey(3); private bool DecideLocally { get { if (Game.IsMultiplayer() && !Game.IsMaster() && !RunStore.IsTempKey(RunInfo.Key)) { return _hostChecks == HostChecks.No; } return true; } } private bool AnyPending { get { if (!TalentsHavePending && !AttrHasPending) { return PerksHavePending; } return true; } } private bool Reduced => Plugin.Cfg.ReducedEffects.Value; private bool ReducedMotion { get { if (!Plugin.Cfg.ReducedMotion.Value) { return Plugin.Cfg.ReducedEffects.Value; } return true; } } private bool CanUndo { get { string text = ((_tab < TabNames.Length) ? TabNames[_tab] : ""); foreach (var (undoKind, key) in _undo) { if ((text == "Class" && undoKind == UndoKind.Talent && _talentPending.ContainsKey(key)) || (text == "Attributes" && undoKind == UndoKind.Attribute && _attrPending.ContainsKey(key))) { return true; } } return false; } } private string[] TabNames { get { if (!DebugAvailable) { return TabsBase; } return TabsDebug; } } private bool _showEffects { get { return EffectsPrefs.Get(); } set { EffectsPrefs.Set(value); } } private bool SeesTeamHealth { get { if (!(CurrentId == "medic")) { if (CurrentId == "mimic") { return ClassStat("mimic.triage") > 0f; } return false; } return true; } } private static Color Accent => ClassTheme.Cur.Accent; private static Color AccentSoft => Color.Lerp(ClassTheme.Cur.Accent, Color.white, 0.35f); private static Color TextMain => ClassTheme.Cur.Text; private static Color TextMuted => ClassTheme.Cur.Muted; private static Color TextSecondary => ClassTheme.Cur.TextSec; public static event Action<ClassDef?>? ClassChanged; private void OnAbilityState(string text) { string[] array = text.Split('|'); if (array.Length >= 6) { int.TryParse(array[0], out _supplyLeft); int.TryParse(array[1], out _supplyCharges); int.TryParse(array[2], out _supplyPrice); int.TryParse(array[3], out _betLeft); int.TryParse(array[4], out _betUses); int.TryParse(array[5], out _limitsLevel); _nextHudBuild = 0f; } } private void ClearAbilityLimits() { _betMarks.Clear(); _cartState = ""; } private string EffectiveAbilityClass() { if (Current == null) { return ""; } if (Current.id == "mimic") { return MimicCopy()?.id ?? ""; } return Current.id; } private BetMark? MyBet() { int localActor = ClassClaims.LocalActor; foreach (KeyValuePair<int, BetMark> betMark in _betMarks) { if (betMark.Value.Actor == localActor || !Game.IsMultiplayer()) { return betMark.Value; } } return null; } private string AbilityLimitText() { string text = EffectiveAbilityClass(); if (!(text == "quartermaster")) { if (text == "gambler") { BetMark betMark = MyBet(); if (betMark != null) { return $" x{betMark.Mult:0.0} {Mathf.CeilToInt(betMark.Remaining)}s" + ((betMark.Armed < 1f) ? " (arming)" : ""); } int num = (LimitsKnown ? _betUses : Plugin.Cfg.BetUsesPerLevel.Value); int num2 = (LimitsKnown ? _betLeft : num); return $" {num2}/{num} this level"; } return ""; } int num3 = (LimitsKnown ? _supplyCharges : (Plugin.Cfg.ResupplyCharges.Value + ((Current?.id == "quartermaster") ? Mathf.FloorToInt(ClassStat("quartermaster.supply_extra") + 0.001f) : 0))); int num4 = (LimitsKnown ? _supplyLeft : num3); string text2 = $" {num4}/{num3} this level"; if (num4 == 0 && LimitsKnown && _supplyPrice >= 0) { text2 = text2 + " - next " + Scrap.Price(_supplyPrice); } return text2; } private bool ResupplyAllowedLocally() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (LimitsKnown && _supplyLeft == 0 && _supplyPrice < 0) { Toast("Resupply: no charges left this level", Color.gray); MenuSound(UiSound.Error); return false; } return true; } private bool BetAllowedLocally() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (MyBet() != null) { Toast("You already have a bet running", Color.gray); MenuSound(UiSound.Error); return false; } if (LimitsKnown && _betLeft == 0) { Toast("Double or Nothing: already used this level", Color.gray); MenuSound(UiSound.Error); return false; } return true; } public void OnBetState(int viewId, int actor, float mult, float remaining, float armed, string message) { //IL_0066: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (message != "") { _betMarks.Remove(viewId); Color value = ((mult <= 0f) ? new Color(1f, 0.42f, 0.38f) : ((mult <= 1.001f) ? new Color(0.7f, 0.7f, 0.72f) : new Color(1f, 0.18f, 0.6f))); Notify(PopupKind.Other, message, value); _nextHudBuild = 0f; return; } if (!_betMarks.TryGetValue(viewId, out BetMark value2)) { value2 = (_betMarks[viewId] = new BetMark()); } value2.Actor = actor; value2.Mult = mult; value2.Remaining = remaining; value2.Armed = armed; value2.At = Time.unscaledTime; value2.Text = ((armed < 1f) ? $"x{mult:0.0} {Mathf.CeilToInt(remaining)}s ARMING" : $"x{mult:0.0} {Mathf.CeilToInt(remaining)}s"); } private void DrawBetMarks() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //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_0121: 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_0140: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) if (_betMarks.Count == 0 || (int)Event.current.type != 7) { return; } Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return; } float unscaledTime = Time.unscaledTime; float num = Mathf.Max(0.01f, _lastUiScale); _betGone.Clear(); foreach (KeyValuePair<int, BetMark> betMark in _betMarks) { BetMark value = betMark.Value; if (unscaledTime - value.At > 4f) { _betGone.Add(betMark.Key); continue; } if ((Object)(object)value.Target == (Object)null && unscaledTime >= value.LookedUp) { value.LookedUp = unscaledTime + 1f; PhotonView val = PhotonView.Find(betMark.Key); value.Target = (((Object)(object)val != (Object)null) ? ((Component)val).transform : null); } if (!((Object)(object)value.Target == (Object)null)) { Vector3 val2 = Game.ToScreen(main, value.Target.position + Vector3.up * 0.7f); if (!(val2.z <= 0f)) { float num2 = val2.x / num; float num3 = ((float)Screen.height - val2.y) / num; float num4 = 260f * _fontMul; float num5 = LineH(_h2Center); ShadowLabel(new Rect(num2 - num4 / 2f, num3 - num5, num4, num5), value.Text, _h2Center, new Color(1f, 0.18f, 0.6f)); } } } foreach (int item in _betGone) { _betMarks.Remove(item); } } public float ClassStat(string name) { return _stats.Custom(name); } private void TickClassStatsSend() { if (!Game.IsMultiplayer()) { return; } PhysGrabber instance = PhysGrabber.instance; float num = (((Object)(object)instance != (Object)null) ? instance.grabStrength : (-1f)); float num2 = (((Object)(object)instance != (Object)null) ? instance.throwStrength : (-10f)); if (Time.unscaledTime >= _nextGripCheck) { _nextGripCheck = Time.unscaledTime + 0.5f; if (Mathf.Abs(num - _sentGrab) > 0.02f || Mathf.Abs(num2 - _sentThrow) > 0.02f) { _classStatsSendAt = 0f; } } if (Time.unscaledTime < _classStatsSendAt) { return; } _classStatsSendAt = Time.unscaledTime + 10f; string currentId = CurrentId; if (currentId != "") { _stats.CustomWithPrefix(currentId + ".", _classStatsBuf); } else { _classStatsBuf.Clear(); } _stats.CustomWithPrefix("set.", _setStatsBuf); foreach (KeyValuePair<string, float> item in _setStatsBuf) { _classStatsBuf[item.Key] = item.Value; } _stats.CustomWithPrefix("perk.", _setStatsBuf); foreach (KeyValuePair<string, float> item2 in _setStatsBuf) { _classStatsBuf[item2.Key] = item2.Value; } _stats.CustomWithPrefix("attr.", _setStatsBuf); foreach (KeyValuePair<string, float> item3 in _setStatsBuf) { _classStatsBuf[item3.Key] = item3.Value; } _stats.CustomWithPrefix("gear.", _setStatsBuf); foreach (KeyValuePair<string, float> item4 in _setStatsBuf) { _classStatsBuf[item4.Key] = item4.Value; } _stats.CustomWithPrefix("shop.", _setStatsBuf); foreach (KeyValuePair<string, float> item5 in _setStatsBuf) { _classStatsBuf[item5.Key] = item5.Value; } _sentGrab = num; _sentThrow = num2; Net.SendClassStats(ClassStats.Encode(currentId, _classStatsBuf), num, num2); } public void OnAllyBuff(AllyBuff b) { //IL_01f7: Unknown result type (might be due to invalid IL or missing references) if (b.Speed > 0f || b.Grip > 0f || b.Guard > 0f) { _buffs.Add(new TimedBuff { Speed = b.Speed, Grip = b.Grip, Guard = b.Guard, Until = Time.time + Mathf.Max(0.5f, b.Duration), Source = (b.Source ?? "") }); } if (b.Source == "Rally Cry" && CurrentId == "brute" && Synergies.Has(Game.LocalPlayer(), "war_cry")) { for (int i = 0; i < Mathf.Clamp(Mathf.RoundToInt(Synergies.V("war_cry")), 0, 3); i++) { AddFrenzy(); } } if (b.HealthPct > 0f) { _pendingHealthPct = b.HealthPct; _pendingHealthAt = Time.time + 0.6f; } if (b.StaminaPct > 0f) { PlayerController instance = PlayerController.instance; if ((Object)(object)instance != (Object)null) { float num = Game.Get(instance, "EnergyStart", 0f); float num2 = Game.Get(instance, "EnergyCurrent", 0f); Game.Set(instance, "EnergyCurrent", Mathf.Min(num, num2 + num * b.StaminaPct / 100f)); } } if (!string.IsNullOrEmpty(b.Source) && (b.Speed > 0f || b.Guard > 0f || b.Grip > 0f)) { Notify(PopupKind.Other, b.Source + ": " + BuffText(b.Speed, b.Grip, b.Guard), ParseColor(Current?.color ?? "#FFFFFF"), "buff:" + b.Source); } } private static string BuffText(float speed, float grip, float guard) { List<string> list = new List<string>(); if (speed > 0f) { list.Add($"+{speed:0}% speed"); } if (grip > 0f) { list.Add($"+{grip:0}% grip"); } if (guard > 0f) { list.Add($"-{guard:0}% damage"); } return string.Join(", ", list); } private void AddSelfBuff(AllyBuff b) { OnAllyBuff(b); } private void AddSelfDyn(Stat s, float v, float seconds) { _selfDyn.Add((s, v, Time.time + seconds)); } private void TickNewClasses(PlayerAvatar local) { //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) float time = Time.time; string currentId = CurrentId; for (int num = _buffs.Count - 1; num >= 0; num--) { if (time >= _buffs[num].Until) { _buffs.RemoveAt(num); } } for (int num2 = _selfDyn.Count - 1; num2 >= 0; num2--) { if (time >= _selfDyn[num2].until) { _selfDyn.RemoveAt(num2); } } float num3 = 0f; float num4 = 0f; foreach (TimedBuff buff in _buffs) { num3 = Mathf.Max(num3, buff.Speed); num4 = Mathf.Max(num4, buff.Grip); } if (num3 > 0f) { _stats.AddDyn(Stat.MoveSpeed, num3); _stats.AddDyn(Stat.SprintSpeed, num3); } if (num4 > 0f) { _stats.AddDyn(Stat.GrabStrength, num4); } foreach (var item in _selfDyn) { _stats.AddDyn(item.stat, item.value); } if (_pendingHealthPct > 0f && time >= _pendingHealthAt) { ApplyPendingHealth(local); } if (time >= _nextNearCheck) { _nextNearCheck = time + 0.5f; _monsterNear = false; foreach (EnemyHealth item2 in Game.LivingEnemies()) { Vector3 val = ((Component)item2).transform.position - ((Component)local).transform.position; if (((Vector3)(ref val)).sqrMagnitude < 100f) { _monsterNear = true; break; } } float num5 = 0f; float num6 = 0f; foreach (var (aura, num7) in NearbyAuras(local)) { if (!(aura.Inspire <= 0f) && !(num7 > aura.InspireRadius)) { num5 = Mathf.Max(num5, aura.InspireSpeed * aura.Inspire / 100f); num6 = Mathf.Max(num6, aura.InspireGrip * aura.Inspire / 100f); } } _inspireFromAllies = (speed: num5, grip: num6); } if (_inspireFromAllies.speed > 0f) { _stats.AddDyn(Stat.MoveSpeed, _inspireFromAllies.speed); _stats.AddDyn(Stat.SprintSpeed, _inspireFromAllies.speed); } if (_inspireFromAllies.grip > 0f) { _stats.AddDyn(Stat.GrabStrength, _inspireFromAllies.grip); } if (currentId != "bloodbound") { TickPactDrain(local); } if (currentId == "gambler" && time >= _gambleCheckAt) { _gambleCheckAt = time + 2f; EnsureGambleRoll(); } switch (currentId) { case "herald": TickHerald(local); break; case "mimic": TickMimic(local); break; case "undertaker": TickUndertaker(local); break; case "physicist": _stats.AddDyn(Stat.ThrowStrength, ClassStat("physicist.throw")); break; case "bloodbound": TickBloodbound(local); break; } TickThirdWave(local, currentId); TickThreats(local); TickAltPassives(local, currentId, time); } private float NewClassDamageMult() { //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) float num = 0f; foreach (TimedBuff buff in _buffs) { num = Mathf.Max(num, buff.Guard); } float num2 = 1f - Mathf.Clamp(num, 0f, 50f) / 100f; switch (CurrentId) { case "herald": if (_monsterNear) { num2 *= 1f - Mathf.Clamp(ClassStat("herald.near_guard"), 0f, 40f) / 100f; } if (_inspire > 50f) { num2 *= 1f - Mathf.Clamp(ClassStat("herald.rod_guard"), 0f, 40f) / 100f; } break; case "undertaker": if (HoldingHead()) { num2 *= 1f - Mathf.Clamp(ClassStat("undertaker.carry_guard"), 0f, 40f) / 100f; } break; case "juggernaut": { float num4 = Mathf.Clamp(ClassStat("juggernaut.alt_anchor"), 0f, 30f); PlayerController instance = PlayerController.instance; Rigidbody val = (((Object)(object)instance != (Object)null) ? Game.Get<Rigidbody>(instance, "rb", null) : null); if (num4 > 0f && (Object)(object)val != (Object)null) { Vector3 linearVelocity = val.linearVelocity; if (((Vector3)(ref linearVelocity)).sqrMagnitude < 0.25f) { num2 *= 1f - num4 / 100f; } } break; } case "cartwright": { float num3 = ClassStat("cartwright.cart_shelter"); if (num3 > 0f && CartNear(4f)) { num2 *= 1f - Mathf.Clamp(num3, 0f, 40f) / 100f; } break; } } PlayerAvatar val2 = Game.LocalPlayer(); if ((Object)(object)val2 != (Object)null) { num2 *= ThirdWaveDamageMult(val2); } if ((Object)(object)val2 != (Object)null) { num2 *= SynergyDamageMult(val2); } return num2; } private void OnHitTaken() { float num = Mathf.Clamp(ClassStat("brute.alt_grudge"), 0f, 60f); if (num > 0f && CurrentId == "brute") { AddSelfDyn(Stat.WeaponDamage, num, 3f); _nextCombatSend = 0f; } if (CurrentId == "herald") { _inspire = Mathf.Min(100f, _inspire + Mathf.Max(0f, ClassStat("herald.hurt_gain"))); } } private bool CartNear(float range) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar val = Game.LocalPlayer(); if ((Object)(object)val == (Object)null) { return false; } if (Time.time >= _nextCartLook) { _nextCartLook = Time.time + 2f; try { _cartsNear = Object.FindObjectsByType<PhysGrabCart>((FindObjectsSortMode)0); } catch { _cartsNear = Array.Empty<PhysGrabCart>(); } } PhysGrabCart[] cartsNear = _cartsNear; foreach (PhysGrabCart val2 in cartsNear) { if ((Object)(object)val2 != (Object)null) { Vector3 val3 = ((Component)val2).transform.position - ((Component)val).transform.position; if (((Vector3)(ref val3)).sqrMagnitude <= range * range) { return true; } } } return false; } private void TickHerald(PlayerAvatar local) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_019a: 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_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) float deltaTime = Time.deltaTime; if (!Game.IsAlive(local)) { _talking = false; return; } bool flag = false; object obj = VoiceInstance.Value(); if (obj != null) { flag = Game.Get(obj, "clipLoudness", 0f) > Plugin.Cfg.HeraldVoiceThreshold.Value; } bool flag2 = !_menuOpen && ((_held.Contains(Plugin.Cfg.HumKey.Value) && !ChatOpen.Value()) || (Pad.Connected && Pad.ChordHeld(Plugin.Cfg.PadHumButton.Value))); _talking = flag || flag2; bool flag3 = ClassStat("herald.alt_whisper") > 0f; float num = (flag3 ? 0f : ClassStat("herald.voice_draw")); if (_talking && num > 0f && Time.time >= _nextVoiceDraw && Game.InLevel()) { _nextVoiceDraw = Time.time + 2f; Vector3 val = ((Component)local).transform.position; if (Synergies.Has(local, "chorus")) { Vector3 forward = ((Component)local).transform.forward; forward.y = 0f; NavMeshHit val2 = default(NavMeshHit); val = (NavMesh.SamplePosition(val + ((Vector3)(ref forward)).normalized * Mathf.Clamp(Synergies.V("chorus"), 0f, 12f), ref val2, 3f, -1) ? ((NavMeshHit)(ref val2)).position : val); } Net.SendClassAction(ClassHost.Act.Investigate, val, new float[1] { Mathf.Min(num, 30f) }, 0, usesCharge: false); } float num2 = Mathf.Max(0f, ClassStat("herald.inspire_gain")) * (flag ? 1f : 0.4f); if (Time.time >= _nextAudienceCheck) { _nextAudienceCheck = Time.time + 0.5f; float num3 = Mathf.Max(1f, ClassStat("herald.inspire_radius")); _audience = false; _whisperTalk = false; foreach (PlayerAvatar item in Game.Players()) { if ((Object)(object)item == (Object)null || (Object)(object)item == (Object)(object)local || !Game.IsAlive(item)) { continue; } Vector3 val3 = ((Component)item).transform.position - ((Component)local).transform.position; if (((Vector3)(ref val3)).sqrMagnitude > num3 * num3) { continue; } _audience = true; if (ClassStat("herald.alt_whisper") > 0f) { object obj2 = Game.Get<object>(item, "voiceChat", null); if (obj2 != null && Game.Get(obj2, "isTalking", fallback: false)) { _whisperTalk = true; } } } } if (_talking && _audience) { _inspire += num2 * deltaTime; } else if (flag3 && _whisperTalk) { _inspire += Mathf.Max(0f, ClassStat("herald.inspire_gain")) * 0.5f * deltaTime; } else { float num4 = Mathf.Max(0f, ClassStat("herald.silent_cap")); float num5 = Mathf.Max(0f, ClassStat("herald.silent_gain")); if (num5 > 0f && _inspire < num4) { _inspire = Mathf.Min(num4, _inspire + num5 * deltaTime); } else { _inspire -= Mathf.Max(0.5f, ClassStat("herald.inspire_decay")) * deltaTime; } } _inspire = Mathf.Clamp(_inspire, 0f, 100f); if (_inspire >= 100f && !_inspireWasFull) { CEv("cls.herald"); } _inspireWasFull = _inspire >= 100f; bool flag4 = (_inspire <= 0f && _lastInspireSent > 0f) || (_inspire >= 100f && _lastInspireSent < 100f); if (Time.unscaledTime >= _nextInspireSend && (Mathf.Abs(_inspire - _lastInspireSent) >= 2f || flag4)) { _nextInspireSend = Time.unscaledTime + ((PlayerScaling.RoomPlayers() > 10) ? 0.5f : 0.3f); _lastInspireSent = _inspire; _auraSentNonZero = true; Net.SendAura(LocalAura()); } } private void RallyCry(Vector3 pos, float speedPct, float duration, float radius, bool copied, float durMult) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) float num = ((copied || CurrentId != "herald") ? 50f : _inspire); float num2 = 0.5f + 0.5f * num / 100f; float num3 = speedPct * num2; float num4 = num3 * 1.25f; float num5 = num3 * 0.83f; float num6 = 0f; float num7 = (copied ? 0f : ClassStat("herald.rally_taunt")); Net.SendClassAction(ClassHost.Act.Rally, pos, new float[7] { radius, num3, num4, num5, duration, num6, num7 }); if (!copied && !(CurrentId != "herald")) { float num8 = ClassStat("herald.full_refund"); if (num8 > 0f && _inspire >= 80f) { _rallyRefund = num8; } else { _inspire *= 0.5f; } } } public ClassDef? MimicCopy() { string text = _copies[_copySlot]; if (!(text == "")) { return Plugin.Db.Get(text); } return null; } private void TickMimic(PlayerAvatar local) { //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) if (!Game.IsAlive(local)) { _copyCandidate = -1; _copyTimer = 0f; } else { if (Time.time < _nextCopyLook) { return; } float num = ((_lastCopyLook < 0f) ? 0.25f : Mathf.Min(1f, Time.time - _lastCopyLook)); _lastCopyLook = Time.time; _nextCopyLook = Time.time + 0.25f; float num2 = Mathf.Max(1f, ClassStat("mimic.copy_range")); float num3 = Mathf.Max(0f, ClassStat("mimic.copy_time")); PlayerAvatar val = null; float num4 = num2 * num2; foreach (PlayerAvatar item in Game.Players()) { if ((Object)(object)item == (Object)null || (Object)(object)item == (Object)(object)local || !Game.IsAlive(item)) { continue; } string text = ClassStats.ClassOf(item); if (!(text == "") && !(text == "mimic")) { Vector3 val2 = ((Component)item).transform.position - ((Component)local).transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num4) { num4 = sqrMagnitude; val = item; } } } if ((Object)(object)val == (Object)null) { _copyCandidate = -1; _copyTimer = 0f; return; } int num5 = Game.ActorNumber(val); if (num5 != _copyCandidate) { _copyCandidate = num5; _copyTimer = 0f; } _copyTimer += num; string text2 = ClassStats.ClassOf(val); if (!(_copyTimer < num3) && !(text2 == _copies[_copySlot])) { LearnCopy(text2, Game.Get(val, "playerName", "a teammate")); } } } private void LearnCopy(string classId, string from) { //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) ClassDef classDef = Plugin.Db.Get(classId); if (classDef == null) { return; } bool flag = ClassStat("mimic.dual") > 0f; if (flag && _copies[1 - _copySlot] == classId) { return; } float num = ((_copies[_copySlot] != "") ? CooldownSeconds() : 0f); bool flag2 = ClassStat("mimic.split") > 0f; if (flag && _copies[_copySlot] != "") { int num2 = 1 - _copySlot; (int, float) tuple = _slotState[num2]; _copies[num2] = _copies[_copySlot]; _copyFrom[num2] = _copyFrom[_copySlot]; _slotState[num2] = (charges: _charges, cdEnd: _cooldownEnd); if (flag2 && (tuple.Item1 < _charges || (tuple.Item1 == _charges && tuple.Item2 > _cooldownEnd))) { (_charges, _cooldownEnd) = tuple; } } _copies[_copySlot] = classId; _copyFrom[_copySlot] = from; if (num > 0f && _cooldownEnd > Time.time) { float num3 = CooldownSeconds(); _cooldownEnd = Time.time + (_cooldownEnd - Time.time) * num3 / num; } float num4 = Mathf.Clamp(ClassStat("mimic.fresh"), 0f, 100f); if (_charges <= 0 && _cooldownEnd > Time.time && num4 > 0f && !_freshUsed) { _cooldownEnd -= (_cooldownEnd - Time.time) * num4 / 100f; _freshUsed = true; } Toast("Copied " + classDef.active.name + " from " + from, ParseColor(classDef.color)); Notify(PopupKind.Other, "Copied: " + classDef.active.name + " (" + from + ")", ParseColor(Current?.color ?? "#FFFFFF"), "mimic"); _nextCombatSend = 0f; } private void MimicSwap() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) if (CurrentId != "mimic" || ClassStat("mimic.dual") <= 0f) { return; } int num = 1 - _copySlot; if (_copies[num] == "") { Toast("No second copy yet", Color.gray); return; } float num2 = CooldownSeconds(); if (ClassStat("mimic.split") > 0f) { (int, float) tuple = (_charges, _cooldownEnd); (_charges, _cooldownEnd) = _slotState[num]; _slotState[_copySlot] = tuple; _copySlot = num; } else { _copySlot = num; float num3 = CooldownSeconds(); if (_cooldownEnd > Time.time && num2 > 0f) { _cooldownEnd = Time.time + (_cooldownEnd - Time.time) * num3 / num2; } } ClassDef classDef = MimicCopy(); if (classDef != null) { Toast("Ready: " + classDef.active.name, ParseColor(classDef.color)); } MenuSound(UiSound.Tick); } private void MimicAfterUse() { float num = Mathf.Clamp(ClassStat("mimic.refund"), 0f, 60f); if (num > 0f && _cooldownEnd > Time.time) { _cooldownEnd -= CooldownSeconds() * num / 100f; } float num2 = Mathf.Clamp(ClassStat("mimic.cross"), 0f, 60f); if (num2 > 0f && ClassStat("mimic.split") > 0f) { int num3 = 1 - _copySlot; (int, float) tuple = _slotState[num3]; if (tuple.Item2 > Time.time) { _slotState[num3] = (charges: tuple.Item1, cdEnd: tuple.Item2 - (tuple.Item2 - Time.time) * num2 / 100f); } } } private bool HoldingHead() { return (Object)(object)Game.HeldComponent<PlayerDeathHead>() != (Object)null; } private void TickUndertaker(PlayerAvatar local) { if (HoldingHead()) { float num = ClassStat("undertaker.head_speed"); if (num > 0f) { _stats.AddDyn(Stat.MoveSpeed, num); _stats.AddDyn(Stat.SprintSpeed, num); } float num2 = ClassStat("undertaker.head_grip"); if (num2 > 0f) { _stats.AddDyn(Stat.GrabStrength, num2); } } } private void ApplyPendingHealth(PlayerAvatar local) { PlayerHealth playerHealth = local.playerHealth; if ((Object)(object)playerHealth == (Object)null || Game.Get(local, "isDisabled", fallback: false)) { if (Time.time - _pendingHealthAt > 5f) { _pendingHealthPct = 0f; } return; } int num = Game.MaxHealth(playerHealth); int num2 = Game.Health(playerHealth); int num3 = Mathf.RoundToInt((float)num * Mathf.Clamp(_pendingHealthPct, 0f, 100f) / 100f); _pendingHealthPct = 0f; if (num3 > num2) { playerHealth.Heal(num3 - num2, false); } } private bool TryBet(float power) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) ValuableObject val = Game.HeldValuable(); if ((Object)(object)val == (Object)null) { Toast("Hold a valuable to bet on it", Color.gray); MenuSound(UiSound.Error); return false; } if (!BetAllowedLocally()) { return false; } int num = ClassHost.ViewId((Component?)(object)val); if (num == 0) { return false; } Net.SendClassAction(ClassHost.Act.Bet, ((Component)val).transform.position, Array.Empty<float>(), num); return true; } private void EnsureGambleRoll() { //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) if (CurrentId != "gambler" || !Game.InLevel()) { return; } RunSave data = _store.Data; string text = RunInfo.Key + ":" + RunInfo.LevelIndex; if (data.gambleKey == text) { return; } RpgData rpg = Plugin.Rpg; if (rpg.blessings.Length == 0 || rpg.curses.Length == 0) { return; } Random random = new Random(StableHash(text + ":" + Game.SteamId(Game.LocalPlayer()))); data.gambleKey = text; data.gambleBless.Clear(); int num = random.Next(rpg.blessings.Length); data.gambleBless.Add(rpg.blessings[num].id); if (random.NextDouble() * 100.0 < (double)ClassStat("gambler.extra_bless") && rpg.blessings.Length > 1) { int num2 = (num + 1 + random.Next(rpg.blessings.Length - 1)) % rpg.blessings.Length; data.gambleBless.Add(rpg.blessings[num2].id); } data.gambleCurse = ((random.NextDouble() * 100.0 < (double)ClassStat("gambler.no_curse")) ? "" : rpg.curses[random.Next(rpg.curses.Length)].id); _store.MarkDirty(); _statsDirty = true; List<string> list = new List<string>(); foreach (string item in data.gambleBless) { PerkDef perkDef = Find(rpg.blessings, item); if (perkDef != null) { list.Add("Blessing: " + perkDef.name + " (" + perkDef.desc + ")"); } } PerkDef perkDef2 = Find(rpg.curses, data.gambleCurse); list.Add((perkDef2 != null) ? ("Curse: " + perkDef2.name + " (" + perkDef2.desc + ")") : "No curse this level!"); Color val = ParseColor(Current?.color ?? "#FFFFFF"); Notify(PopupKind.Perk, string.Join(" | ", list), val, "gamble"); Toast("Fortune's Wheel: " + string.Join(", ", list.ConvertAll((string l) => l.Split('(')[0].Trim())), val, 5f); } private static int StableHash(string s) { int num = -2128831035; foreach (char c in s) { num = (num ^ c) * 16777619; } return num; } private static PerkDef? Find(PerkDef[] list, string id) { foreach (PerkDef perkDef in list) { if (perkDef.id == id) { return perkDef; } } return null; } private void ApplyClassExtras() { string currentId = CurrentId; if (currentId == "gambler") { RunSave data = _store.Data; if (data.gambleKey == RunInfo.Key + ":" + RunInfo.LevelIndex) { float mult = 1f + Mathf.Max(0f, ClassStat("gambler.bless_power")) / 100f; float mult2 = Mathf.Max(0f, 1f - Mathf.Max(0f, ClassStat("gambler.curse_soft")) / 100f); foreach (string item in data.gambleBless) { PerkDef perkDef = Find(Plugin.Rpg.blessings, item); if (perkDef != null) { _stats.AddPermEffects(perkDef.effects, mult); } } PerkDef perkDef2 = Find(Plugin.Rpg.curses, data.gambleCurse); if (perkDef2 != null) { _stats.AddPermEffects(perkDef2.effects, mult2); } } _stats.AddPerm(Stat.GearFind, ClassStat("gambler.gear_find")); } if (currentId == "quartermaster") { _stats.AddPerm(Stat.ScrapBonus, ClassStat("quartermaster.scrap")); } ApplyThirdWaveExtras(currentId); } private void OnLevelStartClasses() { ClearAbilityLimits(); _buffs.Clear(); _selfDyn.Clear(); _inspire = 0f; _pactEnd = 0f; _copies[0] = (_copies[1] = ""); _copyFrom[0] = (_copyFrom[1] = ""); _copySlot = 0; _slotState[0] = (_slotState[1] = (charges: 1, cdEnd: 0f)); _copyCandidate = -1; _copyTimer = 0f; _bloodAcc = 0f; _drainAcc = 0f; _refundAfterUse = false; ClassFx.HideAll(); ThirdWaveReset(); _gambleCheckAt = Time.time + 3f; if (!_cartFollowOn) { SendCartFollow(); } } private void TickBloodbound(PlayerAvatar local) { PlayerHealth playerHealth = local.playerHealth; float num = ClassStat("bloodbound.hit_power"); if ((Object)(object)playerHealth != (Object)null && (float)Game.Health(playerHealth) < (float)Game.MaxHealth(playerHealth) * 0.4f) { num += ClassStat("bloodbound.low_power"); } _stats.AddDyn(Stat.WeaponDamage, num); _stats.AddDyn(Stat.ThrowStrength, ClassStat("bloodbound.throw_power")); float num2 = _stats.Dyn(Stat.WeaponDamage); if (Mathf.Abs(num2 - _lastBloodWeapon) > 0.5f) { _lastBloodWeapon = num2; _nextCombatSend = 0f; } TickPactDrain(local); } private void TickPactDrain(PlayerAvatar local) { if (_pactEnd <= 0f) { return; } PlayerHealth playerHealth = local.playerHealth; if (Time.time < _pactEnd && (Object)(object)playerHealth != (Object)null) { _drainAcc += _pactDrain * Time.deltaTime; if (_drainAcc >= 1f) { int num = Mathf.FloorToInt(_drainAcc); _drainAcc -= num; SpendHealth(num); } } else { _drainAcc = 0f; _pactEnd = 0f; } } private void SpendHealth(float amount) { PlayerAvatar val = Game.LocalPlayer(); PlayerHealth val2 = (((Object)(object)val != (Object)null) ? val.playerHealth : null); if ((Object)(object)val2 == (Object)null || (Object)(object)val == (Object)null || !Game.IsAlive(val)) { return; } int num = Game.Health(val2); _bloodAcc = Mathf.Clamp(_bloodAcc + amount, -50f, 50f); if (_bloodAcc <= -1f) { int num2 = Mathf.FloorToInt(0f - _bloodAcc); _bloodAcc += num2; val2.Heal(num2, false); if (CurrentId == "bloodbound") { CEv("cls.bloodbound", num2); } } else { if (_bloodAcc < 1f) { return; } int num3 = Mathf.FloorToInt(_bloodAcc); _bloodAcc -= num3; int num4 = Mathf.Min(num3, num - 1); if (num4 <= 0) { return; } int num5 = num - num4; try { Game.Set(val2, "health", num5); StatsManager instance = StatsManager.instance; if (instance != null) { instance.SetPlayerHealth(Game.SteamId(val), num5, false); } PhotonView val3 = Game.Get<PhotonView>(val2, "photonView", null); if (Game.IsMultiplayer() && (Object)(object)val3 != (Object)null) { val3.RPC("UpdateHealthRPC", (RpcTarget)1, new object[3] { num5, Game.MaxHealth(val2), false }); } } catch (Exception ex) { Game.WarnOnce("Blood Price failed: " + ex.GetBaseException().Message); } _lastSeenHp = num5; } } private void OnKillNear(float dist) { if (!(CurrentId != "bloodbound") && !(dist > Plugin.Cfg.KillShareRadius.Value + Mathf.Max(0f, ClassStat("bloodbound.feed_range")))) { PlayerAvatar val = Game.LocalPlayer(); PlayerHealth val2 = (((Object)(object)val != (Object)null) ? val.playerHealth : null); int num = Mathf.RoundToInt(Mathf.Clamp(ClassStat("bloodbound.feed"), 0f, 60f)); if ((Object)(object)val2 != (Object)null && num > 0) { Game.HealSelf(val2, num); NoteHeal(num, HealKind.Instant, "Feed"); } float num2 = ClassStat("bloodbound.feed_cd"); if (num2 > 0f && _cooldownEnd > 0f) { _cooldownEnd -= num2; } float num3 = ClassStat("bloodbound.feast_speed"); if (num3 > 0f) { AddSelfBuff(new AllyBuff { Speed = num3, Duration = 5f, Source = "Sanguine Feast" }); } } } public void OnClassNotice(Notice kind, float value, string text) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) switch (kind) { case Notice.Text: if (text != "") { Toast(text, ParseColor(Current?.color ?? "#FFFFFF")); } break; case Notice.BloodCost: if (CurrentId == "bloodbound") { SpendHealth(value); } break; case Notice.Slip: if (value > 0f) { AddSelfBuff(new AllyBuff { Speed = Mathf.Min(value, 40f), Duration = 3f, Source = "" }); } break; case Notice.Popup: if (text != "") { Notify(PopupKind.Other, text, ParseColor(Current?.color ?? "#FFFFFF")); } break; case Notice.AbilityState: OnAbilityState(text); break; case Notice.CartState: _cartState = text; _nextHudBuild = 0f; break; case Notice.RefundAbility: _specialistPending = false; if (_inActive) { _refundAfterUse = true; } else { RefundCharge(); } break; } } private void RefundCharge() { _charges = Mathf.Min(MaxCharges, _charges + 1); if (_charges >= MaxCharges) { _cooldownEnd = 0f; } } public void ShowFx(ClassHost.Fx fx, Vector3 pos, float radius, float seconds) { //IL_0025: 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_004d: 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) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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)