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 BuildBeacon v0.2.0
plugins/BuildBeacon.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using BuildBeacon.Patches; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("BuildBeacon")] [assembly: AssemblyDescription("Boss-trophy-powered beacon that discounts build costs in a radius.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("BuildBeacon")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.0.0")] namespace BuildBeacon { public enum StackMode { Max, Sum } public enum RefundMode { PaidCost, CurrentCost } public enum TrophyPlacement { Inset = 1, Mounted } public class BeaconConfig { public ConfigEntry<bool> Enabled; public ConfigEntry<string> LevelPercents; public ConfigEntry<float> BossPercent; public ConfigEntry<StackMode> Stacking; public ConfigEntry<RefundMode> Refund; public ConfigEntry<bool> ShowRadius; public ConfigEntry<bool> ShowTrophySources; public ConfigEntry<bool> ShrinkGreatBeaconTrophies; public ConfigEntry<TrophyPlacement> Placement; public ConfigEntry<bool> DevMode; public ConfigEntry<bool> VerboseLogging; public ConfigEntry<float> RadiusAtLevel1; public ConfigEntry<float> RadiusPerLevel; public ConfigEntry<float> GreatRadiusAtLevel1; public ConfigEntry<float> GreatRadiusPerLevel; public ConfigEntry<int> MaxLevel; public ConfigEntry<float> HolderRange; public ConfigEntry<int> BossSlots; public ConfigEntry<int> BeaconMobSlots; public ConfigEntry<string> BossRules; public ConfigEntry<string> MobRules; public const string DefaultBossRules = "TrophyEikthyr|Wood\nTrophyEikthyr|Flint\nTrophyEikthyr|Feathers\nTrophyEikthyr|Acorns\nTrophyEikthyr|Dandelion\nTrophyEikthyr|Mushroom\nTrophyEikthyr|Raspberries\nTrophyTheElder|Finewood\nTrophyTheElder|Corewood\nTrophyTheElder|Copper\nTrophyTheElder|Tin\nTrophyTheElder|Bronze\nTrophyTheElder|Bronze Nails\nTrophyTheElder|Blueberries\nTrophyTheElder|Thistle\nTrophyTheElder|Fir Cone\nTrophyTheElder|Pine Cone\nTrophyBonemass|Stone\nTrophyBonemass|Rock\nTrophyBonemass|Iron\nTrophyBonemass|Iron Nails\nTrophyBonemass|Guck\nTrophyBonemass|Chain\nTrophyBonemass|Surtling Core\nTrophyBonemass|Coal\nTrophyDragonQueen|Silver\nTrophyDragonQueen|Silver Necklace\nTrophyDragonQueen|Dragon Tear\nTrophyDragonQueen|Crystal\nTrophyGoblinKing|Black Metal\nTrophyGoblinKing|Tar\nTrophyGoblinKing|Cloudberries\nTrophyGoblinKing|Red Jute\nTrophySeekerQueen|Black Marble\nTrophySeekerQueen|Yggdrasil Wood\nTrophySeekerQueen|Black Core\nTrophySeekerQueen|Refined Eitr\nTrophySeekerQueen|Sap\nTrophySeekerQueen|Wisp\nTrophySeekerQueen|Blue Jute\nTrophySeekerQueen|Majestic Carapace\nTrophySeekerQueen|Sharpening Stone\nTrophyFader|Grausten\nTrophyFader|Warrior Trophy\nTrophyFader|Ashwood\nTrophyFader|Flametal\nTrophyFader|Bloodstone\nTrophyFader|Sulfur\nTrophyFader|Charcoal Resin\nTrophyFader|Proustite Powder\nTrophyFader|Ceramic Plate\nTrophyFader|Pot Shard\nTrophyFader|Kindled Ribs\nTrophyFader|Shield Core\nTrophyFader|Torn Spirit"; public const string DefaultMobRules = "TrophyGreydwarf|Wood|1\nTrophyGreydwarf|Stone|1\nTrophyGreydwarf|Resin|1\nTrophyGreydwarf|Greydwarf Eye|1\nTrophyGreydwarfBrute|Wood|1\nTrophyGreydwarfBrute|Corewood|1\nTrophyGreydwarfBrute|Resin|1\nTrophyGreydwarfShaman|Finewood|1\nTrophyGreydwarfShaman|Resin|1\nTrophyGreydwarfShaman|Greydwarf Eye|1\nTrophyGreydwarfShaman|Queen Bee|1\nTrophyForestTroll|Finewood|1\nTrophyForestTroll|Corewood|1\nTrophyForestTroll|Stone|1\nTrophyForestTroll|Troll Hide|1\nTrophyBjorn|Wood|1\nTrophyBjorn|Finewood|1\nTrophyBjorn|Corewood|1\nTrophyBjorn|Bear Hide|1\nTrophyBjorn|Bear Paw|1\nTrophySkeleton|Bone Fragments|1\nTrophyGhost|Ectoplasm|1\nTrophySkeletonHildir|Bone Fragments|1\nTrophySkeletonHildir|Coal|1\nTrophySkeletonHildir|Surtling Core|1\nTrophyBoar|Leather Scraps|1\nTrophyDeer|Deer Hide|1\nTrophyDeer|Leather Scraps|1\nTrophyBlob|Guck|1\nTrophyDraugr|Ancient Bark|1\nTrophyDraugr|Iron|1\nTrophyDraugrElite|Ancient Bark|1\nTrophyDraugrElite|Iron|1\nTrophyDraugrElite|Chain|1\nTrophyLeech|Bloodbag|1\nTrophyWraith|Chain|1\nTrophyWraith|Ectoplasm|1\nTrophyAbomination|Ancient Bark|1\nTrophySurtling|Surtling Core|1\nTrophySurtling|Coal|1\nTrophySkeletonPoison|Bone Fragments|1\nTrophyKvastur|Guck|1\nTrophyWolf|Wolf Pelt|1\nTrophyWolf|Silver|1\nTrophyFenring|Fenris Claw|1\nTrophyFenring|Wolf Pelt|1\nTrophyHatchling|Obsidian|1\nTrophyHatchling|Crystal|1\nTrophySGolem|Stone|1\nTrophySGolem|Crystal|1\nTrophySGolem|Obsidian|1\nTrophySGolem|Silver|1\nTrophyCultist|Fenris Claw|1\nTrophyUlv|Scale Hide|1\nTrophyUlv|Wolf Pelt|1\nTrophyCultist_Hildir|Obsidian|1\nTrophyGoblin|Black Metal|1\nTrophyGoblinShaman|Tar|1\nTrophyGoblinBrute|Black Metal|1\nTrophyLox|Lox Pelt|1\nTrophyGrowth|Tar|1\nTrophyGoblinBruteBrosBrute|Lox Pelt|1\nTrophyGoblinBruteBrosShaman|Tar|1\nTrophyBjornUndead|Bear Hide|1\nTrophyBjornUndead|Bear Paw|1\nTrophySeeker|Yggdrasil Wood|1\nTrophyTick|Yggdrasil Wood|1\nTrophySeekerBrute|Black Marble|1\nTrophyDvergr|Black Marble|1\nTrophyDvergr|Mechanical Spring|1\nTrophyDvergr|Dvergr Extractor|1\nTrophyDvergr|Dvergr Lantern|1\nTrophyGjall|Yggdrasil Wood|1\nTrophyGjall|Black Marble|1\nTrophyCharredMelee|Ashwood|1\nTrophyCharredMelee|Charred Bone|1\nTrophyCharredMelee|Charred Skull|1\nTrophyCharredMelee|Warrior Trophy|1\nTrophyCharredArcher|Ashwood|1\nTrophyCharredArcher|Charred Bone|1\nTrophyCharredArcher|Charred Skull|1\nTrophyCharredMage|Bloodgold|1\nTrophyCharredMage|Charred Cogwheel|1\nTrophyMorgen|Grausten|1\nTrophyMorgen|Ashwood|1\nTrophyMorgen|Morgen Sinew|1\nTrophyAsksvin|Grausten|1\nTrophyAsksvin|Asksvin Hide|1\nTrophyAsksvin|Asksvin Neck|1\nTrophyAsksvin|Asksvin Pelvis|1\nTrophyAsksvin|Asksvin Ribcage|1\nTrophyAsksvin|Asksvin Skull|1\nTrophyBlob_Lava|Grausten|1\nTrophyBlob_Lava|Flametal|1\nTrophyBlob_Lava|Molten Core|1\nTrophyVolture|Charred Bone|1\nTrophyVolture|Charred Skull|1\nTrophyFallenValkyrie|Celestial Feather|1\nTrophyFallenValkyrie|Bloodgold|1\nTrophyMoose|Timberwood|1\nTrophyMoose|Moose Hide|1\nTrophyMoose|Moose Sinew|1\nTrophyBarka|Timberwood|1\nTrophyBarka|Ice|1\nTrophyBlob_Frost|Frostcore|1\nTrophyBlob_Frost|Ice|1\nTrophySeal|Seal Pelt|1\nTrophyWrithan|Writhan Roots|1\nTrophyWrithan|Timberwood|1\nTrophyJotunWitch|Ice|1\nTrophyJotunWarrior|Frostcore|1\nTrophyElaking|Elaking Hair Bundle|1"; public event Action SettingChanged; public BeaconConfig(ConfigFile cfg) { Enabled = ConfigUtil.Synced(cfg, "1. General", "Enabled", def: true, "Master switch."); LevelPercents = ConfigUtil.Synced(cfg, "1. General", "LevelPercents", "50, 80, 90", "Percentage off at each creature discount level, level 1 first; the number of entries is the top level. The levels of a beacon's creature trophies add up and stop at the top level. The default 50, 80, 90 makes each item go 2x, 5x and 10x as far."); if (LevelPercents.Value.Replace(" ", "") == "25,60,80,90,95") { LevelPercents.Value = (string)((ConfigEntryBase)LevelPercents).DefaultValue; } BossPercent = ConfigUtil.Synced(cfg, "1. General", "BossPercent", 100f, "Percentage off a slotted boss trophy takes from its materials. 100 = free, no gathering needed. 95 = each item goes 20x as far, so building still takes some gathering. Keep it at or above the top of LevelPercents: a boss's materials take the boss's discount, never a creature's.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(50f, 100f)); Stacking = ConfigUtil.Synced(cfg, "1. General", "Stacking", StackMode.Max, "How overlapping beacons' creature discounts combine. Max = the beacon with the highest level counts. Sum = their levels add up, up to the top level."); Refund = ConfigUtil.Synced(cfg, "1. General", "Refund", RefundMode.PaidCost, "PaidCost = refund what was actually paid. CurrentCost = refund current discounted cost."); ShowRadius = ConfigUtil.Local(cfg, "1. General", "ShowRadius", def: true, "Show the radius ring around beacons while holding a build tool (hammer, hoe, cultivator)."); ShowTrophySources = ConfigUtil.Local(cfg, "1. General", "ShowTrophySources", def: true, "In the beacon panel, hovering a material on the Discounts tab lists every trophy that can discount it, including ones you have not slotted yet. Turn off to find them out for yourself."); ShrinkGreatBeaconTrophies = ConfigUtil.Local(cfg, "1. General", "ShrinkGreatBeaconTrophies", def: true, "Size the boss trophies in the Great Beacon's alcoves to fit around the pillar: Eikthyr, the Elder and Moder at vanilla size, Bonemass at 75%, the Queen, Yagluth and Fader at 65%. Off: all at vanilla size."); Placement = ConfigUtil.Local(cfg, "1. General", "TrophyPlacement", TrophyPlacement.Mounted, "How slotted trophies sit in the beacon's alcoves. Inset (1) = scaled down to fit inside the alcove. Mounted (2) = vanilla item stand size, back set into the alcove and the rest standing out of it."); RadiusAtLevel1 = ConfigUtil.Synced(cfg, "2. Radius & Slots", "RadiusAtLevel1", 30f, "Radius at level 1, with no boss holders linked (m)."); RadiusPerLevel = ConfigUtil.Synced(cfg, "2. Radius & Slots", "RadiusPerLevel", 10f, "Extra radius per level (m). Each linked boss holder adds a level."); GreatRadiusAtLevel1 = ConfigUtil.Synced(cfg, "2. Radius & Slots", "GreatRadiusAtLevel1", 65f, "The Great Beacon's radius at level 1 (m)."); GreatRadiusPerLevel = ConfigUtil.Synced(cfg, "2. Radius & Slots", "GreatRadiusPerLevel", 5f, "The Great Beacon's extra radius per level (m). Each boss trophy in its alcoves, linked holder and linked rack adds a level."); MaxLevel = ConfigUtil.Synced(cfg, "2. Radius & Slots", "MaxLevel", 8, "Highest beacon level; holders beyond MaxLevel - 1 add none.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 32)); HolderRange = ConfigUtil.Synced(cfg, "2. Radius & Slots", "HolderRange", 30f, "How far a boss holder may stand from its beacon (m). A holder links to the closest beacon within this distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 100f)); BossSlots = ConfigUtil.Synced(cfg, "2. Radius & Slots", "BossSlots", 8, "Boss trophy slots per beacon. Each boss trophy can be slotted once.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 16)); BeaconMobSlots = ConfigUtil.Synced(cfg, "2. Radius & Slots", "BeaconMobSlots", 4, "Creature trophy slots in the beacon itself. Fixed: bosses do not add any; each trophy rack adds four of its own to the beacon's network.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 32)); BossRules = ConfigUtil.Synced(cfg, "3. Boss Rules", "BossRules", "TrophyEikthyr|Wood\nTrophyEikthyr|Flint\nTrophyEikthyr|Feathers\nTrophyEikthyr|Acorns\nTrophyEikthyr|Dandelion\nTrophyEikthyr|Mushroom\nTrophyEikthyr|Raspberries\nTrophyTheElder|Finewood\nTrophyTheElder|Corewood\nTrophyTheElder|Copper\nTrophyTheElder|Tin\nTrophyTheElder|Bronze\nTrophyTheElder|Bronze Nails\nTrophyTheElder|Blueberries\nTrophyTheElder|Thistle\nTrophyTheElder|Fir Cone\nTrophyTheElder|Pine Cone\nTrophyBonemass|Stone\nTrophyBonemass|Rock\nTrophyBonemass|Iron\nTrophyBonemass|Iron Nails\nTrophyBonemass|Guck\nTrophyBonemass|Chain\nTrophyBonemass|Surtling Core\nTrophyBonemass|Coal\nTrophyDragonQueen|Silver\nTrophyDragonQueen|Silver Necklace\nTrophyDragonQueen|Dragon Tear\nTrophyDragonQueen|Crystal\nTrophyGoblinKing|Black Metal\nTrophyGoblinKing|Tar\nTrophyGoblinKing|Cloudberries\nTrophyGoblinKing|Red Jute\nTrophySeekerQueen|Black Marble\nTrophySeekerQueen|Yggdrasil Wood\nTrophySeekerQueen|Black Core\nTrophySeekerQueen|Refined Eitr\nTrophySeekerQueen|Sap\nTrophySeekerQueen|Wisp\nTrophySeekerQueen|Blue Jute\nTrophySeekerQueen|Majestic Carapace\nTrophySeekerQueen|Sharpening Stone\nTrophyFader|Grausten\nTrophyFader|Warrior Trophy\nTrophyFader|Ashwood\nTrophyFader|Flametal\nTrophyFader|Bloodstone\nTrophyFader|Sulfur\nTrophyFader|Charcoal Resin\nTrophyFader|Proustite Powder\nTrophyFader|Ceramic Plate\nTrophyFader|Pot Shard\nTrophyFader|Kindled Ribs\nTrophyFader|Shield Core\nTrophyFader|Torn Spirit", "Managed by BepInEx/config/BuildBeacon.BossRules.txt on the server; edit that file instead. trophyPrefab|material, one per line. A slotted boss trophy takes BossPercent off the material within the radius (100: free). Material matches the item's prefab name or display name, spaces and case ignored."); MobRules = ConfigUtil.Synced(cfg, "4. Mob Rules", "MobRules", "TrophyGreydwarf|Wood|1\nTrophyGreydwarf|Stone|1\nTrophyGreydwarf|Resin|1\nTrophyGreydwarf|Greydwarf Eye|1\nTrophyGreydwarfBrute|Wood|1\nTrophyGreydwarfBrute|Corewood|1\nTrophyGreydwarfBrute|Resin|1\nTrophyGreydwarfShaman|Finewood|1\nTrophyGreydwarfShaman|Resin|1\nTrophyGreydwarfShaman|Greydwarf Eye|1\nTrophyGreydwarfShaman|Queen Bee|1\nTrophyForestTroll|Finewood|1\nTrophyForestTroll|Corewood|1\nTrophyForestTroll|Stone|1\nTrophyForestTroll|Troll Hide|1\nTrophyBjorn|Wood|1\nTrophyBjorn|Finewood|1\nTrophyBjorn|Corewood|1\nTrophyBjorn|Bear Hide|1\nTrophyBjorn|Bear Paw|1\nTrophySkeleton|Bone Fragments|1\nTrophyGhost|Ectoplasm|1\nTrophySkeletonHildir|Bone Fragments|1\nTrophySkeletonHildir|Coal|1\nTrophySkeletonHildir|Surtling Core|1\nTrophyBoar|Leather Scraps|1\nTrophyDeer|Deer Hide|1\nTrophyDeer|Leather Scraps|1\nTrophyBlob|Guck|1\nTrophyDraugr|Ancient Bark|1\nTrophyDraugr|Iron|1\nTrophyDraugrElite|Ancient Bark|1\nTrophyDraugrElite|Iron|1\nTrophyDraugrElite|Chain|1\nTrophyLeech|Bloodbag|1\nTrophyWraith|Chain|1\nTrophyWraith|Ectoplasm|1\nTrophyAbomination|Ancient Bark|1\nTrophySurtling|Surtling Core|1\nTrophySurtling|Coal|1\nTrophySkeletonPoison|Bone Fragments|1\nTrophyKvastur|Guck|1\nTrophyWolf|Wolf Pelt|1\nTrophyWolf|Silver|1\nTrophyFenring|Fenris Claw|1\nTrophyFenring|Wolf Pelt|1\nTrophyHatchling|Obsidian|1\nTrophyHatchling|Crystal|1\nTrophySGolem|Stone|1\nTrophySGolem|Crystal|1\nTrophySGolem|Obsidian|1\nTrophySGolem|Silver|1\nTrophyCultist|Fenris Claw|1\nTrophyUlv|Scale Hide|1\nTrophyUlv|Wolf Pelt|1\nTrophyCultist_Hildir|Obsidian|1\nTrophyGoblin|Black Metal|1\nTrophyGoblinShaman|Tar|1\nTrophyGoblinBrute|Black Metal|1\nTrophyLox|Lox Pelt|1\nTrophyGrowth|Tar|1\nTrophyGoblinBruteBrosBrute|Lox Pelt|1\nTrophyGoblinBruteBrosShaman|Tar|1\nTrophyBjornUndead|Bear Hide|1\nTrophyBjornUndead|Bear Paw|1\nTrophySeeker|Yggdrasil Wood|1\nTrophyTick|Yggdrasil Wood|1\nTrophySeekerBrute|Black Marble|1\nTrophyDvergr|Black Marble|1\nTrophyDvergr|Mechanical Spring|1\nTrophyDvergr|Dvergr Extractor|1\nTrophyDvergr|Dvergr Lantern|1\nTrophyGjall|Yggdrasil Wood|1\nTrophyGjall|Black Marble|1\nTrophyCharredMelee|Ashwood|1\nTrophyCharredMelee|Charred Bone|1\nTrophyCharredMelee|Charred Skull|1\nTrophyCharredMelee|Warrior Trophy|1\nTrophyCharredArcher|Ashwood|1\nTrophyCharredArcher|Charred Bone|1\nTrophyCharredArcher|Charred Skull|1\nTrophyCharredMage|Bloodgold|1\nTrophyCharredMage|Charred Cogwheel|1\nTrophyMorgen|Grausten|1\nTrophyMorgen|Ashwood|1\nTrophyMorgen|Morgen Sinew|1\nTrophyAsksvin|Grausten|1\nTrophyAsksvin|Asksvin Hide|1\nTrophyAsksvin|Asksvin Neck|1\nTrophyAsksvin|Asksvin Pelvis|1\nTrophyAsksvin|Asksvin Ribcage|1\nTrophyAsksvin|Asksvin Skull|1\nTrophyBlob_Lava|Grausten|1\nTrophyBlob_Lava|Flametal|1\nTrophyBlob_Lava|Molten Core|1\nTrophyVolture|Charred Bone|1\nTrophyVolture|Charred Skull|1\nTrophyFallenValkyrie|Celestial Feather|1\nTrophyFallenValkyrie|Bloodgold|1\nTrophyMoose|Timberwood|1\nTrophyMoose|Moose Hide|1\nTrophyMoose|Moose Sinew|1\nTrophyBarka|Timberwood|1\nTrophyBarka|Ice|1\nTrophyBlob_Frost|Frostcore|1\nTrophyBlob_Frost|Ice|1\nTrophySeal|Seal Pelt|1\nTrophyWrithan|Writhan Roots|1\nTrophyWrithan|Timberwood|1\nTrophyJotunWitch|Ice|1\nTrophyJotunWarrior|Frostcore|1\nTrophyElaking|Elaking Hair Bundle|1", "Managed by BepInEx/config/BuildBeacon.MobRules.txt on the server; edit that file instead. trophyPrefab|material|level, one per line, and trophyPrefab|Stackable for trophies whose every copy counts. Levels add up across a beacon's trophies; see LevelPercents."); DevMode = ConfigUtil.Local(cfg, "5. Dev", "DevMode", def: false, "For mod development. When on, spawning into a world this machine hosts turns on devcommands, god mode and debug fly. Does nothing on dedicated servers or when joining someone else's world."); VerboseLogging = ConfigUtil.Local(cfg, "5. Dev", "VerboseLogging", def: false, "For mod development. Logs the details of registering the pieces (materials, effects, snap points), how each trophy is fitted in its alcove, and the [diag] lines (placements, snapping, slow inventory changes). Off: only what players need."); cfg.SettingChanged += delegate { this.SettingChanged?.Invoke(); }; } } public class BeaconController : MonoBehaviour, Interactable, Hoverable { private sealed class Shard { public Transform T; public Vector3 RestPos; public Vector3 AxisLocal; public Quaternion RestRot; public float Speed; public float Period; public float Phase; public float Angle; } private const string KeyTrophies = "xai_beacon_trophies"; private const float InteractRange = 6f; private const string RpcRequestOpen = "xai_beacon_request_open"; private const string RpcOpenResponse = "xai_beacon_open_response"; private const string RpcRequestOwn = "xai_beacon_request_own"; private const float QueueTimeout = 2f; private const float DropHeight = 1.2f; public CircleProjector m_areaMarker; public GameObject m_activeEffect; public TrophyKind m_ownSlotKind = TrophyKind.Mob; public int m_ownSlotCount; private ZNetView _nview; private BeaconTrophyDisplay _display; private bool _inUse; private ItemData _queuedItem; private float _queuedAt; private readonly Dictionary<string, int> _trophies = new Dictionary<string, int>(); private readonly Dictionary<string, int> _effective = new Dictionary<string, int>(); private readonly List<(string prefab, BossHolder holder)> _bosses = new List<(string, BossHolder)>(); private readonly List<MobRack> _racks = new List<MobRack>(); private readonly List<(MobRack rack, int slot, string prefab, bool counted)> _rackTrophies = new List<(MobRack, int, string, bool)>(); private static int s_toolFrame = -1; private static bool s_holdingTool; private CraftingStation _station; private const float SpinDegreesPerSecond = 18f; private const float BobAmplitude = 0.02f; private const float BobPeriod = 4f; private const float MotionEaseSeconds = 1.5f; private Transform _crystal; private Vector3 _crystalRestPos; private Quaternion _crystalRestRot; private float _bobPhase; private float _motion; private float _spin; private bool _lit; private const string ShardMarker = "_shard_"; private const float ShardBobAmplitude = 0.05f; private readonly List<Shard> _shards = new List<Shard>(); private const string CoreMaterial = "BeaconCore"; private static readonly int ColorId = Shader.PropertyToID("_Color"); private static readonly int EmissionId = Shader.PropertyToID("_EmissionColor"); private Renderer _coreRenderer; private int _coreIndex = -1; private bool _coreSearched; private bool? _coreLit; private MaterialPropertyBlock _coreBlock; public bool IsGreat => m_ownSlotKind == TrophyKind.Boss; public bool IsValid { get { if ((Object)(object)_nview != (Object)null) { return _nview.IsValid(); } return false; } } public IReadOnlyDictionary<string, int> Trophies => _effective; public IReadOnlyList<(string prefab, BossHolder holder)> BossEntries => _bosses; public int BossCount => _bosses.Count; public int MobCount => _trophies.Where((KeyValuePair<string, int> kv) => !DiscountRules.IsBossTrophy(kv.Key)).Sum((KeyValuePair<string, int> kv) => kv.Value); public int TrophyCount => _effective.Values.Sum(); public int HolderCount { get; private set; } public int RackCount => _racks.Count; public IReadOnlyList<(MobRack rack, int slot, string prefab, bool counted)> RackTrophies => _rackTrophies; public int RackSlots => RackCount * 4; public int RackTrophyCount => _rackTrophies.Count; public string MobSlotsText => $"{MobCount + RackTrophyCount}/{MobSlots + RackSlots}"; public int Level => DiscountRules.LevelFor(OwnBossLevels + HolderCount + RackCount); public int MaxLevel => BuildBeaconPlugin.Cfg.MaxLevel.Value; public float Radius { get { if (!IsGreat) { return DiscountRules.RadiusFor(Level); } return DiscountRules.GreatRadiusFor(Level); } } public int BossSlots => BuildBeaconPlugin.Cfg.BossSlots.Value; public int MobSlots { get { if (!IsGreat) { return BuildBeaconPlugin.Cfg.BeaconMobSlots.Value; } return 0; } } public int OwnBossSlots { get { if (!IsGreat) { return 0; } return m_ownSlotCount; } } public int OwnBossCount => _trophies.Where((KeyValuePair<string, int> kv) => DiscountRules.IsBossTrophy(kv.Key)).Sum((KeyValuePair<string, int> kv) => kv.Value); private int OwnBossLevels { get { if (!IsGreat) { return 0; } return _bosses.Count(((string prefab, BossHolder holder) b) => (Object)(object)b.holder == (Object)null); } } public static bool HoldingBuildTool { get { if (s_toolFrame == Time.frameCount) { return s_holdingTool; } s_toolFrame = Time.frameCount; Player localPlayer = Player.m_localPlayer; ItemData val = (((Object)(object)localPlayer != (Object)null) ? ((Humanoid)localPlayer).GetRightItem() : null); s_holdingTool = val != null && (Object)(object)val.m_shared.m_buildPieces != (Object)null; return s_holdingTool; } } public string PieceNameKey { get { if (!IsGreat) { return "$piece_xai_beacon"; } return "$piece_xai_great_beacon"; } } public IEnumerable<string> SlotsOf(TrophyKind kind) { return (from kv in _trophies where DiscountRules.KindOf(kv.Key) == kind || (kind == TrophyKind.Mob && DiscountRules.KindOf(kv.Key) == TrophyKind.None) orderby kv.Key select kv).SelectMany((KeyValuePair<string, int> kv) => Enumerable.Repeat(kv.Key, kv.Value)); } public bool InRangeOf(Player p) { //IL_000f: 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) if ((Object)(object)p != (Object)null) { return Vector3.Distance(((Component)p).transform.position, ((Component)this).transform.position) <= 6f; } return false; } private void Awake() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) _nview = ((Component)this).GetComponent<ZNetView>(); if (IsValid) { _display = new BeaconTrophyDisplay(((Component)this).transform, IsGreat ? new Vector2?(BeaconTrophyDisplay.GreatTrophyFit) : ((Vector2?)null)); WearNTear component = ((Component)this).GetComponent<WearNTear>(); if ((Object)(object)component != (Object)null) { component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyed)); } _nview.Register<long>("xai_beacon_request_open", (Action<long, long>)RPC_RequestOpen); _nview.Register<bool>("xai_beacon_open_response", (Action<long, bool>)RPC_OpenResponse); _nview.Register("xai_beacon_request_own", (Action<long>)RPC_RequestOwn); _crystal = ((Component)this).transform.Find("crystal"); if ((Object)(object)_crystal != (Object)null) { _crystalRestPos = _crystal.localPosition; _crystalRestRot = _crystal.localRotation; _bobPhase = Random.value * 4f; FindShards(); } LoadFromZdo(); BeaconRegistry.Register(this); ((MonoBehaviour)this).InvokeRepeating("LoadFromZdo", 1f, 1f); } } private void OnDestroy() { BeaconRegistry.Unregister(this); } private void Update() { UpdateRing(); AnimateCrystal(); } private void UpdateRing() { if (!((Object)(object)m_areaMarker == (Object)null)) { bool flag = BuildBeaconPlugin.Cfg.ShowRadius.Value && HoldingBuildTool; if (flag) { m_areaMarker.m_radius = Radius; m_areaMarker.m_nrOfSegments = Mathf.Max(20, Mathf.RoundToInt(Radius * 2f)); } if (((Component)m_areaMarker).gameObject.activeSelf != flag) { ((Component)m_areaMarker).gameObject.SetActive(flag); } } } private void OnDestroyed() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) if (!IsValid || !_nview.IsOwner()) { return; } LoadFromZdo(); int num = 0; foreach (KeyValuePair<string, int> item in _trophies.ToList()) { num += DropTrophy(item.Key, item.Value); _trophies.Remove(item.Key); } if (num > 0) { SaveToZdo(); BuildBeaconPlugin.Log.LogInfo((object)$"Beacon destroyed at {((Component)this).transform.position:F1}: dropped {num} trophies"); } } private int DropTrophy(string prefab, int count) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) return SpawnItems(prefab, count, ((Component)this).transform.position + Vector3.up * 1.2f); } public static int SpawnItems(string prefab, int count, Vector3 at) { //IL_0050: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) ItemDrop val = DiscountRules.ItemDropFor(prefab); if ((Object)(object)val == (Object)null) { BuildBeaconPlugin.Log.LogWarning((object)$"No item prefab \"{prefab}\"; {count} lost"); return 0; } int num = Mathf.Max(1, val.m_itemData.m_shared.m_maxStackSize); int num2 = count; while (num2 > 0) { int num3 = Mathf.Min(num2, num); Vector3 val2 = Random.insideUnitSphere * 0.3f; val2.y = Mathf.Abs(val2.y); ItemDrop component = Object.Instantiate<GameObject>(((Component)val).gameObject, at + val2, Quaternion.identity).GetComponent<ItemDrop>(); component.SetStack(num3); ItemDrop.OnCreateNew(component, false); num2 -= num3; } return count; } public void Resync() { LoadFromZdo(); } private void RebuildEffective() { _effective.Clear(); _bosses.Clear(); foreach (KeyValuePair<string, int> trophy in _trophies) { if (trophy.Value > 0 && !DiscountRules.IsBossTrophy(trophy.Key)) { _effective[trophy.Key] = trophy.Value; } } List<(string, BossHolder)> list = new List<(string, BossHolder)>(); foreach (KeyValuePair<string, int> trophy2 in _trophies) { if (trophy2.Value > 0 && DiscountRules.IsBossTrophy(trophy2.Key)) { list.Add((trophy2.Key, null)); } } int num = 0; foreach (BossHolder item in BossHolder.All) { if (!((Object)(object)item == (Object)null) && item.IsValid && !((Object)(object)item.LinkedBeacon != (Object)(object)this)) { num++; if (item.HasTrophy) { list.Add((item.Trophy, item)); } } } HolderCount = num; RebuildRacks(); foreach (var c in from tuple in list orderby DiscountRules.BossOrder(tuple.prefab), (!((Object)(object)tuple.holder == (Object)null)) ? 1 : 0 select tuple) { if (_bosses.Count >= BossSlots) { break; } if (DiscountRules.IsBossTrophy(c.Item1) && !_bosses.Any(((string prefab, BossHolder holder) b) => b.prefab == c.Item1)) { _bosses.Add(c); _effective[c.Item1] = 1; } } } private void RebuildRacks() { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) _racks.Clear(); _rackTrophies.Clear(); foreach (MobRack item in MobRack.All) { if ((Object)(object)item != (Object)null && item.IsValid && (Object)(object)item.LinkedBeacon == (Object)(object)this) { _racks.Add(item); } } Vector3 here = ((Component)this).transform.position; _racks.Sort(delegate(MobRack a, MobRack b) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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) Vector3 val = ((Component)a).transform.position - here; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; val = ((Component)b).transform.position - here; return sqrMagnitude.CompareTo(((Vector3)(ref val)).sqrMagnitude); }); foreach (MobRack rack in _racks) { for (int num = 0; num < 4; num++) { string text = rack.Trophy(num); if (text.Length != 0) { int value; bool flag = DiscountRules.KindOf(text) == TrophyKind.Mob && (DiscountRules.IsStackable(text) || !_effective.TryGetValue(text, out value) || value <= 0); if (flag) { _effective.TryGetValue(text, out var value2); _effective[text] = value2 + 1; } _rackTrophies.Add((rack, num, text, flag)); } } } } public bool CountsRackSlot(MobRack rack, int slot) { foreach (var rackTrophy in _rackTrophies) { if ((Object)(object)rackTrophy.rack == (Object)(object)rack && rackTrophy.slot == slot) { return rackTrophy.counted; } } return false; } public bool RackAddsLevel(MobRack rack) { int num = MaxLevel - 1 - OwnBossLevels - HolderCount; int num2 = _racks.IndexOf(rack); if (num2 >= 0) { return num2 < num; } return false; } private bool NetworkHas(string prefab, MobRack exceptRack = null, int exceptSlot = -1) { if (_trophies.TryGetValue(prefab, out var value) && value > 0) { return true; } foreach (var rackTrophy in _rackTrophies) { if (rackTrophy.prefab == prefab && (!((Object)(object)rackTrophy.rack == (Object)(object)exceptRack) || rackTrophy.slot != exceptSlot)) { return true; } } return false; } public string RackInsertBlockedReason(string prefab, MobRack rack, int slot) { RebuildEffective(); switch (DiscountRules.KindOf(prefab)) { case TrophyKind.Boss: return "$xai_rack_mob_only"; case TrophyKind.Mob: if (DiscountRules.IsStackable(prefab) || !NetworkHas(prefab, rack, slot)) { return null; } return "$xai_beacon_mob_duplicate"; default: return "$xai_beacon_not_a_trophy"; } } public bool CountsHolder(BossHolder holder) { return _bosses.Any(((string prefab, BossHolder holder) b) => (Object)(object)b.holder == (Object)(object)holder); } public string HolderInsertBlockedReason(string prefab, BossHolder holder) { RebuildEffective(); List<(string, BossHolder)> list = _bosses.Where(((string prefab, BossHolder holder) b) => (Object)(object)b.holder != (Object)(object)holder || (Object)(object)holder == (Object)null).ToList(); if (list.Any<(string, BossHolder)>(((string prefab, BossHolder holder) b) => b.prefab == prefab)) { return "$xai_beacon_boss_duplicate"; } if (list.Count >= BossSlots) { return "$xai_beacon_boss_full"; } return null; } public void PokeStation() { if ((Object)(object)_station == (Object)null) { _station = ((Component)this).GetComponent<CraftingStation>(); } if ((Object)(object)_station != (Object)null) { _station.PokeInUse(); } } private void LoadFromZdo() { _trophies.Clear(); if (ZdoUtil.TryGetPackage(_nview, "xai_beacon_trophies", out var pkg)) { int num = pkg.ReadInt(); for (int i = 0; i < num; i++) { _trophies[pkg.ReadString()] = pkg.ReadInt(); } } RebuildEffective(); UpdateVisuals(); } private void SaveToZdo() { ZdoUtil.SetPackage(_nview, "xai_beacon_trophies", delegate(ZPackage pkg) { pkg.Write(_trophies.Count); foreach (KeyValuePair<string, int> trophy in _trophies) { pkg.Write(trophy.Key); pkg.Write(trophy.Value); } }); RebuildEffective(); UpdateVisuals(); } private void UpdateVisuals() { UpdateRing(); bool flag = (_lit = TrophyCount > 0); if ((Object)(object)m_activeEffect != (Object)null && m_activeEffect.activeSelf != flag) { m_activeEffect.SetActive(flag); } SetCoreLit(flag); _display?.Refresh(_trophies); } private void AnimateCrystal() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_crystal == (Object)null)) { float num = (_lit ? 1f : 0f); if (_motion != 0f || num != 0f) { _motion = Mathf.MoveTowards(_motion, num, Time.deltaTime / 1.5f); float num2 = Mathf.SmoothStep(0f, 1f, _motion); _spin = (_spin + 18f * num2 * Time.deltaTime) % 360f; float num3 = Mathf.Sin((Time.time + _bobPhase) * ((float)Math.PI / 2f)) * 0.02f * num2; _crystal.localPosition = _crystalRestPos + Vector3.up * num3; _crystal.localRotation = _crystalRestRot * Quaternion.Euler(0f, _spin, 0f); AnimateShards(num2); } } } private void FindShards() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_0071: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) Transform[] componentsInChildren = ((Component)_crystal).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name.IndexOf("_shard_", StringComparison.Ordinal) >= 0) { MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); Vector3 val2; if (!((Object)(object)component != (Object)null) || !((Object)(object)component.sharedMesh != (Object)null)) { val2 = Vector3.up; } else { Bounds bounds = component.sharedMesh.bounds; val2 = ((Bounds)(ref bounds)).size; } Vector3 val3 = val2; Vector3 axisLocal = ((val3.x >= val3.y && val3.x >= val3.z) ? Vector3.right : ((val3.y >= val3.z) ? Vector3.up : Vector3.forward)); int count = _shards.Count; _shards.Add(new Shard { T = val, RestPos = val.localPosition, RestRot = val.localRotation, AxisLocal = axisLocal, Speed = (40f + 11f * (float)count) * ((count % 2 == 0) ? 1f : (-1f)), Period = 2.5f + 0.37f * (float)count, Phase = 1.7f * (float)count + Random.value }); } } } private void AnimateShards(float ease) { //IL_0079: 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) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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 (Shard shard in _shards) { if (!((Object)(object)shard.T == (Object)null)) { shard.Angle = (shard.Angle + shard.Speed * ease * Time.deltaTime) % 360f; float num = Mathf.Sin((Time.time + shard.Phase) * ((float)Math.PI * 2f / shard.Period)) * 0.05f * ease; shard.T.localRotation = shard.RestRot * Quaternion.AngleAxis(shard.Angle, shard.AxisLocal); shard.T.localPosition = shard.RestPos + shard.RestRot * shard.AxisLocal * num; } } } private void SetCoreLit(bool lit) { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) if (_coreLit == lit) { return; } if (!_coreSearched) { _coreSearched = true; MeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val in componentsInChildren) { Material[] sharedMaterials = ((Renderer)val).sharedMaterials; for (int j = 0; j < sharedMaterials.Length; j++) { if ((Object)(object)sharedMaterials[j] != (Object)null && ((Object)sharedMaterials[j]).name.StartsWith("BeaconCore")) { _coreRenderer = (Renderer)(object)val; _coreIndex = j; break; } } if ((Object)(object)_coreRenderer != (Object)null) { break; } } if ((Object)(object)_coreRenderer == (Object)null) { BuildBeaconPlugin.Log.LogWarning((object)"Beacon: no BeaconCore material on the model; the crystal's core cannot follow the lit state"); } } _coreLit = lit; if (!((Object)(object)_coreRenderer == (Object)null)) { if (_coreBlock == null) { _coreBlock = new MaterialPropertyBlock(); } _coreBlock.Clear(); if (!lit) { Material val2 = _coreRenderer.sharedMaterials[_coreIndex]; Color val3 = (((Object)(object)val2 != (Object)null && val2.HasProperty(ColorId)) ? val2.GetColor(ColorId) : Color.white); val3.a = 0f; _coreBlock.SetColor(ColorId, val3); _coreBlock.SetColor(EmissionId, Color.black); } _coreRenderer.SetPropertyBlock(_coreBlock, _coreIndex); } } private void RPC_RequestOpen(long uid, long playerID) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (_nview.IsOwner()) { if (_inUse && uid != ZNet.GetUID()) { _nview.InvokeRPC(uid, "xai_beacon_open_response", new object[1] { false }); return; } ZDOMan.instance.ForceSendZDO(uid, _nview.GetZDO().m_uid); _nview.GetZDO().SetOwner(uid); _nview.InvokeRPC(uid, "xai_beacon_open_response", new object[1] { true }); } } private void RPC_OpenResponse(long uid, bool granted) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { if (granted) { BeaconUI.Open(this); } else { ((Character)localPlayer).Message((MessageType)2, "$msg_inuse", 0, (Sprite)null, false); } } } private void RPC_RequestOwn(long sender) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (_nview.IsOwner() && (!_inUse || sender == ZNet.GetUID())) { ZDOMan.instance.ForceSendZDO(sender, _nview.GetZDO().m_uid); _nview.GetZDO().SetOwner(sender); } } public void SetInUse(bool inUse) { _inUse = inUse; } public string InsertBlockedReason(string prefab) { switch (DiscountRules.KindOf(prefab)) { case TrophyKind.Boss: { if (!IsGreat) { return "$xai_beacon_boss_use_holder"; } RebuildEffective(); string key = DiscountRules.TrophyKey(prefab); if (_bosses.Any(((string prefab, BossHolder holder) b) => DiscountRules.TrophyKey(b.prefab) == key) || _trophies.Any((KeyValuePair<string, int> kv) => kv.Value > 0 && DiscountRules.TrophyKey(kv.Key) == key)) { return "$xai_beacon_boss_duplicate"; } if (OwnBossCount >= OwnBossSlots) { return "$xai_beacon_boss_full"; } return null; } case TrophyKind.Mob: if (IsGreat) { return "$xai_great_beacon_mob_refused"; } if (!DiscountRules.IsStackable(prefab) && NetworkHas(prefab)) { return "$xai_beacon_mob_duplicate"; } if (MobCount >= MobSlots) { return "$xai_beacon_mob_full"; } return null; default: return "$xai_beacon_not_a_trophy"; } } public bool TryInsertTrophy(Player p, ItemData item) { if ((Object)(object)p == (Object)null || item == null || (Object)(object)item.m_dropPrefab == (Object)null || !IsValid) { return false; } if (!_nview.IsOwner()) { ((Character)p).Message((MessageType)2, "$xai_beacon_busy", 0, (Sprite)null, false); return false; } return InsertNow(p, item); } private bool InsertNow(Player p, ItemData item) { string name = ((Object)item.m_dropPrefab).name; if (DiscountRules.KindOf(name) == TrophyKind.None) { return false; } LoadFromZdo(); string text = InsertBlockedReason(name); if (text != null) { ((Character)p).Message((MessageType)2, text, 0, (Sprite)null, false); return false; } _trophies.TryGetValue(name, out var value); _trophies[name] = value + 1; SaveToZdo(); ((Humanoid)p).GetInventory().RemoveOneItem(item); return true; } private void UpdateQueued() { if (_queuedItem == null) { ((MonoBehaviour)this).CancelInvoke("UpdateQueued"); return; } Player localPlayer = Player.m_localPlayer; if (!_nview.IsOwner()) { if (!(Time.time - _queuedAt < 2f)) { ((MonoBehaviour)this).CancelInvoke("UpdateQueued"); _queuedItem = null; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)2, "$msg_inuse", 0, (Sprite)null, false); } } } else { ((MonoBehaviour)this).CancelInvoke("UpdateQueued"); ItemData queuedItem = _queuedItem; _queuedItem = null; if ((Object)(object)localPlayer != (Object)null && ((Humanoid)localPlayer).GetInventory().ContainsItem(queuedItem)) { InsertNow(localPlayer, queuedItem); } } } public bool TryInsertTrophy(Player p, string prefab) { ItemData val = ((IEnumerable<ItemData>)((Humanoid)p).GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => (Object)(object)i.m_dropPrefab != (Object)null && ((Object)i.m_dropPrefab).name == prefab)); if (val != null) { return TryInsertTrophy(p, val); } return false; } public bool TryRemoveTrophy(Player p, string prefab) { if (!_trophies.TryGetValue(prefab, out var value) || value <= 0) { return false; } ItemDrop val = DiscountRules.ItemDropFor(prefab); if ((Object)(object)val == (Object)null) { return false; } if (!((Humanoid)p).GetInventory().CanAddItem(((Component)val).gameObject, 1)) { ((Character)p).Message((MessageType)2, "$msg_noroom", 0, (Sprite)null, false); return false; } if (!_nview.IsOwner()) { ((Character)p).Message((MessageType)2, "$xai_beacon_busy", 0, (Sprite)null, false); return false; } LoadFromZdo(); if (!_trophies.TryGetValue(prefab, out value) || value <= 0) { return false; } if (value == 1) { _trophies.Remove(prefab); } else { _trophies[prefab] = value - 1; } SaveToZdo(); ((Humanoid)p).GetInventory().AddItem(((Component)val).gameObject, 1); return true; } private bool WardAllowsEdit() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false); } public bool Interact(Humanoid user, bool hold, bool alt) { if (hold || !IsValid || (Object)(object)Game.instance == (Object)null) { return false; } if (!WardAllowsEdit()) { return true; } _nview.InvokeRPC("xai_beacon_request_open", new object[1] { Game.instance.GetPlayerProfile().GetPlayerID() }); return true; } public bool UseItem(Humanoid user, ItemData item) { Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val == (Object)null || item == null || (Object)(object)item.m_dropPrefab == (Object)null || !IsValid) { return false; } string name = ((Object)item.m_dropPrefab).name; if (DiscountRules.KindOf(name) == TrophyKind.None) { return false; } if (!WardAllowsEdit()) { return true; } string text = InsertBlockedReason(name); if (text != null) { ((Character)val).Message((MessageType)2, text, 0, (Sprite)null, false); return true; } if (_nview.IsOwner()) { InsertNow(val, item); return true; } _nview.InvokeRPC("xai_beacon_request_own", Array.Empty<object>()); _queuedItem = item; _queuedAt = Time.time; ((MonoBehaviour)this).CancelInvoke("UpdateQueued"); ((MonoBehaviour)this).InvokeRepeating("UpdateQueued", 0f, 0.1f); return true; } public string GetHoverText() { return Localization.instance.Localize($"{PieceNameKey}\n$xai_beacon_level {Level}/{MaxLevel} $xai_beacon_radius {Radius:0}m $xai_beacon_boss {(IsGreat ? $"{OwnBossCount}/{OwnBossSlots}" : BossCount.ToString())} $xai_beacon_mob {MobSlotsText}\n" + "[<color=yellow><b>$KEY_Use</b></color>] $xai_beacon_open"); } public string GetHoverName() { return Localization.instance.Localize(PieceNameKey); } public float GetHoverOffset() { return 0f; } } public static class BeaconRegistry { private static readonly HashSet<BeaconController> Beacons = new HashSet<BeaconController>(); public static IEnumerable<BeaconController> All => Beacons; public static void Register(BeaconController b) { Beacons.Add(b); } public static void Unregister(BeaconController b) { Beacons.Remove(b); } public static IEnumerable<BeaconController> InRange(Vector3 pos) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Beacons.Where((BeaconController b) => (Object)(object)b != (Object)null && b.IsValid && Vector3.Distance(((Component)b).transform.position, pos) <= b.Radius); } public static Requirement[] GetEffectiveRequirements(Piece piece, Vector3 pos) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return GetEffectiveRequirements(piece.m_resources, pos); } public static Requirement[] GetEffectiveRequirements(Requirement[] source, Vector3 pos, List<DiscountSavings.Step> plan = null, List<CostLine> lines = null) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Expected O, but got Unknown if (source == null || !BuildBeaconPlugin.Cfg.Enabled.Value) { return source; } List<BeaconController> list = InRange(pos).ToList(); if (list.Count == 0) { return source; } Requirement[] array = (Requirement[])(object)new Requirement[source.Length]; bool flag = false; bool flag2 = false; for (int i = 0; i < array.Length; i++) { Requirement src = source[i]; int num = src.m_amount; bool bossFree = false; float num2 = 0f; int streak = 0; bool flag3 = list.Any((BeaconController b) => DiscountRules.BossCovers(b.Trophies, src.m_resItem)); if (flag3 && DiscountRules.BossMakesFree) { num = 0; bossFree = true; } else { if (flag3) { num2 = DiscountRules.BossPercent; } else { bool flag4 = BuildBeaconPlugin.Cfg.Stacking.Value == StackMode.Sum; int num3 = 0; float num4 = 0f; foreach (BeaconController item in list) { int num5 = DiscountRules.MobLevel(item.Trophies, src.m_resItem); if (num5 > 0) { num3 += num5; num4 = Mathf.Max(num4, DiscountRules.PercentForLevel(num5)); } } if (num3 > 0) { num2 = (flag4 ? DiscountRules.PercentForLevel(num3) : num4); } } if (num2 > 0f) { float exact = DiscountRules.ExactMobCost(src.m_amount, num2); num = DiscountRules.RoundCost(exact); if (plan != null) { int count = plan.Count; num = DiscountSavings.Apply(src.m_resItem, exact, num, num2, plan); flag2 |= plan.Count > count; if (plan.Count > count) { streak = plan[plan.Count - 1].Streak; } } } } flag |= num != src.m_amount; lines?.Add(new CostLine { Item = src.m_resItem, Base = src.m_amount, Amount = num, Percent = num2, BossFree = bossFree, Streak = streak }); array[i] = new Requirement { m_resItem = src.m_resItem, m_amount = num, m_amountPerLevel = src.m_amountPerLevel, m_recover = src.m_recover }; } if (!(flag || flag2)) { return source; } return array; } } public sealed class BeaconTrophyDisplay { public const int AlcoveCount = 4; public const string AttachPrefix = "attach_"; private static readonly Quaternion StandAttachRotation = new Quaternion(0f, 0.7071068f, 0.7071068f, 0f); private static readonly Vector3 FitBox = new Vector3(0.24f, 0.34f, 0.28f); private const float MaxUpscale = 1.5f; private readonly Transform[] _mounts; private readonly string[] _shown; private readonly GameObject[] _visuals; private readonly Vector2? _shrinkTo; private TrophyPlacement _placement; private bool _shrinking; private static readonly Dictionary<string, float> GreatTrophyScales = new Dictionary<string, float> { { "TrophyEikthyr", 1f }, { "TrophyTheElder", 1f }, { "TrophyDragonQueen", 1f }, { "TrophyBonemass", 0.75f }, { "TrophySeekerQueen", 0.65f }, { "TrophyGoblinKing", 0.65f }, { "TrophyFader", 0.65f } }; public const float GreatTrophyMaxScale = 0.9f; public static readonly Vector2 GreatTrophyFit = new Vector2(4.5f, 4.5f); private static readonly Dictionary<string, int> GreatTrophyAlcoves = new Dictionary<string, int> { { "TrophyEikthyr", 0 }, { "TrophyTheElder", 1 }, { "TrophyBonemass", 5 }, { "TrophyDragonQueen", 4 }, { "TrophyGoblinKing", 3 }, { "TrophySeekerQueen", 6 }, { "TrophyFader", 2 } }; private static float? GreatScaleFor(string prefab) { string text = DiscountRules.TrophyKey(prefab); foreach (KeyValuePair<string, float> greatTrophyScale in GreatTrophyScales) { if (DiscountRules.TrophyKey(greatTrophyScale.Key) == text) { return greatTrophyScale.Value; } } return null; } private static int GreatAlcoveFor(string prefab) { string text = DiscountRules.TrophyKey(prefab); foreach (KeyValuePair<string, int> greatTrophyAlcofe in GreatTrophyAlcoves) { if (DiscountRules.TrophyKey(greatTrophyAlcofe.Key) == text) { return greatTrophyAlcofe.Value; } } return -1; } public static List<string> ChooseGreat(IReadOnlyDictionary<string, int> trophies, int count) { string[] array = new string[count]; List<string> list = new List<string>(); foreach (string item in (from kv in trophies where kv.Value > 0 select kv.Key).OrderBy(DiscountRules.BossOrder)) { int num = GreatAlcoveFor(item); if (num >= 0 && num < count && array[num] == null) { array[num] = item; } else { list.Add(item); } } foreach (string item2 in list) { int num2 = Array.IndexOf(array, null); if (num2 < 0) { break; } array[num2] = item2; } return array.ToList(); } public BeaconTrophyDisplay(Transform beacon, Vector2? shrinkTo = null) { List<Transform> list = new List<Transform>(); Transform item; while ((Object)(object)(item = beacon.Find("attach_" + list.Count)) != (Object)null) { list.Add(item); } if (list.Count == 0) { list.AddRange((IEnumerable<Transform>)(object)new Transform[4]); } _mounts = list.ToArray(); _shown = new string[_mounts.Length]; _visuals = (GameObject[])(object)new GameObject[_mounts.Length]; _shrinkTo = shrinkTo; } public static List<string> Choose(IReadOnlyDictionary<string, int> trophies, int count = 4) { List<string> source = (from kv in trophies where kv.Value > 0 select kv.Key).ToList(); List<string> list = source.Where(DiscountRules.IsBossTrophy).OrderBy(DiscountRules.BossOrder).ToList(); if (list.Count > count) { list = list.Skip(list.Count - count).ToList(); } IOrderedEnumerable<string> second = source.Where((string t) => !DiscountRules.IsBossTrophy(t)).OrderBy<string, string>((string t) => t, StringComparer.Ordinal); return list.Concat(second).Take(count).ToList(); } public void Refresh(IReadOnlyDictionary<string, int> trophies) { List<string> list = (_shrinkTo.HasValue ? ChooseGreat(trophies, _mounts.Length) : Choose(trophies, _mounts.Length)); TrophyPlacement value = BuildBeaconPlugin.Cfg.Placement.Value; bool flag = _shrinkTo.HasValue && BuildBeaconPlugin.Cfg.ShrinkGreatBeaconTrophies.Value; bool flag2 = (_shrinkTo.HasValue ? (flag != _shrinking) : (value != _placement)); _placement = value; _shrinking = flag; for (int i = 0; i < _mounts.Length; i++) { string text = ((i < list.Count) ? list[i] : null); if (!flag2 && text == _shown[i] && (text == null || (Object)(object)_visuals[i] != (Object)null)) { continue; } if ((Object)(object)_visuals[i] != (Object)null) { Object.Destroy((Object)(object)_visuals[i]); } _visuals[i] = null; _shown[i] = text; if (text == null || !((Object)(object)_mounts[i] != (Object)null)) { continue; } float? num = (flag ? GreatScaleFor(text) : ((float?)null)); GameObject[] visuals = _visuals; int num2 = i; object obj; if (_shrinkTo.HasValue) { if (!num.HasValue) { obj = (flag ? Build(_mounts[i], text, TrophyPlacement.Mounted, _shrinkTo, 0.9f) : Build(_mounts[i], text, TrophyPlacement.Mounted)); } else { Transform mount = _mounts[i]; float? fixedScale = num; obj = Build(mount, text, TrophyPlacement.Mounted, null, 1.5f, fixedScale); } } else { obj = Build(_mounts[i], text, value); } visuals[num2] = (GameObject)obj; } } internal static GameObject Build(Transform mount, string prefabName, TrophyPlacement placement, Vector2? faceFit = null, float maxScale = 1.5f, float? fixedScale = null) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00b3: 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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefabName) : null); if ((Object)(object)val == (Object)null) { BuildBeaconPlugin.Log.LogWarning((object)("Trophy display: no item prefab \"" + prefabName + "\"")); return null; } Transform val2 = val.transform.Find("attach"); if ((Object)(object)val2 == (Object)null) { BuildBeaconPlugin.Log.LogWarning((object)("Trophy display: \"" + prefabName + "\" has no attach child")); return null; } Transform val3 = val2.Find("attachobj"); Transform obj = (((Object)(object)val3 != (Object)null) ? val3 : val2); GameObject val4 = new GameObject("trophy_" + prefabName); val4.transform.SetParent(mount, false); Transform transform = new GameObject("pivot").transform; transform.SetParent(val4.transform, false); transform.localRotation = StandAttachRotation; GameObject val5 = Object.Instantiate<GameObject>(((Component)obj).gameObject, transform, false); val5.transform.localPosition = val2.localPosition; val5.transform.localRotation = val2.localRotation; val5.transform.localScale = val2.localScale; Collider[] componentsInChildren = val5.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } Rigidbody[] componentsInChildren2 = val5.GetComponentsInChildren<Rigidbody>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[i]); } if (!TryMeshBounds(val5, val4.transform, out var bounds)) { BuildBeaconPlugin.Log.LogWarning((object)("Trophy display: \"" + prefabName + "\" has no meshes to show")); return val4; } Vector3 size = ((Bounds)(ref bounds)).size; float num = (fixedScale.HasValue ? fixedScale.Value : (faceFit.HasValue ? Mathf.Min(new float[3] { maxScale, faceFit.Value.x / Mathf.Max(size.x, 0.001f), faceFit.Value.y / Mathf.Max(size.y, 0.001f) }) : ((placement == TrophyPlacement.Inset) ? Mathf.Min(new float[4] { 1.5f, FitBox.x / Mathf.Max(size.x, 0.001f), FitBox.y / Mathf.Max(size.y, 0.001f), FitBox.z / Mathf.Max(size.z, 0.001f) }) : 1f))); val4.transform.localScale = Vector3.one * num; val4.transform.localPosition = (0f - num) * new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).center.y, ((Bounds)(ref bounds)).min.z); BuildBeaconPlugin.Verbose(string.Format("Trophy display: {0} in {1} ({2}), size {3} scaled x{4:F2}", prefabName, ((Object)mount).name, fixedScale.HasValue ? "Fixed" : (faceFit.HasValue ? "Face" : placement.ToString()), ((Vector3)(ref size)).ToString("F2"), num)); return val4; } private static bool TryMeshBounds(GameObject root, Transform space, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); bool flag = false; Matrix4x4 worldToLocalMatrix = space.worldToLocalMatrix; Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); Vector3 val5 = default(Vector3); foreach (Renderer val in componentsInChildren) { Mesh val2 = null; SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null); if (val3 != null) { val2 = val3.sharedMesh; } else if (val is MeshRenderer) { MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); if ((Object)(object)component != (Object)null) { val2 = component.sharedMesh; } } if ((Object)(object)val2 == (Object)null) { continue; } Matrix4x4 val4 = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix; Bounds bounds2 = val2.bounds; for (int j = 0; j < 8; j++) { ((Vector3)(ref val5))..ctor(((j & 1) == 0) ? (-1f) : 1f, ((j & 2) == 0) ? (-1f) : 1f, ((j & 4) == 0) ? (-1f) : 1f); Vector3 val6 = ((Matrix4x4)(ref val4)).MultiplyPoint3x4(((Bounds)(ref bounds2)).center + Vector3.Scale(((Bounds)(ref bounds2)).extents, val5)); if (!flag) { bounds = new Bounds(val6, Vector3.zero); flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val6); } } } return flag; } } internal class BeaconUI : MonoBehaviour { private enum Tab { Trophies, Discounts } private sealed class RowHover : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler { private static readonly Color Grey = new Color(1f, 1f, 1f, 0.2f); private static readonly Color Red = new Color(1f, 0.6f, 0.6f, 0.45f); public Image Square; public bool CtrlRemoves = true; private bool _over; public void OnPointerEnter(PointerEventData e) { _over = true; ((Behaviour)Square).enabled = true; Tint(); } public void OnPointerExit(PointerEventData e) { _over = false; ((Behaviour)Square).enabled = false; } private void OnDisable() { _over = false; if ((Object)(object)Square != (Object)null) { ((Behaviour)Square).enabled = false; } } private void Update() { if (_over) { Tint(); } } private void Tint() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) ((Graphic)Square).color = ((CtrlRemoves && CtrlHeld()) ? Red : Grey); } } private sealed class HoverTarget : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler { public string Topic; public string Text; public List<HoverTrophy> Trophies = new List<HoverTrophy>(); public RectTransform Anchor; public void OnPointerEnter(PointerEventData eventData) { if ((Object)(object)_instance != (Object)null) { _instance.ShowHover(this); } } public void OnPointerExit(PointerEventData eventData) { if ((Object)(object)_instance != (Object)null) { _instance.HideHover(this); } } private void OnDisable() { if ((Object)(object)_instance != (Object)null) { _instance.HideHover(this); } } } private struct HoverTrophy { public Sprite Icon; public string Name; public bool InNetwork; public bool Boss; } private const float PanelW = 640f; private const float PanelH = 664f; private const float TabW = 150f; private const float TabH = 36f; private const float SourceIconSize = 34f; private const float Margin = 20f; private const float RowH = 60f; private const float HeaderRowH = 30f; private const float IconSize = 44f; private const float RowGap = 4f; private const float ListH = 410f; private const int TitleSize = 26; private const int BodySize = 17; private const int SmallSize = 15; private static BeaconUI _instance; private GameObject _panel; private Text _title; private Text _subtitle; private Text _hint; private RectTransform _scrollRt; private float _listTopWithFilter; private float _listTopNoFilter; private const float BottomButtonW = 120f; private const float BottomGap = 16f; private const float FooterH = 56f; private Button _closeButton; private Button _backButton; private Button _tabTrophies; private Button _tabDiscounts; private Button _clearFilter; private InputField _filter; private string _filterText = ""; private bool _openedInventory; private bool _inventorySeen; private bool _hidCrafting; private RectTransform _content; private ScrollRect _scroll; private Sprite _iconFrame; private RectTransform _hoverBox; private Text _hoverText; private RectTransform _hoverTrophies; private const float HoverW = 316f; private const float HoverPad = 8f; private const float HoverTrophySize = 30f; private const float HoverTrophyGap = 4f; private const float HoverTrophyCell = 56f; private const int HoverNameMaxSize = 12; private const int HoverNameMinSize = 9; private HoverTarget _hovered; private BeaconController _beacon; private TrophyKind _picking; private Tab _tab; private static readonly Color Unreachable = new Color(0.5f, 0.5f, 0.5f, 0.14f); private static readonly Color[] LevelColors = (Color[])(object)new Color[3] { new Color(0.95f, 0.52f, 0.12f), new Color(0.96f, 0.8f, 0.18f), new Color(0.32f, 0.78f, 0.26f) }; private static readonly Color BossColor = new Color(0.28f, 0.58f, 1f); private const float SegmentH = 16f; private const float SegmentGap = 3f; private static readonly Dictionary<Sprite, Sprite> s_grey = new Dictionary<Sprite, Sprite>(); private static Sprite s_star; public static bool IsOpen { get { if ((Object)(object)_instance != (Object)null && (Object)(object)_instance._panel != (Object)null) { return _instance._panel.activeSelf; } return false; } } public static BeaconController OpenBeacon { get { if (!IsOpen) { return null; } return _instance._beacon; } } internal static void Init(GameObject host) { if ((Object)(object)_instance == (Object)null) { _instance = host.AddComponent<BeaconUI>(); } } public static void Open(BeaconController beacon) { if (!((Object)(object)_instance == (Object)null) && !((Object)(object)beacon == (Object)null) && beacon.IsValid && !((Object)(object)Player.m_localPlayer == (Object)null)) { _instance.Show(beacon); } } public static void CloseIfOpen() { if (IsOpen) { _instance.Close(); } } private void Show(BeaconController beacon) { EnsureBuilt(); if ((Object)(object)_beacon != (Object)null && (Object)(object)_beacon != (Object)(object)beacon) { _beacon.SetInUse(inUse: false); } _beacon = beacon; _beacon.SetInUse(inUse: true); _picking = TrophyKind.None; _tab = Tab.Trophies; _filterText = ""; _filter.SetTextWithoutNotify(""); _panel.SetActive(true); GUIManager.BlockInput(true); OpenInventoryAlongside(); Refresh(); } private void OpenInventoryAlongside() { InventoryGui instance = InventoryGui.instance; _openedInventory = (Object)(object)instance != (Object)null && !InventoryGui.IsVisible(); _inventorySeen = false; if (_openedInventory) { instance.Show((Container)null, 1); GameObject val = (((Object)(object)instance.m_crafting != (Object)null) ? ((Component)instance.m_crafting).gameObject : null); _hidCrafting = (Object)(object)val != (Object)null && val.activeSelf; if (_hidCrafting) { val.SetActive(false); } } } private void Close() { HideHover(null); if ((Object)(object)_panel != (Object)null) { _panel.SetActive(false); } if (_openedInventory && InventoryGui.IsVisible()) { InventoryGui.instance.Hide(); } if (_hidCrafting && (Object)(object)InventoryGui.instance != (Object)null && (Object)(object)InventoryGui.instance.m_crafting != (Object)null) { ((Component)InventoryGui.instance.m_crafting).gameObject.SetActive(true); } _hidCrafting = false; _openedInventory = false; GUIManager.BlockInput(false); if ((Object)(object)_beacon != (Object)null) { _beacon.SetInUse(inUse: false); } _beacon = null; _picking = TrophyKind.None; } private void Update() { if (!IsOpen) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)_beacon == (Object)null || !_beacon.IsValid || (Object)(object)localPlayer == (Object)null || !_beacon.InRangeOf(localPlayer)) { Close(); return; } _beacon.PokeStation(); if (_openedInventory) { if (InventoryGui.IsVisible()) { _inventorySeen = true; } else if (_inventorySeen) { Close(); return; } } if (ZInput.GetKeyDown((KeyCode)27, true)) { if (_picking != TrophyKind.None) { _picking = TrophyKind.None; Refresh(); } else { Close(); } } } internal static void OnInventoryCtrlClick(ItemData item) { if (!((Object)(object)_instance == (Object)null) && !((Object)(object)_instance._beacon == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null)) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)item?.m_dropPrefab == (Object)null || DiscountRules.KindOf(((Object)item.m_dropPrefab).name) == TrophyKind.None) { ((Character)localPlayer).Message((MessageType)2, "$xai_beacon_not_a_trophy", 0, (Sprite)null, false); } else if (_instance._beacon.TryInsertTrophy(localPlayer, item)) { _instance._picking = TrophyKind.None; _instance.Refresh(); } } } private static Button Quiet(Button button) { ButtonSfx val = (((Object)(object)button != (Object)null) ? ((Component)button).GetComponent<ButtonSfx>() : null); if ((Object)(object)val != (Object)null) { val.m_selectSfxPrefab = null; } return button; } private void AddClickSound(GameObject go) { ButtonSfx val = (((Object)(object)_closeButton != (Object)null) ? ((Component)_closeButton).GetComponent<ButtonSfx>() : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)go.GetComponent<ButtonSfx>() != (Object)null)) { go.AddComponent<ButtonSfx>().m_sfxPrefab = val.m_sfxPrefab; } } private static bool CtrlHeld() { if (!ZInput.GetKey((KeyCode)306, true)) { return ZInput.GetKey((KeyCode)305, true); } return true; } private void EnsureBuilt() { //IL_0021: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0172: 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_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Expected O, but got Unknown //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Expected O, but got Unknown //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02af: 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_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Expected O, but got Unknown //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_03d2: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_0412: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_0452: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) //IL_0476: Unknown result type (might be due to invalid IL or missing references) //IL_0490: Unknown result type (might be due to invalid IL or missing references) //IL_04a6: Unknown result type (might be due to invalid IL or missing references) //IL_04c4: Unknown result type (might be due to invalid IL or missing references) //IL_04cd: Unknown result type (might be due to invalid IL or missing references) //IL_04d6: Unknown result type (might be due to invalid IL or missing references) //IL_04e6: Unknown result type (might be due to invalid IL or missing references) //IL_0532: Unknown result type (might be due to invalid IL or missing references) //IL_053c: Expected O, but got Unknown //IL_0597: Unknown result type (might be due to invalid IL or missing references) //IL_05a1: Expected O, but got Unknown //IL_05e1: Unknown result type (might be due to invalid IL or missing references) //IL_05e3: Unknown result type (might be due to invalid IL or missing references) //IL_05ef: Unknown result type (might be due to invalid IL or missing references) //IL_0624: Unknown result type (might be due to invalid IL or missing references) //IL_062e: Expected O, but got Unknown //IL_0645: Unknown result type (might be due to invalid IL or missing references) //IL_0647: Unknown result type (might be due to invalid IL or missing references) //IL_0653: Unknown result type (might be due to invalid IL or missing references) //IL_0688: Unknown result type (might be due to invalid IL or missing references) //IL_0692: Expected O, but got Unknown //IL_06b5: Unknown result type (might be due to invalid IL or missing references) //IL_06b7: Unknown result type (might be due to invalid IL or missing references) //IL_06c3: Unknown result type (might be due to invalid IL or missing references) //IL_06cb: Unknown result type (might be due to invalid IL or missing references) //IL_06cd: Unknown result type (might be due to invalid IL or missing references) //IL_0702: Unknown result type (might be due to invalid IL or missing references) //IL_0704: Unknown result type (might be due to invalid IL or missing references) //IL_0705: Unknown result type (might be due to invalid IL or missing references) //IL_070c: Unknown result type (might be due to invalid IL or missing references) //IL_0713: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_panel != (Object)null) { return; } GUIManager instance = GUIManager.Instance; Font averiaSerifBold = instance.AveriaSerifBold; Color valheimOrange = GUIManager.Instance.ValheimOrange; Color valheimBeige = GUIManager.Instance.ValheimBeige; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0f, 1f); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0f, 0f); Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor(1f, 0f); _panel = instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, val, val, Vector2.zero, 640f, 664f, true); ((Object)_panel).name = "BuildBeaconPanel"; _panel.SetActive(false); float num = 600f; float num2 = -20f; Vector2 val5 = default(Vector2); ((Vector2)(ref val5))..ctor(0.5f, 1f); _title = instance.CreateText("", _panel.transform, val5, val5, new Vector2(0f, num2), averiaSerifBold, 26, valheimOrange, true, Color.black, num, 34f, false).GetComponent<Text>(); Place((Component)(object)_title, val5, new Vector2(0f, num2)); _title.alignment = (TextAnchor)1; num2 -= 38f; _subtitle = instance.CreateText("", _panel.transform, val5, val5, new Vector2(0f, num2), averiaSerifBold, 15, valheimBeige, true, Color.black, num, 22f, false).GetComponent<Text>(); Place((Component)(object)_subtitle, val5, new Vector2(0f, num2)); _subtitle.alignment = (TextAnchor)1; num2 -= 32f; _tabTrophies = Quiet(instance.CreateButton(L("$xai_beacon_tab_trophies"), _panel.transform, val5, val5, new Vector2(-79f, num2 - 18f), 150f, 36f).GetComponent<Button>()); ((UnityEvent)_tabTrophies.onClick).AddListener((UnityAction)delegate { SetTab(Tab.Trophies); }); _tabDiscounts = Quiet(instance.CreateButton(L("$xai_beacon_tab_discounts"), _panel.transform, val5, val5, new Vector2(79f, num2 - 18f), 150f, 36f).GetComponent<Button>()); ((UnityEvent)_tabDiscounts.onClick).AddListener((UnityAction)delegate { SetTab(Tab.Discounts); }); num2 -= 44f; _filter = instance.CreateInputField(_panel.transform, val2, val2, new Vector2(20f, num2), (ContentType)0, L("$xai_beacon_filter_placeholder"), 17, num - 40f - 8f, 34f).GetComponent<InputField>(); Place((Component)(object)_filter, val2, new Vector2(20f, num2 - 2f)); ((UnityEvent<string>)(object)_filter.onValueChanged).AddListener((UnityAction<string>)delegate(string v) { _filterText = v ?? ""; if (_tab == Tab.Discounts) { Refresh(); } }); Vector2 val6 = default(Vector2); ((Vector2)(ref val6))..ctor(1f, 1f); _clearFilter = Quiet(instance.CreateButton("X", _panel.transform, val6, val6, new Vector2(-20f, num2), 40f, 34f).GetComponent<Button>()); Place((Component)(object)_clearFilter, val6, new Vector2(-20f, num2 - 2f)); ((UnityEvent)_clearFilter.onClick).AddListener((UnityAction)delegate { _filter.text = ""; }); num2 -= 44f; ColorBlock val7 = default(ColorBlock); ((ColorBlock)(ref val7)).normalColor = new Color(0.8f, 0.7f, 0.5f, 0.8f); ((ColorBlock)(ref val7)).highlightedColor = new Color(0.9f, 0.8f, 0.6f, 1f); ((ColorBlock)(ref val7)).pressedColor = new Color(0.7f, 0.6f, 0.4f, 1f); ((ColorBlock)(ref val7)).selectedColor = new Color(0.9f, 0.8f, 0.6f, 1f); ((ColorBlock)(ref val7)).disabledColor = new Color(0.5f, 0.5f, 0.5f, 0.5f); ((ColorBlock)(ref val7)).colorMultiplier = 1f; ((ColorBlock)(ref val7)).fadeDuration = 0.1f; ColorBlock val8 = val7; GameObject val9 = instance.CreateScrollView(_panel.transform, false, true, 8f, 4f, val8, new Color(0f, 0f, 0f, 0.35f), num, 410f); RectTransform component = val9.GetComponent<RectTransform>(); component.anchorMin = val2; component.anchorMax = val2; component.pivot = val2; component.anchoredPosition = new Vector2(20f, num2); _scrollRt = component; _listTopWithFilter = num2; _listTopNoFilter = num2 + 44f; num2 -= 420f; _scroll = val9.GetComponentInChildren<ScrollRect>(); FollowWrapperHeight(component, (RectTransform)((Component)_scroll).transform); _content = _scroll.content; VerticalLayoutGroup obj = ((Component)_content).GetComponent<VerticalLayoutGroup>() ?? ((Component)_content).gameObject.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).spacing = 4f; ((LayoutGroup)obj).padding = new RectOffset(4, 4, 4, 4); if ((Object)(object)((Component)_content).GetComponent<ContentSizeFitter>() == (Object)null) { ((Component)_content).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2; } _closeButton = Quiet(instance.CreateButton(L("$xai_beacon_close"), _panel.transform, val4, val4, new Vector2(-80f, 40f), 120f, 40f).GetComponent<Button>()); ((UnityEvent)_closeButton.onClick).AddListener(new UnityAction(Close)); _backButton = Quiet(instance.CreateButton(L("$xai_beacon_back"), _panel.transform, val3, val3, new Vector2(80f, 40f), 120f, 40f).GetComponent<Button>()); ((UnityEvent)_backButton.onClick).AddListener((UnityAction)delegate { _picking = TrophyKind.None; Refresh(); }); Vector2 pivot = default(Vector2); ((Vector2)(ref pivot))..ctor(0f, 0.5f); _hint = instance.CreateText("", _panel.transform, val3, val3, new Vector2(20f, 40f), averiaSerifBold, 15, valheimBeige, true, Color.black, num - 120f - 16f, 56f, false).GetComponent<Text>(); RectTransform component2 = ((Component)_hint).GetComponent<RectTransform>(); Vector2 anchorMin = (component2.anchorMax = val3); component2.anchorMin = anchorMin; component2.pivot = pivot; _hint.alignment = (TextAnchor)3; _hint.fontStyle = (FontStyle)2; _hint.resizeTextForBestFit = true; _hint.resizeTextMinSize = 11; _hint.resizeTextMaxSize = 15; _iconFrame = instance.GetSprite("item_background"); BuildHoverBox(); } private void Refresh() { //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_beacon == (Object)null)) { HideHover(null); _title.text = L(_beacon.PieceNameKey); _subtitle.text = string.Format("{0} {1}/{2} · ", L("$xai_beacon_level"), _beacon.Level, _beacon.MaxLevel) + string.Format("{0} {1:0}m · ", L("$xai_beacon_radius"), _beacon.Radius) + string.Format("{0} {1} · ", L("$xai_beacon_boss_section"), _beacon.BossCount) + L("$xai_beacon_mob_section") + " " + L(_beacon.MobSlotsText); ((Selectable)_tabTrophies).interactable = _tab != Tab.Trophies; ((Selectable)_tabDiscounts).interactable = _tab != Tab.Discounts; bool flag = _tab == Tab.Discounts; ((Component)_filter).gameObject.SetActive(flag); ((Component)_clearFilter).gameObject.SetActive(flag); ((Selectable)_clearFilter).interactable = _filterText.Length > 0; bool flag2 = _tab == Tab.Trophies && _picking != TrophyKind.None; ((Component)_backButton).gameObject.SetActive(flag2); float num = (flag ? _listTopWithFilter : _listTopNoFilter); _scrollRt.anchoredPosition = new Vector2(20f, num); float num2 = 74f; _scrollRt.sizeDelta = new Vector2(_scrollRt.sizeDelta.x, 664f + num - num2); float num3 = 600f; float num4 = (flag2 ? 136f : 0f); RectTransform component = ((Component)_hint).GetComponent<RectTransform>(); component.anchoredPosition = new Vector2(20f + num4, 40f); component.sizeDelta = new Vector2(num3 - 120f - 16f - num4, 56f); ClearRows(); if (_tab == Tab.Discounts) { BuildDiscounts(); } else if (_picking != TrophyKind.None) { BuildPicker(_picking); } else { BuildSlots(); } _scroll.verticalNormalizedPosition = 1f; } } private void BuildSlots() { _hint.text = L("$xai_beacon_hint_slots"); if (_beacon.IsGreat) { AddSectionHeader(string.Format("{0} {1}/{2}", L("$xai_beacon_boss_section"), _beacon.OwnBossCount, _beacon.OwnBossSlots)); foreach (string item in _beacon.SlotsOf(TrophyKind.Boss)) { AddTrophyRow(item); } if (_beacon.OwnBossCount < _beacon.OwnBossSlots) { AddRow(null, L("$xai_beacon_empty_boss_slot"), L("$xai_beacon_click_to_add_boss"), null, delegate { _picking = TrophyKind.Boss; Refresh(); }, wholeRowClick: true); } foreach (var bossEntry in _beacon.BossEntries) { var (prefab, _) = bossEntry; if ((Object)(object)bossEntry.holder != (Object)null) { AddTrophyRow(prefab, L("$xai_beacon_on_holder")); } } } else { AddSectionHeader(string.Format("{0} {1}", L("$xai_beacon_boss_section"), _beacon.BossCount)); foreach (var (prefab2, bossHolder) in _beacon.BossEntries) { AddTrophyRow(prefab2, ((Object)(object)bossHolder != (Object)null) ? L("$xai_beacon_on_holder") : null); } if (_beacon.BossCount == 0) { AddRow(null, L("$xai_beacon_no_bosses"), L("$xai_beacon_no_bosses_hint"), null, null, wholeRowClick: true); } } if (_beacon.MobSlots > 0 || _beacon.MobCount > 0) { AddSectionHeader(string.Format("{0} {1}/{2}", L("$xai_beacon_mob_section"), _beacon.MobCount, _beacon.MobSlots)); foreach (string item2 in _beacon.SlotsOf(TrophyKind.Mob)) { AddTrophyRow(item2); } if (_beacon.MobCount < _beacon.MobSlots) { AddRow(null, L("$xai_beacon_empty_mob_slot"), L("$xai_beacon_click_to_add_mob"), null, delegate { _picking = TrophyKind.Mob; Refresh(); }, wholeRowClick: true); } } if (_beacon.RackCount <= 0) { return; } AddSectionHeader(string.Format("{0} {1}/{2}", L("$xai_beacon_racks_section"), _beacon.RackTrophyCount, _beacon.RackSlots)); foreach (var rackTrophy in _beacon.RackTrophies) { AddTrophyRow(rackTrophy.prefab, rackTrophy.counted ? L("$xai_beacon_on_rack") : (L("$xai_beacon_on_rack") + ", " + L("$xai_beacon_not_counted"))); } } private void AddTrophyRow(string prefab, string placedOn = null) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) bool flag = placedOn != null; string captured = prefab; Action remove = (flag ? null : ((Action)delegate { if (_beacon.TryRemoveTrophy(Player.m_localPlayer, captured)) { Refresh(); } })); string text = DiscountRules.ItemDisplayName(prefab) ?? prefab; GameObject val = AddRow(IconFor(prefab), flag ? $"{text} <size={15}><color=#c8b89a>({placedOn})</color></size>" : text, DiscountRules.DescribeTrophy(prefab), flag ? null : L("$xai_beacon_remove"), remove); string trophyName = DiscountRules.ItemDisplayName(prefab) ?? prefab; Image component = val.GetComponent<Image>(); Button obj = val.AddComponent<Button>(); AddClickSound(val); ((Selectable)obj).transition = (Transition)0; ((Selectable)obj).targetGraphic = (Graphic)(object)component; ((UnityEvent)obj.onClick).AddListener((UnityAction)delegate { if (CtrlHeld() && remove != null) { remove(); } else { ShowDiscountsFor(trophyName); } }); Transform val2 = val.transform.Find("icon"); if ((Object)(object)val2 != (Object)null) { GameObject val3 = new GameObject("iconHover", new Type[2] { typeof(RectTransform), typeof(Image) }); val3.transform.SetParent(val.transform, false); val3.transform.SetSiblingIndex(val2.GetSiblingIndex()); RectTransform val4 = (RectTransform)val2; RectTransform val5 = (RectTransform)val3.transform; val5.anchorMin = val4.anchorMin; val5.anchorMax = val4.anchorMax; val5.pivot = val4.pivot; val5.sizeDelta = val4.sizeDelta; val5.anchoredPosition = val4.anchoredPosition; Image component2 = val3.GetComponent<Image>(); component2.sprite = _iconFrame; ((Graphic)component2).raycastTarget = false; ((Behaviour)component2).enabled = false; RowHover rowHover = val.AddComponent<RowHover>(); rowHover.Square = component2; rowHover.CtrlRemoves = remove != null; } } private void BuildPicker(TrophyKind kind) { _hint.text = L((kind == TrophyKind.Boss) ? "$xai_beacon_hint_picker_boss" : "$xai_beacon_hint_picker_mob"); List<(string, int)> list = (from i in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems() where (Object)(object)i.m_dropPrefab != (Object)null && DiscountRules.KindOf(((Object)i.m_dropPrefab).name) == kind group i by ((Object)i.m_dropPrefab).name into g select (prefab: g.Key, count: g.Sum((ItemData i) => i.m_stack))).OrderBy(delegate((string prefab, int count) c) { string text3 = DiscountRules.ItemDisplayName(c.prefab); if (text3 == null) { (text3, _) = c; } return text3; }).ToList(); if (list.Count == 0) { AddRow(null, L((kind == TrophyKind.Boss) ? "$xai_beacon_no_boss_trophies" : "$xai_beacon_no_mob_trophies"), "", null, null, wholeRowClick: true); return; } foreach (var item in list) { string captured = item.Item1; string text = _beacon.InsertBlockedReason(item.Item1); Sprite icon = IconFor(item.Item1); string text2 = DiscountRules.ItemDisplayName(item.Item1); if (text2 == null) { (text2, _) = item; } AddRow(icon, $"{text2} x{item.Item2}", (text != null) ? L(text) : DiscountRules.DescribeTrophy(item.Item1), (text != null) ? null : L("$xai_beacon_add"), delegate { if (_beacon.TryInsertTrophy(Player.m_localPlayer, captured)) { _picking = TrophyKind.None; Refresh(); } }); } } private void ShowDiscountsFor(string filter) { _filterText = filter; _filter.SetTextWithoutNotify(filter); SetTab(Tab.Discounts); } private void SetTab(Tab tab) { if (_tab == Tab.Discounts && tab != Tab.Discounts) { _filterText = ""; _filter.SetTextWithoutNotify(""); } _tab = tab; _picking = TrophyKind.None; Refresh(); } private void BuildDiscounts() { _hint.text = L("$xai_beacon_levels_note"); List<MaterialDiscount> list = DiscountRules.Breakdown(_beacon.Trophies); if (list.Count == 0) { AddRow(null, L("$xai_beacon_no_discounts"), L("$xai_beacon_no_discounts_hint"), null, null, wholeRowClick: true); return; } string filter = _filterText.Trim(); List<MaterialDiscount> list2 = ((filter.Length == 0) ? list : list.Where((MaterialDiscount d) => MatchesFilter(d, filter)).ToList()); if (list2.Count == 0) { AddRow(null, L("$xai_beacon_filter_none") + " \"" + filter + "\"", "", null, null, wholeRowClick: true); return; } int trophyColumns = list2.Max((MaterialDiscount r) => r.Sources.Count); foreach (MaterialDiscount item in list2) { AddDiscountRow(item, trophyColumns); } } private static Color LevelColor(int level, int top) { //IL_0037: 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) int num = LevelColors.Length - 1; if (top <= 1) { return LevelColors[num]; } float num2 = Mathf.Clamp01((float)(level - 1) / (float)(top - 1)); return LevelColors[Mathf.RoundToInt(num2 * (float)num)]; } private void AddLevelBar(Transform row, MaterialDiscount d, Vector2 pos, float width) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) int reachable = DiscountRules.MaxMobLevel(d.Item); int topLevel = DiscountRules.TopLevel; int shown = Mathf.Clamp(d.Level, 0, topLevel); Color color = LevelColor(Mathf.Max(shown, 1), topLevel); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(1f, 0.5f); GameObject val2 = new GameObject("levelBar", new Type[2] { typeof(RectTransform), typeof(Image) }); val2.transform.SetParent(row, false); RectTransform component = val2.GetComponent<RectTransform>(); component.anchorMin = val; component.anchorMax = va