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 STARCODE Events v0.5.0
plugins/Starcode.Events.dll
Decompiled 2 hours 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.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using ExitGames.Client.Photon; using HarmonyLib; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.AI; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace Starcode.Events; public sealed class Card { public string Id; public string Ja; public string En; public string DescriptionJa; public string DescriptionEn; public string Icon; public string Effect; public string Attribute; public bool Permanent; public int Danger; public int DeckCount; public int Amount; public double WeightPerCard; [JsonIgnore] public double Weight => (double)DeckCount * WeightPerCard; } public sealed class EventSettings { public double DebuffPercent = 95.0; public double BuffPercent = 5.0; public Card[] Events; public static EventSettings Read(string json, string defaultsJson) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 JToken val = JToken.Parse(json); if ((int)val.Type != 2) { return val.ToObject<EventSettings>(); } EventSettings eventSettings = JsonConvert.DeserializeObject<EventSettings>(defaultsJson); List<Card> list = eventSettings.Events.ToList(); HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); Card[] array = val.ToObject<Card[]>(); foreach (Card previous in array) { if (previous == null || string.IsNullOrWhiteSpace(previous.Id) || !hashSet.Add(previous.Id)) { throw new FormatException("Invalid or duplicate event ID in legacy configuration."); } Card card = list.Find((Card c) => c.Id == previous.Id); if (card != null) { card.DeckCount = previous.DeckCount; card.WeightPerCard = previous.WeightPerCard; continue; } previous.Attribute = ((previous.Effect == "apex") ? "debuff" : "buff"); previous.Amount = ((previous.Effect == "maxHp") ? 2 : ((previous.Effect == "heal") ? 25 : 0)); if (previous.Effect == "maxHp") { previous.DescriptionJa = "最大HPが1回につき2増える。"; previous.DescriptionEn = "Gain 2 maximum HP per stack."; } list.Add(previous); } eventSettings.Events = list.ToArray(); return eventSettings; } } public sealed class EventOdds { public readonly Card Card; public readonly double FirstSlot; public readonly double InOffer; public EventOdds(Card card, double firstSlot, double inOffer) { Card = card; FirstSlot = firstSlot; InOffer = inOffer; } } public sealed class Catalog { private readonly Card[] cards; private readonly Random random; private readonly double debuffChance; public Catalog(EventSettings settings, Random random) { if (settings == null || !(settings.DebuffPercent >= 0.0) || !(settings.DebuffPercent <= 100.0) || !(settings.BuffPercent >= 0.0) || !(settings.BuffPercent <= 100.0) || Math.Abs(settings.DebuffPercent + settings.BuffPercent - 100.0) > 1E-09) { throw new FormatException("DebuffPercent and BuffPercent must be between 0 and 100 and sum to 100."); } Card[] events = settings.Events; if (events == null || events.Any((Card c) => c == null || string.IsNullOrWhiteSpace(c.Id) || string.IsNullOrWhiteSpace(c.Ja) || c.DeckCount < 0 || c.WeightPerCard < 0.0 || double.IsNaN(c.Weight) || double.IsInfinity(c.Weight) || c.Danger < 1 || c.Danger > 5 || !SupportedEffect(c))) { throw new FormatException("Invalid event definition."); } if (events.Select((Card c) => c.Id).Distinct<string>(StringComparer.Ordinal).Count() != events.Length) { throw new FormatException("Duplicate event ID."); } cards = events.Where((Card c) => c.Weight > 0.0).ToArray(); if (cards.Length < 3 || double.IsInfinity(cards.Sum((Card c) => c.Weight))) { throw new FormatException("At least three positive weights and a finite total are required."); } this.random = random; debuffChance = settings.DebuffPercent / 100.0; } private static bool SupportedEffect(Card card) { bool flag = card.Effect == "maxHp" || card.Effect == "maxStamina"; bool flag2 = card.Effect == "moveSpeed"; bool flag3 = card.Effect == "healScale"; bool flag4 = card.Effect == "enemyHp" || card.Effect == "enemySpeed" || card.Effect == "enemyVision"; if (card.Attribute == "debuff") { if ((!(card.Effect == "apex") || card.Permanent || card.Amount != 0) && ((!flag && !flag2) || card.Amount < (flag2 ? (-90) : (-100)) || card.Amount >= 0) && (!flag4 || card.Amount <= 0) && (!flag3 || card.Amount < -100 || card.Amount >= 0) && (!(card.Effect == "enemyAttack") || card.Permanent || card.Amount <= 0 || card.Amount > 100) && (!(card.Effect == "mapJam") || card.Permanent || card.Amount != 1) && (!(card.Effect == "hunterAim") || card.Permanent || card.Amount <= 0 || card.Amount > 75) && (!(card.Effect == "quota") || card.Permanent || card.Amount <= 0 || card.Amount > 100) && (!(card.Effect == "enemyAudio") || card.Permanent || card.Amount < -100 || card.Amount >= 0) && (!(card.Effect == "treasureMass") || card.Permanent || card.Amount <= 0 || card.Amount > 100) && (!(card.Effect == "treasureValue") || card.Permanent || card.Amount < -90 || card.Amount >= 0) && (!(card.Effect == "durability") || card.Permanent || card.Amount < -90 || card.Amount >= 0)) { if (card.Effect == "extraSlots" && !card.Permanent && card.Amount > 0) { return card.Amount <= 3; } return false; } return true; } if (card.Attribute == "buff") { if ((!(card.Effect == "heal") || card.Permanent || card.Amount <= 0) && ((!flag && !flag2) || card.Amount <= 0 || (card.Permanent && card.Amount > 2)) && (!flag4 || card.Amount < -90 || card.Amount >= 0 || (card.Permanent && card.Amount < -2))) { if (flag3 && card.Amount > 0) { if (card.Permanent) { return card.Amount <= 2; } return true; } return false; } return true; } return false; } public Card[] Draw() { List<Card> list = cards.ToList(); Card[] array = new Card[3]; for (int i = 0; i < array.Length; i++) { bool debuff = random.NextDouble() < debuffChance; Card[] array2 = list.Where((Card c) => c.Attribute == "debuff" == debuff).ToArray(); if (array2.Length == 0) { array2 = list.ToArray(); } double num = random.NextDouble() * array2.Sum((Card c) => c.Weight); int num2 = 0; while (num2 < array2.Length - 1 && num >= array2[num2].Weight) { num -= array2[num2++].Weight; } array[i] = array2[num2]; list.Remove(array[i]); } return array; } private double ConditionalChance(Card target, Card first, Card second) { double num = 0.0; double num2 = 0.0; Card[] array = cards; foreach (Card card in array) { if (card != first && card != second) { if (card.Attribute == target.Attribute) { num += card.Weight; } else { num2 += card.Weight; } } } double num3 = ((target.Attribute == "debuff") ? debuffChance : (1.0 - debuffChance)); if (num2 == 0.0) { num3 = 1.0; } return num3 * (target.Weight / num); } public EventOdds[] GetOdds() { return cards.Select(delegate(Card card) { double num = ConditionalChance(card, null, null); double num2 = num; foreach (Card first in cards.Where((Card c) => c != card)) { double num3 = ConditionalChance(first, null, null); num2 += num3 * ConditionalChance(card, first, null); Card[] source = cards; Func<Card, bool> predicate = (Card c) => c != card && c != first; foreach (Card item in source.Where(predicate)) { num2 += num3 * ConditionalChance(item, first, null) * ConditionalChance(card, first, item); } } return new EventOdds(card, num, num2); }).ToArray(); } public string[] Probabilities() { return (from odds in GetOdds() select $"{odds.Card.Id} ({odds.Card.Attribute}): first {odds.FirstSlot:P3}, any card {odds.InOffer:P3}").ToArray(); } } public sealed class RunState { private readonly Dictionary<string, int> stacks = new Dictionary<string, int>(); public Card Active { get; private set; } public Card Selected { get; private set; } public bool Committed { get; private set; } public void BeginStage() { Active = null; Selected = null; Committed = false; } public void Reset() { BeginStage(); stacks.Clear(); } public int Count(string id) { if (!stacks.TryGetValue(id, out var value)) { return 0; } return value; } public Dictionary<string, int> Snapshot() { return new Dictionary<string, int>(stacks); } public void Restore(IEnumerable<KeyValuePair<string, int>> saved, IEnumerable<Card> definitions) { Reset(); HashSet<string> hashSet = new HashSet<string>(definitions.Select((Card card) => card.Id), StringComparer.Ordinal); foreach (KeyValuePair<string, int> item in saved) { if (item.Value > 0 && hashSet.Contains(item.Key)) { stacks[item.Key] = item.Value; } } } public bool Commit(Card card) { if (Committed) { return false; } stacks[card.Id] = checked(Count(card.Id) + 1); if (!card.Permanent) { Active = card; } Selected = card; Committed = true; return true; } internal bool ClearActive() { if (Active == null) { return false; } Active = null; Selected = null; return true; } internal bool AddPermanent(Card card) { if (!card.Permanent || Count(card.Id) == int.MaxValue) { return false; } stacks[card.Id] = Count(card.Id) + 1; return true; } internal void ClearPermanent(IEnumerable<Card> definitions) { foreach (Card item in definitions.Where((Card c) => c.Permanent)) { stacks.Remove(item.Id); } } public int MaxHpModifier(IEnumerable<Card> definitions) { return Modifier(definitions, "maxHp"); } internal int Modifier(IEnumerable<Card> definitions, string effect) { long num = 0L; foreach (Card definition in definitions) { if (definition.Permanent && definition.Effect == effect) { num += (long)definition.Amount * (long)Count(definition.Id); } } if (Active != null && Active.Effect == effect) { num += Active.Amount; } return (int)Math.Max(-2147483648L, Math.Min(2147483647L, num)); } } public sealed class StageVote { private readonly HashSet<int> eligible; private readonly Dictionary<int, int> votes = new Dictionary<int, int>(); public int EligibleCount => eligible.Count; public StageVote(IEnumerable<int> eligibleActors) { eligible = new HashSet<int>(eligibleActors); } public bool Cast(int actor, int card) { if (!eligible.Contains(actor) || card < 0 || card >= 3) { return false; } votes[actor] = card; return true; } public int[] Totals(IEnumerable<int> connected) { HashSet<int> hashSet = new HashSet<int>(connected); int[] array = new int[3]; foreach (KeyValuePair<int, int> vote in votes) { if (hashSet.Contains(vote.Key)) { array[vote.Value]++; } } return array; } public int[] Leaders(int host, IEnumerable<int> connected) { int[] totals = Totals(connected); int[] array = (from i in Enumerable.Range(0, 3) where totals[i] == totals.Max() select i).ToArray(); if (!votes.TryGetValue(host, out var value) || !array.Contains(value)) { return array; } return new int[1] { value }; } } public sealed class StageSnapshot { public int Serial; public int Revision; public int Stage; public string Round; public float SecondsRemaining; public Card[] Cards; public Card[] PermanentCards; public int[] Totals; public int[] Tied; public int[] HealActors; public int Eligible; public int MaxHpModifier; public int MaxStaminaModifier; public int MoveSpeedModifier; public int HealScaleModifier; public int EnemyAttackModifier; public int TreasureMassModifier; public int EnemyAudioModifier; public Dictionary<string, int> Stacks; public Card Selected; public string Enemy; public static bool FromHost(int sender, int currentHost, int observedHost) { if (sender > 0 && sender == currentHost) { return currentHost == observedHost; } return false; } public bool IsNewerThan(StageSnapshot previous) { if (Serial < 1 || Revision < 1 || string.IsNullOrEmpty(Round)) { return false; } if (previous != null && Serial <= previous.Serial) { if (Serial == previous.Serial && Round == previous.Round) { return Revision > previous.Revision; } return false; } return true; } } [BepInPlugin("starcode.repo.events", "STARCODE R.E.P.O. Events", "0.5.0")] public sealed class Plugin : BaseUnityPlugin { private const string NetworkTag = "starcode.events.v8"; private const byte SnapshotEvent = 171; private const byte VoteEvent = 172; private const string Id = "starcode.repo.events"; private const string SaveKey = "starcodeEventSelectionsV1"; private Room networkRoom; private int networkMaster; private int networkSerial; private bool authorityChanged; private float nextPublish; private float voteEndsAt; private StageVote ballot; private StageSnapshot networkSnapshot; private int localVote = -1; private string lastHealRound; private string traceOfferRound; private string traceResultRound; private string traceEffectRound; private string traceStaminaRound; private string traceMovementRound; private static readonly FieldInfo SaveDictionaries = AccessTools.Field(typeof(StatsManager), "dictionaryOfDictionaries"); private static readonly FieldInfo MaxHp = AccessTools.Field(typeof(PlayerHealth), "maxHealth"); private static readonly FieldInfo CurrentHp = AccessTools.Field(typeof(PlayerHealth), "health"); private static readonly FieldInfo HealthSet = AccessTools.Field(typeof(PlayerHealth), "healthSet"); private static readonly FieldInfo AvatarHealth = AccessTools.Field(typeof(PlayerAvatar), "playerHealth"); private static readonly FieldInfo ControlledAvatar = AccessTools.Field(typeof(PlayerController), "playerAvatarScript"); private static readonly FieldInfo SpawnObjects = AccessTools.Field(typeof(EnemySetup), "spawnObjects"); private static readonly FieldInfo RankThree = AccessTools.Field(typeof(EnemyDirector), "enemiesDifficulty3"); private static readonly FieldInfo DebugEnemies = AccessTools.Field(typeof(EnemyDirector), "debugEnemy"); private static readonly FieldInfo LevelNumber = AccessTools.Field(typeof(LevelUI), "textNumber"); private static readonly FieldInfo LevelMoon = AccessTools.Field(typeof(LevelUI), "textMoon"); private static readonly FieldInfo MapActive = AccessTools.Field(typeof(MapToolController), "Active"); private static readonly FieldInfo CurrentMenuPage = AccessTools.Field(typeof(MenuManager), "currentMenuPage"); private static Plugin instance; private readonly Random random = new Random(); private readonly RunState run = new RunState(); private Catalog catalog; private Card[] definitions; private Card[] offer; private EnemySetup replacement; private readonly Dictionary<int, EnemySetup> apexGroups = new Dictionary<int, EnemySetup>(); private bool selectingEnemies; private bool healPending; private int originalSlots; private int replacedSlots; private float deadline; private PlayerHealth trackedHealth; private int appliedBonus; private PlayerController staminaController; private float staminaApplied; private ConfigEntry<bool> english; private ConfigEntry<bool> debug; private Harmony harmony; private Font japaneseFont; private readonly Vector3[] hudCorners = (Vector3[])(object)new Vector3[4]; private GUIStyle statusStyle; private EventSettings eventSettings; private Dictionary<string, EventOdds> menuOdds; private bool eventMenuOpen; private Vector2 eventMenuScroll; private Dictionary<string, int> pendingLoad; private bool consoleOpen; private string command = ""; private string commandStatus = ""; private float movementMultiplier = 1f; private static readonly FieldInfo EnemyCurrentHealth = AccessTools.Field(typeof(EnemyHealth), "healthCurrent"); private readonly Dictionary<EnemyHealth, int> enemyBaseHealth = new Dictionary<EnemyHealth, int>(); private int reconciledEnemyModifier; private static readonly FieldInfo EnemyAgent = AccessTools.Field(typeof(EnemyNavMeshAgent), "Agent"); private readonly Dictionary<NavMeshAgent, float> enemyBaseSpeeds = new Dictionary<NavMeshAgent, float>(); private int enemySpeedModifier; private float enemyVisionMultiplier = 1f; private bool buildingEnemySetup; private static readonly FieldInfo AvailableHaul = AccessTools.Field(typeof(RoundDirector), "haulGoalMax"); private static readonly FieldInfo DamageSourceEnemy = AccessTools.Field(typeof(HurtCollider), "enemyHost"); private static readonly FieldInfo DamageSourcePlayer = AccessTools.Field(typeof(HurtCollider), "playerCausingHurt"); private static readonly FieldInfo Appraised = AccessTools.Field(typeof(ValuableObject), "dollarValueSet"); private static readonly FieldInfo OriginalValue = AccessTools.Field(typeof(ValuableObject), "dollarValueOriginal"); private static readonly FieldInfo CurrentValue = AccessTools.Field(typeof(ValuableObject), "dollarValueCurrent"); private static readonly FieldInfo ValuableView = AccessTools.Field(typeof(ValuableObject), "photonView"); private readonly Dictionary<ValuableObject, float> valuableOriginalAppraisals = new Dictionary<ValuableObject, float>(); private readonly Dictionary<Rigidbody, float> valuableBaseMasses = new Dictionary<Rigidbody, float>(); private int valuableMassModifier; private static readonly FieldInfo SoundLowPass = AccessTools.Field(typeof(Sound), "LowPassLogic"); private static readonly FieldInfo LowPassVolume = AccessTools.Field(typeof(AudioLowPassLogic), "Volume"); private readonly Dictionary<Type, FieldInfo[]> enemySoundFields = new Dictionary<Type, FieldInfo[]>(); private readonly Dictionary<Sound, EnemyParent> enemySounds = new Dictionary<Sound, EnemyParent>(); private readonly Dictionary<Sound, float> enemyLoopVolumes = new Dictionary<Sound, float>(); private float enemyAudioMultiplier = 1f; private static readonly FieldInfo NativeMapActive = AccessTools.Field(typeof(Map), "Active"); private static readonly FieldInfo NativeMapParent = AccessTools.Field(typeof(Map), "ActiveParent"); private Map hiddenMap; private bool NetworkActive { get { if (Object.op_Implicit((Object)(object)GameManager.instance) && SemiFunc.IsMultiplayer()) { return PhotonNetwork.InRoom; } return false; } } private bool SnapshotForStage { get { if (networkSnapshot != null && Object.op_Implicit((Object)(object)RunManager.instance) && SemiFunc.RunIsLevel()) { return networkSnapshot.Stage == SemiFunc.RunGetLevelsCompleted(); } return false; } } private void UpdateNetwork() { //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown Room val = (NetworkActive ? PhotonNetwork.CurrentRoom : null); int num = ((val != null && PhotonNetwork.MasterClient != null) ? PhotonNetwork.MasterClient.ActorNumber : 0); if (val != networkRoom || num != networkMaster) { bool flag = networkRoom != null; authorityChanged = val != null && val == networkRoom; networkRoom = val; networkMaster = num; networkSerial = 0; nextPublish = 0f; voteEndsAt = 0f; networkSnapshot = null; ballot = null; localVote = -1; lastHealRound = null; traceOfferRound = (traceResultRound = (traceEffectRound = (traceStaminaRound = (traceMovementRound = null)))); if (flag || val != null) { run.Reset(); offer = null; healPending = false; RestorePlayerEffects(); } if (val != null) { Player localPlayer = PhotonNetwork.LocalPlayer; Hashtable val2 = new Hashtable(); ((Dictionary<object, object>)(object)val2).Add((object)"starcode.events.v8", (object)true); localPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); } if (authorityChanged) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Event voting suspended after host migration. Start a new room to resume."); } } if (val == null || authorityChanged || !Object.op_Implicit((Object)(object)RunManager.instance)) { return; } if (PhotonNetwork.IsMasterClient && networkSnapshot != null && Time.realtimeSinceStartup >= nextPublish) { PublishSnapshot(); } if (!PhotonNetwork.IsMasterClient) { offer = ((SnapshotForStage && networkSnapshot.Selected == null && Time.realtimeSinceStartup < voteEndsAt) ? networkSnapshot.Cards : null); if (offer != null) { SemiFunc.CursorUnlock(0.15f); } } } private IEnumerator MultiplayerSelection() { double until = Time.realtimeSinceStartup + 3f; while (NetworkActive && PhotonNetwork.IsMasterClient && !authorityChanged && !AllPlayersCompatible() && (double)Time.realtimeSinceStartup < until) { yield return null; } if (!NetworkActive || !PhotonNetwork.IsMasterClient || authorityChanged || !AllPlayersCompatible()) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Skipped multiplayer events: every active player must have the same protocol."); yield break; } int host = PhotonNetwork.LocalPlayer.ActorNumber; ballot = new StageVote(ConnectedActors()); localVote = -1; offer = catalog.Draw(); voteEndsAt = Time.realtimeSinceStartup + 25f; networkSnapshot = new StageSnapshot { Serial = ++networkSerial, Stage = SemiFunc.RunGetLevelsCompleted(), Round = Guid.NewGuid().ToString("N"), Cards = offer, Eligible = ballot.EligibleCount }; PublishSnapshot(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Multiplayer offer: " + string.Join(", ", offer.Select((Card card) => card.Id).ToArray()))); while (HasAuthority(host) && Time.realtimeSinceStartup < voteEndsAt) { SemiFunc.CursorUnlock(0.15f); yield return null; } if (!HasAuthority(host)) { yield break; } if (!AllPlayersCompatible()) { offer = null; ballot = null; voteEndsAt = 0f; PublishSnapshot(); yield break; } int[] leaders = ballot.Leaders(host, ConnectedActors()); if (leaders.Length > 1) { networkSnapshot.Tied = leaders; voteEndsAt = Time.realtimeSinceStartup + 8f; PublishSnapshot(); while (HasAuthority(host) && offer != null && Time.realtimeSinceStartup < voteEndsAt) { SemiFunc.CursorUnlock(0.15f); yield return null; } } if (HasAuthority(host)) { if (offer != null) { CommitSelection(leaders[0]); } networkSnapshot.Selected = run.Selected; networkSnapshot.HealActors = ConnectedActors(); ballot = null; PublishSnapshot(); } } private bool HasAuthority(int host) { if (NetworkActive && PhotonNetwork.IsMasterClient && !authorityChanged && PhotonNetwork.LocalPlayer.ActorNumber == host) { return networkSnapshot != null; } return false; } private bool AllPlayersCompatible() { object value; return PhotonNetwork.PlayerList.Where((Player player) => !player.IsInactive).All((Player player) => player.IsLocal || (((Dictionary<object, object>)(object)player.CustomProperties).TryGetValue((object)"starcode.events.v8", out value) && object.Equals(value, true))); } private static int[] ConnectedActors() { return (from player in PhotonNetwork.PlayerList where !player.IsInactive select player.ActorNumber).ToArray(); } private void PublishSnapshot() { //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Expected O, but got Unknown //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) if (NetworkActive && PhotonNetwork.IsMasterClient && networkSnapshot != null) { networkSnapshot.Revision++; networkSnapshot.Stacks = run.Snapshot(); networkSnapshot.PermanentCards = definitions.Where((Card card) => card.Permanent && run.Count(card.Id) > 0).ToArray(); networkSnapshot.MaxHpModifier = run.MaxHpModifier(definitions); networkSnapshot.MaxStaminaModifier = run.Modifier(definitions, "maxStamina"); networkSnapshot.MoveSpeedModifier = run.Modifier(definitions, "moveSpeed"); networkSnapshot.HealScaleModifier = run.Modifier(definitions, "healScale"); networkSnapshot.EnemyAttackModifier = run.Modifier(definitions, "enemyAttack"); networkSnapshot.TreasureMassModifier = run.Modifier(definitions, "treasureMass"); networkSnapshot.EnemyAudioModifier = run.Modifier(definitions, "enemyAudio"); if (ballot != null) { networkSnapshot.Totals = ballot.Totals(ConnectedActors()); } float realtimeSinceStartup = Time.realtimeSinceStartup; networkSnapshot.SecondsRemaining = Mathf.Max(0f, voteEndsAt - realtimeSinceStartup); nextPublish = realtimeSinceStartup + 2f; object[] obj = new object[2] { "starcode.events.v8", JsonConvert.SerializeObject((object)networkSnapshot) }; RaiseEventOptions val = new RaiseEventOptions(); val.Receivers = (ReceiverGroup)0; PhotonNetwork.RaiseEvent((byte)171, (object)obj, val, SendOptions.SendReliable); TraceResult(); } } private void Vote(int index) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (!SnapshotForStage || networkSnapshot.Selected != null || Time.realtimeSinceStartup >= voteEndsAt) { return; } if (networkSnapshot.Tied != null) { if (PhotonNetwork.IsMasterClient && Extensions.Contains(networkSnapshot.Tied, index)) { CommitSelection(index); } return; } int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber; if (PhotonNetwork.IsMasterClient) { if (ballot == null || !ballot.Cast(actorNumber, index)) { return; } PublishSnapshot(); } else { object[] obj = new object[3] { "starcode.events.v8", networkSnapshot.Round, index }; RaiseEventOptions val = new RaiseEventOptions(); val.Receivers = (ReceiverGroup)2; if (!PhotonNetwork.RaiseEvent((byte)172, (object)obj, val, SendOptions.SendReliable)) { return; } } localVote = index; } private void OnPhotonEvent(EventData message) { if (!NetworkActive || authorityChanged || (message.Code != 171 && message.Code != 172) || !(message.CustomData is object[] array) || array.Length < 2 || !object.Equals(array[0], "starcode.events.v8")) { return; } if (message.Code == 172) { if (PhotonNetwork.IsMasterClient && ballot != null && networkSnapshot != null && networkSnapshot.Tied == null && !(Time.realtimeSinceStartup >= voteEndsAt) && array.Length == 3 && object.Equals(array[1], networkSnapshot.Round) && array[2] is int && Extensions.Contains(ConnectedActors(), message.Sender) && ballot.Cast(message.Sender, (int)array[2])) { PublishSnapshot(); } return; } Player masterClient = PhotonNetwork.MasterClient; string text = array[1] as string; if (PhotonNetwork.IsMasterClient || masterClient == null || !StageSnapshot.FromHost(message.Sender, masterClient.ActorNumber, networkMaster) || text == null || text.Length > 65536) { return; } StageSnapshot stageSnapshot; try { stageSnapshot = JsonConvert.DeserializeObject<StageSnapshot>(text); } catch (JsonException) { return; } if (stageSnapshot != null && stageSnapshot.Cards != null && stageSnapshot.Cards.Length == 3 && !stageSnapshot.Cards.Any((Card card) => card == null) && stageSnapshot.Stacks != null && (stageSnapshot.Totals == null || stageSnapshot.Totals.Length == 3) && stageSnapshot.PermanentCards != null && !stageSnapshot.PermanentCards.Any((Card card) => card == null) && stageSnapshot.IsNewerThan(networkSnapshot)) { if (networkSnapshot == null || networkSnapshot.Round != stageSnapshot.Round) { localVote = -1; } if (stageSnapshot.Selected != null && (networkSnapshot == null || networkSnapshot.Selected == null || networkSnapshot.Round != stageSnapshot.Round)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Host selection received: " + stageSnapshot.Selected.Id)); } voteEndsAt = Time.realtimeSinceStartup + Mathf.Clamp(stageSnapshot.SecondsRemaining, 0f, 25f); networkSnapshot = stageSnapshot; TraceResult(); } } private void TraceDisplayedOffer() { if (debug.Value && !(networkSnapshot.Round == traceOfferRound)) { traceOfferRound = networkSnapshot.Round; WriteSyncTrace("offer", new { cards = offer.Select((Card card) => card.Id).ToArray() }); } } private void TraceResult() { if (debug.Value && networkSnapshot.Selected != null && !(networkSnapshot.Round == traceResultRound)) { traceResultRound = networkSnapshot.Round; WriteSyncTrace("result", new { cards = networkSnapshot.Cards.Select((Card card) => card.Id).ToArray(), selected = networkSnapshot.Selected.Id, effect = networkSnapshot.Selected.Effect, permanent = networkSnapshot.Selected.Permanent, modifier = networkSnapshot.MaxHpModifier, staminaModifier = networkSnapshot.MaxStaminaModifier, speedModifier = networkSnapshot.MoveSpeedModifier, healScaleModifier = networkSnapshot.HealScaleModifier, enemyAttackModifier = networkSnapshot.EnemyAttackModifier, treasureMassModifier = networkSnapshot.TreasureMassModifier, enemyAudioModifier = networkSnapshot.EnemyAudioModifier, votes = networkSnapshot.Totals, stacks = networkSnapshot.Stacks }); } } private void TraceAppliedHealth(PlayerHealth hp) { if (debug.Value && NetworkActive && SnapshotForStage && networkSnapshot.Selected != null && !(networkSnapshot.Round == traceEffectRound)) { traceEffectRound = networkSnapshot.Round; int num = (int)MaxHp.GetValue(hp); WriteSyncTrace("health", new { baseline = (long)num - (long)appliedBonus, maximum = num, applied = appliedBonus }); } } private void TraceAppliedStamina(PlayerController controller) { if (debug.Value && Object.op_Implicit((Object)(object)controller) && NetworkActive && SnapshotForStage && networkSnapshot.Selected != null && !(networkSnapshot.Selected.Effect != "maxStamina") && !(networkSnapshot.Round == traceStaminaRound)) { traceStaminaRound = networkSnapshot.Round; float energyStart = controller.EnergyStart; WriteSyncTrace("stamina", new { baseline = energyStart - staminaApplied, maximum = energyStart, applied = staminaApplied }); } } private void TraceAppliedMovement(float native, float scaled) { if (debug.Value && !(native <= 0f) && NetworkActive && SnapshotForStage && networkSnapshot.Selected != null && !(networkSnapshot.Selected.Effect != "moveSpeed") && !(networkSnapshot.Round == traceMovementRound) && movementMultiplier != 1f) { traceMovementRound = networkSnapshot.Round; WriteSyncTrace("movement", new { baseline = native, target = scaled, multiplier = movementMultiplier }); } } private void WriteSyncTrace(string kind, object data) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("SYNC_CHECK " + JsonConvert.SerializeObject((object)new { kind = kind, round = networkSnapshot.Round, stage = networkSnapshot.Stage, actor = PhotonNetwork.LocalPlayer.ActorNumber, role = (PhotonNetwork.IsMasterClient ? "host" : "client"), data = data }))); } private int EffectiveModifier(string effect) { if (!NetworkActive || PhotonNetwork.IsMasterClient) { return run.Modifier(definitions, effect); } if (networkSnapshot == null) { return 0; } if (SnapshotForStage) { switch (effect) { case "maxHp": return networkSnapshot.MaxHpModifier; case "maxStamina": return networkSnapshot.MaxStaminaModifier; case "moveSpeed": return networkSnapshot.MoveSpeedModifier; case "healScale": return networkSnapshot.HealScaleModifier; case "enemyAttack": return networkSnapshot.EnemyAttackModifier; case "treasureMass": return networkSnapshot.TreasureMassModifier; case "enemyAudio": return networkSnapshot.EnemyAudioModifier; } } long val = networkSnapshot.PermanentCards.Where((Card card) => card.Effect == effect).Sum((Card card) => (long)card.Amount * (long)DisplayCount(card.Id)); return (int)Math.Max(-2147483648L, Math.Min(2147483647L, val)); } private int DisplayCount(string id) { if (!NetworkActive || PhotonNetwork.IsMasterClient) { return run.Count(id); } if (networkSnapshot == null || !networkSnapshot.Stacks.TryGetValue(id, out var value)) { return 0; } return value; } private void HealFromHost(PlayerHealth hp) { if (SnapshotForStage && networkSnapshot.Selected != null && !(networkSnapshot.Selected.Effect != "heal") && !(lastHealRound == networkSnapshot.Round) && networkSnapshot.HealActors != null && Extensions.Contains(networkSnapshot.HealActors, PhotonNetwork.LocalPlayer.ActorNumber)) { lastHealRound = networkSnapshot.Round; hp.Heal(networkSnapshot.Selected.Amount, true); } } private void Awake() { //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Expected O, but got Unknown //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Expected O, but got Unknown //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Expected O, but got Unknown //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Expected O, but got Unknown //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Expected O, but got Unknown //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Expected O, but got Unknown //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Expected O, but got Unknown //IL_0406: Unknown result type (might be due to invalid IL or missing references) //IL_0412: Expected O, but got Unknown //IL_0457: Unknown result type (might be due to invalid IL or missing references) //IL_046e: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Expected O, but got Unknown //IL_0479: Expected O, but got Unknown //IL_04a6: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Expected O, but got Unknown //IL_04c8: Expected O, but got Unknown //IL_04f5: Unknown result type (might be due to invalid IL or missing references) //IL_0503: Expected O, but got Unknown //IL_0530: Unknown result type (might be due to invalid IL or missing references) //IL_053e: Expected O, but got Unknown try { english = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "English", false, "Use English card text."); debug = ((BaseUnityPlugin)this).Config.Bind<bool>("Developer", "Enabled", false, "Log multiplayer verification records and enable F8 developer commands."); string text = Path.Combine(Paths.ConfigPath, "starcode.repo.events.json"); string text2 = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "events.json"); if (!File.Exists(text)) { File.Copy(text2, text); } string text3 = File.ReadAllText(text); EventSettings eventSettings = (this.eventSettings = EventSettings.Read(text3, File.ReadAllText(text2))); definitions = eventSettings.Events; catalog = new Catalog(eventSettings, random); if (text3.TrimStart(new char[0]).StartsWith("[", StringComparison.Ordinal)) { string text4 = text + ".migration"; File.WriteAllText(text4, JsonConvert.SerializeObject((object)eventSettings, (Formatting)1)); File.Replace(text4, text, text + ".pre-attributes"); } if (MaxHp == null || CurrentHp == null || HealthSet == null || AvatarHealth == null || ControlledAvatar == null || SpawnObjects == null || RankThree == null || DebugEnemies == null) { throw new MissingFieldException("This game build does not expose the expected event fields."); } instance = this; harmony = new Harmony("starcode.repo.events"); harmony.Patch((MethodBase)AccessTools.Method(typeof(LevelGenerator), "EnemySetup", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "BeforeEnemySetup", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Harmony obj = harmony; MethodInfo methodInfo = AccessTools.Method(typeof(EnemyDirector), "GetEnemy", (Type[])null, (Type[])null); HarmonyMethod val = new HarmonyMethod(typeof(Plugin), "AfterGetEnemy", (Type[])null); val.priority = 0; obj.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(PlayerHealth), "UpdateHealthRPC", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "AfterHealthReplaced", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(PlayerHealth), "Heal", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "BeforeHeal", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(PlayerController), "FixedUpdate", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "ScaleNativeMovement", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); HarmonyMethod val2 = new HarmonyMethod(typeof(Plugin), "BeforeEnemyHealthInitialized", (Type[])null); harmony.Patch((MethodBase)AccessTools.Method(typeof(EnemyHealth), "Awake", (Type[])null, (Type[])null), val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(EnemyHealth), "OnSpawn", (Type[])null, (Type[])null), val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); if (EnemyCurrentHealth == null) { throw new MissingFieldException("Enemy health field unavailable."); } InstallEnemyAiPatches(harmony); InstallAdvancedStagePatches(harmony); InstallExtractionPatches(harmony); InstallValuableMassPatches(harmony); if (definitions.Any((Card card) => card.Effect == "enemyAudio")) { InstallEnemyAudioPatches(harmony); } InstallEnemyDamagePatches(harmony); if (definitions.Any((Card card) => card.Effect == "treasureValue")) { InstallValuableValuePatches(harmony); } harmony.Patch((MethodBase)AccessTools.Method(typeof(EnemyDirector), "AmountSetup", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "ModifyEnemyAmounts", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); if (SaveDictionaries == null) { throw new MissingFieldException("Event save dictionary unavailable."); } harmony.Patch((MethodBase)AccessTools.Method(typeof(StatsManager), "SaveGame", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "BeforeSave", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "AfterSave", (Type[])null), (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(StatsManager), "LoadGame", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "BeforeLoad", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "AfterLoad", (Type[])null), (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(SemiFunc), "MenuActionSingleplayerGame", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "BeforeStartRun", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(SemiFunc), "MenuActionHostGame", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "BeforeStartRun", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); SceneManager.activeSceneChanged += SceneChanged; PhotonNetwork.NetworkingClient.EventReceived += OnPhotonEvent; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Event system ready."); } catch (Exception ex) { if (harmony != null) { harmony.UnpatchSelf(); } instance = null; ((BaseUnityPlugin)this).Logger.LogError((object)ex); ((Behaviour)this).enabled = false; } } private void OnDestroy() { SceneManager.activeSceneChanged -= SceneChanged; PhotonNetwork.NetworkingClient.EventReceived -= OnPhotonEvent; RestorePlayerEffects(); if (harmony != null) { harmony.UnpatchSelf(); } if (Object.op_Implicit((Object)(object)japaneseFont)) { Object.Destroy((Object)(object)japaneseFont); } if ((Object)(object)instance == (Object)(object)this) { instance = null; } } private void SceneChanged(Scene before, Scene after) { consoleOpen = false; valuableOriginalAppraisals.Clear(); RestorePlayerEffects(); run.BeginStage(); offer = null; replacement = null; healPending = false; if (!Object.op_Implicit((Object)(object)RunManager.instance) || SemiFunc.MenuLevel() || SemiFunc.RunIsLobby() || SemiFunc.RunIsArena()) { run.Reset(); } if (NetworkActive && PhotonNetwork.IsMasterClient && networkSnapshot != null) { networkSnapshot.Stage = -1; networkSnapshot.Selected = null; voteEndsAt = 0f; PublishSnapshot(); } } private static void BeforeEnemySetup(ref IEnumerator __result) { if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)GameManager.instance) || !Object.op_Implicit((Object)(object)RunManager.instance) || !SemiFunc.RunIsLevel()) { return; } if (SemiFunc.IsMultiplayer()) { if (!instance.NetworkActive || !PhotonNetwork.IsMasterClient) { return; } instance.UpdateNetwork(); } instance.RestorePendingLoad(); __result = instance.WithSelection(__result); } private static SortedDictionary<string, Dictionary<string, int>> SaveData(StatsManager stats) { return (SortedDictionary<string, Dictionary<string, int>>)SaveDictionaries.GetValue(stats); } private static void BeforeSave(StatsManager __instance, string __0, out bool __state) { __state = Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)GameManager.instance) && SemiFunc.IsMasterClientOrSingleplayer() && !string.IsNullOrEmpty(__0); if (__state) { SaveData(__instance)["starcodeEventSelectionsV1"] = instance.pendingLoad ?? instance.run.Snapshot(); } } private static void AfterSave(StatsManager __instance, bool __state) { if (__state) { SaveData(__instance).Remove("starcodeEventSelectionsV1"); } } private static void BeforeLoad(StatsManager __instance, out bool __state) { __state = Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)GameManager.instance) && SemiFunc.IsMasterClientOrSingleplayer(); if (__state) { instance.pendingLoad = null; SaveData(__instance)["starcodeEventSelectionsV1"] = new Dictionary<string, int>(); } } private static void AfterLoad(StatsManager __instance, Exception __exception, bool __state) { if (__state) { SortedDictionary<string, Dictionary<string, int>> sortedDictionary = SaveData(__instance); if (__exception == null && Object.op_Implicit((Object)(object)instance) && sortedDictionary.TryGetValue("starcodeEventSelectionsV1", out var value)) { instance.pendingLoad = new Dictionary<string, int>(value); } sortedDictionary.Remove("starcodeEventSelectionsV1"); } } private static void BeforeStartRun(string __0) { if (Object.op_Implicit((Object)(object)instance) && string.IsNullOrEmpty(__0)) { instance.pendingLoad = null; instance.run.Reset(); } } private void RestorePendingLoad() { if (pendingLoad != null) { run.Restore(pendingLoad, definitions); pendingLoad = null; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Restored event selections: " + JsonConvert.SerializeObject((object)run.Snapshot()))); } } private IEnumerator WithSelection(IEnumerator original) { try { if (!run.Committed && SemiFunc.IsMultiplayer()) { { IEnumerator voting = MultiplayerSelection(); try { while (voting.MoveNext()) { yield return voting.Current; } } finally { IDisposable disposable2 = voting as IDisposable; if (disposable2 != null) { disposable2.Dispose(); } } } } else if (!run.Committed) { offer = catalog.Draw(); deadline = Time.realtimeSinceStartup + 25f; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Offer: " + string.Join(", ", offer.Select((Card c) => c.Id).ToArray()))); while (offer != null && Time.realtimeSinceStartup < deadline) { SemiFunc.CursorUnlock(0.15f); yield return null; } if (offer != null) { Choose(0); } } ReconcileExistingAppraisals(); Plugin plugin = this; Plugin plugin2 = this; int num = 0; plugin2.replacedSlots = 0; plugin.originalSlots = num; replacement = FindReplacement(); if (NetworkActive && PhotonNetwork.IsMasterClient && networkSnapshot != null) { networkSnapshot.Enemy = (Object.op_Implicit((Object)(object)replacement) ? ((Object)replacement).name : null); PublishSnapshot(); } while (true) { buildingEnemySetup = true; selectingEnemies = Object.op_Implicit((Object)(object)replacement); bool moved; try { moved = original.MoveNext(); } finally { Plugin plugin3 = this; Plugin plugin4 = this; bool flag = false; plugin4.selectingEnemies = false; plugin3.buildingEnemySetup = flag; } if (!moved) { break; } yield return original.Current; } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Enemy slots: {replacedSlots} replaced of {originalSlots} planned enemies"); } finally { offer = null; replacement = null; foreach (EnemySetup value in apexGroups.Values) { Object.Destroy((Object)(object)value); } apexGroups.Clear(); if (original is IDisposable disposable) { disposable.Dispose(); } } } private EnemySetup FindReplacement() { if (run.Active == null || run.Active.Effect != "apex") { return null; } if (HasExternalSpawnConfig()) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Apex skipped: another spawn configuration plugin is active."); return null; } EnemyDirector val = Object.FindFirstObjectByType<EnemyDirector>(); List<EnemySetup> list = (Object.op_Implicit((Object)(object)val) ? ((List<EnemySetup>)RankThree.GetValue(val)) : null); EnemySetup[] array = (EnemySetup[])((list == null) ? ((Array)new EnemySetup[0]) : ((Array)list.Where(IsReplacementCandidate).Distinct().ToArray())); if (array.Length == 0) { ((BaseUnityPlugin)this).Logger.LogError((object)"Apex skipped: no single-enemy tier-three setup is available."); return null; } EnemySetup val2 = array[random.Next(array.Length)]; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Apex enemy: " + ((Object)val2).name)); return val2; } private static List<PrefabRef> GetSpawnObjects(EnemySetup setup) { if (!Object.op_Implicit((Object)(object)setup)) { return null; } return (List<PrefabRef>)SpawnObjects.GetValue(setup); } private static bool IsReplacementCandidate(EnemySetup setup) { List<PrefabRef> spawnObjects = GetSpawnObjects(setup); if (spawnObjects != null && spawnObjects.Count == 1) { return OrdinaryEnemyCount(spawnObjects) == 1; } return false; } private static int OrdinaryEnemyCount(List<PrefabRef> objects) { if (objects == null) { return 0; } GameObject val = null; int num = 0; foreach (PrefabRef @object in objects) { GameObject val2 = ((PrefabRef<GameObject>)(object)@object)?.Prefab; if (!Object.op_Implicit((Object)(object)val2)) { return 0; } if (!Object.op_Implicit((Object)(object)val2.GetComponent<EnemyGnomeDirector>()) && !Object.op_Implicit((Object)(object)val2.GetComponent<EnemyBangDirector>())) { if (!Object.op_Implicit((Object)(object)val2.GetComponent<EnemyParent>()) || (Object.op_Implicit((Object)(object)val) && (Object)(object)val != (Object)(object)val2)) { return 0; } val = val2; num++; } } return num; } private static void AfterGetEnemy(EnemyDirector __instance, ref EnemySetup __result) { if (!Object.op_Implicit((Object)(object)instance) || !instance.selectingEnemies) { return; } EnemySetup[] array = (EnemySetup[])DebugEnemies.GetValue(__instance); if (array != null && array.Length > 0) { return; } List<PrefabRef> spawnObjects = GetSpawnObjects(__result); if (spawnObjects == null || spawnObjects.Count == 0) { return; } int num = OrdinaryEnemyCount(spawnObjects); if (num == 0) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("Apex preserved an unsupported enemy setup: " + ((Object)__result).name)); return; } instance.originalSlots += num; EnemySetup value = instance.replacement; if (num > 1 && !instance.apexGroups.TryGetValue(num, out value)) { value = Object.Instantiate<EnemySetup>(instance.replacement); PrefabRef element = GetSpawnObjects(instance.replacement)[0]; SpawnObjects.SetValue(value, Enumerable.Repeat<PrefabRef>(element, num).ToList()); instance.apexGroups.Add(num, value); } __result = value; instance.replacedSlots += num; } private void Choose(int index) { if (NetworkActive) { Vote(index); } else { CommitSelection(index); } } private void CommitSelection(int index) { if (offer != null && index >= 0 && index < offer.Length) { CommitCard(offer[index]); } } private void CommitCard(Card card) { offer = null; if (run.Commit(card)) { healPending = card.Effect == "heal"; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Selected: " + card.Id + " (" + card.Attribute + ") | run count: " + run.Count(card.Id))); } } private void Update() { UpdateNetwork(); if (debug.Value && Input.GetKeyDown((KeyCode)289)) { consoleOpen = !consoleOpen; } if (debug.Value && consoleOpen && Object.op_Implicit((Object)(object)GameManager.instance) && Object.op_Implicit((Object)(object)RunManager.instance) && SemiFunc.RunIsLevel()) { SemiFunc.CursorUnlock(0.15f); } if (offer != null && !consoleOpen) { if (Input.GetKeyDown((KeyCode)49)) { Choose(0); } else if (Input.GetKeyDown((KeyCode)50)) { Choose(1); } else if (Input.GetKeyDown((KeyCode)51)) { Choose(2); } } if (!Object.op_Implicit((Object)(object)GameManager.instance) || !Object.op_Implicit((Object)(object)RunManager.instance) || (SemiFunc.IsMultiplayer() && (!NetworkActive || authorityChanged))) { return; } if (SemiFunc.MenuLevel() || SemiFunc.RunIsLobby() || SemiFunc.RunIsArena()) { RestorePlayerEffects(); run.Reset(); } else { if (!SemiFunc.RunIsLevel() && !SemiFunc.RunIsShop()) { return; } if (!NetworkActive || PhotonNetwork.IsMasterClient) { RestorePendingLoad(); } if (!Object.op_Implicit((Object)(object)LevelGenerator.Instance) || !SemiFunc.LevelGenDone()) { return; } PlayerController controller = PlayerController.instance; ApplyStamina(controller, EffectiveModifier("maxStamina")); TraceAppliedStamina(controller); movementMultiplier = MovementMultiplier(EffectiveModifier("moveSpeed")); UpdateEnemyHealth(); UpdateEnemyAiEffects(); UpdateValuableMasses(); UpdateEnemyAudio(); UpdateMapVisibility(); PlayerAvatar controlledAvatar = GetControlledAvatar(); PlayerHealth val = (PlayerHealth)(Object.op_Implicit((Object)(object)controlledAvatar) ? /*isinst with value type is only supported in some contexts*/: null); if (Object.op_Implicit((Object)(object)val) && (bool)HealthSet.GetValue(val) && (int)MaxHp.GetValue(val) > 0) { if ((Object)(object)trackedHealth != (Object)(object)val) { RestoreHealth(); trackedHealth = val; } ApplyMaxHealth(val); TraceAppliedHealth(val); if (NetworkActive && !PhotonNetwork.IsMasterClient) { HealFromHost(val); } if (healPending && run.Active != null) { healPending = false; val.Heal(run.Active.Amount, true); } } } } private static void AfterHealthReplaced(PlayerHealth __instance, PhotonMessageInfo __4, PhotonView ___photonView) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)GameManager.instance) && !((Object)(object)instance.trackedHealth != (Object)(object)__instance) && (!SemiFunc.IsMultiplayer() || SemiFunc.MasterAndOwnerOnlyRPC(__4, ___photonView))) { instance.appliedBonus = 0; instance.ApplyMaxHealth(__instance); } } private static void BeforeHeal(PlayerHealth __instance, ref int __0) { if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)GameManager.instance) || (Object)(object)instance.trackedHealth != (Object)(object)__instance) { return; } instance.ApplyMaxHealth(__instance); int num = instance.EffectiveModifier("healScale"); if (num != 0 && __0 > 0) { long num2 = int.MaxValue - Math.Max(0, (int)CurrentHp.GetValue(__instance)); int num3 = (int)Math.Min(num2, Math.Max(0.0, Math.Round((double)__0 * (1.0 + (double)num / 100.0), MidpointRounding.AwayFromZero))); if (instance.debug.Value) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)$"Player heal amount: {__0} -> {num3}"); } __0 = num3; } } private void ApplyMaxHealth(PlayerHealth hp) { int num = (int)MaxHp.GetValue(hp); long num2 = (long)num - (long)appliedBonus; int num3 = (int)Math.Max(1L, Math.Min(2147483647L, num2 + EffectiveModifier("maxHp"))); if (num3 != num) { MaxHp.SetValue(hp, num3); appliedBonus = (int)(num3 - num2); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Max HP: {num} -> {num3} (base {num2}, event {appliedBonus:+0;-0;0})"); } if ((int)CurrentHp.GetValue(hp) > num3) { CurrentHp.SetValue(hp, num3); PlayerAvatar controlledAvatar = GetControlledAvatar(); if (Object.op_Implicit((Object)(object)controlledAvatar) && Object.op_Implicit((Object)(object)StatsManager.instance)) { StatsManager.instance.SetPlayerHealth(SemiFunc.PlayerGetSteamID(controlledAvatar), num3, false); } } } private static PlayerAvatar GetControlledAvatar() { PlayerController val = PlayerController.instance; if (!Object.op_Implicit((Object)(object)val)) { return null; } object? value = ControlledAvatar.GetValue(val); return (PlayerAvatar)((value is PlayerAvatar) ? value : null); } private void ApplyStamina(PlayerController controller, int modifier) { if ((Object)(object)staminaController != (Object)(object)controller) { RestoreStamina(); staminaController = controller; } if (Object.op_Implicit((Object)(object)controller) && (modifier != 0 || staminaApplied != 0f)) { float num = controller.EnergyStart - staminaApplied; float num2 = Mathf.Max(1f, num + (float)modifier); if (num2 != controller.EnergyStart) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Max stamina: {controller.EnergyStart} -> {num2} (base {num})"); controller.EnergyStart = num2; staminaApplied = num2 - num; } controller.EnergyCurrent = Mathf.Min(controller.EnergyCurrent, num2); } } private void RestoreStamina() { if (Object.op_Implicit((Object)(object)staminaController) && staminaApplied != 0f) { PlayerController obj = staminaController; obj.EnergyStart -= staminaApplied; staminaController.EnergyCurrent = Mathf.Min(staminaController.EnergyCurrent, staminaController.EnergyStart); } staminaController = null; staminaApplied = 0f; } private void RestorePlayerEffects() { RestoreHealth(); RestoreStamina(); movementMultiplier = 1f; RestoreEnemyHealth(); RestoreEnemyAiEffects(); RestoreValuableMasses(); RestoreEnemyAudio(); RestoreMapVisibility(); } private void RestoreHealth() { if (Object.op_Implicit((Object)(object)trackedHealth)) { MaxHp.SetValue(trackedHealth, (int)MaxHp.GetValue(trackedHealth) - appliedBonus); } trackedHealth = null; appliedBonus = 0; } private void OnGUI() { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_0108: 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_0135: Invalid comparison between Unknown and I4 //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Unknown result type (might be due to invalid IL or missing references) //IL_0579: Unknown result type (might be due to invalid IL or missing references) DrawDeveloperConsole(); if (IsMainMenu()) { DrawEventMenu(); return; } eventMenuOpen = false; if (offer == null) { DrawEventStatus(); return; } bool value = english.Value; if (!value) { EnsureJapaneseFont(); } GUI.depth = -100; float num = Mathf.Min(Screen.width - 24, 960); Rect val = default(Rect); ((Rect)(ref val))..ctor(((float)Screen.width - num) / 2f, (float)Screen.height * 0.27f, num, 245f); GUIStyle val2 = new GUIStyle(GUI.skin.label); val2.fontSize = 17; val2.alignment = (TextAnchor)4; GUIStyle val3 = val2; GUIStyle val4 = new GUIStyle(GUI.skin.label); val4.wordWrap = true; GUIStyle val5 = val4; GUIStyle val6 = new GUIStyle(GUI.skin.button); if (!value && Object.op_Implicit((Object)(object)japaneseFont)) { Font val7 = (val6.font = japaneseFont); Font font = (val5.font = val7); val3.font = font; } GUI.Box(val, ""); bool flag = NetworkActive && SnapshotForStage; if (flag && (int)Event.current.type == 7) { TraceDisplayedOffer(); } int[] array = (flag ? networkSnapshot.Totals : null); double num2 = (flag ? (voteEndsAt - Time.realtimeSinceStartup) : (deadline - Time.realtimeSinceStartup)); string text = (value ? "Choose an event" : "イベントを選択"); if (flag) { text = ((networkSnapshot.Tied == null) ? ((value ? "Event vote" : "イベント投票") + " " + (array?.Sum() ?? 0) + "/" + networkSnapshot.Eligible) : (value ? "Host decides the tie" : "同票・ホストが決定")); } GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 8f, num, 30f), text + " " + Mathf.Max(0, Mathf.CeilToInt((float)num2)) + " s", val3); float num3 = (num - 32f) / 3f; int num4 = 0; while (offer != null && num4 < offer.Length) { Card card = offer[num4]; float num5 = ((Rect)(ref val)).x + 8f + (float)num4 * (num3 + 8f); float num6 = ((Rect)(ref val)).y + 46f; Color color = GUI.color; if (flag && localVote == num4) { GUI.color = new Color(0.55f, 0.9f, 0.7f, 1f); } GUI.Box(new Rect(num5, num6, num3, 184f), ""); GUI.color = color; GUI.Label(new Rect(num5 + 8f, num6 + 7f, num3 - 16f, 38f), card.Icon + " " + (value ? card.En : card.Ja), val5); string text2 = ((!card.Permanent) ? (value ? "Single stage" : "単発型") : (value ? "Permanent" : "永久型")); GUI.Label(new Rect(num5 + 8f, num6 + 46f, num3 - 16f, 28f), AttributeLabel(card, value) + " " + text2 + " " + (value ? "Danger " : "危険度 ") + card.Danger + (card.Permanent ? (" ×" + DisplayCount(card.Id)) : ""), val5); GUI.Label(new Rect(num5 + 8f, num6 + 77f, num3 - 16f, 61f), value ? card.DescriptionEn : card.DescriptionJa, val5); string text3 = (value ? "Select" : "選択") + " [" + (num4 + 1) + "]"; if (flag) { text3 = (value ? "Vote" : "投票") + " [" + (num4 + 1) + "] " + ((array != null) ? array[num4] : 0) + (value ? " votes" : "票"); } bool enabled = GUI.enabled; if (flag && networkSnapshot.Tied != null) { GUI.enabled = enabled && PhotonNetwork.IsMasterClient && networkSnapshot.Tied.Contains(num4); } if (GUI.Button(new Rect(num5 + 8f, num6 + 146f, num3 - 16f, 28f), text3, val6)) { Choose(num4); } GUI.enabled = enabled; num4++; } } private static bool IsMainMenu() { MenuManager val = MenuManager.instance; MenuPageMain val2 = MenuPageMain.instance; if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2) || !((Behaviour)val2).isActiveAndEnabled || CurrentMenuPage == null) { return false; } object? value = CurrentMenuPage.GetValue(val); MenuPage val3 = (MenuPage)((value is MenuPage) ? value : null); if (Object.op_Implicit((Object)(object)val3)) { return (Object)(object)((Component)val3).GetComponentInChildren<MenuPageMain>(true) == (Object)(object)val2; } return false; } private void DrawEventMenu() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Invalid comparison between Unknown and I4 //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: 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_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) bool value = english.Value; if (!value) { EnsureJapaneseFont(); } GUIStyle val = new GUIStyle(GUI.skin.button); val.fontSize = 18; GUIStyle val2 = val; GUIStyle val3 = new GUIStyle(GUI.skin.label); val3.fontSize = 16; val3.wordWrap = true; val3.richText = false; GUIStyle val4 = val3; GUIStyle val5 = new GUIStyle(val4); val5.fontSize = 21; val5.fontStyle = (FontStyle)1; GUIStyle val6 = val5; if (!value && Object.op_Implicit((Object)(object)japaneseFont)) { Font val7 = (val6.font = japaneseFont); Font font = (val4.font = val7); val2.font = font; } GUI.depth = -100; float num = Mathf.Min(590f, (float)Screen.width * 0.48f); float num2 = Screen.width - 24; if (!eventMenuOpen) { if (!GUI.Button(new Rect(num2 - 160f, 32f, 160f, 40f), value ? "Events" : "イベント", val2)) { return; } if (menuOdds == null) { menuOdds = catalog.GetOdds().ToDictionary<EventOdds, string>((EventOdds row) => row.Card.Id, StringComparer.Ordinal); } eventMenuOpen = true; eventMenuScroll = Vector2.zero; return; } Rect val10 = default(Rect); ((Rect)(ref val10))..ctor(num2 - num, 32f, num, (float)(Screen.height - 64)); if ((int)Event.current.type == 7) { Color color = GUI.color; GUI.color = new Color(0.065f, 0.08f, 0.09f, 0.97f); GUI.DrawTexture(val10, (Texture)(object)Texture2D.whiteTexture); GUI.color = color; } if (GUI.Button(new Rect(num2 - 110f, 46f, 92f, 32f), value ? "Close" : "閉じる", val2)) { eventMenuOpen = false; } GUILayout.BeginArea(new Rect(((Rect)(ref val10)).x + 18f, ((Rect)(ref val10)).y + 14f, ((Rect)(ref val10)).width - 36f, ((Rect)(ref val10)).height - 28f)); GUILayout.Label(value ? "Events" : "イベント一覧", val6, (GUILayoutOption[])(object)new GUILayoutOption[0]); GUILayout.Label(value ? $"Per draw: debuff {eventSettings.DebuffPercent:0.##}% / buff {eventSettings.BuffPercent:0.##}%" : $"各枠の属性設定\u3000デバフ {eventSettings.DebuffPercent:0.##}% / バフ {eventSettings.BuffPercent:0.##}%", val4, (GUILayoutOption[])(object)new GUILayoutOption[0]); GUILayout.Label(value ? "Odds include fallback when a category runs out." : "候補不足時の繰り替えも確率に反映しています。", val4, (GUILayoutOption[])(object)new GUILayoutOption[0]); GUILayout.Space(10f); eventMenuScroll = GUILayout.BeginScrollView(eventMenuScroll, (GUILayoutOption[])(object)new GUILayoutOption[0]); Card[] array = definitions; foreach (Card card in array) { EventOdds value2; bool flag = menuOdds.TryGetValue(card.Id, out value2); GUILayout.Label((value ? card.En : card.Ja) + " [" + AttributeLabel(card, value) + "・" + (card.Permanent ? (value ? "Permanent" : "永続") : (value ? "Single stage" : "単発")) + "]", val6, (GUILayoutOption[])(object)new GUILayoutOption[0]); GUILayout.Label(value ? card.DescriptionEn : card.DescriptionJa, val4, (GUILayoutOption[])(object)new GUILayoutOption[0]); GUILayout.Label(flag ? string.Format(value ? "First slot {0:P2} Appears among three {1:P2}" : "第1枠 {0:P2}\u3000\u30003枚中に登場 {1:P2}", value2.FirstSlot, value2.InOffer) : (value ? "Disabled · 0%" : "抽選対象外・0%"), val4, (GUILayoutOption[])(object)new GUILayoutOption[0]); GUILayout.Space(12f); } GUILayout.EndScrollView(); GUILayout.EndArea(); } private void EnsureJapaneseFont() { if (!Object.op_Implicit((Object)(object)japaneseFont)) { japaneseFont = Font.CreateDynamicFontFromOSFont(new string[3] { "Yu Gothic UI", "Meiryo", "MS Gothic" }, 16); } } private void DrawEventStatus() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Expected O, but got Unknown //IL_0569: Unknown result type (might be due to invalid IL or missing references) //IL_0570: Expected O, but got Unknown //IL_063d: Unknown result type (might be due to invalid IL or missing references) //IL_066c: Unknown result type (might be due to invalid IL or missing references) if ((int)Event.current.type != 7 || !Object.op_Implicit((Object)(object)GameManager.instance) || !Object.op_Implicit((Object)(object)RunManager.instance) || (SemiFunc.IsMultiplayer() && (!NetworkActive || authorityChanged)) || (!SemiFunc.RunIsLevel() && !SemiFunc.RunIsShop()) || !Object.op_Implicit((Object)(object)MapToolController.instance) || !Object.op_Implicit((Object)(object)LevelUI.instance) || MapActive == null || !(bool)MapActive.GetValue(MapToolController.instance)) { return; } TextMeshProUGUI val = (TextMeshProUGUI)((LevelNumber == null) ? null : /*isinst with value type is only supported in some contexts*/); if (Object.op_Implicit((Object)(object)val) && ((Behaviour)val).isActiveAndEnabled && Object.op_Implicit((Object)(object)((Graphic)val).canvas)) { TextMeshProUGUI val2 = (TextMeshProUGUI)((LevelMoon == null) ? null : /*isinst with value type is only supported in some contexts*/); Canvas rootCanvas = ((Graphic)val).canvas.rootCanvas; Camera camera = (((int)rootCanvas.renderMode == 0) ? null : rootCanvas.worldCamera); Vector2 val3 = BottomCenter(((TMP_Text)val).rectTransform, camera); if (Object.op_Implicit((Object)(object)val2) && ((Behaviour)val2).isActiveAndEnabled) { val3.y = Mathf.Min(val3.y, BottomCenter(((TMP_Text)val2).rectTransform, camera).y); } if (val3.x < 0.72f || val3.x > 0.98f || val3.y < 0.25f || val3.y > 0.58f) { ((Vector2)(ref val3))..ctor(0.85f, 0.46f); } bool value = english.Value; if (!value) { EnsureJapaneseFont(); } if (statusStyle == null) { GUIStyle val4 = new GUIStyle(GUI.skin.label); val4.wordWrap = true; val4.richText = false; val4.fontSize = 16; statusStyle = val4; } statusStyle.font = (value ? GUI.skin.font : japaneseFont); List<string> list = new List<string>(); list.Add(value ? "Current event" : "現在のイベント"); bool flag = NetworkActive && !PhotonNetwork.IsMasterClient; Card card = ((!flag) ? run.Selected : (SnapshotForStage ? networkSnapshot.Selected : null)); list.Add((card != null) ? Describe(card, value) : (value ? "None" : "なし")); if (SnapshotForStage && !string.IsNullOrEmpty(networkSnapshot.Enemy)) { list.Add(networkSnapshot.Enemy); } list.Add(""); list.Add(value ? "Permanent effects" : "永続効果"); Card[] array = ((!flag) ? definitions.Where((Card c) => c.Permanent && run.Count(c.Id) > 0).ToArray() : ((networkSnapshot == null) ? new Card[0] : networkSnapshot.PermanentCards)); if (array.Length == 0) { list.Add(value ? "None" : "なし"); } Card[] array2 = array; foreach (Card card2 in array2) { int num2 = DisplayCount(card2.Id); string text = card2.Effect switch { "moveSpeed" => value ? "Movement speed" : "移動速度", "enemyHp" => value ? "Enemy max HP" : "敵の最大HP", "enemySpeed" => value ? "Enemy movement speed" : "敵の移動速度", "enemyVision" => value ? "Enemy detection range" : "敵の索敵距離", "healScale" => value ? "Healing received" : "回復量", "maxStamina" => value ? "Max stamina" : "最大スタミナ", _ => value ? "Max HP" : "最大HP", }; bool flag2 = card2.Effect != "maxHp" && card2.Effect != "maxStamina"; list.Add((value ? card2.En : card2.Ja) + " ×" + num2 + " " + text + (value ? " total " : " 合計 ") + ((long)card2.Amount * (long)num2).ToString("+0;-0;0") + (flag2 ? "%" : "")); } GUIContent val5 = new GUIContent(string.Join("\n", list.ToArray())); float num3 = Mathf.Min(390, Screen.width - 24); float num4 = Mathf.Clamp(val3.x * (float)Screen.width - num3 / 2f, 12f, (float)Screen.width - num3 - 12f); float num5 = Mathf.Clamp((1f - val3.y) * (float)Screen.height + 10f, 12f, (float)(Screen.height - 12)); float num6 = statusStyle.CalcHeight(val5, num3 - 24f) + 18f; if (num5 + num6 > (float)(Screen.height - 12)) { num5 = Mathf.Max(12f, (float)Screen.height - num6 - 12f); } GUI.depth = -100; GUI.Box(new Rect(num4, num5, num3, num6), ""); GUI.Label(new Rect(num4 + 12f, num5 + 8f, num3 - 24f, num6 - 16f), val5, statusStyle); } } private Vector2 BottomCenter(RectTransform rect, Camera camera) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) rect.GetWorldCorners(hudCorners); Vector3 val = (hudCorners[0] + hudCorners[3]) / 2f; if (Object.op_Implicit((Object)(object)camera)) { return Vector2.op_Implicit(camera.WorldToViewportPoint(val)); } Vector2 val2 = RectTransformUtility.WorldToScreenPoint((Camera)null, val); return new Vector2(val2.x / (float)Screen.width, val2.y / (float)Screen.height); } private static string Describe(Card card, bool en) { return (en ? card.En : card.Ja) + " [" + AttributeLabel(card, en) + "]\n" + (en ? card.DescriptionEn : card.DescriptionJa); } private static string AttributeLabel(Card card, bool en) { if (!(card.Attribute == "debuff")) { if (!en) { return "バフ"; } return "Buff"; } if (!en) { return "デバフ"; } return "Debuff"; } private void DrawDeveloperConsole() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Invalid comparison between Unknown and I4 //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Invalid comparison between Unknown and I4 //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Invalid comparison between Unknown and I4 if (!debug.Value || !consoleOpen) { return; } GUI.depth = -101; GUILayout.BeginArea(new Rect(20f, 20f, (float)Mathf.Min(610, Screen.width - 40), 135f), GUI.skin.box); GUILayout.Label("STARCODE / Developer (F8)", (GUILayoutOption[])(object)new GUILayoutOption[0]); GUI.SetNextControlName("StarcodeCommand"); command = GUILayout.TextField(command, 128, (GUILayoutOption[])(object)new GUILayoutOption[0]); if (GUILayout.Button("Run command", (GUILayoutOption[])(object)new GUILayoutOption[0]) || ((int)Event.current.type == 4 && (int)Event.current.keyCode == 13 && GUI.GetNameOfFocusedControl() == "StarcodeCommand")) { if ((int)Event.current.type == 4) { Event.current.Use(); } commandStatus = ExecuteDeveloperCommand(command); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Developer: " + commandStatus)); command = ""; } GUILayout.Label((commandStatus.Length == 0) ? "Type help for available commands." : commandStatus, (GUILayoutOption[])(object)new GUILayoutOption[0]); GUILayout.EndArea(); } private string ExecuteDeveloperCommand(string input) { string[] args = input.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (args.Length == 0 || args[0] == "help") { return "draw | apply ID | clear | stacks | add ID | reset | ranks | spawns | apex | odds"; } if (args.Length != ((!(args[0] == "apply") && !(args[0] == "add")) ? 1 : 2)) { return "Invalid arguments. Type help."; } switch (args[0]) { case "odds": { string[] array = catalog.Probabilities(); foreach (string text in array) { ((BaseUnityPlugin)this).Logger.LogInfo((object)text); } return "Event odds written to BepInEx log."; } case "stacks": { Dictionary<string, int> counts = ((NetworkActive && !PhotonNetwork.IsMasterClient && networkSnapshot != null) ? networkSnapshot.Stacks : run.Snapshot()); ((BaseUnityPlugin)this).Logger.LogInfo((object)JsonConvert.SerializeObject((object)definitions.Where((Card c) => c.Permanent).ToDictionary((Card c) => c.Id, (Card c) => counts.ContainsKey(c.Id) ? counts[c.Id] : 0))); return "Permanent stacks written to BepInEx log."; } case "ranks": return LogEnemyRanks(); case "spawns": return LogEnemySpawns(); default: if (!Object.op_Implicit((Object)(object)GameManager.instance) || !Object.op_Implicit((Object)(object)RunManager.instance) || !SemiFunc.RunIsLevel() || SemiFunc.IsMultiplayer()) { return "State-changing commands require a single-player stage."; } switch (args[0]) { case "draw": if (run.Committed || offer == null) { return "Reroll requires an open selection."; } offer = catalog.Draw(); deadline = Time.realtimeSinceStartup + 25f; return "Offer: " + string.Join(", ", offer.Select((Card c) => c.Id).ToArray()); case "clear": if (!run.ClearActive()) { return "No single-stage effect is active."; } healPending = false; return "Single-stage effect cleared. Completed heals, appraisals, quotas and spawned enemies are retained."; case "reset": run.ClearPermanent(definitions); return "Permanent stacks reset."; case "add": { Card card2 = definitions.FirstOrDefault((Card c) => c.Permanent && c.Id == args[1]); if (card2 == null) { return "Unknown permanent event."; } if (!run.AddPermanent(card2)) { return "Stack limit reached."; } return "Added " + card2.Id; } case "apex": case "apply": { string id = ((args[0] == "apex") ? "apex" : args[1]); Card card = definitions.FirstOrDefault((Card c) => c.Id == id); if (card == null) { return "Unknown event ID."; } if (run.Committed || offer == null) { return "Forced selection requires an open selection."; } CommitCard(card); return "Selected " + id; } default: return "Unknown command. Type help."; } } } private string LogEnemyRanks() { EnemyDirector val = Object.FindFirstObjectByType<EnemyDirector>(); if (!Object.op_Implicit((Object)(object)val)) { return "Enemy director unavailable."; } for (int i = 1; i <= 3; i++) { FieldInfo fieldInfo = AccessTools.Field(typeof(EnemyDirector), "enemiesDifficulty" + i); List<EnemySetup> list = ((fieldInfo == null) ? null : (fieldInfo.GetValue(val) as List<EnemySetup>)); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Tier " + i + ": " + ((list == null) ? "unavailable" : string.Join(", ", (from e in list where Object.op_Implicit((Object)(object)e) select ((Object)e).name).ToArray())))); } return "Enemy tiers written to BepInEx log."; } private string LogEnemySpawns() { EnemyDirector val = Object.FindFirstObjectByType<EnemyDirector>(); FieldInfo fieldInfo = AccessTools.Field(typeof(EnemyDirector), "enemiesSpawned"); List<EnemyParent> list = ((Object.op_Implicit((Object)(object)val) && fieldInfo != null) ? (fieldInfo.GetValue(val) as List<EnemyParent>) : null); if (list == null) { return "Spawn roster unavailable."; } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Enemy roster: " + string.Join(", ", (from e in list where Object.op_Implicit((Object)(object)e) group e by ((Object)((Component)e).gameObject).name into @group select @group.Key + " x" + @group.Count()).ToArray()))); return $"Roster written to BepInEx log. Apex replacements: {replacedSlots}/{originalSlots}."; } private static float MovementMultiplier(int percent) { return Math.Max(0.1f, 1f + (float)percent / 100f); } private static float ScaleMovement(float native) { if (!Object.op_Implicit((Object)(object)instance) || instance.movementMultiplier == 1f) { return native; } float num = native * instance.movementMultiplier; instance.TraceAppliedMovement(native, num); return num; } private static IEnumerable<CodeInstruction> ScaleNativeMovement(IEnumerable<CodeInstruction> instructions) { return ScaleFloatFieldReads(instructions, typeof(PlayerController), "ScaleMovement", "MoveSpeed", "SprintSpeed", "CrouchSpeed"); } private static IEnumerable<CodeInstruction> ScaleFloatFieldReads(IEnumerable<CodeInstruction> instructions, Type owner, string scaler, params string[] fieldNames) { HashSet<FieldInfo> fields = new HashSet<FieldInfo>(); foreach (string text in fieldNames) { FieldInfo fieldInfo = AccessTools.Field(owner, text); if (fieldInfo == null) { throw new MissingFieldException(owner.FullName, text); } fields.Add(fieldInfo); } MethodInfo scale = AccessTools.Method(typeof(Plugin), scaler, (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { yield return instruction; if (instruction.opcode == OpCodes.Ldfld && fields.Contains(instruction.operand as FieldInfo)) { yield return new CodeInstruction(OpCodes.Call, (object)scale); } } } private static void BeforeEnemyHealthInitialized(EnemyHealth __instance) { if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)GameManager.instance) && Object.op_Implicit((Object)(object)RunManager.instance) && SemiFunc.RunIsLevel() && SemiFunc.IsMasterClientOrSingleplayer()) { instance.ApplyEnemyHealth(__instance, instance.run.Modifier(instance.definitions, "enemyHp")); } } private void UpdateEnemyHealth() { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } int num = (SemiFunc.RunIsLevel() ? run.Modifier(definitions, "enemyHp") : 0); if (num == reconciledEnemyModifier) { return; } reconciledEnemyModifier = num; EnemyHealth[] array = Object.FindObjectsByType<EnemyHealth>((FindObjectsInactive)1, (FindObjectsSortMode)0); foreach (EnemyHealth enemy in array) { if (ApplyEnemyHealth(enemy, num)) { ClampEnemyHealth(enemy); } } } private bool ApplyEnemyHealth(EnemyHealth enemy, int modifier) { if (!enemyBaseHealth.TryGetValue(enemy, out var value)) { if (modifier == 0 || enemy.health <= 0) { return false; } value = enemy.health; enemyBaseHealth.Add(enemy, value); } enemy.health = (int)Math.Max(1.0, Math.Min(2147483647.0, Math.Round((double)value * (1.0 + (double)modifier / 100.0), MidpointRounding.AwayFromZero))); if (modifier == 0) { enemyBaseHealth.Remove(enemy); } return true; } private static void ClampEnemyHealth(EnemyHealth enemy) { if ((int)EnemyCurrentHealth.GetValue(enemy) > enemy.health) { EnemyCurrentHealth.SetValue(enemy, enemy.health); } } private void RestoreEnemyHealth() { foreach (KeyValuePair<EnemyHealth, int> item in enemyBaseHealth) { if (Object.op_Implicit((Object)(object)item.Key)) { item.Key.health = item.Value; ClampEnemyHealth(item.Key); } } enemyBaseHealth.Clear(); reconciledEnemyModifier = 0; } private static void InstallEnemyAiPatches(Harmony harmony) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.EnumeratorMoveNext((MethodBase)AccessTools.Method(typeof(EnemyVision), "Vision", (Type[])null, (Type[])null)); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "ScaleNativeEnemyVision", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); HarmonyMethod val = new HarmonyMethod(typeof(Plugin), "InterceptEnemyAgentSpeed", (Type[])null); string[] array = new string[3] { "Update", "UpdateAgent", "OverrideAgent" }; foreach (string text in array) { harmony.Patch((MethodBase)AccessTools.Method(typeof(EnemyNavMeshAgent), text, (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); } } private void UpdateEnemyAiEffects() { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } bool flag = SemiFunc.RunIsLevel(); enemyVisionMultiplier = (flag ? MovementMultiplier(run.Modifier(definitions, "enemyVision")) : 1f); int num = (flag ? run.Modifier(definitions, "enemySpeed") : 0); if (num == enemySpeedModifier) { return; } if (num == 0) { RestoreEnemySpeeds(); return; } enemySpeedModifier = num; EnemyNavMeshAgent[] array = Object.FindObjectsByType<EnemyNavMeshAgent>((FindObjectsInactive)1, (FindObjectsSortMode)0); foreach (EnemyNavMeshAgent obj in array) { object? value = EnemyAgent.GetValue(obj); NavMeshAgent val = (NavMeshAgent)((value is NavMeshAgent) ? value : null); if (Object.op_Implicit((Object)(object)val)) { if (!enemyBaseSpeeds.TryGetValue(val, out var value2)) { value2 = val.speed; } SetEnemyAgentSpeed(val, value2); } } } private void RestoreEnemyAiEffects() { enemyVisionMultiplier = 1f; RestoreEnemySpeeds(); } private void RestoreEnemySpeeds() { foreach (KeyValuePair<NavMeshAgent, float> enemyBaseSpeed in enemyBaseSpeeds) { if (Object.op_Implicit((Object)(object)enemyBaseSpeed.Key)) { enemyBaseSpeed.Key.speed = enemyBaseSpeed.Value; } } enemyBaseSpeeds.Clear(); enemySpeedModifier = 0; } private static void SetEnemyAgentSpeed(NavMeshAgent agent, float native) { if (!Object.op_Implicit((Object)(object)instance) || instance.enemySpeedModifier == 0) { agent.speed = native; return; } instance.enemyBaseSpeeds[agent] = native; agent.speed = native * MovementMultiplier(instance.enemySpeedModifier); } private static float ScaleEnemyVision(float native) { if (!Object.op_Implicit((Object)(object)instance)) { return native; } return native * instance.enemyVisionMultiplier; } private static IEnumerable<CodeInstruction> ScaleNativeEnemyVision(IEnumerable<CodeInstruction> instructions) { return ScaleFloatFieldReads(instructions, typeof(EnemyVision), "ScaleEnemyVision", "VisionDistance", "VisionDistanceClose", "VisionDistanceCloseCrouch"); } private static IEnumerable<CodeInstruction> InterceptEnemyAgentSpeed(IEnumerable<CodeInstruction> instructions) { MethodInfo original = AccessTools.PropertySetter(typeof(NavMeshAgent), "speed"); MethodInfo replacement = AccessTools.Method(typeof(Plugin), "SetEnemyAgentSpeed", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Callvirt && object.Equals(instruction.operand, original)) { instruction.opcode = OpCodes.Call; instruction.operand = replacement; } yield return instruction; } } private static bool HasExternalSpawnConfig() { return Chainloader.PluginInfos.Values.Any((PluginInfo p) => p.Metadata.GUID.IndexOf("spawnconfig", StringComparison.OrdinalIgnoreCase) >= 0 || p.Metadata.Name.IndexOf("spawnconfig", StringComparison.OrdinalIgnoreCase) >= 0); } private static int AdjustTierOneCount(int original) { if (!Object.op_Implicit((Object)(object)instance) || !instance.buildingEnemySetup || instance.run.Active == null || instance.run.Active.Effect != "extraSlots") { return original; } if (HasExternalSpawnConfig()) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)"Reinforcements skipped: another spawn configuration plugin is active."); return original; } int num = original + instance.run.Active.Amount; ((BaseUnityPlugin)instance).Logger.LogInfo((object)$"Tier-one enemy slots: {original} -> {num}"); return num; } private static IEnumerable<CodeInstruction> ModifyEnemyAmounts(IEnumerable<CodeInstruction> instructions) { FieldInfo amount = AccessTools.Field(typeof(EnemyDirector), "amountCurve1Value"); MethodInfo adjust = AccessTools.Method(typeof(Plugin), "AdjustTierOneCount", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Stfld && object.Equals(instruction.operand, amount)) { CodeInstruction call = new CodeInstruction(OpCodes.Call, (object)adjust); call.labels.AddRange(instruction.labels); instruction.labels.Clear(); yield return call; } yield return instruction; } } private static void InstallExtractionPatches(Harmony harmony) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.EnumeratorMoveNext((MethodBase)AccessTools.Method(typeof(RoundDirector), "StartRound", (Type[])null, (Type[])null)); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "ModifyRoundQuota", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); HarmonyMethod val = new HarmonyMethod(typeof(Plugin), "ReplaceDurabilityReads", (Type[])null); string[] array = new string[3] { "BreakLight", "BreakMedium", "BreakHeavy" }; foreach (string text in array) { harmony.Patch((MethodBase)AccessTools.Method(typeof(PhysGrabObjectImpactDetector), text, (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); } } private static int AdjustRoundQuota(int original) { int num = original; if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)GameManager.instance) && Object.op_Implicit((Object)(object)RunManager.instance) && SemiFunc.RunIsLevel() && SemiFunc.IsMasterClientOrSingleplayer() && instance.run.Active != null && instance.run.Active.Effect == "quota" && original > 0) { int amount = instance.run.Active.Amount; int num2 = ((Object.op_Implicit((Object)(object)RoundDirector.instance) && AvailableHaul != null) ? Math.Max(original, (int)AvailableHaul.GetValue(RoundDirector.instance)) : original); num = (int)Math.Min(num2, Math.Round((double)original * (1.0 + (double)amount / 100.0), MidpointRounding.AwayFromZero)); ((BaseUnityPlugin)instance).Logger.LogInfo((object)$"Extraction goal: {original} -> {num} (available {num2})"); } return num; } private static float EffectiveDurability(PhysGrabObjectImpactDetector detector) { float durability = detector.durability; if (!Object.op_Implicit((Object)(object)instance) || !detector.isValuable || !Object.op_Implicit((Object)(object)GameManager.instance) || !Object.op_Implicit((Object)(object)RunManager.instance) || !SemiFunc.RunIsLevel() || !SemiFunc.IsMasterClientOrSingleplayer() || instance.run.Active == null || instance.run.Active.Effect != "durability") { return durability; } return Mathf.Clamp(durability * MovementMultiplier(instance.run.Active.Amount), 0f, 100f); } private static IEnumerable<CodeInstruction> ModifyRoundQuota(IEnumerable<CodeInstruction> instructions) { MethodInfo original = AccessTools.Method(typeof(RoundDirector), "StartRoundLogic", (Type[])null, (Type[])null); MethodInfo replacement = AccessTools.Method(typeof(Plugin), "AdjustRoundQuota", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { if ((instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt) && object.Equals(instruction.operand, original)) { CodeInstruction call = new CodeInstruction(OpCodes.Call, (object)replacement); call.labels.AddRange(instruction.labels); instruction.labels.Clear(); yield return call; } yield return instruction; } } private static IEnumerable<CodeInstruction> ReplaceDurabilityReads(IEnumerable<CodeInstruction> instructions) { FieldInfo original = AccessTools.Field(typeof(PhysGrabObjectImpactDetector), "durability"); MethodInfo replacement = AccessTools.Method(typeof(Plugin), "EffectiveDurability", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldfld && object.Equals(instruction.operand, original)) { instruction.opcode = OpCodes.Call; instruction.operand = replacement; } yield return instruction; } } private static void InstallEnemyDamagePatches(Harmony harmony) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown harmony.Patch((MethodBase)AccessTools.Method(typeof(HurtCollider), "PlayerHurt", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "ReplaceEnemyDamageReads", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); HarmonyMethod val = new HarmonyMethod(typeof(Plugin), "ReplaceDirectEnemyHurtCalls", (Type[])null); harmony.Patch((MethodBase)AccessTools.Method(typeof(EnemySnatcher), "BackKickHitApply", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(EnemySnatcher), "FrontPunchHitApply", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(EnemySpinny), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); } private static int EnemyDamageModifier() { if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)GameManager.instance) || !Object.op_Implicit((Object)(object)RunManager.instance) || !SemiFunc.RunIsLevel() || (SemiFunc.IsMultiplayer() && (!instance.NetworkActive || instance.authorityChanged))) { return 0; } return instance.EffectiveModifier("enemyAttack"); } private static int ScaleEnemyDamage(int native, int modifier) { if (native <= 0 || modifier == 0) { return native; } return (int)Math.Min(2147483647.0, Math.Round((double)native * (1.0 + (double)modifier / 100.0), MidpointRounding.AwayFromZero)); } private static int EffectiveColliderDamage(HurtCollider collider) { int num = EnemyDamageModifier(); if (num == 0) { return collider.playerDamage; } PlayerAvatar val = (PlayerAvatar)((DamageSourcePlayer == null) ? null : /*isinst with value type is only supported in some contexts*/); if (Object.op_Implicit((Object)(object)val)) { return collider.playerDamage; } Enemy val2 = (Enemy)((DamageSourceEnemy == null) ? null : /*isinst with value type is only supported in some contexts*/); if (!Object.op_Implicit((Object)(object)val2) && !Object.op_Implicit((Object)(object)((Component)collider).GetComponentInParent<EnemyParent>())) { return collider.playerDamage; } return ScaleEnemyDamage(collider.playerDamage, num); } private static void HurtFromEnemy(PlayerHealth health, int damage, bool allowDeath, int enemyIndex, bool hurtFreeze) { health.Hurt(ScaleEnemyDamage(damage, EnemyDamageModifier()), allowDeath, enemyIndex, hurtFreeze); } private static IEnumerable<CodeInstruction> ReplaceEnemyDamageReads(IEnumerable<CodeInstruction> instructions) { FieldInfo original = AccessTools.Field(typeof(HurtCollider), "playerDamage"); MethodInfo replacement = AccessTools.Method(typeof(Plugin), "EffectiveColliderDamage", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldfld && object.Equals(instruction.operand, original)) { instruction.opcode = OpCodes.Call; instruction.operand = replacement; } yield return instruction; } } private static IEnumerable<CodeInstruction> ReplaceDirectEnemyHurtCalls(IEnumerable<CodeInstruction> instructions) { MethodInfo original = AccessTools.Method(typeof(PlayerHealth), "Hurt", (Type[])null, (Type[])null); MethodInfo replacement = AccessTools.Method(typeof(Plugin), "HurtFromEnemy", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { if ((instruction.opcode == OpCodes.Callvirt || instruction.opcode == OpCodes.Call) && object.Equals(instruction.operand, original)) { instruction.opcode = OpCodes.Call; instruction.operand = replacement; } yield return instruction; } } private static void InstallValuableValuePatches(Harmony harmony) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_0095: Expected O, but got Unknown if (Appraised == null || OriginalValue == null || CurrentValue == null || ValuableView == null || AvailableHaul == null) { throw new MissingFieldException("Valuable appraisal fields unavailable."); } harmony.Patch((MethodBase)AccessTools.Method(typeof(ValuableObject), "DollarValueSetLogic", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "BeforeNativeAppraisal", (Type[])null), new HarmonyMethod(typeof(Plugin), "AfterNativeAppraisal", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private bool ValueEffectActive() { if (Object.op_Implicit((Object)(object)GameManager.instance) && Object.op_Implicit((Object)(object)RunManager.instance) && SemiFunc.RunIsLevel() && SemiFunc.IsMasterClientOrSingleplayer() && run.Active != null) { return run.Active.Effect == "treasureValue"; } return false; } private void ReconcileExistingAppraisals() { if (!ValueEffectActive() || !Object.op_Implicit((Object)(object)RoundDirector.instance)) { return; } RoundDirector obj = RoundDirector.instance; long num = (int)AvailableHaul.GetValue(obj); ValuableObject[] array = Object.FindObjectsByType<ValuableObject>((FindObjectsInactive)1, (FindObjectsSortMode)0); foreach (ValuableObject val in array) { if (!(bool)Appraised.GetValue(val)) { continue; } float num2 = (float)OriginalValue.GetValue(val); float num3 = (float)CurrentValue.GetValue(val); PhotonView val2 = null; if (SemiFunc.IsMultiplayer()) { object? value = ValuableView.GetValue(val); val2 = (PhotonView)((value is PhotonView) ? value : null); if (!Object.op_Implicit((Object)(object)val2) || val2.ViewID == 0 || num3 != num2) { continue; } } if (ApplyAppraisal(val, num2, num3, out var adjusted)) { num += (long)(int)(float)CurrentValue.GetValue(val) - (long)(int)num3; if (Object.op_Implicit((Object)(object)val2)) { val2.RPC("DollarValueSetRPC", (RpcTarget)1, new object[1] { adjusted }); } } } AvailableHaul.SetValue(obj, (int)Math.Max(0L, Math.Min(2147483647L, num))); } private static void BeforeNativeAppraisal(ValuableObject __instance, out bool __state) { __state = Object.op_Implicit((Object)(object)instance) && instance.ValueEffectActive() && !(bool)Appraised.GetValue(__instance); } private static void AfterNativeAppraisal(ValuableObject __instance, bool __state) { if (__state && Object.op_Implicit((Object)(object)instance) && instance.ValueEffectActive() && (bool)Appraised.GetValue(__instance)) { instance.ApplyAppraisal(__instance, (float)OriginalValue.GetValue(__instance), (float)CurrentValue.GetValue(__instance), out var _); } } private bool ApplyAppraisal(ValuableObject item, float original, float current, out float adjusted) { adjusted = original; if (original <= 0f || valuableOriginalAppraisals.ContainsKey(item)) { return false; } float num = MovementMultiplier(run.Active.Amount); adjusted = Mathf.Max(1f, Mathf.Round(original * num)); valuableOriginalAppraisals.Add(item, original); OriginalValue.SetValue(item, adjusted); CurrentValue.SetValue(item, Mathf.Max(0f, Mathf.Round(current * num))); if (debug.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Valuable appraisal: {original} -> {adjusted}"); } return true; } private static void InstallValuableMassPatches(Harmony harmony) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown HarmonyMethod val = new HarmonyMethod(typeof(Plugin), "InterceptValuableMass", (Type[])null); harmony.Patch((MethodBase)AccessTools.Method(typeof(PhysGrabObject), "OverrideTimersTick", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(PhysGrabObject), "ResetMass", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); } private void UpdateValuableMasses() { int num = EffectiveModifier("treasureMass"); if (num == valuableMassModifier) { return; } if (num == 0) { RestoreValuableMasses(); return; } valuableMassM