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 BindingLectern v0.1.3
BepInEx/plugins/BindingLectern/BindingLectern.dll
Decompiled 3 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using On.RoR2; using ProperSave; using R2API; using RoR2; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] namespace BindingLectern; internal sealed class LecternPlacement : IPlacementSurface { private readonly TrialGongInteraction gong; private readonly Scene scene; private readonly Vector3 anchor; private readonly Quaternion rotation; private readonly int mask = LayerMask.op_Implicit(((LayerIndex)(ref LayerIndex.world)).mask) | LayerMask.op_Implicit(((LayerIndex)(ref LayerIndex.defaultLayer)).mask); private LecternPlacement(TrialGongInteraction gong, Scene scene) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) this.gong = gong; this.scene = scene; anchor = (Object.op_Implicit((Object)(object)gong.mainHurtBox) ? ((Component)gong.mainHurtBox).transform.position : ((Component)gong).transform.position); rotation = Quaternion.Euler(0f, ((Component)gong).transform.eulerAngles.y, 0f); } private bool IsSceneSolid(Collider c) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)c) && ((Component)c).gameObject.scene == scene && !c.isTrigger && !Object.op_Implicit((Object)(object)c.attachedRigidbody)) { return !Object.op_Implicit((Object)(object)((Component)c).GetComponentInParent<CharacterBody>()); } return false; } private bool IsGround(Collider c) { if (IsSceneSolid(c) && !((Component)c).transform.IsChildOf(((Component)gong).transform)) { return !Object.op_Implicit((Object)(object)((Component)c).GetComponentInParent<NetworkIdentity>()); } return false; } public SurfacePoint? Sample(float x, float z) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) foreach (RaycastHit item in from h in Physics.RaycastAll(new Vector3(x, anchor.y + 6f, z), Vector3.down, 26f, mask, (QueryTriggerInteraction)1) orderby ((RaycastHit)(ref h)).distance select h) { RaycastHit current = item; if (IsGround(((RaycastHit)(ref current)).collider) && ((RaycastHit)(ref current)).point.y <= anchor.y + 2f && ((RaycastHit)(ref current)).point.y >= anchor.y - 16f) { return new SurfacePoint(((RaycastHit)(ref current)).point.y, ((RaycastHit)(ref current)).normal.y); } } return null; } public bool IsClear(float x, float y, float z) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) Collider[] array = Physics.OverlapBox(new Vector3(x, y + 0.98f, z), new Vector3(0.46f, 0.72f, 0.45f), rotation, mask, (QueryTriggerInteraction)1); foreach (Collider val in array) { if (Object.op_Implicit((Object)(object)val) && ((Component)val).gameObject.scene == scene && !val.isTrigger && !Object.op_Implicit((Object)(object)((Component)val).GetComponentInParent<CharacterBody>())) { return false; } } Transform preferredSpawnPosition = gong.preferredSpawnPosition; if (Object.op_Implicit((Object)(object)preferredSpawnPosition)) { Vector3 val2 = Vector3.ProjectOnPlane(new Vector3(x, y, z) - preferredSpawnPosition.position, Vector3.up); if (((Vector3)(ref val2)).sqrMagnitude < 2.25f) { return false; } } return true; } public static bool TryFind(TrialGongInteraction gong, Scene scene, out Vector3 position, out string diagnostics) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) LecternPlacement lecternPlacement = new LecternPlacement(gong, scene); PlacementResult result2; bool result = PlacementRules.Find(lecternPlacement, lecternPlacement.anchor.x, lecternPlacement.anchor.z, ((Component)gong).transform.eulerAngles.y * ((float)Math.PI / 180f), out result2); position = new Vector3(result2.X, result2.Y, result2.Z); string? text = ((object)lecternPlacement.anchor/*cast due to .constrained prefix*/).ToString(); PlacementResult placementResult = result2; diagnostics = "anchor=" + text + " " + placementResult.ToString(); return result; } } public static class Model { public static void Load(Transform parent, string folder) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Expected O, but got Unknown //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Expected O, but got Unknown //IL_0199: Unknown result type (might be due to invalid IL or missing references) using BinaryReader binaryReader = new BinaryReader(File.OpenRead(Path.Combine(folder, "lectern.mesh"))); if (binaryReader.ReadInt32() != 1279607636) { throw new InvalidDataException("Invalid lectern mesh"); } int num = binaryReader.ReadInt32(); for (int i = 0; i < num; i++) { int num2 = binaryReader.ReadInt32(); Vector3[] array = (Vector3[])(object)new Vector3[num2]; Vector2[] array2 = (Vector2[])(object)new Vector2[num2]; for (int j = 0; j < num2; j++) { array[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); array2[j] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle()); } int num3 = binaryReader.ReadInt32(); int[] array3 = new int[num3]; for (int k = 0; k < num3; k++) { array3[k] = binaryReader.ReadInt32(); } Mesh val = new Mesh { name = "Meshy6Lectern" }; val.indexFormat = (IndexFormat)1; val.vertices = array; val.uv = array2; val.triangles = array3; val.RecalculateNormals(); val.RecalculateBounds(); GameObject val2 = new GameObject("Lectern mesh " + i); val2.transform.SetParent(parent, false); val2.AddComponent<MeshFilter>().sharedMesh = val; Material val3 = new Material(Shader.Find("Hopoo Games/Deferred/Standard") ?? Shader.Find("Standard")); Texture2D val4 = new Texture2D(2, 2); ImageConversion.LoadImage(val4, File.ReadAllBytes(Path.Combine(folder, "texture" + i + ".jpg"))); val3.mainTexture = (Texture)(object)val4; val3.color = Color.white; val3.SetFloat("_Glossiness", 0.12f); ((Renderer)val2.AddComponent<MeshRenderer>()).sharedMaterial = val3; } } } public sealed class OfferVisual : MonoBehaviour { private Lectern lectern; private PickupDisplay display; private TextMesh label; private int displayed = -1; private void Start() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) lectern = ((Component)this).GetComponent<Lectern>(); GameObject val = new GameObject("Floating offered page"); val.transform.SetParent(((Component)this).transform, false); val.transform.localPosition = new Vector3(0f, 2.35f, 0f); display = val.AddComponent<PickupDisplay>(); display.coloredParticleSystems = Array.Empty<ParticleSystem>(); display.verticalWave = new Wave { amplitude = 0.12f, frequency = 0.35f }; display.spinSpeed = 35f; display.onModelDiscovered += OnModelReady; GameObject val2 = new GameObject("Offer name and price"); val2.transform.SetParent(((Component)this).transform, false); val2.transform.localPosition = new Vector3(0f, 3.15f, 0f); label = val2.AddComponent<TextMesh>(); label.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); ((Renderer)((Component)label).GetComponent<MeshRenderer>()).sharedMaterial = label.font.material; label.characterSize = 0.025f; label.fontSize = 48; label.anchor = (TextAnchor)4; label.alignment = (TextAlignment)1; label.color = new Color(0.65f, 0.92f, 1f); val2.AddComponent<FaceViewingCamera>(); } private void Update() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Invalid comparison between Unknown and I4 //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)lectern) || !Object.op_Implicit((Object)(object)display) || lectern.Output < 0 || lectern.Output >= Plugin.Names.Length || displayed == lectern.Output) { return; } ItemIndex val = ItemCatalog.FindItemIndex(Plugin.Names[lectern.Output]); if ((int)val != -1) { PickupIndex val2 = PickupCatalog.FindPickupIndex(val); if (!(val2 == PickupIndex.none)) { UniquePickup val3 = default(UniquePickup); ((UniquePickup)(ref val3))..ctor(val2); display.SetPickup(ref val3, false); displayed = lectern.Output; label.text = Language.GetString(ItemCatalog.GetItemDef(val).nameToken) + "\n2 pages"; } } } private void OnModelReady(PickupDisplay ready) { Collider[] componentsInChildren = ((Component)ready).GetComponentsInChildren<Collider>(); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } } private void OnDestroy() { if (Object.op_Implicit((Object)(object)display)) { display.onModelDiscovered -= OnModelReady; } } } public sealed class FaceViewingCamera : MonoBehaviour { private void OnWillRenderObject() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)Camera.current)) { ((Component)this).transform.rotation = ((Component)Camera.current).transform.rotation; } } } internal static class PageBias { private static Run run; private static ReincarnationRules rules; private static PickupIndex[] pickups; private static int generationDepth; private static bool installed; internal static bool SaveEnabled; private static readonly BindingFlags Fields = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly FieldInfo basicSelector = typeof(BasicPickupDropTable).GetField("selector", Fields); private static readonly FieldInfo explicitSelector = typeof(ExplicitPickupDropTable).GetField("weightedSelection", Fields); internal static bool HasAppeared { get { if (Ready()) { return rules.HasAppeared; } return false; } } internal static void RestoreSeen() { if (Ready()) { rules.Observe(0); } } private static bool Ready() { if (!NetworkServer.active || !Object.op_Implicit((Object)(object)Run.instance)) { return false; } bool num = (Object)(object)run != (Object)(object)Run.instance; if (num) { run = Run.instance; rules = new ReincarnationRules((int)run.seed ^ (int)(run.seed >> 32) ^ 0x5245494E); pickups = null; } if (SaveEnabled && !rules.HasAppeared && SaveBridge.SeenWhileLoading()) { rules.Observe(0); } if (num) { Plugin.Instance.LogBias(rules.HasAppeared ? "Restored used Reincarnation boost; normal page odds remain active." : "Reincarnation boost armed: 50% for eligible random pages until first appearance."); } if (pickups == null) { ItemIndex[] source = ((IEnumerable<string>)Plugin.Names).Select((Func<string, ItemIndex>)ItemCatalog.FindItemIndex).ToArray(); if (source.Any((ItemIndex i) => (int)i == -1)) { return false; } pickups = ((IEnumerable<ItemIndex>)source).Select((Func<ItemIndex, PickupIndex>)PickupCatalog.FindPickupIndex).ToArray(); if (pickups.Any((PickupIndex i) => i == PickupIndex.none)) { pickups = null; return false; } } return true; } internal static int NextOffer(OutputDeck deck) { if (!Ready()) { return deck.Next(); } return deck.Next(rules); } internal static void ObserveOffer(int output) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (Ready()) { Observe(pickups[output], "lectern offer"); } } private static void Observe(PickupIndex pickup, string source) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (Ready() && !(pickup != pickups[0]) && rules.Observe(0)) { Plugin.Instance.LogBias("First Reincarnation appeared (" + source + "); normal page odds restored for the rest of this run."); } } private static List<int> Eligible(PickupDropTable table) { //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) WeightedSelection<UniquePickup> val = ((table is BasicPickupDropTable) ? basicSelector : ((table is ExplicitPickupDropTable) ? explicitSelector : null))?.GetValue(table) as WeightedSelection<UniquePickup>; List<int> list = new List<int>(); if (val != null) { for (int i = 0; i < val.Count; i++) { ChoiceInfo<UniquePickup> choice = val.GetChoice(i); int num = Array.IndexOf(pickups, choice.value.pickupIndex); if (choice.weight > 0f && num >= 0 && !list.Contains(num) && run.IsPickupAvailable(choice.value.pickupIndex)) { list.Add(num); } } } else { for (int j = 0; j < pickups.Length; j++) { if (run.availablePageTierDropList.Contains(pickups[j]) && run.IsPickupAvailable(pickups[j])) { list.Add(j); } } } return list; } private static UniquePickup Reweight(UniquePickup result, PickupDropTable table) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (generationDepth != 0 || !Ready() || rules.HasAppeared) { return result; } int num = Array.IndexOf(pickups, result.pickupIndex); if (num < 0) { return result; } return ((UniquePickup)(ref result)).WithPickupIndex(pickups[rules.Choose(num, Eligible(table))]); } private static void ReweightDistinct(List<UniquePickup> results, PickupDropTable table) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (generationDepth != 0 || !Ready() || rules.HasAppeared) { return; } int[] array = results.Select((UniquePickup p) => Array.IndexOf(pickups, p.pickupIndex)).ToArray(); rules.ChooseDistinct(array, Eligible(table)); for (int num = 0; num < array.Length; num++) { if (array[num] >= 0) { int index = num; UniquePickup val = results[num]; results[index] = ((UniquePickup)(ref val)).WithPickupIndex(pickups[array[num]]); } } } private static UniquePickup Generate(orig_GeneratePickup orig, PickupDropTable self, Xoroshiro128Plus rng) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) generationDepth++; UniquePickup result; try { result = orig.Invoke(self, rng); } finally { generationDepth--; } return Reweight(result, self); } private static void Distinct(orig_GenerateDistinctPickups orig, PickupDropTable self, List<UniquePickup> output, int count, Xoroshiro128Plus rng, bool allowLoop) { generationDepth++; try { orig.Invoke(self, output, count, rng, allowLoop); } finally { generationDepth--; } ReweightDistinct(output, self); } private static PickupIndex Legacy(orig_GenerateDrop orig, PickupDropTable self, Xoroshiro128Plus rng) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) generationDepth++; PickupIndex val; try { val = orig.Invoke(self, rng); } finally { generationDepth--; } return Reweight(new UniquePickup(val), self).pickupIndex; } private static PickupIndex[] LegacyDistinct(orig_GenerateUniqueDrops orig, PickupDropTable self, int count, Xoroshiro128Plus rng) { generationDepth++; PickupIndex[] source; try { source = orig.Invoke(self, count, rng); } finally { generationDepth--; } List<UniquePickup> list = ((IEnumerable<PickupIndex>)source).Select((Func<PickupIndex, UniquePickup>)((PickupIndex p) => new UniquePickup(p))).ToList(); ReweightDistinct(list, self); return list.Select((UniquePickup p) => p.pickupIndex).ToArray(); } private static void Droplet(orig_CreatePickupDroplet_CreatePickupInfo_Vector3_Vector3 orig, CreatePickupInfo info, Vector3 position, Vector3 velocity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(info, position, velocity); Observe(((CreatePickupInfo)(ref info)).pickup.pickupIndex, "spawned droplet"); } private static void Assigned(orig_OnPickupAssigned orig, GenericPickupController self) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self); if (((Component)self).gameObject.activeInHierarchy) { Observe(self.pickup.pickupIndex, "world pickup/reroll"); } } private static void Options(orig_SetOptionsServer orig, PickupPickerController self, Option[] options) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self, options); if (!((Component)self).gameObject.activeInHierarchy || options == null) { return; } foreach (Option val in options) { if (val.available) { Observe(val.pickup.pickupIndex, "page choice"); } } } private static void Shop(orig_SetPickup orig, ShopTerminalBehavior self, UniquePickup pickup, bool hidden) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self, pickup, hidden); if (((Component)self).gameObject.activeInHierarchy && !hidden) { Observe(pickup.pickupIndex, "shop offer"); } } private static void Given(Inventory inventory, ItemIndex item, int count) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (count > 0 && Ready() && PlayerCharacterMasterController.instances.Any((PlayerCharacterMasterController p) => Object.op_Implicit((Object)(object)p.master) && (Object)(object)p.master.inventory == (Object)(object)inventory) && (item == ItemCatalog.FindItemIndex("PageDie") || item == ItemCatalog.FindItemIndex("PageDieConsumed"))) { Observe(pickups[0], "inventory award"); } } private static void EndRun(Run ended) { if ((Object)(object)run == (Object)(object)ended) { run = null; rules = null; pickups = null; } } internal static void Install() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown if (!installed) { installed = true; PickupDropTable.GeneratePickup += new hook_GeneratePickup(Generate); PickupDropTable.GenerateDistinctPickups += new hook_GenerateDistinctPickups(Distinct); PickupDropTable.GenerateDrop += new hook_GenerateDrop(Legacy); PickupDropTable.GenerateUniqueDrops += new hook_GenerateUniqueDrops(LegacyDistinct); PickupDropletController.CreatePickupDroplet_CreatePickupInfo_Vector3_Vector3 += new hook_CreatePickupDroplet_CreatePickupInfo_Vector3_Vector3(Droplet); GenericPickupController.OnPickupAssigned += new hook_OnPickupAssigned(Assigned); PickupPickerController.SetOptionsServer += new hook_SetOptionsServer(Options); ShopTerminalBehavior.SetPickup += new hook_SetPickup(Shop); Inventory.onServerItemGiven += Given; Run.onRunDestroyGlobal += EndRun; } } internal static void Uninstall() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown if (installed) { installed = false; PickupDropTable.GeneratePickup -= new hook_GeneratePickup(Generate); PickupDropTable.GenerateDistinctPickups -= new hook_GenerateDistinctPickups(Distinct); PickupDropTable.GenerateDrop -= new hook_GenerateDrop(Legacy); PickupDropTable.GenerateUniqueDrops -= new hook_GenerateUniqueDrops(LegacyDistinct); PickupDropletController.CreatePickupDroplet_CreatePickupInfo_Vector3_Vector3 -= new hook_CreatePickupDroplet_CreatePickupInfo_Vector3_Vector3(Droplet); GenericPickupController.OnPickupAssigned -= new hook_OnPickupAssigned(Assigned); PickupPickerController.SetOptionsServer -= new hook_SetOptionsServer(Options); ShopTerminalBehavior.SetPickup -= new hook_SetPickup(Shop); Inventory.onServerItemGiven -= Given; Run.onRunDestroyGlobal -= EndRun; run = null; rules = null; pickups = null; } } } public struct SurfacePoint { public float Y; public float NormalY; public SurfacePoint(float y, float normalY = 1f) { Y = y; NormalY = normalY; } } public interface IPlacementSurface { SurfacePoint? Sample(float x, float z); bool IsClear(float x, float y, float z); } public struct PlacementResult { public float X; public float Y; public float Z; public int Tried; public int NoGround; public int Steep; public int Unsupported; public int Uneven; public int Blocked; public override string ToString() { return $"tried={Tried} noGround={NoGround} steep={Steep} unsupported={Unsupported} uneven={Uneven} blocked={Blocked}"; } } public static class PlacementRules { public const float HalfFootprint = 0.44f; public static bool Find(IPlacementSurface surface, float x, float z, float yaw, out PlacementResult result) { result = default(PlacementResult); float num = (float)Math.Cos(yaw); float num2 = (float)Math.Sin(yaw); float[] array = new float[7] { 1.8f, 2.3f, 2.8f, 3.4f, 4f, 4.8f, 5.6f }; foreach (float num3 in array) { for (int j = 0; j < 24; j++) { double num4 = (double)j * Math.PI / 12.0; float num5 = (float)Math.Cos(num4) * num3; float num6 = (float)Math.Sin(num4) * num3; float num7 = x + num * num5 + num2 * num6; float num8 = z - num2 * num5 + num * num6; result.Tried++; SurfacePoint? surfacePoint = surface.Sample(num7, num8); if (!surfacePoint.HasValue) { result.NoGround++; continue; } if (surfacePoint.Value.NormalY < 0.85f) { result.Steep++; continue; } float num9 = surfacePoint.Value.Y; float num10 = num9; bool flag = true; int[] array2 = new int[2] { -1, 1 }; foreach (int num11 in array2) { int[] array3 = new int[2] { -1, 1 }; foreach (int num12 in array3) { float num13 = 0.44f * (float)num11; float num14 = 0.44f * (float)num12; SurfacePoint? surfacePoint2 = surface.Sample(num7 + num * num13 + num2 * num14, num8 - num2 * num13 + num * num14); if (!surfacePoint2.HasValue || surfacePoint2.Value.NormalY < 0.85f) { flag = false; continue; } num9 = Math.Min(num9, surfacePoint2.Value.Y); num10 = Math.Max(num10, surfacePoint2.Value.Y); } } if (!flag) { result.Unsupported++; continue; } if (num10 - num9 > 0.22f) { result.Uneven++; continue; } float y = num10 + 0.015f; if (!surface.IsClear(num7, y, num8)) { result.Blocked++; continue; } result.X = num7; result.Y = y; result.Z = num8; return true; } } return false; } } [BepInPlugin("com.rodanius.bindinglectern", "Binding Lectern", "0.1.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal static Plugin Instance; internal static readonly string[] Names = new string[7] { "PageDie", "PageWarpGate", "PageTeamInvisibility", "PageUpgradeItem", "PageClarity", "PageSummonFeralToddlers", "PagePurify" }; internal static ItemIndex[] Pages; internal static ItemIndex[] Spent; internal static ItemIndex Scrap; internal static Random Rng; private GameObject prefab; private OutputDeck deck; private Run activeRun; private void Awake() { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) Instance = this; PageBias.Install(); if (Chainloader.PluginInfos.ContainsKey("com.KingEnderBrine.ProperSave")) { SaveBridge.Install(); PageBias.SaveEnabled = true; } try { prefab = PrefabAPI.CreateEmptyPrefab("BindingLectern"); prefab.AddComponent<Lectern>(); prefab.AddComponent<EntityLocator>().entity = prefab; prefab.layer = LayerIndex.defaultLayer.intVal; BoxCollider obj = prefab.AddComponent<BoxCollider>(); obj.center = new Vector3(0f, 0.85f, 0f); obj.size = new Vector3(0.88f, 1.7f, 0.86f); Model.Load(prefab.transform, Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "assets")); NetworkModCompatibilityHelper.networkModList = NetworkModCompatibilityHelper.networkModList.Concat(new string[1] { "com.rodanius.bindinglectern;0.1.3" }).ToArray(); SceneManager.sceneLoaded += SceneLoaded; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Lectern initialization failed; no scene modifications made. " + ex)); } } internal void LogBias(string text) { ((BaseUnityPlugin)this).Logger.LogInfo((object)text); } private void OnDestroy() { SceneManager.sceneLoaded -= SceneLoaded; PageBias.Uninstall(); if (PageBias.SaveEnabled) { SaveBridge.Uninstall(); PageBias.SaveEnabled = false; } } private void SceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (((Scene)(ref scene)).name == "bazaar") { ((MonoBehaviour)this).StartCoroutine(Spawn(scene)); } } private unsafe IEnumerator Spawn(Scene scene) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active) { yield break; } TrialGongInteraction gong = null; for (int n = 0; n < 100; n++) { if (Object.op_Implicit((Object)(object)gong)) { break; } if (!((Scene)(ref scene)).isLoaded || !NetworkServer.active) { yield break; } gong = (from g in Object.FindObjectsOfType<TrialGongInteraction>() where ((Component)g).gameObject.scene == scene orderby ((Component)g).transform.position.y select g).FirstOrDefault(); if (!Object.op_Implicit((Object)(object)gong)) { yield return (object)new WaitForSeconds(0.1f); } } if (!((Scene)(ref scene)).isLoaded || !Object.op_Implicit((Object)(object)gong) || !Object.op_Implicit((Object)(object)Run.instance) || !Object.op_Implicit((Object)(object)prefab)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"No Bazaar gong found; lectern not spawned."); } else { if (Object.FindObjectsOfType<Lectern>().Any((Lectern l) => ((Component)l).gameObject.scene == scene)) { yield break; } Pages = ((IEnumerable<string>)Names).Select((Func<string, ItemIndex>)ItemCatalog.FindItemIndex).ToArray(); Spent = Names.Select((string text) => ItemCatalog.FindItemIndex(text + "Consumed")).ToArray(); Scrap = ItemCatalog.FindItemIndex("PageShredded"); if (Pages.Any((ItemIndex p) => (int)p == -1) || Spent.Any((ItemIndex p) => (int)p == -1) || (int)Scrap == -1) { ((BaseUnityPlugin)this).Logger.LogError((object)"Missing Hallowed Concepts page catalog; no lectern spawned."); yield break; } if ((Object)(object)activeRun != (Object)(object)Run.instance) { activeRun = Run.instance; deck = new OutputDeck(Names.Length, (int)activeRun.seed ^ 0x4C454354); Rng = new Random((int)(activeRun.seed >> 32) ^ 0x50414745); } yield return (object)new WaitForFixedUpdate(); Vector3 position = Vector3.zero; bool found = false; string diagnostics = ""; for (int n = 0; n < 4; n++) { if (found) { break; } if (!((Scene)(ref scene)).isLoaded || !NetworkServer.active || !Object.op_Implicit((Object)(object)gong)) { yield break; } Physics.SyncTransforms(); found = LecternPlacement.TryFind(gong, scene, out position, out diagnostics); if (!found) { yield return (object)new WaitForSecondsRealtime(0.5f); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Lectern placement: gong=" + ((object)((Component)gong).transform.position/*cast due to .constrained prefix*/).ToString() + " " + diagnostics)); if (!found) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("No supported clear lectern position near gong after expanded search; " + diagnostics)); yield break; } int num = PageBias.NextOffer(deck); GameObject obj = Object.Instantiate<GameObject>(prefab, position, Quaternion.Euler(0f, ((Component)gong).transform.eulerAngles.y, 0f)); obj.GetComponent<Lectern>().Output = num; SceneManager.MoveGameObjectToScene(obj, scene); obj.SetActive(true); NetworkServer.Spawn(obj); PageBias.ObserveOffer(num); ManualLogSource logger = ((BaseUnityPlugin)this).Logger; Vector3 val = position; logger.LogInfo((object)("Spawned Binding Lectern near existing gong at " + ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString() + " output=" + Names[num])); } } } public class Lectern : NetworkBehaviour, IInteractable { public int Output = -1; private float nextTrade; private Collider interactionCollider; private string OutputName { get { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (Output < 0 || Output >= Plugin.Names.Length) { return "page"; } ItemDef itemDef = ItemCatalog.GetItemDef(ItemCatalog.FindItemIndex(Plugin.Names[Output])); if (!Object.op_Implicit((Object)(object)itemDef)) { return "page"; } return Language.GetString(itemDef.nameToken); } } private void Awake() { interactionCollider = ((Component)this).GetComponent<Collider>(); } private void Start() { ((Component)this).gameObject.AddComponent<OfferVisual>(); } public override bool OnSerialize(NetworkWriter writer, bool initialState) { writer.Write(Output); return true; } public override void OnDeserialize(NetworkReader reader, bool initialState) { Output = reader.ReadInt32(); } public string GetContextString(Interactor activator) { return "Bind 2 pages into " + OutputName + " (Shredded Pages first)"; } private static Inventory InventoryOf(Interactor actor) { CharacterBody val = (Object.op_Implicit((Object)(object)actor) ? ((Component)actor).GetComponent<CharacterBody>() : null); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.healthComponent) || !val.healthComponent.alive) { return null; } return val.inventory; } private static ItemIndex[] Inputs() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected I4, but got Unknown return ((IEnumerable<string>)Plugin.Names).Select((Func<string, ItemIndex>)ItemCatalog.FindItemIndex).Concat(Plugin.Names.Select((string n) => ItemCatalog.FindItemIndex(n + "Consumed"))).Concat((IEnumerable<ItemIndex>)(object)new ItemIndex[1] { (ItemIndex)(int)ItemCatalog.FindItemIndex("PageShredded") }) .ToArray(); } public Interactability GetInteractability(Interactor actor) { Inventory inv = InventoryOf(actor); if (Output >= 0 && Output < Plugin.Names.Length && Object.op_Implicit((Object)(object)inv) && (from i in Inputs() where (int)i != -1 select i).Sum((ItemIndex i) => inv.GetItemCountPermanent(i)) >= 2) { return (Interactability)2; } return (Interactability)1; } public void OnInteractionBegin(Interactor actor) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown if (!NetworkServer.active || Output < 0 || Time.fixedTime < nextTrade || (int)GetInteractability(actor) != 2 || !Object.op_Implicit((Object)(object)interactionCollider)) { return; } Vector3 val = ((Component)actor).transform.position - interactionCollider.ClosestPoint(((Component)actor).transform.position); if (((Vector3)(ref val)).sqrMagnitude > Mathf.Pow(actor.maxInteractionDistance + 1f, 2f)) { return; } Inventory val2 = InventoryOf(actor); ItemIndex[] array = Inputs(); int[] array2 = TradeRules.Select(((IEnumerable<ItemIndex>)array).Select((Func<ItemIndex, int>)val2.GetItemCountPermanent).ToArray(), array.Length - 1, Plugin.Rng); if (array2 != null) { nextTrade = Time.fixedTime + 0.75f; bool flag = array2.Any((int i) => i >= 7 && i < 14) || val2.GetItemCountPermanent(Plugin.Spent[Output]) > 0; if (Output == 0 && val2.GetItemCountPermanent(ItemCatalog.FindItemIndex("PageDieCooldown")) > 0) { flag = true; } int[] array3 = array2; foreach (int num2 in array3) { val2.RemoveItemPermanent(array[num2], 1); } val2.GiveItemPermanent(flag ? Plugin.Spent[Output] : Plugin.Pages[Output], 1); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = "Bound two pages into " + OutputName + (flag ? " (spent until its normal recharge)." : ".") }); } } public bool ShouldIgnoreSpherecastForInteractibility(Interactor a) { return false; } public bool ShouldShowOnScanner() { return true; } public bool ShouldProximityHighlight() { return true; } public int GetInteractablePriority(Interactor a) { return 0; } public bool ShouldSpawnLesserInteractionRewards(Interactor a) { return false; } } public sealed class ReincarnationRules { private readonly Random rng; public bool HasAppeared { get; private set; } public ReincarnationRules(int seed) { rng = new Random(seed); } public bool Observe(int page) { if (page != 0 || HasAppeared) { return false; } HasAppeared = true; return true; } public int Choose(int original, IList<int> eligible) { if (HasAppeared || original < 0 || !eligible.Contains(original) || !eligible.Contains(0) || eligible.Count < 2) { return original; } if (rng.NextDouble() < 0.5) { return 0; } int[] array = eligible.Where((int i) => i != 0).Distinct().ToArray(); return array[rng.Next(array.Length)]; } public void ChooseDistinct(int[] outputs, IList<int> eligible) { if (HasAppeared || !eligible.Contains(0) || eligible.Count < 2) { return; } List<int> list = eligible.Distinct().ToList(); List<int> list2 = new List<int>(list); for (int i = 0; i < outputs.Length; i++) { if (list.Contains(outputs[i])) { if (list2.Count == 0) { list2.AddRange(list); } int original = (list2.Contains(outputs[i]) ? outputs[i] : list2[rng.Next(list2.Count)]); outputs[i] = Choose(original, list2); list2.Remove(outputs[i]); } } } } internal static class SaveBridge { private const string Key = "com.rodanius.bindinglectern.reincarnationSeen.v1"; private static SaveFile cached; private static bool seen; [MethodImpl(MethodImplOptions.NoInlining)] internal static void Install() { SaveFile.OnGatherSaveData += Gather; Loading.OnLoadingEnded += Loaded; } [MethodImpl(MethodImplOptions.NoInlining)] internal static void Uninstall() { SaveFile.OnGatherSaveData -= Gather; Loading.OnLoadingEnded -= Loaded; cached = null; } [MethodImpl(MethodImplOptions.NoInlining)] internal static bool SeenWhileLoading() { if (!Loading.IsLoading) { return false; } return Read(Loading.CurrentSave); } private static bool Read(SaveFile file) { if (file == null) { return false; } if (file != cached) { cached = file; seen = file.TryGetModdedData<string>("com.rodanius.bindinglectern.reincarnationSeen.v1") == "seen"; } return seen; } private static void Gather(Dictionary<string, object> data) { data["com.rodanius.bindinglectern.reincarnationSeen.v1"] = (PageBias.HasAppeared ? "seen" : "armed"); } private static void Loaded(SaveFile file) { if (Read(file)) { PageBias.RestoreSeen(); } cached = null; } } public sealed class OutputDeck { private readonly int count; private readonly Random rng; private readonly List<int> bag = new List<int>(); public OutputDeck(int count, int seed) { if (count < 1) { throw new ArgumentOutOfRangeException("count"); } this.count = count; rng = new Random(seed); } public int Next(ReincarnationRules bias = null) { if (bag.Count == 0) { for (int i = 0; i < count; i++) { bag.Add(i); } TradeRules.Shuffle(bag, rng); } int index = bag.Count - 1; int num = bias?.Choose(bag[index], bag) ?? bag[index]; bag.Remove(num); return num; } } public static class TradeRules { public static int[] Select(int[] counts, int scrap, Random rng) { int[] array = (int[])counts.Clone(); int[] array2 = new int[2]; for (int i = 0; i < 2; i++) { if (array[scrap] > 0) { array2[i] = scrap; array[scrap]--; continue; } int num = 0; for (int j = 0; j < array.Length; j++) { if (j != scrap) { num += array[j]; } } if (num == 0) { return null; } int num2 = rng.Next(num); for (int k = 0; k < array.Length; k++) { if (k != scrap) { num2 -= array[k]; if (num2 < 0) { array2[i] = k; array[k]--; break; } } } } return array2; } public static void Shuffle(List<int> bag, Random rng) { for (int num = bag.Count - 1; num > 0; num--) { int index = rng.Next(num + 1); int value = bag[num]; bag[num] = bag[index]; bag[index] = value; } } }