using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using CMF; using FalseGods.Application.Arena; using FalseGods.Application.Combat; using FalseGods.Application.Presentation; using FalseGods.Core.Bosses.Combat; using FalseGods.Core.Simulation; using FalseGods.Integration.Sulfur.Arena; using FalseGods.Integration.Sulfur.Combat; using FalseGods.Protocol.Wire; using FalseGods.RuntimeContracts.Arena; using FalseGods.RuntimeContracts.Diagnostics; using FalseGods.RuntimeContracts.Multiplayer; using HarmonyLib; using I2.Loc; using LevelGeneration; using MakerGraphTool; using MakerGraphTool.Nodes; using Microsoft.CodeAnalysis; using Pathfinding; using Pathfinding.Graphs.Navmesh; using PerfectRandom.Sulfur.Core; using PerfectRandom.Sulfur.Core.DevTools; using PerfectRandom.Sulfur.Core.Effects; using PerfectRandom.Sulfur.Core.Items; using PerfectRandom.Sulfur.Core.LevelGeneration; using PerfectRandom.Sulfur.Core.Movement; using PerfectRandom.Sulfur.Core.Stats; using PerfectRandom.Sulfur.Core.UI; using PerfectRandom.Sulfur.Core.Units; using PerfectRandom.Sulfur.Core.Units.AI; using PerfectRandom.Sulfur.Core.Weapons; using PerfectRandom.Sulfur.Gameplay; using PerfectRandom.Sulfur.Gameplay.Triggers; using Sonity; using Sonity.Internal; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.AddressableAssets.ResourceLocators; using UnityEngine.Events; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceLocations; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("FalseGods.Integration.Sulfur")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+6e5740a80f810ab422551028733810b527fb614d")] [assembly: AssemblyProduct("FalseGods.Integration.Sulfur")] [assembly: AssemblyTitle("FalseGods.Integration.Sulfur")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FalseGods.Integration.Sulfur.Simulation { public sealed class SeededAuthoritativeRandom : IAuthoritativeRandom { private readonly Random _random; public SeededAuthoritativeRandom(int seed) { _random = new Random(seed); } public int NextInt(int minInclusive, int maxExclusive) { return _random.Next(minInclusive, maxExclusive); } public float NextFloat() { return (float)_random.NextDouble(); } } public sealed class SulfurLocalPlayer { public bool TryGetLocalParticipantIndex(out int playerIndex) { GameManager instance = StaticInstance.Instance; Player val = (((Object)(object)instance != (Object)null) ? instance.PlayerScript : null); if ((Object)(object)val != (Object)null) { playerIndex = val.playerIndex; return true; } playerIndex = -1; return false; } } public sealed class SulfurParticipantQuery : IEncounterParticipantQuery { private readonly List _ids = new List(); public IReadOnlyList Participants { get { //IL_0044: Unknown result type (might be due to invalid IL or missing references) _ids.Clear(); List list = ActivePlayers(); if (list == null) { return _ids; } for (int i = 0; i < list.Count; i++) { Player val = list[i]; if ((Object)(object)val != (Object)null && FightingPlayers.IsFighting(val)) { _ids.Add(new ParticipantId(val.playerIndex)); } } return _ids; } } public bool TryGetPosition(ParticipantId participant, out SimVector2 position) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) List list = ActivePlayers(); if (list != null) { for (int i = 0; i < list.Count; i++) { Player val = list[i]; if ((Object)(object)val != (Object)null && val.playerIndex == ((ParticipantId)(ref participant)).Value && FightingPlayers.IsFighting(val)) { Vector3 position2 = ((Component)val).transform.position; position = new SimVector2(position2.x, position2.z); return true; } } } position = default(SimVector2); return false; } private static List? ActivePlayers() { GameManager instance = StaticInstance.Instance; if (!((Object)(object)instance != (Object)null)) { return null; } return instance.Players; } } public sealed class SulfurSimulationClock : ISimulationClock { public long Tick => Time.frameCount; public float Time => Time.time; } } namespace FalseGods.Integration.Sulfur.Presentation { public sealed class SulfurArenaAtmosphere : IArenaAtmospherePort, IDisposable { private const string CaveBossRoomKey = "Assets/_Core/Prefabs/LevelGeneration/Chunks/Caves/CaveCousinNew.prefab"; private const float MusicFadeSeconds = 10f; private readonly MonoBehaviour _host; private readonly ILogger _logger; private AssetReference _room; private MusicTrigger _music; private bool _searchedForMusic; private Coroutine _pendingDepth; private bool _playing; public SulfurArenaAtmosphere(MonoBehaviour host, ILogger logger = null) { if (!((Object)(object)host != (Object)null)) { throw new ArgumentNullException("host"); } _host = host; _logger = logger; } public void Warm() { FindTheMusic(); } public void SetRoomDepth(float startDistance, float endDistance, float afterSeconds = 0f, float overSeconds = 0f) { CancelPendingDepth(); if (afterSeconds <= 0f) { Apply(startDistance, endDistance, overSeconds); } else { _pendingDepth = _host.StartCoroutine(AfterAPause(startDistance, endDistance, afterSeconds, overSeconds)); } } public void StartBattleMusic() { MusicTrigger val = FindTheMusic(); if ((Object)(object)val == (Object)null) { return; } try { val.StartMusic(); _playing = true; ILogger logger = _logger; if (logger != null) { logger.Log("[music] the boss's own battle music is playing, on the game's music mix."); } } catch (Exception ex) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[music] the battle music would not start (" + ex.Message + ")."); } } } public void StopBattleMusic() { if (!_playing || (Object)(object)_music == (Object)null) { return; } _playing = false; try { _music.StopMusic(10f); ILogger logger = _logger; if (logger != null) { logger.Log($"[music] the battle music is fading out over {10f:0}s."); } } catch (Exception ex) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[music] the battle music would not stop (" + ex.Message + ")."); } } } public void Dispose() { CancelPendingDepth(); _music = null; _searchedForMusic = false; if (_room != null) { try { _room.ReleaseAsset(); } catch (Exception) { } _room = null; } } private IEnumerator AfterAPause(float start, float end, float afterSeconds, float overSeconds) { yield return (object)new WaitForSecondsRealtime(afterSeconds); _pendingDepth = null; Apply(start, end, overSeconds); } private void Apply(float start, float end, float overSeconds) { SulfurLevelFog.TryApply(start, end, _logger, overSeconds); } private void CancelPendingDepth() { if (_pendingDepth != null) { _host.StopCoroutine(_pendingDepth); _pendingDepth = null; } } private MusicTrigger FindTheMusic() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_music != (Object)null || _searchedForMusic) { return _music; } try { if (_room == null) { _room = new AssetReference("Assets/_Core/Prefabs/LevelGeneration/Chunks/Caves/CaveCousinNew.prefab"); } AsyncOperationHandle val = _room.LoadAssetAsync(); GameObject val2 = val.WaitForCompletion(); if ((int)val.Status != 1 || (Object)(object)val2 == (Object)null) { ILogger logger = _logger; if (logger != null) { logger.LogWarning($"[music] the cave boss's room would not load ({val.Status}); the fight " + "will be fought without its music."); } return null; } _searchedForMusic = true; _music = val2.GetComponentInChildren(true); if ((Object)(object)_music == (Object)null) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[music] the cave boss's room carries no music trigger any more; the fight will be fought without its music."); } return null; } ILogger logger3 = _logger; if (logger3 != null) { logger3.Log("[music] the boss's battle music has been found on its own room."); } return _music; } catch (Exception ex) { ILogger logger4 = _logger; if (logger4 != null) { logger4.LogWarning("[music] the battle music could not be fetched (" + ex.Message + "); trying again at the next encounter."); } return null; } } } public sealed class SulfurBossVoice : IBossVoicePort { private const string RoarFieldName = "roarSoundEvent"; private const float RoarCarriesTimes = 4f; private readonly Transform _mouth; private readonly SoundParameterInternals[] _carry = (SoundParameterInternals[])(object)new SoundParameterInternals[1] { (SoundParameterInternals)new SoundParameterDistanceScale(4f) }; private readonly ILogger? _logger; private const int MaxAttempts = 8; private SoundEvent? _roar; private bool _fetching; private int _attempts; private int _roars; public SulfurBossVoice(Transform lifetime, ILogger? logger = null) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown if ((Object)(object)lifetime == (Object)null) { throw new ArgumentNullException("lifetime"); } GameObject val = new GameObject("FalseGodsBossVoice"); val.transform.SetParent(lifetime, false); _mouth = val.transform; _logger = logger; } public void Warm() { Fetch(); } public void Roar(ArenaWorldPoint at) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) SoundEvent roar = _roar; if ((Object)(object)roar == (Object)null) { Fetch(); return; } try { _mouth.position = new Vector3(((ArenaWorldPoint)(ref at)).X, ((ArenaWorldPoint)(ref at)).Y, ((ArenaWorldPoint)(ref at)).Z); roar.Play(_mouth, _carry); CheckItCarried(roar, ++_roars == 1); } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[voice] the boss's roar would not play (" + ex.Message + ")."); } } } private void CheckItCarried(SoundEvent roar, bool first) { //IL_001c: 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_0081: 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) try { AudioListener val = Object.FindObjectOfType(); string text = (((Object)(object)val != (Object)null) ? (Vector3.Distance(((Component)val).transform.position, _mouth.position).ToString("0.#") + "m") : "nobody listening"); AudioSource lastPlayedAudioSource = roar.GetLastPlayedAudioSource(_mouth); if ((Object)(object)lastPlayedAudioSource == (Object)null) { ILogger? logger = _logger; if (logger != null) { string[] obj = new string[5] { "[voice] the roar made no sound: nothing was allocated for it, from ", null, null, null, null }; Vector3 position = _mouth.position; obj[1] = ((Vector3)(ref position)).ToString("0.#"); obj[2] = " with the ear "; obj[3] = text; obj[4] = " off."; logger.LogWarning(string.Concat(obj)); } } else if (first) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log($"[voice] the boss roars {lastPlayedAudioSource.maxDistance:0.#}m, on the game's " + "'" + (((Object)(object)lastPlayedAudioSource.outputAudioMixerGroup == (Object)null) ? "" : ((Object)lastPlayedAudioSource.outputAudioMixerGroup).name) + "' " + $"mix; the ear was {text} off and heard it at {lastPlayedAudioSource.volume:0.##}."); } } } catch (Exception ex) { ILogger? logger3 = _logger; if (logger3 != null) { logger3.LogWarning("[voice] could not tell whether the roar carried (" + ex.Message + ")."); } } } private async void Fetch() { if ((Object)(object)_roar != (Object)null || _fetching || _attempts >= 8) { return; } _fetching = true; _attempts++; try { UnitSO asset = AssetAccess.GetAsset(UnitIds.GoblinCousin); if ((Object)(object)asset == (Object)null) { Gave("the game has no definition for the cave boss"); return; } GameObject val = await asset.FetchAndLoadUnitLoader().Task; CousinHelper val2 = (((Object)(object)val != (Object)null) ? val.GetComponent() : null); if ((Object)(object)val2 == (Object)null) { Gave("the cave boss carries no helper to take a roar from"); return; } ref SoundEvent? roar = ref _roar; object? obj = typeof(CousinHelper).GetField("roarSoundEvent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val2); roar = (SoundEvent?)((obj is SoundEvent) ? obj : null); if ((Object)(object)_roar == (Object)null) { Gave("the cave boss's 'roarSoundEvent' is not where it was"); return; } ILogger? logger = _logger; if (logger != null) { logger.Log("[voice] the boss has found its voice ('" + ((Object)_roar).name + "')."); } } catch (Exception ex) { Gave("could not be fetched (" + ex.Message + ")"); } finally { _fetching = false; } } private void Gave(string reason) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning((_attempts >= 8) ? $"[voice] the boss's roar {reason}; after {_attempts} tries it will rage silently." : ("[voice] the boss's roar " + reason + "; trying again at the next encounter.")); } } } } namespace FalseGods.Integration.Sulfur.Navigation { public sealed class AstarNavigationPort : INavigationPort { private const float BakeClearHeight = 300f; private const float NavBoundsHeight = 4f; private const float FloorBandHalf = 1.5f; private readonly Func _arenaRoot; private readonly ILogger _logger; private AstarPath _appliedGraph; private TileMeshes _savedTiles; private bool[][] _savedWalkable; private IntRect _appliedRect; private bool _applied; public AstarNavigationPort(Func arenaRoot, ILogger logger = null) { _arenaRoot = arenaRoot ?? throw new ArgumentNullException("arenaRoot"); _logger = logger; } public NavigationApplyResult Apply() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0123: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0145: 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_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0213: 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_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_03b8: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_040b: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_0453: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Unknown result type (might be due to invalid IL or missing references) if (_applied) { return NavigationApplyResult.Failed("arena navigation is already applied"); } AstarPath active = AstarPath.active; RecastGraph recast = (((Object)(object)active != (Object)null && active.data != null) ? active.data.recastGraph : null); if (recast == null) { return NavigationApplyResult.Failed("no active recast graph (no loaded level)"); } if (!((NavGraph)recast).isScanned) { return NavigationApplyResult.Failed("the level's navigation is not built here (no scanned recast tiles)"); } GameObject val = _arenaRoot(); if ((Object)(object)val == (Object)null) { return NavigationApplyResult.Failed("no realized arena to build navigation for"); } Bounds val2 = WorldBounds(val); TileLayout val3 = default(TileLayout); ((TileLayout)(ref val3))..ctor(recast); IntRect touchingTiles = ((TileLayout)(ref val3)).GetTouchingTiles(val2, 0.5f); Bounds tileBoundsInGraphSpace = ((TileLayout)(ref val3)).GetTileBoundsInGraphSpace(touchingTiles.xmin, touchingTiles.ymin, ((IntRect)(ref touchingTiles)).Width, ((IntRect)(ref touchingTiles)).Height); Vector3 val4 = val3.transform.Transform(((Bounds)(ref tileBoundsInGraphSpace)).center); Vector3 val5 = default(Vector3); ((Vector3)(ref val5))..ctor((float)((IntRect)(ref touchingTiles)).Width * ((TileLayout)(ref val3)).TileWorldSizeX, 4f, (float)((IntRect)(ref touchingTiles)).Height * ((TileLayout)(ref val3)).TileWorldSizeZ); IntRect val6 = default(IntRect); int num = default(int); float yOffset = default(float); NavmeshPrefab.SnapToGraph(val3, new Vector3(val4.x, ((Bounds)(ref val2)).center.y, val4.z), Quaternion.identity, new Bounds(Vector3.zero, val5), ref val6, ref num, ref yOffset); if (val6.xmin < 0 || val6.ymin < 0 || val6.xmax >= ((NavmeshBase)recast).tileXCount || val6.ymax >= ((NavmeshBase)recast).tileZCount) { return NavigationApplyResult.Failed($"arena navigation footprint tiles [{val6.xmin},{val6.ymin}]..[{val6.xmax}," + $"{val6.ymax}] extend past the level's navigable area ({((NavmeshBase)recast).tileXCount}x{((NavmeshBase)recast).tileZCount} " + "tiles); move toward the level centre and try again"); } byte[] array; try { array = BakeInClearSpace(recast, val, val4, val5); } catch (Exception ex) { return NavigationApplyResult.Failed("arena navmesh bake threw: " + ex.Message); } if (array == null) { return NavigationApplyResult.Failed("arena navmesh bake produced no data"); } TileMeshes tiles = TileMeshes.Deserialize(array); int num2 = 0; if (tiles.tileMeshes != null) { for (int i = 0; i < tiles.tileMeshes.Length; i++) { int num3 = num2; int[] triangles = tiles.tileMeshes[i].triangles; num2 = num3 + ((triangles != null) ? triangles.Length : 0) / 3; } } if (num2 == 0) { return NavigationApplyResult.Failed("arena navmesh baked 0 triangles (floor did not rasterize)"); } ((TileMeshes)(ref tiles)).Rotate(num); if (((IntRect)(ref tiles.tileRect)).Width != ((IntRect)(ref val6)).Width || ((IntRect)(ref tiles.tileRect)).Height != ((IntRect)(ref val6)).Height) { return NavigationApplyResult.Failed($"baked tile dims {((IntRect)(ref tiles.tileRect)).Width}x{((IntRect)(ref tiles.tileRect)).Height} do not match the graph rect " + $"{((IntRect)(ref val6)).Width}x{((IntRect)(ref val6)).Height}"); } tiles.tileRect = val6; TileMeshes val7; bool[][] walkablePerTile; try { val7 = SnapshotTiles(recast, val6, out walkablePerTile); } catch (Exception ex2) { return NavigationApplyResult.Failed("level tile snapshot threw: " + ex2.Message); } active.AddWorkItem((Action)delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) recast.ReplaceTiles(tiles, yOffset); }); active.FlushWorkItems(); float y = val.transform.position.y; int num4 = CountWalkable(recast, val2, y - 1.5f, y + 1.5f); if (num4 == 0) { RestoreSnapshot(active, recast, val7, val6, walkablePerTile); return NavigationApplyResult.Failed("applied arena navmesh added no walkable floor nodes; level tiles restored"); } _appliedGraph = active; _savedTiles = val7; _savedWalkable = walkablePerTile; _appliedRect = val6; _applied = true; ILogger logger = _logger; if (logger != null) { logger.Log($"[arena-nav] applied {num2} baked triangles over tiles " + $"[{val6.xmin},{val6.ymin}] {((IntRect)(ref val6)).Width}x{((IntRect)(ref val6)).Height}; " + $"{num4} walkable floor node(s)"); } return NavigationApplyResult.Applied(num4); } public void Remove() { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (!_applied) { return; } try { AstarPath active = AstarPath.active; if ((Object)(object)active == (Object)null || active != _appliedGraph) { ILogger logger = _logger; if (logger != null) { logger.Log("[arena-nav] graph was rebuilt since apply; nothing to restore"); } return; } RecastGraph val = ((active.data != null) ? active.data.recastGraph : null); if (val != null) { RestoreSnapshot(active, val, _savedTiles, _appliedRect, _savedWalkable); ILogger logger2 = _logger; if (logger2 != null) { logger2.Log("[arena-nav] level tiles restored to baseline (geometry + walkability)"); } } } finally { _applied = false; _appliedGraph = null; _savedTiles = default(TileMeshes); _savedWalkable = null; } } private static void RestoreSnapshot(AstarPath astar, RecastGraph recast, TileMeshes saved, IntRect rect, bool[][] savedWalkable) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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) astar.AddWorkItem((Action)delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) recast.ReplaceTiles(saved, 0f); RestoreWalkability(recast, rect, savedWalkable); }); astar.FlushWorkItems(); } private static byte[] BakeInClearSpace(RecastGraph recast, GameObject root, Vector3 alignedCentre, Vector3 alignedSize) { //IL_0007: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate(root, root.transform.position + Vector3.up * 300f, root.transform.rotation); ((Object)val).name = "FalseGodsArenaNavBake"; try { Bounds val2 = WorldBounds(val); GameObject val3 = new GameObject("FalseGodsArenaNavBakeHolder"); val3.transform.position = new Vector3(alignedCentre.x, ((Bounds)(ref val2)).center.y, alignedCentre.z); try { NavmeshPrefab obj = val3.AddComponent(); obj.applyOnStart = false; obj.removeTilesWhenDisabled = false; obj.bounds = new Bounds(Vector3.zero, alignedSize); return obj.Scan(recast); } finally { Object.Destroy((Object)(object)val3); } } finally { Object.Destroy((Object)(object)val); } } private static TileMeshes SnapshotTiles(RecastGraph recast, IntRect rect, out bool[][] walkablePerTile) { //IL_0213: 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_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) int width = ((IntRect)(ref rect)).Width; int height = ((IntRect)(ref rect)).Height; TileMesh[] array = (TileMesh[])(object)new TileMesh[width * height]; walkablePerTile = new bool[width * height][]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int num = j + i * width; NavmeshTile tile = ((NavmeshBase)recast).GetTile(rect.xmin + j, rect.ymin + i); if (tile == null || tile.tris.Length == 0) { array[num] = new TileMesh { triangles = Array.Empty(), verticesInTileSpace = Array.Empty(), tags = Array.Empty() }; walkablePerTile[num] = Array.Empty(); continue; } Int3 val = (Int3)new Vector3((float)(rect.xmin + j) * ((NavmeshBase)recast).TileWorldSizeX, 0f, (float)(rect.ymin + i) * ((NavmeshBase)recast).TileWorldSizeZ); Int3[] array2 = (Int3[])(object)new Int3[tile.vertsInGraphSpace.Length]; for (int k = 0; k < array2.Length; k++) { array2[k] = tile.vertsInGraphSpace[k] - val; } int[] array3 = new int[tile.tris.Length]; for (int l = 0; l < array3.Length; l++) { array3[l] = tile.tris[l]; } int num2 = array3.Length / 3; uint[] array4 = new uint[num2]; bool[] array5 = new bool[num2]; TriangleMeshNode[] nodes = tile.nodes; if (nodes != null) { for (int m = 0; m < num2 && m < nodes.Length; m++) { if (nodes[m] != null) { array4[m] = ((GraphNode)nodes[m]).Tag; array5[m] = ((GraphNode)nodes[m]).Walkable; } } } array[num] = new TileMesh { triangles = array3, verticesInTileSpace = array2, tags = array4 }; walkablePerTile[num] = array5; } } return new TileMeshes { tileMeshes = array, tileRect = rect, tileWorldSize = new Vector2(((NavmeshBase)recast).TileWorldSizeX, ((NavmeshBase)recast).TileWorldSizeZ) }; } private static void RestoreWalkability(RecastGraph recast, IntRect rect, bool[][] walkablePerTile) { //IL_002f: 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) if (walkablePerTile == null) { return; } int width = ((IntRect)(ref rect)).Width; int height = ((IntRect)(ref rect)).Height; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { bool[] array = walkablePerTile[j + i * width]; if (array == null || array.Length == 0) { continue; } TriangleMeshNode[] array2 = ((NavmeshBase)recast).GetTile(rect.xmin + j, rect.ymin + i)?.nodes; if (array2 == null) { continue; } for (int k = 0; k < array2.Length && k < array.Length; k++) { if (array2[k] != null) { ((GraphNode)array2[k]).Walkable = array[k]; } } } } } private static int CountWalkable(RecastGraph recast, Bounds xzBounds, float yMin, float yMax) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) float minX = ((Bounds)(ref xzBounds)).center.x - ((Bounds)(ref xzBounds)).extents.x; float maxX = ((Bounds)(ref xzBounds)).center.x + ((Bounds)(ref xzBounds)).extents.x; float minZ = ((Bounds)(ref xzBounds)).center.z - ((Bounds)(ref xzBounds)).extents.z; float maxZ = ((Bounds)(ref xzBounds)).center.z + ((Bounds)(ref xzBounds)).extents.z; int count = 0; ((NavGraph)recast).GetNodes((Action)delegate(GraphNode node) { //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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (node.Walkable) { Vector3 val = (Vector3)node.position; if (!(val.y < yMin) && !(val.y > yMax) && !(val.x < minX) && !(val.x > maxX) && !(val.z < minZ) && !(val.z > maxZ)) { count++; } } }); return count; } private static Bounds WorldBounds(GameObject go) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_002b: 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_0057: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = go.GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { return new Bounds(go.transform.position, new Vector3(24f, 8f, 24f)); } Bounds bounds = componentsInChildren[0].bounds; for (int i = 1; i < componentsInChildren.Length; i++) { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds); } return bounds; } } public sealed class NativeLevelNavigationPort : INavigationPort { private readonly ILogger? _logger; public NativeLevelNavigationPort(ILogger? logger = null) { _logger = logger; } public NavigationApplyResult Apply() { ILogger? logger = _logger; if (logger != null) { logger.Log("[nav] arena navigation left to the level's own scan (native level load)."); } return NavigationApplyResult.Applied(0); } public void Remove() { } } } namespace FalseGods.Integration.Sulfur.Combat { public static class BossWeaponDamage { private sealed class Binding : IDisposable { private BossAttackReceiver? _receiver; public Binding(BossAttackReceiver receiver) { _receiver = receiver; } public void Dispose() { if ((Object)(object)_receiver != (Object)null) { Object.Destroy((Object)(object)_receiver); } _receiver = null; } } public static IDisposable Bind(GameObject collisionBody, IBossDamageSink sink, ILogger? logger) { if ((Object)(object)collisionBody == (Object)null) { throw new ArgumentNullException("collisionBody"); } if (sink == null) { throw new ArgumentNullException("sink"); } BossAttackReceiver bossAttackReceiver = collisionBody.AddComponent(); bossAttackReceiver.Initialize(sink); LogProjectileLayerDiagnosis(collisionBody, logger); return new Binding(bossAttackReceiver); } private static void LogProjectileLayerDiagnosis(GameObject collisionBody, ILogger? logger) { try { ProjectileSystem instance = StaticInstance.Instance; if ((Object)(object)instance == (Object)null) { if (logger != null) { logger.LogWarning("ProjectileSystem is not up yet; cannot verify the boss layer is in its collision mask."); } return; } int value = ((LayerMask)(ref instance.collisionLayers)).value; string text = LayerMask.LayerToName(collisionBody.layer); bool flag = (value & (1 << collisionBody.layer)) != 0; if (logger != null) { logger.Log($"weapon-damage bound: projectile mask=0x{value:X8}, boss layer '{text}' included={flag}."); } if (!flag && logger != null) { logger.LogWarning("Projectiles do not raycast layer '" + text + "' - bullets will pass through the boss."); } } catch (Exception ex) { if (logger != null) { logger.LogWarning("Projectile layer diagnosis failed: " + ex.Message); } } } } internal sealed class BossAttackReceiver : MonoBehaviour, IAttackReceiver { private IBossDamageSink? _sink; public void Initialize(IBossDamageSink sink) { _sink = sink; } public bool ReceiveAttack(float damage, DamageTypes damageType, DamageSourceData sourceData, Data hitbox, Vector3? collisionPoint = null) { if (_sink == null || float.IsNaN(damage) || damage <= 0f) { return false; } _sink.ApplyWeaponDamage(damage); return true; } } public static class FightingPlayers { private static IPlayerLifeQuery? _lives; public static void AskedOf(IPlayerLifeQuery? lives) { _lives = lives; } public static bool IsFighting(Unit? playerUnit) { if ((Object)(object)playerUnit == (Object)null) { return false; } IPlayerLifeQuery lives = _lives; if (lives == null) { return true; } try { return !lives.IsOutOfTheFight((object)playerUnit); } catch (Exception) { return true; } } public static bool IsFighting(Player? player) { if ((Object)(object)player != (Object)null) { return IsFighting(player.playerUnit); } return false; } public static void FillFighting(List into) { if (into == null) { return; } into.Clear(); GameManager instance = StaticInstance.Instance; List list = (((Object)(object)instance != (Object)null) ? instance.Players : null); if (list == null) { return; } for (int i = 0; i < list.Count; i++) { Player val = list[i]; Unit val2 = (((Object)(object)val != (Object)null) ? val.playerUnit : null); if ((Object)(object)val2 != (Object)null && IsFighting(val)) { into.Add(val2); } } } public static Unit? NearestTo(Vector3 from) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) GameManager instance = StaticInstance.Instance; List list = (((Object)(object)instance != (Object)null) ? instance.Players : null); if (list == null) { return null; } Unit result = null; float num = float.MaxValue; for (int i = 0; i < list.Count; i++) { Player val = list[i]; Unit val2 = (((Object)(object)val != (Object)null) ? val.playerUnit : null); if (!((Object)(object)val2 == (Object)null) && IsFighting(val)) { Vector3 val3 = ((Component)val2).transform.position - from; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = val2; } } } return result; } } public static class OurDestructibles { private static IDestructibleOwnership? _ownership; public static void ClaimedWith(IDestructibleOwnership? ownership) { _ownership = ownership; } public static void Claim(GameObject? destructible) { if ((Object)(object)destructible == (Object)null) { return; } try { IDestructibleOwnership? ownership = _ownership; if (ownership != null) { ownership.ClaimAsOurs((object)destructible); } } catch (Exception) { } } } public sealed class SulfurBattlefieldCleanup : IBattlefieldCleanupPort { private readonly ILogger? _logger; public SulfurBattlefieldCleanup(ILogger? logger = null) { _logger = logger; } public int SweepCorpses(ArenaWorldPoint around, float radius) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) int result = SweepBodies(new Vector3(((ArenaWorldPoint)(ref around)).X, ((ArenaWorldPoint)(ref around)).Y, ((ArenaWorldPoint)(ref around)).Z), radius); SweepGore(); return result; } private int SweepBodies(Vector3 around, float radius) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) UnitManager instance = StaticInstance.Instance; List list = (((Object)(object)instance != (Object)null) ? instance.KilledUnits : null); if (list == null) { return 0; } float num = radius * radius; int num2 = 0; for (int num3 = list.Count - 1; num3 >= 0; num3--) { Unit val = list[num3]; if ((Object)(object)val == (Object)null) { list.RemoveAt(num3); } else if (!val.isPlayer && !val.IsAlive) { Vector3 val2 = ((Component)val).transform.position - around; if (!(((Vector3)(ref val2)).sqrMagnitude > num)) { try { Npc val3 = (Npc)(object)((val is Npc) ? val : null); if (val3 != null) { val3.SinkIntoGroundEndless(); } else { Object.Destroy((Object)(object)((Component)val).gameObject); } list.RemoveAt(num3); num2++; } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[cleanup] a body could not be cleared (" + ex.Message + "); leaving it."); } } } } } return num2; } private void SweepGore() { try { GibSystemNEW instance = StaticInstance.Instance; if (instance != null) { instance.DeactivateAllGibs(); } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[cleanup] the gore could not be cleared (" + ex.Message + ")."); } } } } public sealed class SulfurBossArmPort : IBossArmPort { private const string ArtRootName = "Root"; private const float ThrowRange = 100f; private readonly MonoBehaviour _host; private readonly ILogger? _logger; private readonly List _raised = new List(); private readonly List _stations = new List(); private readonly List _artRoots = new List(); private readonly List> _quarry = new List>(); private static readonly List EmptyQuarry = new List(0); private ArmPlacement _placement; private int _generation; private bool _ours; public int Raised { get { Forget(); return _raised.Count; } } public SulfurBossArmPort(MonoBehaviour host, ILogger? logger = null) { _host = host ?? throw new ArgumentNullException("host"); _logger = logger; } public void Raise(int count, ArmPlacement placement) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (count <= 0 || Raised > 0) { return; } UnitSO asset = AssetAccess.GetAsset(UnitIds.GoblinCousinArm); if ((Object)(object)asset == (Object)null) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[arm] the game has no definition for the cousin's arm; the boss rages empty-handed."); } return; } _placement = placement; _ours = true; int generation = ++_generation; for (int i = 0; i < count; i++) { RaiseOne(asset, StandingPoint(placement, i), i, generation); } ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log($"[arm] {count} arm(s) rising at the boss's sides ({((ArmPlacement)(ref placement)).SideDistance:0.#}m out, " + $"{((ArmPlacement)(ref placement)).ForwardOffset:0.#}m forward, {((ArmPlacement)(ref placement)).Lift:0.#}m up, {((ArmPlacement)(ref placement)).Scale:0.##}x); " + "they follow it until it is supplied again."); } } public void Follow(ArmPlacement placement) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) _placement = placement; for (int i = 0; i < _raised.Count; i++) { Put(_raised[i], _artRoots[i], _stations[i], placement); if (_ours) { FightingPlayers.FillFighting(_quarry[i]); } } } public void Adopt(int count) { if (count <= 0 || Raised >= count) { return; } GameManager instance = StaticInstance.Instance; List list = (((Object)(object)instance != (Object)null) ? instance.aliveNpcs : null); if (list == null) { return; } ushort value = UnitIds.GoblinCousinArm.value; for (int i = 0; i < list.Count; i++) { if (_raised.Count >= count) { break; } Npc val = list[i]; if (!((Object)(object)val == (Object)null) && ((Unit)val).IsAlive && !((Object)(object)((Unit)val).unitSO == (Object)null) && ((Unit)val).unitSO.id.value == value && !Holding((Unit)(object)val)) { _ours = false; _raised.Add((Unit)(object)val); _stations.Add(_raised.Count - 1); _artRoots.Add(FindArtRoot((Unit)(object)val)); _quarry.Add(EmptyQuarry); } } if (_raised.Count > 0) { ILogger? logger = _logger; if (logger != null) { logger.Log($"[arm] carrying {_raised.Count} arm(s) the session put here; this peer places them " + "itself from now on."); } } } public void Release() { if (_raised.Count != 0) { _generation++; ILogger? logger = _logger; if (logger != null) { logger.Log($"[arm] letting go of {_raised.Count} arm(s); they are the host's to end."); } _raised.Clear(); _stations.Clear(); _artRoots.Clear(); _quarry.Clear(); } } private bool Holding(Unit arm) { for (int i = 0; i < _raised.Count; i++) { if (_raised[i] == arm) { return true; } } return false; } public void LowerAll() { _generation++; int num = 0; for (int i = 0; i < _raised.Count; i++) { Unit val = _raised[i]; if ((Object)(object)val == (Object)null) { continue; } try { val.Die(); num++; } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[arm] an arm could not be taken down (" + ex.Message + "); leaving it."); } } } _raised.Clear(); _stations.Clear(); _artRoots.Clear(); _quarry.Clear(); if (num > 0) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log($"[arm] {num} arm(s) sink back into the ground."); } } } private async void RaiseOne(UnitSO definition, Vector3 position, int station, int generation) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) Unit val; try { val = await definition.SpawnUnitAsync(_host, position, default(Quaternion)); } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[arm] an arm failed to rise: " + ex.Message); } return; } if ((Object)(object)val == (Object)null) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[arm] an arm failed to rise (the game returned no unit)."); } return; } if (generation != _generation) { try { val.Die(); return; } catch (Exception) { return; } } try { val.SetInvulnerable(true); } catch (Exception ex3) { ILogger? logger3 = _logger; if (logger3 != null) { logger3.LogWarning("[arm] an arm could not be made invulnerable (" + ex3.Message + ")."); } } ReachAcrossTheRoom(val); Transform val2 = FindArtRoot(val); List list = new List(4); FightingPlayers.FillFighting(list); AimWithoutSight(val, list); _raised.Add(val); _stations.Add(station); _artRoots.Add(val2); _quarry.Add(list); Put(val, val2, station, _placement); } private static void Put(Unit? arm, Transform? artRoot, int station, ArmPlacement placement) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)arm == (Object)null)) { Transform transform = ((Component)arm).transform; if (((ArmPlacement)(ref placement)).Scale > 0f) { transform.localScale = new Vector3(((ArmPlacement)(ref placement)).Scale, ((ArmPlacement)(ref placement)).Scale, ((ArmPlacement)(ref placement)).Scale); } Vector3 val = Vector3.zero; if ((Object)(object)artRoot != (Object)null) { val = artRoot.position - transform.position; val.y = 0f; } transform.position = StandingPoint(placement, station) - val; } } private void ReachAcrossTheRoom(Unit arm) { try { Npc val = (Npc)(object)((arm is Npc) ? arm : null); if (val != null) { val.rangedAttackRange = 100f; } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[arm] an arm kept its own throwing range (" + ex.Message + "); it will only answer players close to the boss."); } } } private void AimWithoutSight(Unit arm, List quarry) { try { Unit obj = ((arm is Npc) ? arm : null); AiAgent val = ((obj != null) ? ((Npc)obj).AiAgent : null); if (!((Object)(object)val == (Object)null)) { val.overridetargets.AddUnits(quarry, (TargetType)2); } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[arm] an arm could not be told who to throw at (" + ex.Message + "); it will only answer players it can see."); } } } private static Transform? FindArtRoot(Unit unit) { Transform val = ((Component)unit).transform.Find("Root"); if (!((Object)(object)val != (Object)null)) { return null; } return val; } private static Vector3 StandingPoint(ArmPlacement placement, int station) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_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) float num = ((station % 2 == 0) ? 1f : (-1f)); int num2 = station / 2 + 1; SimVector2 bossFacing = ((ArmPlacement)(ref placement)).BossFacing; float x = ((SimVector2)(ref bossFacing)).X; bossFacing = ((ArmPlacement)(ref placement)).BossFacing; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(x, 0f, ((SimVector2)(ref bossFacing)).Z); Vector3 val2 = Vector3.right; if (((Vector3)(ref val)).sqrMagnitude > 0.0001f) { val = ((Vector3)(ref val)).normalized; val2 = Vector3.Cross(Vector3.up, val); } else { val = Vector3.forward; } ArenaWorldPoint bossAt = ((ArmPlacement)(ref placement)).BossAt; float x2 = ((ArenaWorldPoint)(ref bossAt)).X; bossAt = ((ArmPlacement)(ref placement)).BossAt; float y = ((ArenaWorldPoint)(ref bossAt)).Y; bossAt = ((ArmPlacement)(ref placement)).BossAt; return new Vector3(x2, y, ((ArenaWorldPoint)(ref bossAt)).Z) + val2 * (num * ((ArmPlacement)(ref placement)).SideDistance * (float)num2) + Vector3.up * ((ArmPlacement)(ref placement)).Lift + val * ((ArmPlacement)(ref placement)).ForwardOffset; } private void Forget() { for (int num = _raised.Count - 1; num >= 0; num--) { Unit val = _raised[num]; if ((Object)(object)val == (Object)null || !val.IsAlive) { _raised.RemoveAt(num); _stations.RemoveAt(num); _artRoots.RemoveAt(num); _quarry.RemoveAt(num); } } } } public sealed class SulfurBossPresence : IBossPresencePort { private const string ArmourFieldName = "armor"; private const string BossBarLabelFieldName = "bossName"; private readonly Func _solidBody; private readonly ILogger? _logger; private GameObject? _listing; private Npc? _npc; private bool _onTheBar; private float _shownHealth = -1f; private OnLanguageChange? _renameOnLanguageChange; public SulfurBossPresence(Func solidBody, ILogger? logger = null) { _solidBody = solidBody ?? throw new ArgumentNullException("solidBody"); _logger = logger; } public void Declare() { //IL_0026: 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_008f: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_npc != (Object)null) { return; } Collider val = _solidBody(); if ((Object)(object)val == (Object)null) { return; } UnitSO asset; try { asset = AssetAccess.GetAsset(UnitIds.GoblinCousin); } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[presence] the game would not give up a creature definition to borrow (" + ex.Message + "); homing weapons and aim assist will not see the boss."); } return; } if ((Object)(object)asset == (Object)null) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[presence] the game has no cave-boss definition to borrow; homing weapons and aim assist will not see the boss."); } return; } try { _listing = new GameObject("FalseGodsBossPresence"); _listing.transform.SetParent(((Component)val).transform, false); _listing.transform.localPosition = MiddleOf(val); Npc val2 = _listing.AddComponent(); ((Unit)val2).unitSO = asset; ((Unit)val2).mainCollider = val; val2.center = _listing.transform; EmptyTheArmour(val2); StaticInstance.Instance.aliveNpcs.Add(val2); _npc = val2; ILogger? logger3 = _logger; if (logger3 != null) { logger3.Log("[presence] the boss is on the game's enemy list: homing weapons follow it and aim assist holds on it. It is listed only - the game does not run it."); } } catch (Exception ex2) { ILogger? logger4 = _logger; if (logger4 != null) { logger4.LogWarning("[presence] the boss could not be listed as an enemy (" + ex2.Message + "); homing weapons and aim assist will not see it."); } Withdraw(); } } public void ShowHealthBar() { Npc npc = _npc; if ((Object)(object)npc == (Object)null || _onTheBar) { return; } try { ((Unit)npc).AttachToBossUI(true); _onTheBar = true; _shownHealth = 1f; NameTheBoss(npc); KeepTheNameInThePlayersLanguage(); ILogger? logger = _logger; if (logger != null) { logger.Log("[boss-bar] the boss is on the game's own boss bar."); } } catch (Exception ex) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[boss-bar] the boss could not be put on the game's boss bar (" + ex.Message + "); the fight runs without it."); } } } public void ReportHealth(float fraction) { Npc npc = _npc; if ((Object)(object)npc == (Object)null || !_onTheBar) { return; } float num = ((fraction < 0f) ? 0f : ((fraction > 1f) ? 1f : fraction)); if (Math.Abs(num - _shownHealth) < 0.0001f) { return; } _shownHealth = num; try { OnHealthChange onHealthChange = ((Unit)npc).onHealthChange; if (onHealthChange != null) { onHealthChange.Invoke(num); } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[boss-bar] the boss's health could not be shown (" + ex.Message + ")."); } } } public void HideHealthBar() { Npc npc = _npc; if ((Object)(object)npc == (Object)null || !_onTheBar) { return; } _onTheBar = false; _shownHealth = -1f; StopFollowingTheLanguage(); try { ((Unit)npc).AttachToBossUI(false); } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[boss-bar] the boss could not be taken off the boss bar (" + ex.Message + ")."); } } } private void NameTheBoss(Npc npc) { try { UIManager instance = StaticInstance.Instance; BossHealth val = (((Object)(object)instance != (Object)null) ? instance.bossUI : null); if ((Object)(object)val == (Object)null) { return; } object? obj = typeof(BossHealth).GetField("bossName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val); TMP_Text val2 = (TMP_Text)((obj is TMP_Text) ? obj : null); if ((Object)(object)val2 == (Object)null) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[boss-bar] the bar's 'bossName' is not where it was; the borrowed creature's own name will be shown."); } } else { FalseGodTitle val3 = FalseGodTitle.For(LocalizationManager.CurrentLanguageCode); val2.text = FalseGodTitle.Compose(LocalizationManager.FixRTL_IfNeeded(val3.Word, 0, false), val3.Joiner, ((Unit)npc).GetActorName(), LocalizationManager.IsRight2Left); } } catch (Exception ex) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[boss-bar] the boss's name could not be set (" + ex.Message + ")."); } } } private void KeepTheNameInThePlayersLanguage() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown if (_renameOnLanguageChange != null) { return; } try { AsyncAssetLoading instance = StaticInstance.Instance; if ((Object)(object)instance == (Object)null) { return; } _renameOnLanguageChange = (OnLanguageChange)delegate { Npc npc = _npc; if ((Object)(object)npc != (Object)null && _onTheBar) { NameTheBoss(npc); } }; instance.onLanguageChange = (OnLanguageChange)Delegate.Combine((Delegate?)(object)instance.onLanguageChange, (Delegate?)(object)_renameOnLanguageChange); } catch (Exception ex) { _renameOnLanguageChange = null; ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[boss-bar] the boss's name will not follow a language change (" + ex.Message + ")."); } } } private void StopFollowingTheLanguage() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown OnLanguageChange renameOnLanguageChange = _renameOnLanguageChange; _renameOnLanguageChange = null; if (renameOnLanguageChange == null) { return; } try { AsyncAssetLoading instance = StaticInstance.Instance; if ((Object)(object)instance != (Object)null) { instance.onLanguageChange = (OnLanguageChange)Delegate.Remove((Delegate?)(object)instance.onLanguageChange, (Delegate?)(object)renameOnLanguageChange); } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[boss-bar] the boss's rename could not be unsubscribed from language changes (" + ex.Message + ")."); } } } public void Withdraw() { HideHealthBar(); StopFollowingTheLanguage(); Npc npc = _npc; _npc = null; if ((Object)(object)npc != (Object)null) { try { GameManager instance = StaticInstance.Instance; if (instance != null) { instance.aliveNpcs.Remove(npc); } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[presence] the boss could not be taken off the enemy list (" + ex.Message + ")."); } } } if ((Object)(object)_listing != (Object)null) { try { Object.Destroy((Object)(object)_listing); } catch (Exception) { } _listing = null; } } private static Vector3 MiddleOf(Collider body) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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) CapsuleCollider val = (CapsuleCollider)(object)((body is CapsuleCollider) ? body : null); if (val == null) { BoxCollider val2 = (BoxCollider)(object)((body is BoxCollider) ? body : null); if (val2 == null) { return Vector3.zero; } return val2.center; } return val.center; } private void EmptyTheArmour(Npc npc) { try { FieldInfo field = typeof(Unit).GetField("armor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Type type = field?.FieldType.GetElementType(); if (field != null && type != null && field.GetValue(npc) == null) { field.SetValue(npc, Array.CreateInstance(type, 0)); } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[presence] the listing's armour could not be emptied (" + ex.Message + ")."); } } } } public sealed class SulfurBossReward : IBossRewardPort { private const int Draws = 2; private const int Money = 2500; private static readonly (ItemId Item, float Weight)[] Table = new(ItemId, float)[42] { (ItemIds.Weapon_Gravekeeper, 20f), (ItemIds.Weapon_Mario, 20f), (ItemIds.Weapon_Termite, 20f), (ItemIds.Weapon_Knop, 20f), (ItemIds.Weapon_Bronco, 20f), (ItemIds.Weapon_Mossman, 20f), (ItemIds.Weapon_Beck, 20f), (ItemIds.Weapon_Breacher8, 20f), (ItemIds.Weapon_Socom9, 20f), (ItemIds.Weapon_WyattPulsar, 30f), (ItemIds.Weapon_FlickerZip, 30f), (ItemIds.Weapon_StarAndWitness, 30f), (ItemIds.Weapon_Augusta, 30f), (ItemIds.Weapon_PalehorseTopclipper, 30f), (ItemIds.Weapon_Vrede, 30f), (ItemIds.Weapon_Balthazar, 30f), (ItemIds.Weapon_D4RT, 30f), (ItemIds.Weapon_DeathStar, 30f), (ItemIds.Weapon_Dolphin99, 30f), (ItemIds.Weapon_ImpalaGravita, 30f), (ItemIds.Weapon_Flock, 30f), (ItemIds.Weapon_Nunchaku, 30f), (ItemIds.Weapon_TailorMarksman, 30f), (ItemIds.Weapon_Sai, 40f), (ItemIds.Weapon_Bo, 40f), (ItemIds.Weapon_Corpsemaker, 40f), (ItemIds.Weapon_Katana, 40f), (ItemIds.Weapon_Valet, 40f), (ItemIds.Item_CryptKey, 40f), (ItemIds.Weapon_NeuraxisF22, 40f), (ItemIds.Weapon_PierreFusil, 40f), (ItemIds.Weapon_Salamander, 40f), (ItemIds.Weapon_Typhoon, 40f), (ItemIds.Weapon_Rokua, 18f), (ItemIds.Weapon_M11Ramshack, 18f), (ItemIds.Weapon_Catacoil, 18f), (ItemIds.Weapon_Duhar, 18f), (ItemIds.Weapon_Majordome, 18f), (ItemIds.Weapon_Rektor, 18f), (ItemIds.Weapon_Ferryman, 18f), (ItemIds.Attachment_Insurance, 18f), (ItemIds.Manual_GoblinCooking, 18f) }; private readonly ILogger? _logger; public SulfurBossReward(ILogger? logger = null) { _logger = logger; } public void DropReward(ArenaWorldPoint at) { //IL_0072: 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_00a0: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((ArenaWorldPoint)(ref at)).X, ((ArenaWorldPoint)(ref at)).Y, ((ArenaWorldPoint)(ref at)).Z); try { LootManager instance = StaticInstance.Instance; if ((Object)(object)instance == (Object)null) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[reward] the game has no loot manager to pay through; nothing dropped."); } return; } int missing; LootTable val2 = BuildTable(out missing); if ((Object)(object)val2 == (Object)null) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[reward] not one item of the boss's table could be resolved; nothing dropped. The item database is loaded on demand, so this means it was asked too early."); } return; } Room val3 = Room.FindClosestRoom(val, (Room)null, 3f); for (int i = 0; i < 2; i++) { instance.SpawnLootFrom(val2, val, val3); } instance.SpawnMoney(2500, val, val3); ILogger? logger3 = _logger; if (logger3 != null) { logger3.Log($"[reward] the boss pays out: {2} draw(s) from a table of " + $"{val2.entries.Count} and {2500} in money" + ((missing > 0) ? $" ({missing} item(s) this build does not have were left out)" : string.Empty) + ". This peer rolled its own."); } } catch (Exception ex) { ILogger? logger4 = _logger; if (logger4 != null) { logger4.LogWarning("[reward] the boss's payout failed (" + ex.Message + "); nothing dropped."); } } } private static LootTable? BuildTable(out int missing) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) missing = 0; LootTable val = ScriptableObject.CreateInstance(); val.entries = new List(Table.Length); for (int i = 0; i < Table.Length; i++) { ItemDefinition asset = AssetAccess.GetAsset(Table[i].Item); if ((Object)(object)asset == (Object)null) { missing++; } else { val.AddEntry(asset, Table[i].Weight); } } if (val.entries.Count <= 0) { return null; } return val; } } public sealed class SulfurCarriedLoadMirror { private sealed class Load { private readonly List _drawn = new List(); public Unit Goblin { get; } public int Shown => _drawn.Count; public Load(Unit goblin) { Goblin = goblin; } public void Show(int crates, Mesh look, Material lookMaterial) { //IL_008e: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown if ((Object)(object)Goblin == (Object)null) { return; } while (_drawn.Count < crates) { GameObject val; if ((Object)(object)look != (Object)null && (Object)(object)lookMaterial != (Object)null) { val = new GameObject("FalseGods_CarriedCrate"); val.AddComponent().sharedMesh = look; ((Renderer)val.AddComponent()).sharedMaterial = lookMaterial; } else { val = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)val).name = "FalseGods_CarriedCrate"; Collider component = val.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } val.transform.SetParent(((Component)Goblin).transform, false); val.transform.localScale = Vector3.one * 0.5f; val.transform.localPosition = new Vector3(0f, 1.9f + (float)_drawn.Count * 0.55f, 0f); _drawn.Add(val); } } public void Clear() { for (int i = 0; i < _drawn.Count; i++) { if ((Object)(object)_drawn[i] != (Object)null) { Object.Destroy((Object)(object)_drawn[i]); } } _drawn.Clear(); } } private const float MatchRadius = 8f; private const float StackSpacing = 0.55f; private const float StackBase = 1.9f; private const int MaxDrawnStack = 5; private readonly SulfurThrownCratePort _crates; private readonly ILogger _logger; private readonly List _loads = new List(); public SulfurCarriedLoadMirror(SulfurThrownCratePort crates, ILogger logger = null) { _crates = crates ?? throw new ArgumentNullException("crates"); _logger = logger; } public void PickedUp(ArenaWorldPoint at, int count) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) Forget(); if (count <= 0) { return; } Unit val = NearestCivilianTo(new Vector3(((ArenaWorldPoint)(ref at)).X, ((ArenaWorldPoint)(ref at)).Y, ((ArenaWorldPoint)(ref at)).Z)); if (!((Object)(object)val == (Object)null)) { Load load = Find(val); if (load == null) { load = new Load(val); _loads.Add(load); } _crates.TryGetLook(out var mesh, out var material); load.Show(Math.Min(count + load.Shown, 5), mesh, material); } } public void PutDown(ArenaWorldPoint from) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) Forget(); Unit val = NearestCivilianTo(new Vector3(((ArenaWorldPoint)(ref from)).X, ((ArenaWorldPoint)(ref from)).Y, ((ArenaWorldPoint)(ref from)).Z)); if (!((Object)(object)val == (Object)null)) { Find(val)?.Clear(); } } public void Clear() { for (int i = 0; i < _loads.Count; i++) { _loads[i].Clear(); } _loads.Clear(); } private Load Find(Unit goblin) { for (int i = 0; i < _loads.Count; i++) { if (_loads[i].Goblin == goblin) { return _loads[i]; } } return null; } private void Forget() { for (int num = _loads.Count - 1; num >= 0; num--) { if ((Object)(object)_loads[num].Goblin == (Object)null || !_loads[num].Goblin.IsAlive) { _loads[num].Clear(); _loads.RemoveAt(num); } } } private static Unit NearestCivilianTo(Vector3 point) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) GameManager instance = StaticInstance.Instance; List list = (((Object)(object)instance != (Object)null) ? instance.aliveNpcs : null); if (list == null) { return null; } Unit result = null; float num = 64f; for (int i = 0; i < list.Count; i++) { Npc val = list[i]; if (!((Object)(object)val == (Object)null) && ((Unit)val).IsAlive && ((Unit)val).IsCivilian) { Vector3 val2 = ((Component)val).transform.position - point; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = (Unit)(object)val; } } } return result; } } public sealed class SulfurCarrierPort : ICarrierPort { private enum Leg { ToSource, ToPile } private sealed class Carrier { private readonly List _drawn = new List(); private readonly List _carried = new List(); public int ExplosivesHeld { get { int num = 0; for (int i = 0; i < _carried.Count; i++) { if (_carried[i].Explosive) { num++; } } return num; } } public Unit Unit { get; } public Npc Npc { get; } public Leg Leg { get; set; } public int SourceIndex { get; set; } public int Load { get; set; } public ArenaWorldPoint Fetch { get; set; } public CratePileId FetchPile { get; set; } public bool Aimed { get; set; } public float OnLeg { get; set; } public float Handling { get; set; } public float Waited { get; set; } public Vector3 Destination { get; set; } public Vector3 LastPosition { get; set; } public Vector3 StillSince { get; set; } public float Still { get; set; } public Carrier(Unit unit, int sourceIndex) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) Unit = unit; Npc = (Npc)(object)((unit is Npc) ? unit : null); SourceIndex = sourceIndex; Leg = Leg.ToSource; LastPosition = (((Object)(object)unit != (Object)null) ? ((Component)unit).transform.position : Vector3.zero); } public void Shoulder(List picked, int took) { for (int i = 0; i < picked.Count && i < took; i++) { _carried.Add(picked[i]); } while (_carried.Count < Load) { _carried.Add((_carried.Count > 0) ? _carried[_carried.Count - 1] : default(SulfurThrownCratePort.CrateLook)); } Redraw(); } public void DrawLoad() { if (!((Object)(object)Unit == (Object)null)) { Redraw(); } } private void Redraw() { int num = Math.Min(Load, 5); while (_drawn.Count > num) { GameObject val = _drawn[_drawn.Count - 1]; _drawn.RemoveAt(_drawn.Count - 1); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } while (_drawn.Count < num) { _drawn.Add(MakeOne(((Component)Unit).transform, _drawn.Count, LookAt(_drawn.Count, num))); } } private SulfurThrownCratePort.CrateLook LookAt(int place, int drawn) { if (place >= _carried.Count) { return default(SulfurThrownCratePort.CrateLook); } if (place == drawn - 1 && _carried.Count > drawn && ExplosivesHeld > 0 && !AnyExplosiveWithin(drawn - 1)) { return FirstExplosive(); } return _carried[place]; } private bool AnyExplosiveWithin(int places) { for (int i = 0; i < places && i < _carried.Count; i++) { if (_carried[i].Explosive) { return true; } } return false; } private SulfurThrownCratePort.CrateLook FirstExplosive() { for (int i = 0; i < _carried.Count; i++) { if (_carried[i].Explosive) { return _carried[i]; } } return default(SulfurThrownCratePort.CrateLook); } private static GameObject MakeOne(Transform on, int place, SulfurThrownCratePort.CrateLook look) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) GameObject val; if (look.Known) { val = new GameObject("FalseGods_CarriedCrate"); val.AddComponent().sharedMesh = look.Mesh; ((Renderer)val.AddComponent()).sharedMaterial = look.Material; } else { val = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)val).name = "FalseGods_CarriedCrate"; Collider component = val.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } val.transform.SetParent(on, false); val.transform.localScale = Vector3.one * 0.5f; val.transform.localPosition = new Vector3(0f, 1.9f + (float)place * 0.55f, 0f); return val; } public void ClearDrawnLoad() { _carried.Clear(); for (int i = 0; i < _drawn.Count; i++) { if ((Object)(object)_drawn[i] != (Object)null) { Object.Destroy((Object)(object)_drawn[i]); } } _drawn.Clear(); } } private static readonly UnitId CarrierUnit = UnitIds.GoblinCivilian; private const float ArrivalRadius = 2.5f; private const float LegTimeoutSeconds = 45f; private const float HandlingSeconds = 0.75f; private const float StackSpacing = 0.55f; private const float StackBase = 1.9f; private const float SetDownMinRadius = 1.2f; private const float SetDownMaxRadius = 4f; private const float SetDownHeight = 1.2f; private const float SetDownFlightSeconds = 0.55f; private const float SetDownApexHeight = 1.6f; private const float PickUpReach = 9f; private const float StillTooLongSeconds = 5f; private const float StillEnough = 0.05f; private const int MaxDrawnStack = 5; private readonly MonoBehaviour _host; private readonly IThrownCratePort _crates; private readonly ILogger _logger; private readonly Action _announceTaken; private readonly Action _announceSetDown; private readonly List _carriers = new List(); private bool _reportedDeactivationTrap; private bool _pending; private readonly List _justPickedUp = new List(); private readonly List _claimedHeaps = new List(); private float _routeClock; private float _replaceAfterSeconds; private readonly List _mourning = new List(); private int _nextSetDownSeed = 1; private float _observedWalkSpeed; public int Working { get { Forget(); return _carriers.Count; } } public float ObservedWalkSpeed => _observedWalkSpeed; public int Carried { get { Forget(); int num = 0; for (int i = 0; i < _carriers.Count; i++) { num += _carriers[i].Load; } return num; } } public SulfurCarrierPort(MonoBehaviour host, IThrownCratePort crates, ILogger logger = null, Action announceTaken = null, Action announceSetDown = null) { _host = host ?? throw new ArgumentNullException("host"); _crates = crates ?? throw new ArgumentNullException("crates"); _logger = logger; _announceTaken = announceTaken; _announceSetDown = announceSetDown; } public void Warm(ArenaWorldPoint at) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) MakeOneAndThrowItAway(at); } private async void MakeOneAndThrowItAway(ArenaWorldPoint at) { //IL_0016: 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) try { UnitSO asset = AssetAccess.GetAsset(CarrierUnit); if ((Object)(object)asset == (Object)null) { return; } Unit val = await asset.SpawnUnitAsync(_host, new Vector3(((ArenaWorldPoint)(ref at)).X, ((ArenaWorldPoint)(ref at)).Y, ((ArenaWorldPoint)(ref at)).Z), default(Quaternion)); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); ILogger logger = _logger; if (logger != null) { logger.Log("[carrier] one villager was made and dismissed while the level was still loading, so the first of the route is not the first ever built."); } } } catch (Exception ex) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[carrier] the village could not be warmed ahead of time (" + ex.Message + "); the first carrier will pay for it instead."); } } } public void Advance(float deltaSeconds, int wanted, int loadPerCarrier, float replaceAfterSeconds, IReadOnlyList sources, ArenaWorldPoint deliverTo, CratePileId deliverPile) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) _routeClock += deltaSeconds; _replaceAfterSeconds = replaceAfterSeconds; Forget(); if (sources != null && sources.Count != 0) { PutOnTheRoute(wanted, sources); TakeOffTheRoute(wanted); for (int i = 0; i < _carriers.Count; i++) { Advance(_carriers[i], deltaSeconds, loadPerCarrier, sources, deliverTo, deliverPile); } } } public void DismissAll() { int num = 0; for (int i = 0; i < _carriers.Count; i++) { if (Remove(_carriers[i], spillLoad: false)) { num++; } } _carriers.Clear(); _mourning.Clear(); if (num > 0) { ILogger logger = _logger; if (logger != null) { logger.Log($"[carrier] {num} carrier(s) taken off the route with the encounter."); } } } public void Disband() { int num = 0; int num2 = 0; for (int i = 0; i < _carriers.Count; i++) { Carrier carrier = _carriers[i]; num2 += DropWhatItIsHolding(carrier); carrier.ClearDrawnLoad(); if (SendBackToItsOwnLife(carrier)) { num++; } } _carriers.Clear(); _mourning.Clear(); if (num > 0 || num2 > 0) { ILogger logger = _logger; if (logger != null) { logger.Log($"[carrier] the errand is over: {num} villager(s) went back to their own lives, " + $"{num2} crate(s) put down where they stood."); } } } private bool SendBackToItsOwnLife(Carrier carrier) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) Npc npc = carrier.Npc; if ((Object)(object)npc == (Object)null || (Object)(object)carrier.Unit == (Object)null) { return false; } try { npc.SetForcedDestination(Vector3.zero); npc.ActivateBehaviourTree(); return true; } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[carrier] a villager could not be given its own behaviour back (" + ex.Message + "); it will stand where it is."); } return false; } } private int DropWhatItIsHolding(Carrier carrier) { //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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (carrier.Load <= 0 || carrier.LastPosition == Vector3.zero) { return 0; } ArenaWorldPoint at = default(ArenaWorldPoint); ((ArenaWorldPoint)(ref at))..ctor(carrier.LastPosition.x, carrier.LastPosition.y, carrier.LastPosition.z); int result = TossLoadAround(carrier, at, CratePileId.Loose); carrier.Load = 0; return result; } private void Advance(Carrier carrier, float deltaSeconds, int loadPerCarrier, IReadOnlyList sources, ArenaWorldPoint deliverTo, CratePileId deliverPile) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_01df: 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_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Invalid comparison between Unknown and I4 //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) carrier.OnLeg += deltaSeconds; carrier.DrawLoad(); if (HasSeizedUp(carrier, deltaSeconds)) { PutBackOnTheRoute(carrier, sources); return; } switch (carrier.Leg) { case Leg.ToSource: { if (!carrier.Aimed) { AimAtSomethingToFetch(carrier, sources); Begin(carrier, Leg.ToSource, carrier.Fetch); carrier.Aimed = true; break; } if (!HasArrived(carrier, carrier.Fetch)) { RepeatIfStuck(carrier, carrier.Fetch); break; } carrier.Handling += deltaSeconds; if (carrier.Handling < 0.75f) { break; } int num = loadPerCarrier - carrier.Load; if (num > 0) { Vector3 val = (((Object)(object)carrier.Unit != (Object)null) ? ((Component)carrier.Unit).transform.position : carrier.LastPosition); ArenaWorldPoint val2 = default(ArenaWorldPoint); ((ArenaWorldPoint)(ref val2))..ctor(val.x, val.y, val.z); _justPickedUp.Clear(); int num2 = ((_crates is SulfurThrownCratePort sulfurThrownCratePort) ? sulfurThrownCratePort.TakeFrom(carrier.FetchPile, num, val2, 9f, _justPickedUp) : _crates.TakeFrom(carrier.FetchPile, num, val2, 9f)); if (num2 > 0) { carrier.Load += num2; carrier.Shoulder(_justPickedUp, num2); _announceTaken?.Invoke(val2, carrier.FetchPile, num2, 9f); } } if (carrier.Load <= 0) { AimAtSomethingToFetch(carrier, sources); Begin(carrier, Leg.ToSource, carrier.Fetch); break; } if (carrier.Load < loadPerCarrier) { CratePileId fetchPile = carrier.FetchPile; if ((int)((CratePileId)(ref fetchPile)).Kind == 1 && carrier.Waited < 3f) { carrier.Waited += deltaSeconds; break; } } Begin(carrier, Leg.ToPile, deliverTo); break; } case Leg.ToPile: if (!HasArrived(carrier, deliverTo)) { Retarget(carrier, deliverTo); RepeatIfStuck(carrier, deliverTo); break; } carrier.Handling += deltaSeconds; if (!(carrier.Handling < 0.75f)) { SetDown(carrier, deliverTo, deliverPile); carrier.SourceIndex++; AimAtSomethingToFetch(carrier, sources); Begin(carrier, Leg.ToSource, carrier.Fetch); } break; } } private void AimAtSomethingToFetch(Carrier carrier, IReadOnlyList sources) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) ArenaWorldPoint fetch = sources[carrier.SourceIndex % sources.Count]; carrier.Fetch = fetch; carrier.FetchPile = CratePileId.Source(carrier.SourceIndex % sources.Count); Vector3 val = (((Object)(object)carrier.Unit != (Object)null) ? ((Component)carrier.Unit).transform.position : Vector3.zero); ArenaWorldPoint val2 = default(ArenaWorldPoint); ((ArenaWorldPoint)(ref val2))..ctor(val.x, val.y, val.z); ArenaWorldPoint fetch2 = default(ArenaWorldPoint); if (_crates.TryFindNearestResting(CratePileId.Loose, val2, ref fetch2, HeapsBeingCollected(carrier), 9f)) { carrier.Fetch = fetch2; carrier.FetchPile = CratePileId.Loose; } } private IReadOnlyList HeapsBeingCollected(Carrier except) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) _claimedHeaps.Clear(); for (int i = 0; i < _carriers.Count; i++) { Carrier carrier = _carriers[i]; if (carrier != except && carrier.Aimed && carrier.Leg == Leg.ToSource) { CratePileId fetchPile = carrier.FetchPile; if ((int)((CratePileId)(ref fetchPile)).Kind == 0) { _claimedHeaps.Add(carrier.Fetch); } } } return _claimedHeaps; } private int TossLoadAround(Carrier carrier, ArenaWorldPoint at, CratePileId pile) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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) int load = carrier.Load; if (load <= 0) { return 0; } Vector3 val = (((Object)(object)carrier.Unit != (Object)null) ? ((Component)carrier.Unit).transform.position : carrier.LastPosition); ArenaWorldPoint val2 = default(ArenaWorldPoint); ((ArenaWorldPoint)(ref val2))..ctor(val.x, val.y + 1.9f, val.z); int num = _nextSetDownSeed++; int explosivesHeld = carrier.ExplosivesHeld; int result = _crates.TossRing(val2, at, pile, load, num, explosivesHeld); Action announceSetDown = _announceSetDown; if (announceSetDown != null) { announceSetDown(val2, at, pile, load, num, explosivesHeld); return result; } return result; } private static bool HasSeizedUp(Carrier carrier, float deltaSeconds) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_003d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)carrier.Unit == (Object)null) { return false; } Vector3 position = ((Component)carrier.Unit).transform.position; Vector3 val = position - carrier.StillSince; if (((Vector3)(ref val)).sqrMagnitude > 0.0025000002f) { carrier.StillSince = position; carrier.Still = 0f; return false; } carrier.Still += deltaSeconds; return carrier.Still >= 5f; } private void PutBackOnTheRoute(Carrier carrier, IReadOnlyList sources) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) carrier.Still = 0f; if ((Object)(object)carrier.Unit == (Object)null || sources == null || sources.Count == 0) { return; } ArenaWorldPoint destination = sources[(carrier.SourceIndex >= 0 && carrier.SourceIndex < sources.Count) ? carrier.SourceIndex : 0]; try { carrier.Unit.TeleportTo(new Vector3(((ArenaWorldPoint)(ref destination)).X, ((ArenaWorldPoint)(ref destination)).Y, ((ArenaWorldPoint)(ref destination)).Z)); carrier.StillSince = ((Component)carrier.Unit).transform.position; carrier.LastPosition = ((Component)carrier.Unit).transform.position; } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[carrier] a stuck carrier could not be moved (" + ex.Message + "); it will be tried again."); } return; } carrier.Aimed = false; Begin(carrier, Leg.ToSource, destination); ILogger logger2 = _logger; if (logger2 != null) { logger2.Log($"[carrier] one stood still for {5f:0.#}s and was put back at its " + $"production point, still holding {carrier.Load}."); } } private static float Flat(ArenaWorldPoint a, ArenaWorldPoint b) { float num = ((ArenaWorldPoint)(ref a)).X - ((ArenaWorldPoint)(ref b)).X; float num2 = ((ArenaWorldPoint)(ref a)).Z - ((ArenaWorldPoint)(ref b)).Z; return num * num + num2 * num2; } private void SetDown(Carrier carrier, ArenaWorldPoint at, CratePileId pile) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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) int num = TossLoadAround(carrier, at, pile); ILogger logger = _logger; if (logger != null) { logger.Log($"[carrier] delivered {num} to {pile}; {_crates.RestingOn(pile)} now on that pile."); } carrier.Load = 0; carrier.ClearDrawnLoad(); } private void Spill(Carrier carrier) { //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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (carrier.Load > 0 && !(carrier.LastPosition == Vector3.zero)) { ArenaWorldPoint at = default(ArenaWorldPoint); ((ArenaWorldPoint)(ref at))..ctor(carrier.LastPosition.x, carrier.LastPosition.y, carrier.LastPosition.z); int load = carrier.Load; int num = TossLoadAround(carrier, at, CratePileId.Loose); ILogger logger = _logger; if (logger != null) { logger.Log($"[carrier] a carrier died holding {load}; {num} spilled where it fell — " + "the boss cannot fire those."); } carrier.Load = 0; } } private void PutOnTheRoute(int wanted, IReadOnlyList sources) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) for (int num = _mourning.Count - 1; num >= 0; num--) { if (_mourning[num] <= _routeClock) { _mourning.RemoveAt(num); } } int num2 = wanted - _mourning.Count; if (_carriers.Count < num2 && !_pending) { int count = _carriers.Count; ArenaWorldPoint val = sources[count % sources.Count]; _pending = true; SpawnOne(new Vector3(((ArenaWorldPoint)(ref val)).X, ((ArenaWorldPoint)(ref val)).Y, ((ArenaWorldPoint)(ref val)).Z), count); } } private void TakeOffTheRoute(int wanted) { int num = _carriers.Count - 1; while (num >= wanted && num >= 0) { Remove(_carriers[num], spillLoad: true); _carriers.RemoveAt(num); num--; } } private async void SpawnOne(Vector3 at, int sourceIndex) { //IL_0016: 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) Unit unit = null; try { UnitSO asset = AssetAccess.GetAsset(CarrierUnit); if ((Object)(object)asset == (Object)null) { ILogger logger = _logger; if (logger != null) { logger.LogWarning($"[carrier] the game has no definition for {CarrierUnit.value}; the boss " + "will have to do without carriers."); } return; } unit = await asset.SpawnUnitAsync(_host, at, default(Quaternion)); } catch (Exception ex) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[carrier] a carrier failed to spawn: " + ex.Message); } } finally { _pending = false; } if (!((Object)(object)unit == (Object)null)) { Carrier item = new Carrier(unit, sourceIndex); ReportTheDeactivationTrapOnce(unit); _carriers.Add(item); } } private void Forget() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) for (int num = _carriers.Count - 1; num >= 0; num--) { Carrier carrier = _carriers[num]; if ((Object)(object)carrier.Unit != (Object)null && carrier.Unit.IsAlive) { carrier.LastPosition = ((Component)carrier.Unit).transform.position; } else { Spill(carrier); carrier.ClearDrawnLoad(); _carriers.RemoveAt(num); if (_replaceAfterSeconds > 0f) { _mourning.Add(_routeClock + _replaceAfterSeconds); ILogger logger = _logger; if (logger != null) { logger.Log($"[carrier] one is down; the route stays {_replaceAfterSeconds:0.#}s short " + $"({_carriers.Count} still working)."); } } } } } private bool Remove(Carrier carrier, bool spillLoad) { if (spillLoad) { Spill(carrier); } carrier.ClearDrawnLoad(); if ((Object)(object)carrier.Unit == (Object)null) { return false; } try { Object.Destroy((Object)(object)((Component)carrier.Unit).gameObject); return true; } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[carrier] a carrier could not be removed (" + ex.Message + "); leaving it."); } return false; } } private void Begin(Carrier carrier, Leg leg, ArenaWorldPoint destination) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) carrier.Leg = leg; carrier.OnLeg = 0f; carrier.Handling = 0f; carrier.Waited = 0f; SendTo(carrier, destination); } private void SendTo(Carrier carrier, ArenaWorldPoint destination) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) Npc npc = carrier.Npc; if ((Object)(object)npc == (Object)null) { return; } try { Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((ArenaWorldPoint)(ref destination)).X, ((ArenaWorldPoint)(ref destination)).Y, ((ArenaWorldPoint)(ref destination)).Z); carrier.Destination = val; npc.SetForcedDestination(val); npc.ActivateBehaviour(); } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[carrier] a carrier could not be sent on its way (" + ex.Message + ")."); } } } private void Retarget(Carrier carrier, ArenaWorldPoint destination) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((ArenaWorldPoint)(ref destination)).X, ((ArenaWorldPoint)(ref destination)).Y, ((ArenaWorldPoint)(ref destination)).Z); Vector3 val2 = carrier.Destination - val; if (!(((Vector3)(ref val2)).sqrMagnitude < 1f)) { SendTo(carrier, destination); } } private void RepeatIfStuck(Carrier carrier, ArenaWorldPoint destination) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!(carrier.OnLeg < 45f)) { carrier.OnLeg = 0f; ILogger logger = _logger; if (logger != null) { logger.LogWarning("[carrier] a carrier has been on one leg too long; sending it again."); } SendTo(carrier, destination); } } private static bool HasArrived(Carrier carrier, ArenaWorldPoint destination) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) Unit unit = carrier.Unit; if ((Object)(object)unit == (Object)null) { return false; } Npc npc = carrier.Npc; AiAgent val = (((Object)(object)npc != (Object)null) ? npc.AiAgent : null); if ((Object)(object)val != (Object)null && val.onDestination) { return true; } Vector3 position = ((Component)unit).transform.position; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(((ArenaWorldPoint)(ref destination)).X, position.y, ((ArenaWorldPoint)(ref destination)).Z); Vector3 val3 = position - val2; return ((Vector3)(ref val3)).sqrMagnitude <= 6.25f; } private void ReportTheDeactivationTrapOnce(Unit unit) { if (_reportedDeactivationTrap) { return; } _reportedDeactivationTrap = true; try { UnitSO unitSO = unit.unitSO; if ((Object)(object)unitSO == (Object)null) { return; } Npc val = (Npc)(object)((unit is Npc) ? unit : null); float num = (_observedWalkSpeed = ((val != null && (Object)(object)val.AiAgent != (Object)null && (Object)(object)val.AiAgent.navMeshAgent != (Object)null) ? ((AIBase)val.AiAgent.navMeshAgent).maxSpeed : 0f)); ILogger logger = _logger; if (logger != null) { logger.Log($"[carrier] {CarrierUnit.value}: canBeDeactivated={unitSO.canBeDeactivated}, " + $"canPanic={unitSO.canPanic}, isCivilian={unitSO.isCivilian}, walk speed={num:0.00} m/s."); } if (!unitSO.canBeDeactivated) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[carrier] this unit's behaviour tree cannot be switched off, so its own AI will fight the errand; the walk needs re-issuing every tick instead."); } } } catch (Exception ex) { ILogger logger3 = _logger; if (logger3 != null) { logger3.LogWarning("[carrier] the carrier unit could not be described: " + ex.Message); } } } } public sealed class SulfurCrateImpact : IThrownCrateImpact { private sealed class CrateDamager : IDamager { private readonly Transform _transform; public string SourceName => "False Gods crate"; public Unit SourceUnit => null; public Weapon SourceWeapon => null; public Transform Transform => _transform; public bool CreatedByPlayer => false; public CrateDamager(Transform transform) { _transform = transform; } public void SetOwner(Unit unit) { } } private const float PlayerCenterHeight = 0.9f; private readonly int _damage; private readonly float _contactRadius; private readonly float _splashRadius; private readonly float _knockbackSpeed; private readonly float _knockbackLift; private readonly ILogger _logger; public Action Hit { get; set; } public SulfurCrateImpact(int damage, float contactRadius, float splashRadius, float knockbackSpeed, float knockbackLift, ILogger logger = null) { _damage = damage; _contactRadius = contactRadius; _splashRadius = splashRadius; _knockbackSpeed = knockbackSpeed; _knockbackLift = knockbackLift; _logger = logger; } public bool Contact(ArenaWorldPoint at) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) List list = LivePlayers(); if (list == null) { return false; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((ArenaWorldPoint)(ref at)).X, ((ArenaWorldPoint)(ref at)).Y, ((ArenaWorldPoint)(ref at)).Z); float num = _contactRadius * _contactRadius; bool result = false; for (int i = 0; i < list.Count; i++) { Player val2 = list[i]; if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.playerUnit == (Object)null) && FightingPlayers.IsFighting(val2)) { Vector3 val3 = ((Component)val2).transform.position + Vector3.up * 0.9f - val; if (!(((Vector3)(ref val3)).sqrMagnitude > num)) { Strike(val2, val); result = true; } } } return result; } public bool Splash(ArenaWorldPoint at) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) List list = LivePlayers(); if (list == null) { return false; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((ArenaWorldPoint)(ref at)).X, ((ArenaWorldPoint)(ref at)).Y, ((ArenaWorldPoint)(ref at)).Z); float num = _splashRadius * _splashRadius; bool result = false; for (int i = 0; i < list.Count; i++) { Player val2 = list[i]; if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.playerUnit == (Object)null) && FightingPlayers.IsFighting(val2)) { Vector3 val3 = ((Component)val2).transform.position - val; val3.y = 0f; if (!(((Vector3)(ref val3)).sqrMagnitude > num)) { Strike(val2, val); result = true; } } } return result; } private static List LivePlayers() { GameManager instance = StaticInstance.Instance; if (!((Object)(object)instance != (Object)null)) { return null; } return instance.Players; } private void Strike(Player player, Vector3 impact) { //IL_0019: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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) try { player.playerUnit.ReceiveDamage((float)_damage, (DamageTypes)8, (IDamager)(object)new CrateDamager(((Component)player).transform), Data.Default, (Vector3?)null); Hit?.Invoke(); } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] a crate hit could not deal damage (" + ex.Message + "); skipped."); } } try { ExtendedAdvancedWalkerController movement = player.movement; if ((Object)(object)movement != (Object)null) { Vector3 val = ((Component)player).transform.position - impact; val.y = 0f; Vector3 val2 = ((((Vector3)(ref val)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref val)).normalized : Vector3.forward); ((AdvancedWalkerController)movement).SetMomentum(val2 * _knockbackSpeed + Vector3.up * _knockbackLift); ILogger logger2 = _logger; if (logger2 != null) { logger2.Log($"[crate] hit a player for {_damage}, knockback {_knockbackSpeed:0.#} + lift {_knockbackLift:0.#}."); } } } catch (Exception ex2) { ILogger logger3 = _logger; if (logger3 != null) { logger3.LogWarning("[crate] a crate hit could not knock the player back (" + ex2.Message + "); skipped."); } } } } public sealed class SulfurDamagePort : IDamagePort { private sealed class BossDamager : IDamager { private readonly Transform _transform; public string SourceName => "False Gods boss"; public Unit SourceUnit => null; public Weapon SourceWeapon => null; public Transform Transform => _transform; public bool CreatedByPlayer => false; public BossDamager(Transform transform) { _transform = transform; } public void SetOwner(Unit unit) { } } private readonly ILogger? _logger; public SulfurDamagePort(ILogger? logger) { _logger = logger; } public void ApplyDamage(ParticipantId target, int amount) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (amount <= 0) { return; } Player val = FindPlayer(((ParticipantId)(ref target)).Value); if ((Object)(object)val == (Object)null || (Object)(object)val.playerUnit == (Object)null) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning($"Boss damage: no live player for participant {((ParticipantId)(ref target)).Value}; hit not applied."); } return; } try { val.playerUnit.ReceiveDamage((float)amount, (DamageTypes)8, (IDamager)(object)new BossDamager(((Component)val).transform), Data.Default, (Vector3?)null); } catch (Exception ex) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning($"Boss damage: applying {amount} to player {((ParticipantId)(ref target)).Value} threw ({ex.Message}); skipped."); } } } private static Player? FindPlayer(int playerIndex) { GameManager instance = StaticInstance.Instance; if ((Object)(object)instance == (Object)null) { return null; } List players = instance.Players; if (players == null) { return null; } for (int i = 0; i < players.Count; i++) { Player val = players[i]; if ((Object)(object)val != (Object)null && val.playerIndex == playerIndex && FightingPlayers.IsFighting(val)) { return val; } } return null; } } public sealed class SulfurMinionSpawnPort : IMinionSpawnPort { private static readonly Dictionary Roster = new Dictionary { [MinionBands.Vanguard] = (UnitId[])(object)new UnitId[7] { UnitIds.GoblinYoung, UnitIds.GoblinYoung, UnitIds.GoblinYoung, UnitIds.GoblinYoung, UnitIds.GoblinSpearman, UnitIds.GoblinSpearman, UnitIds.GoblinArcher }, [MinionBands.Warband] = (UnitId[])(object)new UnitId[7] { UnitIds.GoblinYoung, UnitIds.GoblinYoung, UnitIds.GoblinSpearman, UnitIds.GoblinSpearman, UnitIds.GoblinSpearman, UnitIds.GoblinArcher, UnitIds.GoblinBarrelBoy }, [MinionBands.Coven] = (UnitId[])(object)new UnitId[7] { UnitIds.GoblinSpearman, UnitIds.GoblinSpearman, UnitIds.GoblinArcher, UnitIds.GoblinWizardFire, UnitIds.GoblinWizardFrost, UnitIds.GoblinWizardElectricity, UnitIds.GoblinWizardPoison }, [MinionBands.Emergency] = (UnitId[])(object)new UnitId[5] { UnitIds.GoblinBarrelBoy, UnitIds.GoblinBarrelBoy, UnitIds.GoblinSpearman, UnitIds.GoblinSpearman, UnitIds.GoblinWizardPoison } }; private const float PlaceReuseSpacing = 1.2f; private const float GoldenAngleDegrees = 137.50777f; private readonly MonoBehaviour _host; private readonly ILogger? _logger; private readonly bool _outlined; private readonly List _spawned = new List(); private readonly Dictionary _outlines = new Dictionary(); public int Alive { get { Forget(); return _spawned.Count; } } public SulfurMinionSpawnPort(MonoBehaviour host, ILogger? logger = null, bool outlined = false) { _host = host ?? throw new ArgumentNullException("host"); _logger = logger; _outlined = outlined; } public int SizeOf(MinionBandId band) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (!Roster.TryGetValue(band, out UnitId[] value)) { return 0; } return value.Length; } public void Summon(MinionBandId band, IReadOnlyList places) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_00b1: Unknown result type (might be due to invalid IL or missing references) if (!Roster.TryGetValue(band, out UnitId[] value)) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning($"[minion] the roster has no band called '{band}'; nothing summoned."); } return; } if (places == null || places.Count == 0) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning($"[minion] the {band} band was called up, but the room authored no places to " + "put minions; nothing summoned."); } return; } int alive = Alive; int num = 0; int num2 = 0; List list = new List(value.Length); for (int i = 0; i < value.Length; i++) { UnitId val = value[i]; UnitSO asset = AssetAccess.GetAsset(val); if ((Object)(object)asset == (Object)null) { ILogger? logger3 = _logger; if (logger3 != null) { logger3.LogWarning($"[minion] the game has no definition for {val.value}; that one is skipped."); } } else { SpawnOne(asset, PlaceFor(places, i)); list.Add(asset.displayName ?? val.value.ToString()); num2 += asset.SpawnCost; num++; } } ILogger? logger4 = _logger; if (logger4 != null) { logger4.Log($"[minion] the {band} band arrives: {num} of {value.Length} at {places.Count} " + string.Format("authored place(s), worth {0} (a vanilla cave patrol is 15) — {1}; ", num2, string.Join(", ", list)) + $"{alive} of this port's were still standing when it was called."); } } private static Vector3 PlaceFor(IReadOnlyList places, int index) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) ArenaWorldPoint val = places[index % places.Count]; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(((ArenaWorldPoint)(ref val)).X, ((ArenaWorldPoint)(ref val)).Y, ((ArenaWorldPoint)(ref val)).Z); int num = index / places.Count; if (num == 0) { return val2; } float num2 = (float)index * 137.50777f * ((float)Math.PI / 180f); float num3 = 1.2f * (float)num; return new Vector3(val2.x + Mathf.Cos(num2) * num3, val2.y, val2.z + Mathf.Sin(num2) * num3); } public void DespawnAll() { int num = 0; for (int i = 0; i < _spawned.Count; i++) { Unit val = _spawned[i]; if ((Object)(object)val == (Object)null) { continue; } try { Object.Destroy((Object)(object)((Component)val).gameObject); num++; } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[minion] a minion could not be removed (" + ex.Message + "); leaving it."); } } } foreach (Unit key in _outlines.Keys) { Unoutline(key, keepEntry: true); } _outlines.Clear(); _spawned.Clear(); if (num > 0) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log($"[minion] {num} minion(s) removed with the encounter."); } } } private async void SpawnOne(UnitSO definition, Vector3 position) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) Unit val; try { val = await definition.SpawnUnitAsync(_host, position, default(Quaternion)); } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[minion] a minion failed to spawn: " + ex.Message); } return; } if ((Object)(object)val == (Object)null) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[minion] a minion failed to spawn (the game returned no unit)."); } } else { SendItAfterThePlayers(val); _spawned.Add(val); Outline(val); } } private void Outline(Unit unit) { if (!_outlined || (Object)(object)unit == (Object)null) { return; } try { SulfurCustomRendering instance = SulfurCustomRendering.instance; if (!((Object)(object)instance == (Object)null)) { Renderer[] componentsInChildren = ((Component)unit).GetComponentsInChildren(true); if (componentsInChildren != null && componentsInChildren.Length != 0) { instance.AddOutlinedRenderers(componentsInChildren); _outlines[unit] = componentsInChildren; } } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[minion] one could not be outlined (" + ex.Message + "); it fights unmarked."); } } } private void Unoutline(Unit? unit, bool keepEntry = false) { if ((Object)(object)unit == (Object)null || _outlines.Count == 0 || !_outlines.TryGetValue(unit, out Renderer[] value)) { return; } try { SulfurCustomRendering instance = SulfurCustomRendering.instance; if (instance != null) { instance.RemoveOutlinedRenderers(value); } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[minion] an outline could not be cleared (" + ex.Message + ")."); } } if (!keepEntry) { _outlines.Remove(unit); } } private void SendItAfterThePlayers(Unit unit) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) try { Npc val = (Npc)(object)((unit is Npc) ? unit : null); AiAgent val2 = (((Object)(object)val != (Object)null) ? val.AiAgent : null); if (!((Object)(object)val2 == (Object)null)) { Unit val3 = FightingPlayers.NearestTo(((Component)unit).transform.position); if ((Object)(object)val3 != (Object)null) { val2.ReportLastSeen(val3, ((Component)val3).transform.position, ((Component)unit).transform.position, true); } } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[minion] a minion could not be pointed at the fight (" + ex.Message + "); it will have to notice the players on its own."); } } } private void Forget() { for (int num = _spawned.Count - 1; num >= 0; num--) { Unit val = _spawned[num]; if ((Object)(object)val == (Object)null || !val.IsAlive) { Unoutline(val); _spawned.RemoveAt(num); } } } } public sealed class SulfurPlayerMotionPort : IPlayerMotionPort { public PlayerMotion TryReadLocalPlayer() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_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_0085: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) GameManager instance = StaticInstance.Instance; Player val = (((Object)(object)instance != (Object)null) ? instance.PlayerScript : null); if ((Object)(object)val == (Object)null) { return default(PlayerMotion); } Vector3 position = ((Component)val).transform.position; ExtendedAdvancedWalkerController movement = val.movement; if ((Object)(object)movement == (Object)null) { return new PlayerMotion(new SimVector2(position.x, position.z), SimVector2.Zero); } Vector3 velocity = ((Controller)movement).GetVelocity(); return new PlayerMotion(new SimVector2(position.x, position.z), new SimVector2(velocity.x, velocity.z)); } public void ReadPlayersToThrowAt(IList into) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_00a1: 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_00af: 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_00b8: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) into.Clear(); GameManager instance = StaticInstance.Instance; List list = (((Object)(object)instance != (Object)null) ? instance.Players : null); if (list == null) { return; } SimVector2 val2 = default(SimVector2); for (int i = 0; i < list.Count; i++) { Player val = list[i]; if (!((Object)(object)val == (Object)null) && FightingPlayers.IsFighting(val)) { Vector3 position = ((Component)val).transform.position; ((SimVector2)(ref val2))..ctor(position.x, position.z); ExtendedAdvancedWalkerController movement = val.movement; if ((Object)(object)movement == (Object)null) { into.Add(new PlayerAim(val.playerIndex, val2, position.y, SimVector2.Zero, false)); continue; } Vector3 velocity = ((Controller)movement).GetVelocity(); into.Add(new PlayerAim(val.playerIndex, val2, position.y, new SimVector2(velocity.x, velocity.z), true)); } } } } public sealed class SulfurThrownCratePort : IThrownCratePort { internal readonly struct CrateLook { public Mesh Mesh { get; } public Material Material { get; } public bool Explosive { get; } public bool Known { get { if ((Object)(object)Mesh != (Object)null) { return (Object)(object)Material != (Object)null; } return false; } } public CrateLook(Mesh mesh, Material material, bool explosive) { Mesh = mesh; Material = material; Explosive = explosive; } } private sealed class DestructibleSpec { public UnitId Unit; public string Name; public bool CubeMesh; public string MeshPathFragment; public string MaterialPathFragment; public string BreakEffectPathFragment; public ExplosionTypes Explosion; public string TopMeshPathFragment; public string TopMaterialPathFragment; } private sealed class DestructibleTemplate { public UnitSO Definition; public GameObject Template; public string Name; public bool Explodes; public CrateLook Look; public readonly List Handles = new List(); public void Release() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Template != (Object)null) { Object.Destroy((Object)(object)Template); Template = null; } foreach (AsyncOperationHandle handle in Handles) { try { Addressables.Release(handle); } catch (Exception) { } } Handles.Clear(); } } private enum Phase { Resting, Lifting, Flying, Tossing } private sealed class ManagedCrate { public CrateLook Look { get; } public bool Explodes { get; } public float Fuse { get; set; } public Action WhenItGoesOff { get; set; } public int Id { get; } public Unit Unit { get; } public Breakable Breakable { get; } public Phase Phase { get; private set; } public CratePileId Pile { get; set; } public bool LootWhenFired { get; set; } public float Elapsed { get; set; } public Vector3 Start { get; private set; } public Vector3 Target { get; private set; } public float FlightSeconds { get; private set; } public float ApexHeight { get; private set; } public Vector3 LiftFrom { get; private set; } public Vector3 Hover { get; private set; } public float LiftSeconds { get; private set; } public float HoldSeconds { get; private set; } public ManagedCrate(Unit unit, Breakable breakable, int id, bool explodes, CrateLook look) { Unit = unit; Breakable = breakable; Id = id; Explodes = explodes; Look = look; } public void BeginFlight(Vector3 start, Vector3 target, float flightSeconds, float apexHeight) { //IL_0001: 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) Start = start; Target = target; FlightSeconds = ((flightSeconds > 0f) ? flightSeconds : 0.01f); ApexHeight = apexHeight; Elapsed = 0f; Phase = Phase.Flying; } public void BeginToss(Vector3 start, Vector3 target, float flightSeconds, float apexHeight, CratePileId pile) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) Start = start; Target = target; FlightSeconds = ((flightSeconds > 0f) ? flightSeconds : 0.01f); ApexHeight = apexHeight; Pile = pile; Elapsed = 0f; Phase = Phase.Tossing; } public void RestWhereItLanded() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) Elapsed = 0f; Pile = CratePileId.Loose; Phase = Phase.Resting; } public void Settle() { Elapsed = 0f; Phase = Phase.Resting; } public void BeginLift(Vector3 liftFrom, Vector3 hover, Vector3 target, CrateVolleyShape shape, int place) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) LiftFrom = liftFrom; Hover = hover; Target = target; LiftSeconds = ((((CrateVolleyShape)(ref shape)).LiftSeconds > 0f) ? ((CrateVolleyShape)(ref shape)).LiftSeconds : 0.01f); float num = ((((CrateVolleyShape)(ref shape)).FireIntervalSeconds > 0f) ? (((CrateVolleyShape)(ref shape)).FireIntervalSeconds * (float)place) : 0f); float holdSeconds = ((((CrateVolleyShape)(ref shape)).HoldSeconds > 0f) ? ((CrateVolleyShape)(ref shape)).HoldSeconds : 0f) + num; HoldSeconds = holdSeconds; FlightSeconds = ((((CrateVolleyShape)(ref shape)).FlightSeconds > 0f) ? ((CrateVolleyShape)(ref shape)).FlightSeconds : 0.01f); ApexHeight = ((CrateVolleyShape)(ref shape)).ApexHeight; Elapsed = 0f; Phase = Phase.Lifting; } } private static readonly DestructibleSpec[] Specs = new DestructibleSpec[3] { new DestructibleSpec { Unit = UnitIds.WoodenBarrel, Name = "barrel", MeshPathFragment = "Barrel_Wood", MaterialPathFragment = "Barrels/BarrelWood", BreakEffectPathFragment = "BarrelBreakEffect" }, new DestructibleSpec { Unit = UnitIds.WoodenCrate, Name = "crate", CubeMesh = true, MaterialPathFragment = "Crate", BreakEffectPathFragment = "CrateBreakEffect" }, new DestructibleSpec { Unit = UnitIds.ExplosiveBarrel, Name = "explosive barrel", MeshPathFragment = "Barrel_Explosion", MaterialPathFragment = "Barrels/BarrelWood", BreakEffectPathFragment = "BarrelBreakEffect (Exploding)", Explosion = (ExplosionTypes)3, TopMeshPathFragment = "PileSulfur", TopMaterialPathFragment = "SulfurYellow" } }; private const ExplosionTypes BarrelExplosion = (ExplosionTypes)3; private const float LandedFuseSeconds = 1.5f; private const float LandingSpeedKeptAlong = 0.5f; private const float CargoMass = 800f; private const float CargoLinearDamping = 0.1f; private const float CargoAngularDamping = 0.05f; private const float LandingSpeedKeptDown = 0.05f; private const float LandingSpinKept = 0.25f; private const float BarrelDamage = 50f; private const string BreakableLayerName = "Breakable"; private const int MaxLooseCrates = 60; private const float LootChance = 0.1f; private const int LootSalt = 70001; private const float SetDownMinRadius = 1.2f; private const float SetDownMaxRadius = 4f; private const float SetDownHeight = 1.2f; private const float SetDownFlightSeconds = 0.55f; private const float SetDownApexHeight = 1.6f; private static readonly string[] WallLayerNames = new string[4] { "GeometryNoNavMesh", "StaticDoodad", "InvisibleGeometry", "LevelGenBlock" }; private readonly ILogger _logger; private readonly IThrownCrateImpact _impact; private readonly List _crates = new List(); private readonly List _templates = new List(); private readonly List _ordinary = new List(); private DestructibleTemplate _explosive; private FieldInfo _explosionOnDeath; private bool _prepared; private bool _warnedAboutNoKinds; private int _nextKind; private int _cratesMade; private bool _applyingRemoteDeath; private readonly HashSet _reportedDeaths = new HashSet(); private FieldInfo _preventDroppingLoot; private bool _warnedAboutLootFlag; private int _wallMask; private bool _wallMaskBuilt; private bool _looseNeedsCapping; private int _nextThrowSeed = 1; private const int LeadChoiceSalt = 40009; private const int TargetChoiceSalt = 50021; private bool _breakingItOurselves; public int InFlight => CountWhere((Phase phase) => phase != Phase.Resting); public int Resting => CountWhere((Phase phase) => phase == Phase.Resting); public Action Died { get; set; } public Action Exploded { get; set; } private bool TemplatesStillStanding() { for (int i = 0; i < _templates.Count; i++) { if (_templates[i] == null || (Object)(object)_templates[i].Template == (Object)null) { return false; } } return _templates.Count > 0; } public SulfurThrownCratePort(ILogger logger = null, IThrownCrateImpact impact = null) { _logger = logger; _impact = impact; } public int RestingOn(CratePileId pile) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) int num = 0; for (int i = 0; i < _crates.Count; i++) { if (IsOn(_crates[i], pile)) { num++; } } return num; } private static bool IsOn(ManagedCrate crate, CratePileId pile) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)crate.Unit != (Object)null && crate.Fuse <= 0f && crate.Pile == pile) { if (crate.Phase != Phase.Resting) { return crate.Phase == Phase.Tossing; } return true; } return false; } private int CountWhere(Func predicate) { int num = 0; for (int i = 0; i < _crates.Count; i++) { if (predicate(_crates[i].Phase)) { num++; } } return num; } public bool Prepare() { if (_prepared && TemplatesStillStanding()) { return true; } if (_prepared) { _templates.Clear(); _ordinary.Clear(); _explosive = null; _prepared = false; ILogger logger = _logger; if (logger != null) { logger.Log("[crate] the level took the destructible templates with it; rebuilding them."); } } try { if (_preventDroppingLoot == null) { _preventDroppingLoot = PrivateField(typeof(Breakable), "preventDroppingLoot"); if (_preventDroppingLoot == null && !_warnedAboutLootFlag) { _warnedAboutLootFlag = true; ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[crate] could not find the loot gate on the game's breakable; a landing crate will be removed quietly instead of breaking. Landing still drops nothing."); } } } List list = new List(); DestructibleSpec[] specs = Specs; foreach (DestructibleSpec destructibleSpec in specs) { DestructibleTemplate destructibleTemplate = BuildKind(destructibleSpec); if (destructibleTemplate != null) { _templates.Add(destructibleTemplate); list.Add(destructibleSpec.Name); } } if (_templates.Count == 0) { if (!_warnedAboutNoKinds) { _warnedAboutNoKinds = true; ILogger logger3 = _logger; if (logger3 != null) { logger3.LogWarning("[crate] no destructible kind could be assembled; throwing is unavailable."); } } return false; } _warnedAboutNoKinds = false; foreach (DestructibleTemplate template in _templates) { if (template.Explodes) { _explosive = template; } else { _ordinary.Add(template); } } _prepared = true; ILogger logger4 = _logger; if (logger4 != null) { logger4.Log("[crate] destructible content ready: " + string.Join(", ", list) + "."); } return true; } catch (Exception arg) { ILogger logger5 = _logger; if (logger5 != null) { logger5.LogWarning($"[crate] destructible content could not be prepared: {arg}"); } return false; } } private DestructibleTemplate BuildKind(DestructibleSpec spec) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Invalid comparison between Unknown and I4 UnitSO asset = AssetAccess.GetAsset(spec.Unit); if ((Object)(object)asset == (Object)null) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] the game has no definition for the " + spec.Name + "; skipped."); } return null; } DestructibleTemplate destructibleTemplate = new DestructibleTemplate { Definition = asset, Name = spec.Name }; Material material = null; Mesh val; if (spec.CubeMesh) { val = CubeMesh(); } else { val = LoadAddressableMesh(spec.MeshPathFragment, destructibleTemplate, out material, out var error); if ((Object)(object)val == (Object)null) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[crate] no " + spec.Name + " mesh could be sourced (" + error + "); skipped."); } destructibleTemplate.Release(); return null; } } Material debrisMaterial; object breakSound; string error2; GameObject val2 = LoadBreakEffect(spec.BreakEffectPathFragment, destructibleTemplate, out debrisMaterial, out breakSound, out error2); if ((Object)(object)val2 == (Object)null) { ILogger logger3 = _logger; if (logger3 != null) { logger3.LogWarning("[crate] no " + spec.Name + " break effect could be sourced (" + error2 + "); it will vanish without debris."); } } Material val3 = LoadBodyMaterial(spec.MaterialPathFragment, destructibleTemplate); Material material2 = (((Object)(object)val3 != (Object)null) ? val3 : (((Object)(object)debrisMaterial != (Object)null) ? debrisMaterial : material)); string error3; GameObject val4 = BuildTemplate(asset, val, material2, val2, breakSound, out error3); if ((Object)(object)val4 != (Object)null) { AddTheMarkingOnTop(spec, destructibleTemplate, val4); } if ((Object)(object)val4 == (Object)null) { ILogger logger4 = _logger; if (logger4 != null) { logger4.LogWarning("[crate] the " + spec.Name + " template could not be assembled (" + error3 + "); skipped."); } destructibleTemplate.Release(); return null; } destructibleTemplate.Template = val4; destructibleTemplate.Explodes = (int)spec.Explosion > 0; destructibleTemplate.Look = LookOf(val4, destructibleTemplate.Explodes); return destructibleTemplate; } private void MakeItGoOff(Unit unit) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown unit.onDeath = (OnDeath)Delegate.Combine((Delegate?)(object)unit.onDeath, (Delegate?)new OnDeath(BlowUp)); } private void BlowUp(Unit unit) { //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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) try { Vector3 val; if (!((Object)(object)unit.mainCollider != (Object)null)) { val = ((Component)unit).transform.position; } else { Bounds bounds = unit.mainCollider.bounds; val = ((Bounds)(ref bounds)).center; } Vector3 val2 = val; StaticInstance.Instance.QueueExplosion((ExplosionTypes)3, val2, Vector3.zero, Vector3.up, 50f, 1f, unit); Exploded?.Invoke(ToPoint(val2), ShotOutOfTheAir(unit)); } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] a barrel would not go off (" + ex.Message + ")."); } } } private static CrateLook LookOf(GameObject template, bool explosive) { MeshFilter component = template.GetComponent(); MeshRenderer component2 = template.GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null)) { return new CrateLook(component.sharedMesh, ((Renderer)component2).sharedMaterial, explosive); } return default(CrateLook); } private void AddTheMarkingOnTop(DestructibleSpec spec, DestructibleTemplate template, GameObject body) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(spec.TopMeshPathFragment)) { return; } Material material; string error; Mesh val = LoadAddressableMesh(spec.TopMeshPathFragment, template, out material, out error); if ((Object)(object)val == (Object)null) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] the " + spec.Name + "'s marking could not be sourced (" + error + "); it will look like ordinary cargo."); } } else { GameObject val2 = new GameObject("Marking"); val2.transform.SetParent(body.transform, false); val2.layer = body.layer; val2.AddComponent().sharedMesh = val; MeshRenderer val3 = val2.AddComponent(); Material val4 = LoadBodyMaterial(spec.TopMaterialPathFragment, template); if ((Object)(object)val4 != (Object)null) { ((Renderer)val3).sharedMaterial = val4; } } } private static Mesh CubeMesh() { GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3); obj.SetActive(false); Mesh sharedMesh = obj.GetComponent().sharedMesh; Object.Destroy((Object)(object)obj); return sharedMesh; } private DestructibleTemplate PickKind() { int num = _nextKind++; if (_ordinary.Count == 0) { return _templates[num % _templates.Count]; } return _ordinary[num % _ordinary.Count]; } internal bool TryGetLook(out Mesh mesh, out Material material) { mesh = null; material = null; if (!_prepared || _templates.Count == 0) { return false; } for (int i = 0; i < _templates.Count; i++) { GameObject template = _templates[i].Template; if ((Object)(object)template == (Object)null) { continue; } MeshFilter componentInChildren = template.GetComponentInChildren(true); MeshRenderer componentInChildren2 = template.GetComponentInChildren(true); if (!((Object)(object)componentInChildren == (Object)null) && !((Object)(object)componentInChildren2 == (Object)null)) { mesh = componentInChildren.sharedMesh; material = ((Renderer)componentInChildren2).sharedMaterial; if ((Object)(object)mesh != (Object)null && (Object)(object)material != (Object)null) { return true; } } } return false; } private Unit SpawnFrom(DestructibleTemplate kind, Vector3 position, out Breakable breakable) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) breakable = null; Unit val = UnitSO.SpawnUnit(kind.Definition, kind.Template, position, Quaternion.identity); if ((Object)(object)val == (Object)null) { return null; } ((Component)val).gameObject.SetActive(true); OurDestructibles.Claim(((Component)val).gameObject); if (kind.Explodes) { MakeItGoOff(val); } breakable = (Breakable)(object)((val is Breakable) ? val : null); if ((Object)(object)breakable != (Object)null) { breakable.BreakOnFirstContact = false; breakable.TakeDamageOnCollision = false; } return val; } public bool Throw(ArenaWorldPoint from, ArenaWorldPoint to, float flightSeconds, float apexHeight) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) if (flightSeconds <= 0f) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] a throw needs a positive flight time."); } return false; } if (!Prepare()) { return false; } try { Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((ArenaWorldPoint)(ref from)).X, ((ArenaWorldPoint)(ref from)).Y, ((ArenaWorldPoint)(ref from)).Z); Vector3 target = default(Vector3); ((Vector3)(ref target))..ctor(((ArenaWorldPoint)(ref to)).X, ((ArenaWorldPoint)(ref to)).Y, ((ArenaWorldPoint)(ref to)).Z); DestructibleTemplate destructibleTemplate = PickKind(); Breakable breakable; Unit val2 = SpawnFrom(destructibleTemplate, val, out breakable); if ((Object)(object)val2 == (Object)null) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[crate] the game returned no unit for the destructible."); } return false; } if ((Object)(object)val2.Rigidbody != (Object)null) { val2.Rigidbody.useGravity = false; val2.Rigidbody.isKinematic = true; } SetLootAllowed(breakable, SeededRandom.Unit01(_nextThrowSeed++, 70001) < 0.10000000149011612); ManagedCrate managedCrate = new ManagedCrate(val2, breakable, NextCrateId(), destructibleTemplate.Explodes, destructibleTemplate.Look); managedCrate.BeginFlight(val, target, flightSeconds, apexHeight); _crates.Add(managedCrate); return true; } catch (Exception arg) { ILogger logger3 = _logger; if (logger3 != null) { logger3.LogWarning($"[crate] the crate could not be thrown: {arg}"); } return false; } } public bool ThrowExplosive(ArenaWorldPoint from, ArenaWorldPoint to, float flightSeconds, float apexHeight, Action whenItGoesOff) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) if (flightSeconds <= 0f) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] a throw needs a positive flight time."); } return false; } if (!Prepare()) { return false; } if (_explosive == null) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[crate] this build has no exploding destructible; the barrel was not thrown."); } return false; } try { Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((ArenaWorldPoint)(ref from)).X, ((ArenaWorldPoint)(ref from)).Y, ((ArenaWorldPoint)(ref from)).Z); Vector3 target = default(Vector3); ((Vector3)(ref target))..ctor(((ArenaWorldPoint)(ref to)).X, ((ArenaWorldPoint)(ref to)).Y, ((ArenaWorldPoint)(ref to)).Z); Breakable breakable; Unit val2 = SpawnFrom(_explosive, val, out breakable); if ((Object)(object)val2 == (Object)null) { ILogger logger3 = _logger; if (logger3 != null) { logger3.LogWarning("[crate] the game returned no unit for the barrel."); } return false; } if ((Object)(object)val2.Rigidbody != (Object)null) { val2.Rigidbody.useGravity = false; val2.Rigidbody.isKinematic = true; } SetLootAllowed(breakable, allowed: false); ManagedCrate managedCrate = new ManagedCrate(val2, breakable, NextCrateId(), explodes: true, _explosive.Look) { WhenItGoesOff = whenItGoesOff }; managedCrate.BeginFlight(val, target, flightSeconds, apexHeight); _crates.Add(managedCrate); ILogger logger4 = _logger; if (logger4 != null) { logger4.Log($"[crate] a barrel is on its way to ({((ArenaWorldPoint)(ref to)).X:0.0}, {((ArenaWorldPoint)(ref to)).Y:0.0}, {((ArenaWorldPoint)(ref to)).Z:0.0})."); } return true; } catch (Exception arg) { ILogger logger5 = _logger; if (logger5 != null) { logger5.LogWarning($"[crate] the barrel could not be thrown: {arg}"); } return false; } } public bool Drop(ArenaWorldPoint at, CratePileId pile, bool explosive = false) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) if (!Prepare()) { return false; } try { Vector3 position = default(Vector3); ((Vector3)(ref position))..ctor(((ArenaWorldPoint)(ref at)).X, ((ArenaWorldPoint)(ref at)).Y, ((ArenaWorldPoint)(ref at)).Z); DestructibleTemplate destructibleTemplate = ((explosive && _explosive != null) ? _explosive : PickKind()); Breakable breakable; Unit val = SpawnFrom(destructibleTemplate, position, out breakable); if ((Object)(object)val == (Object)null) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] the game returned no unit for the resting destructible."); } return false; } if ((Object)(object)val.Rigidbody != (Object)null) { val.Rigidbody.isKinematic = false; val.Rigidbody.useGravity = true; } SetLootAllowed(breakable, allowed: false); _crates.Add(new ManagedCrate(val, breakable, NextCrateId(), destructibleTemplate.Explodes, destructibleTemplate.Look) { Pile = pile }); if ((int)((CratePileId)(ref pile)).Kind == 0) { CapLooseCrates(); } return true; } catch (Exception arg) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning($"[crate] the crate could not be dropped: {arg}"); } return false; } } public int TossRing(ArenaWorldPoint from, ArenaWorldPoint at, CratePileId pile, int count, int seed, int explosives) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (count <= 0 || !Prepare()) { return 0; } int num = 0; ArenaWorldPoint to = default(ArenaWorldPoint); for (int i = 0; i < count; i++) { SpreadOffset val = ShotgunSpread.Offset(seed, i, count, 1.2f, 4f); ((ArenaWorldPoint)(ref to))..ctor(((ArenaWorldPoint)(ref at)).X + ((SpreadOffset)(ref val)).X, ((ArenaWorldPoint)(ref at)).Y + 1.2f, ((ArenaWorldPoint)(ref at)).Z + ((SpreadOffset)(ref val)).Z); if (Toss(from, to, pile, 0.55f, 1.6f, i < explosives)) { num++; } } return num; } private bool Toss(ArenaWorldPoint from, ArenaWorldPoint to, CratePileId pile, float flightSeconds, float apexHeight, bool explosive = false) { //IL_0044: 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_00d5: 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) if (!Prepare()) { return false; } try { Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((ArenaWorldPoint)(ref from)).X, ((ArenaWorldPoint)(ref from)).Y, ((ArenaWorldPoint)(ref from)).Z); DestructibleTemplate destructibleTemplate = ((explosive && _explosive != null) ? _explosive : PickKind()); Breakable breakable; Unit val2 = SpawnFrom(destructibleTemplate, val, out breakable); if ((Object)(object)val2 == (Object)null) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] the game returned no unit for the tossed destructible."); } return false; } if ((Object)(object)val2.Rigidbody != (Object)null) { val2.Rigidbody.isKinematic = true; val2.Rigidbody.useGravity = false; } SetLootAllowed(breakable, allowed: false); ManagedCrate managedCrate = new ManagedCrate(val2, breakable, NextCrateId(), destructibleTemplate.Explodes, destructibleTemplate.Look); managedCrate.BeginToss(val, new Vector3(((ArenaWorldPoint)(ref to)).X, ((ArenaWorldPoint)(ref to)).Y, ((ArenaWorldPoint)(ref to)).Z), flightSeconds, apexHeight, pile); _crates.Add(managedCrate); return true; } catch (Exception arg) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning($"[crate] the crate could not be tossed: {arg}"); } return false; } } public int LaunchVolley(CratePileId pile, IReadOnlyList aims, CrateVolleyShape shape) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00db: 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) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014d: 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_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: 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) if (aims == null || aims.Count == 0 || !Prepare()) { return 0; } List list = new List(); for (int i = 0; i < _crates.Count; i++) { if (list.Count >= ((CrateVolleyShape)(ref shape)).Count) { break; } if (IsOn(_crates[i], pile)) { list.Add(_crates[i]); } } if (list.Count == 0) { return 0; } Vector3 target = default(Vector3); for (int j = 0; j < list.Count; j++) { ManagedCrate managedCrate = list[j]; int index = ((aims.Count != 1) ? ((int)(SeededRandom.Unit01(((CrateVolleyShape)(ref shape)).Seed, 50021 + j) * (double)aims.Count) % aims.Count) : 0); CrateVolleyAim val = aims[index]; ArenaWorldPoint val2 = ((SeededRandom.Unit01(((CrateVolleyShape)(ref shape)).Seed, 40009 + j) < (double)((CrateVolleyShape)(ref shape)).LeadShare) ? ((CrateVolleyAim)(ref val)).Lead : ((CrateVolleyAim)(ref val)).Current); SpreadOffset val3 = ShotgunSpread.Offset(((CrateVolleyShape)(ref shape)).Seed, j, list.Count, ((CrateVolleyShape)(ref shape)).SpreadMinRadius, ((CrateVolleyShape)(ref shape)).SpreadMaxRadius); ((Vector3)(ref target))..ctor(((ArenaWorldPoint)(ref val2)).X + ((SpreadOffset)(ref val3)).X, ((ArenaWorldPoint)(ref val2)).Y, ((ArenaWorldPoint)(ref val2)).Z + ((SpreadOffset)(ref val3)).Z); Vector3 position = ((Component)managedCrate.Unit).transform.position; managedCrate.BeginLift(position, position + Vector3.up * ((CrateVolleyShape)(ref shape)).LiftHeight, target, shape, j); managedCrate.LootWhenFired = SeededRandom.Unit01(((CrateVolleyShape)(ref shape)).Seed, 70001 + j) < 0.10000000149011612; if ((Object)(object)managedCrate.Breakable != (Object)null) { managedCrate.Breakable.BreakOnFirstContact = false; managedCrate.Breakable.TakeDamageOnCollision = false; } if ((Object)(object)managedCrate.Unit.Rigidbody != (Object)null) { managedCrate.Unit.Rigidbody.isKinematic = true; managedCrate.Unit.Rigidbody.useGravity = false; } } return list.Count; } private int NextCrateId() { return ++_cratesMade; } private bool ShotOutOfTheAir(Unit unit) { if (_breakingItOurselves) { return false; } for (int i = 0; i < _crates.Count; i++) { if (_crates[i].Unit == unit) { Phase phase = _crates[i].Phase; if (phase != Phase.Flying) { return phase == Phase.Lifting; } return true; } } return false; } public void ReadBlast(out float damage, out float radius) { damage = 0f; radius = 0f; try { ExplosionDefinition asset = AssetAccess.GetAsset((ExplosionTypes)3); if (!((Object)(object)asset == (Object)null)) { damage = 50f; radius = asset.data.damageRadius; } } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] the game's barrel blast could not be measured (" + ex.Message + "); the boss will not take a share of one."); } } } public bool Destroy(int crateId, CrateDeath death) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) for (int num = _crates.Count - 1; num >= 0; num--) { ManagedCrate managedCrate = _crates[num]; if (managedCrate.Id == crateId) { _crates.RemoveAt(num); if ((Object)(object)managedCrate.Unit == (Object)null) { return false; } _applyingRemoteDeath = true; try { if ((int)death == 0) { BreakAsShot(managedCrate); } else { BreakNoLoot(managedCrate); } } finally { _applyingRemoteDeath = false; } return true; } } if (!_reportedDeaths.Remove(crateId)) { ILogger logger = _logger; if (logger != null) { logger.LogWarning($"[crate] a destruction named crate {crateId}, which this peer never had."); } } return false; } private void Report(ManagedCrate crate, CrateDeath death) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (_applyingRemoteDeath) { return; } _reportedDeaths.Add(crate.Id); try { Died?.Invoke(crate.Id, death); } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] a destruction could not be reported (" + ex.Message + "); skipped."); } } } public void Advance(float deltaSeconds) { //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0141: 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_0198: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) BurnFuses(deltaSeconds); for (int num = _crates.Count - 1; num >= 0; num--) { ManagedCrate managedCrate = _crates[num]; if ((Object)(object)managedCrate.Unit == (Object)null) { _crates.RemoveAt(num); Report(managedCrate, (CrateDeath)0); } else { switch (managedCrate.Phase) { case Phase.Lifting: AdvanceLift(managedCrate, deltaSeconds); break; case Phase.Tossing: { managedCrate.Elapsed += deltaSeconds; float num3 = managedCrate.Elapsed / managedCrate.FlightSeconds; if (num3 >= 1f) { Settle(managedCrate); } else { ((Component)managedCrate.Unit).transform.position = ArcPoint(managedCrate, num3); } break; } case Phase.Flying: { managedCrate.Elapsed += deltaSeconds; float num2 = managedCrate.Elapsed / managedCrate.FlightSeconds; if (num2 >= 1f) { if (Land(managedCrate)) { _crates.RemoveAt(num); } break; } Vector3 position = ((Component)managedCrate.Unit).transform.position; Vector3 val = ArcPoint(managedCrate, num2); if (HitsGeometry(position, val, out var point)) { ((Component)managedCrate.Unit).transform.position = point; _crates.RemoveAt(num); IThrownCrateImpact impact = _impact; if (impact != null) { impact.Splash(ToPoint(point)); } BreakNoLoot(managedCrate); } else { ((Component)managedCrate.Unit).transform.position = val; if (_impact != null && _impact.Contact(ToPoint(val))) { _crates.RemoveAt(num); BreakNoLoot(managedCrate); Report(managedCrate, (CrateDeath)1); } } break; } } } } if (_looseNeedsCapping) { _looseNeedsCapping = false; CapLooseCrates(); } } private void Settle(ManagedCrate crate) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) crate.Settle(); if ((Object)(object)crate.Unit != (Object)null && (Object)(object)crate.Unit.Rigidbody != (Object)null) { crate.Unit.Rigidbody.isKinematic = false; crate.Unit.Rigidbody.useGravity = true; } CratePileId pile = crate.Pile; if ((int)((CratePileId)(ref pile)).Kind == 0) { _looseNeedsCapping = true; } } private void AdvanceLift(ManagedCrate crate, float deltaSeconds) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) crate.Elapsed += deltaSeconds; if (crate.Elapsed < crate.LiftSeconds) { Vector3 position = Vector3.Lerp(crate.LiftFrom, crate.Hover, crate.Elapsed / crate.LiftSeconds); ((Component)crate.Unit).transform.position = position; } else if (crate.Elapsed < crate.LiftSeconds + crate.HoldSeconds) { ((Component)crate.Unit).transform.position = crate.Hover; } else { SetLootAllowed(crate.Breakable, crate.LootWhenFired); crate.BeginFlight(crate.Hover, crate.Target, crate.FlightSeconds, crate.ApexHeight); } } private static Vector3 ArcPoint(ManagedCrate crate, float progress) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_002f: Unknown result type (might be due to invalid IL or missing references) Vector3 result = Vector3.Lerp(crate.Start, crate.Target, BallisticArc.HorizontalFraction(progress)); result.y += BallisticArc.Height(progress, crate.ApexHeight); return result; } private bool HitsGeometry(Vector3 from, Vector3 to, out Vector3 point) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) point = to; int num = WallMask(); if (num == 0) { return false; } Vector3 val = to - from; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.0001f) { return false; } RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(from, val / magnitude, ref val2, magnitude, num, (QueryTriggerInteraction)1)) { point = ((RaycastHit)(ref val2)).point; return true; } return false; } private int WallMask() { if (_wallMaskBuilt) { return _wallMask; } int num = 0; string[] wallLayerNames = WallLayerNames; for (int i = 0; i < wallLayerNames.Length; i++) { int num2 = LayerMask.NameToLayer(wallLayerNames[i]); if (num2 >= 0) { num |= 1 << num2; } } if (num == 0) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] none of the arena's wall layers were found; flying crates will pass through walls instead of breaking on them."); } } _wallMask = num; _wallMaskBuilt = true; return _wallMask; } public void Release() { for (int i = 0; i < _crates.Count; i++) { ManagedCrate managedCrate = _crates[i]; if ((Object)(object)managedCrate.Unit != (Object)null) { Object.Destroy((Object)(object)((Component)managedCrate.Unit).gameObject); } } _crates.Clear(); foreach (DestructibleTemplate template in _templates) { template.Release(); } _templates.Clear(); _prepared = false; } private Mesh LoadAddressableMesh(string meshPathFragment, DestructibleTemplate template, out Material material, out string error) { //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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_00f0: Unknown result type (might be due to invalid IL or missing references) material = null; error = null; string diagnostic; IResourceLocation val = FindLocation(meshPathFragment, null, out diagnostic); if (val == null) { error = "no catalog entry whose path contains '" + meshPathFragment + "'. " + diagnostic; return null; } try { AsyncOperationHandle val2 = Addressables.LoadAssetAsync(val); GameObject val3 = val2.WaitForCompletion(); if ((int)val2.Status != 1 || (Object)(object)val3 == (Object)null) { error = $"model at '{val.InternalId}' did not load (status={val2.Status})"; try { Addressables.Release(val2); } catch (Exception) { } return null; } MeshFilter componentInChildren = val3.GetComponentInChildren(); if ((Object)(object)componentInChildren == (Object)null || (Object)(object)componentInChildren.sharedMesh == (Object)null) { error = "model at '" + val.InternalId + "' has no mesh"; try { Addressables.Release(val2); } catch (Exception) { } return null; } MeshRenderer componentInChildren2 = val3.GetComponentInChildren(); material = (((Object)(object)componentInChildren2 != (Object)null) ? ((Renderer)componentInChildren2).sharedMaterial : null); template.Handles.Add(AsyncOperationHandle.op_Implicit(val2)); ILogger logger = _logger; if (logger != null) { logger.Log("[crate] " + template.Name + " mesh found at '" + val.InternalId + "'."); } return componentInChildren.sharedMesh; } catch (Exception ex3) { error = ex3.Message; return null; } } private GameObject BuildTemplate(UnitSO definition, Mesh mesh, Material material, GameObject breakEffect, object breakSound, out string error) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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) //IL_012a: Expected O, but got Unknown error = null; try { GameObject val = new GameObject("FalseGodsThrownCrate"); val.SetActive(false); val.layer = ResolveBreakableLayer(); val.AddComponent().sharedMesh = mesh; MeshRenderer val2 = val.AddComponent(); if ((Object)(object)material != (Object)null) { ((Renderer)val2).sharedMaterial = material; } BoxCollider val3 = val.AddComponent(); Bounds bounds = mesh.bounds; val3.center = ((Bounds)(ref bounds)).center; bounds = mesh.bounds; val3.size = ((Bounds)(ref bounds)).size; Rigidbody obj = val.AddComponent(); obj.useGravity = false; obj.isKinematic = true; obj.mass = 800f; obj.linearDamping = 0.1f; obj.angularDamping = 0.05f; Breakable val4 = val.AddComponent(); ((Unit)val4).unitSO = definition; ((Unit)val4).spawnOnDeath = (((Object)(object)breakEffect != (Object)null) ? new List { breakEffect } : new List()); ((Unit)val4).spawnOnDeath_LQ = new List(); if (breakSound != null) { PrivateField(typeof(Breakable), "soundEventBreak")?.SetValue(val4, breakSound); } Hitmesh obj2 = val.AddComponent(); obj2.owner = (Unit)(object)val4; obj2.hitmeshCollider = (Collider)(object)val3; obj2.hitShapes = Array.Empty(); return val; } catch (Exception ex) { error = ex.Message; return null; } } private GameObject LoadBreakEffect(string breakEffectPathFragment, DestructibleTemplate template, out Material debrisMaterial, out object breakSound, out string error) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Invalid comparison between Unknown and I4 //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) debrisMaterial = null; breakSound = null; error = null; string diagnostic; IResourceLocation val = FindLocation(breakEffectPathFragment + ".prefab", null, out diagnostic) ?? FindLocation(breakEffectPathFragment + "_LQ", null, out diagnostic) ?? FindLocation(breakEffectPathFragment, null, out diagnostic); if (val == null) { error = "no catalog entry whose path contains '" + breakEffectPathFragment + "'. " + diagnostic; return null; } try { AsyncOperationHandle val2 = Addressables.LoadAssetAsync(val); GameObject val3 = val2.WaitForCompletion(); if ((int)val2.Status != 1 || (Object)(object)val3 == (Object)null) { error = $"break effect at '{val.InternalId}' did not load (status={val2.Status})"; try { Addressables.Release(val2); } catch (Exception) { } return null; } debrisMaterial = ScavengeBodyMaterial(val3, out var name); breakSound = ScavengeBreakSound(val3); template.Handles.Add(AsyncOperationHandle.op_Implicit(val2)); ILogger logger = _logger; if (logger != null) { logger.Log("[crate] " + template.Name + " break effect found at '" + val.InternalId + "' (body material: " + (((Object)(object)debrisMaterial != (Object)null) ? ("'" + name + "'") : "none") + ", break sound: " + ((breakSound != null) ? "yes" : "none") + ")."); } return val3; } catch (Exception ex2) { error = ex2.Message; return null; } } private Material LoadBodyMaterial(string bodyMaterialPathFragment, DestructibleTemplate template) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Invalid comparison between Unknown and I4 //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) string diagnostic; IResourceLocation val = FindLocationOfType(bodyMaterialPathFragment, null, typeof(Material), out diagnostic); if (val == null) { ILogger logger = _logger; if (logger != null) { logger.Log("[crate] no addressable " + template.Name + " body material '" + bodyMaterialPathFragment + "'; using a stand-in."); } return null; } try { AsyncOperationHandle val2 = Addressables.LoadAssetAsync(val); Material val3 = val2.WaitForCompletion(); if ((int)val2.Status != 1 || (Object)(object)val3 == (Object)null) { try { Addressables.Release(val2); } catch (Exception) { } return null; } template.Handles.Add(AsyncOperationHandle.op_Implicit(val2)); ILogger logger2 = _logger; if (logger2 != null) { logger2.Log("[crate] " + template.Name + " body material found at '" + val.InternalId + "'."); } return val3; } catch (Exception) { return null; } } private static Material ScavengeBodyMaterial(GameObject effect, out string name) { name = null; MeshRenderer[] componentsInChildren = effect.GetComponentsInChildren(true); foreach (MeshRenderer val in componentsInChildren) { if ((Object)(object)((Renderer)val).sharedMaterial != (Object)null) { name = ((Object)((Renderer)val).sharedMaterial).name; return ((Renderer)val).sharedMaterial; } } Renderer[] componentsInChildren2 = effect.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren2) { if ((Object)(object)val2.sharedMaterial != (Object)null) { name = ((Object)val2.sharedMaterial).name; return val2.sharedMaterial; } } return null; } private static object ScavengeBreakSound(GameObject effect) { Component[] componentsInChildren = effect.GetComponentsInChildren(true); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { object obj = PrivateField(((object)val).GetType(), "soundEventBreak")?.GetValue(val); if (obj != null) { return obj; } } } return null; } private bool Land(ManagedCrate crate) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) ((Component)crate.Unit).transform.position = crate.Target; IThrownCrateImpact impact = _impact; if (impact != null) { impact.Splash(ToPoint(crate.Target)); } if (crate.Explodes) { crate.Fuse = 1.5f; crate.RestWhereItLanded(); HandBackToPhysics(crate); ILogger logger = _logger; if (logger != null) { logger.Log($"[crate] a barrel landed at ({crate.Target.x:0.0}, {crate.Target.y:0.0}, " + $"{crate.Target.z:0.0}); {1.5f:0.#}s to get clear."); } return false; } BreakNoLoot(crate); return true; } private static void HandBackToPhysics(ManagedCrate crate) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_009a: 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_00ab: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)crate.Unit == (Object)null) && !((Object)(object)crate.Unit.Rigidbody == (Object)null)) { crate.Unit.Rigidbody.isKinematic = false; crate.Unit.Rigidbody.useGravity = true; Vector3 val = ArcVelocityAtLanding(crate); crate.Unit.Rigidbody.linearVelocity = new Vector3(val.x * 0.5f, val.y * 0.05f, val.z * 0.5f); crate.Unit.Rigidbody.angularVelocity = new Vector3(val.z, 0f, 0f - val.x) * 0.25f; } } private static Vector3 ArcVelocityAtLanding(ManagedCrate crate) { //IL_0021: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) float num = crate.FlightSeconds * 0.05f; if (num <= 0f) { return Vector3.zero; } return (ArcPoint(crate, 1f) - ArcPoint(crate, 0.95f)) / num; } private void BurnFuses(float deltaSeconds) { for (int num = _crates.Count - 1; num >= 0; num--) { ManagedCrate managedCrate = _crates[num]; if (!(managedCrate.Fuse <= 0f) && !((Object)(object)managedCrate.Unit == (Object)null)) { managedCrate.Fuse -= deltaSeconds; if (!(managedCrate.Fuse > 0f)) { managedCrate.Fuse = 0f; _crates.RemoveAt(num); Detonate(managedCrate); } } } } private void Detonate(ManagedCrate crate) { BreakNoLoot(crate); if (crate.WhenItGoesOff == null) { return; } try { crate.WhenItGoesOff(); } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] answering a barrel going off failed (" + ex.Message + ")."); } } } private void BreakAsShot(ManagedCrate crate) { _breakingItOurselves = true; try { if ((Object)(object)crate.Breakable != (Object)null) { crate.Breakable.Break(); } else { Object.Destroy((Object)(object)((Component)crate.Unit).gameObject); } } catch (Exception arg) { ILogger logger = _logger; if (logger != null) { logger.LogWarning($"[crate] a crate could not be broken cleanly: {arg}"); } if ((Object)(object)crate.Unit != (Object)null) { Object.Destroy((Object)(object)((Component)crate.Unit).gameObject); } } finally { _breakingItOurselves = false; } } private void BreakNoLoot(ManagedCrate crate) { _breakingItOurselves = true; try { if ((Object)(object)crate.Breakable != (Object)null && _preventDroppingLoot != null) { _preventDroppingLoot.SetValue(crate.Breakable, true); crate.Breakable.Break(); } else { Object.Destroy((Object)(object)((Component)crate.Unit).gameObject); } } catch (Exception arg) { ILogger logger = _logger; if (logger != null) { logger.LogWarning($"[crate] a crate could not be broken cleanly: {arg}"); } if ((Object)(object)crate.Unit != (Object)null) { Object.Destroy((Object)(object)((Component)crate.Unit).gameObject); } } finally { _breakingItOurselves = false; } } public int TakeFrom(CratePileId pile, int count, ArenaWorldPoint near, float radius) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) return TakeFrom(pile, count, near, radius, null); } internal int TakeFrom(CratePileId pile, int count, ArenaWorldPoint near, float radius, List looks) { //IL_004b: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_0096: Unknown result type (might be due to invalid IL or missing references) if (count <= 0) { return 0; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((ArenaWorldPoint)(ref near)).X, 0f, ((ArenaWorldPoint)(ref near)).Z); float num = radius * radius; int num2 = 0; for (int num3 = _crates.Count - 1; num3 >= 0 && num2 < count; num3--) { ManagedCrate managedCrate = _crates[num3]; if (!IsOn(managedCrate, pile)) { continue; } if ((Object)(object)managedCrate.Unit != (Object)null) { Vector3 position = ((Component)managedCrate.Unit).transform.position; Vector3 val2 = new Vector3(position.x, 0f, position.z) - val; if (((Vector3)(ref val2)).sqrMagnitude > num) { continue; } } if ((Object)(object)managedCrate.Unit != (Object)null) { try { Object.Destroy((Object)(object)((Component)managedCrate.Unit).gameObject); } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] a crate could not be picked up: " + ex.Message); } continue; } } looks?.Add(managedCrate.Look); _crates.RemoveAt(num3); num2++; } return num2; } public void Clear() { int num = 0; for (int i = 0; i < _crates.Count; i++) { ManagedCrate managedCrate = _crates[i]; if ((Object)(object)managedCrate.Unit == (Object)null) { continue; } try { Object.Destroy((Object)(object)((Component)managedCrate.Unit).gameObject); num++; } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] one could not be cleared (" + ex.Message + ")."); } } } _crates.Clear(); if (num > 0) { ILogger logger2 = _logger; if (logger2 != null) { logger2.Log($"[crate] {num} destructible(s) cleared with the level."); } } } public bool TryFindNearestResting(CratePileId pile, ArenaWorldPoint near, out ArenaWorldPoint at, IReadOnlyList spokenFor = null, float keepApart = 0f) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) at = default(ArenaWorldPoint); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((ArenaWorldPoint)(ref near)).X, 0f, ((ArenaWorldPoint)(ref near)).Z); float num = float.MaxValue; bool result = false; for (int i = 0; i < _crates.Count; i++) { ManagedCrate managedCrate = _crates[i]; if (IsOn(managedCrate, pile)) { Vector3 position = ((Component)managedCrate.Unit).transform.position; Vector3 val2 = new Vector3(position.x, 0f, position.z) - val; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude >= num) && !AlreadySpokenFor(position, spokenFor, keepApart)) { num = sqrMagnitude; at = ToPoint(position); result = true; } } } return result; } private static bool AlreadySpokenFor(Vector3 here, IReadOnlyList spokenFor, float keepApart) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (spokenFor == null || keepApart <= 0f) { return false; } float num = keepApart * keepApart; for (int i = 0; i < spokenFor.Count; i++) { float x = here.x; ArenaWorldPoint val = spokenFor[i]; float num2 = x - ((ArenaWorldPoint)(ref val)).X; float z = here.z; val = spokenFor[i]; float num3 = z - ((ArenaWorldPoint)(ref val)).Z; if (num2 * num2 + num3 * num3 <= num) { return true; } } return false; } private void CapLooseCrates() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) int num = RestingOn(CratePileId.Loose); if (num <= 60) { return; } int num2 = num - 60; for (int i = 0; i < _crates.Count; i++) { if (num2 <= 0) { break; } ManagedCrate managedCrate = _crates[i]; if (IsOn(managedCrate, CratePileId.Loose)) { if ((Object)(object)managedCrate.Unit != (Object)null) { Object.Destroy((Object)(object)((Component)managedCrate.Unit).gameObject); } _crates.RemoveAt(i); i--; num2--; } } ILogger logger = _logger; if (logger != null) { logger.Log($"[crate] {num - 60} abandoned crate(s) cleared; the loose pile was over " + $"its ceiling of {60}."); } } private void SetLootAllowed(Breakable breakable, bool allowed) { if ((Object)(object)breakable == (Object)null || _preventDroppingLoot == null) { return; } try { _preventDroppingLoot.SetValue(breakable, !allowed); } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[crate] a crate's loot rule could not be set: " + ex.Message); } } } private static ArenaWorldPoint ToPoint(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new ArenaWorldPoint(position.x, position.y, position.z); } private int ResolveBreakableLayer() { int num = LayerMask.NameToLayer("Breakable"); if (num < 0) { return 0; } return num; } private static IResourceLocation FindLocation(string pathFragment, string avoidFragment, out string diagnostic) { return FindLocationOfType(pathFragment, avoidFragment, typeof(GameObject), out diagnostic); } private static IResourceLocation FindLocationOfType(string pathFragment, string avoidFragment, Type resourceType, out string diagnostic) { diagnostic = null; List list = new List(); foreach (IResourceLocator resourceLocator in Addressables.ResourceLocators) { IEnumerable allLocations; try { allLocations = resourceLocator.AllLocations; } catch (Exception) { continue; } if (allLocations == null) { continue; } foreach (IResourceLocation item in allLocations) { if (item != null && item.InternalId != null && !(item.ResourceType != resourceType)) { string internalId = item.InternalId; if (internalId.IndexOf(pathFragment, StringComparison.OrdinalIgnoreCase) >= 0 && (avoidFragment == null || internalId.IndexOf(avoidFragment, StringComparison.OrdinalIgnoreCase) < 0)) { return item; } if (list.Count < 12 && LooksLikeADestructible(internalId)) { list.Add(internalId); } } } } diagnostic = ((list.Count > 0) ? ("nearby destructible-looking paths: " + string.Join("; ", list)) : "no destructible-looking paths were found in the catalog either."); return null; } private static bool LooksLikeADestructible(string id) { if (id.IndexOf("Crate", StringComparison.OrdinalIgnoreCase) < 0 && id.IndexOf("Barrel", StringComparison.OrdinalIgnoreCase) < 0) { return id.IndexOf("Breakable", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static FieldInfo PrivateField(Type type, string name) { return type?.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic); } } } namespace FalseGods.Integration.Sulfur.Arena { public sealed class HijackedArenaLoad { public bool Success { get; } public string FailureReason { get; } public ArenaWorldPoint PlayerSpawn { get; } private HijackedArenaLoad(bool success, string failureReason, ArenaWorldPoint playerSpawn) { //IL_0015: 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) Success = success; FailureReason = failureReason; PlayerSpawn = playerSpawn; } public static HijackedArenaLoad Loaded(ArenaWorldPoint playerSpawn) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return new HijackedArenaLoad(success: true, null, playerSpawn); } public static HijackedArenaLoad Failed(string reason) { //IL_0004: 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) return new HijackedArenaLoad(success: false, reason, default(ArenaWorldPoint)); } } public sealed class HijackedArenaRoomSource { private readonly Func _load; private readonly Func _realizedRoot; private readonly Action _release; private readonly ILogger _logger; private bool _holdsContent; public HijackedArenaRoomSource(Func load, Func realizedRoot, Action release, ILogger logger = null) { _load = load ?? throw new ArgumentNullException("load"); _realizedRoot = realizedRoot ?? throw new ArgumentNullException("realizedRoot"); _release = release ?? throw new ArgumentNullException("release"); _logger = logger; } public Room Acquire() { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) Release(); HijackedArenaLoad hijackedArenaLoad; try { hijackedArenaLoad = _load(); } catch (Exception arg) { ILogger logger = _logger; if (logger != null) { logger.LogWarning($"[arena-room] arena content threw while loading: {arg}"); } return null; } if (hijackedArenaLoad == null || !hijackedArenaLoad.Success) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[arena-room] arena content unavailable: " + (hijackedArenaLoad?.FailureReason ?? "no result")); } return null; } _holdsContent = true; GameObject val = _realizedRoot(); if ((Object)(object)val == (Object)null) { ILogger logger3 = _logger; if (logger3 != null) { logger3.LogWarning("[arena-room] arena content loaded but produced no realized hierarchy."); } Release(); return null; } try { ArenaWorldPoint playerSpawn = hijackedArenaLoad.PlayerSpawn; return SulfurArenaRoom.Build(val, new Vector3(((ArenaWorldPoint)(ref playerSpawn)).X, ((ArenaWorldPoint)(ref playerSpawn)).Y, ((ArenaWorldPoint)(ref playerSpawn)).Z), _logger); } catch (Exception arg2) { ILogger logger4 = _logger; if (logger4 != null) { logger4.LogWarning($"[arena-room] arena could not be dressed as a room: {arg2}"); } Release(); return null; } } public void Release() { if (!_holdsContent) { return; } _holdsContent = false; try { _release(); } catch (Exception arg) { ILogger logger = _logger; if (logger != null) { logger.LogWarning($"[arena-room] releasing arena content threw: {arg}"); } } } } public sealed class ArenaFogRange { public float StartDistance { get; } public float EndDistance { get; } public ArenaFogRange(float startDistance, float endDistance) { StartDistance = startDistance; EndDistance = endDistance; } } public readonly struct ArenaLevel : IEquatable { public WorldEnvironmentIds Environment { get; } public int LevelIndex { get; } public ArenaLevel(WorldEnvironmentIds environment, int levelIndex) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) Environment = environment; LevelIndex = levelIndex; } public bool Equals(ArenaLevel other) { //IL_0001: 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) if (Environment == other.Environment) { return LevelIndex == other.LevelIndex; } return false; } public override bool Equals(object obj) { if (obj is ArenaLevel other) { return Equals(other); } return false; } public override int GetHashCode() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected I4, but got Unknown return (Environment * 397) ^ LevelIndex; } public override string ToString() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return $"{Environment} level {LevelIndex}"; } } public static class LevelGenerationHijack { private static readonly HashSet NeuteredNodes = new HashSet { typeof(CreateMainPathNode), typeof(AddExtraRoomsNode), typeof(SpawnEnemiesNode), typeof(SpawnEventsNode) }; public static bool IsArmed { get; private set; } public static ArenaLevel? ArenaMode { get; private set; } public static bool IsArenaModeOn => ArenaMode.HasValue; public static HijackedArenaRoomSource? ArenaRooms { get; set; } public static ArenaFogRange? Fog { get; set; } public static ILogger? Logger { get; set; } public static int ArenaRunsFinished { get; private set; } public static void EnterArenaMode(ArenaLevel level) { if (!ArenaMode.HasValue || !ArenaMode.Value.Equals(level)) { ArenaMode = level; ILogger? logger = Logger; if (logger != null) { logger.Log($"[levelgen] arena mode ON for {level}; every generation of that level on this peer " + "builds the boss arena, whoever asked for it."); } } } public static void LeaveArenaMode(string? because = null) { if (ArenaMode.HasValue) { ILogger? logger = Logger; if (logger != null) { logger.Log($"[levelgen] arena mode OFF (was {ArenaMode}" + ((because == null) ? string.Empty : ("; " + because)) + "); that level generates normally again."); } ArenaMode = null; } } public static bool TryArmForRun(ArenaLevel generating) { ArenaLevel? arenaMode = ArenaMode; if (!arenaMode.HasValue || !arenaMode.Value.Equals(generating)) { return false; } IsArmed = true; return true; } public static void Disarm() { if (IsArmed) { ArenaRunsFinished++; } IsArmed = false; } public static bool IsNeutered(Type nodeType) { if (nodeType != null) { return NeuteredNodes.Contains(nodeType); } return false; } } public static class LevelGenerationHijackPatches { private const string HarmonyId = "ryuka.sulfur.false_gods.levelgen"; private static bool _installed; public static void Install(ILogger? logger) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0054: 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_008f: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown if (_installed) { return; } LevelGenerationHijack.Logger = logger; try { Harmony val = new Harmony("ryuka.sulfur.false_gods.levelgen"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(MakerNodeBase), "StartExecution", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(LevelGenerationHijackPatches), "ObserveOrSkipStep", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(CreateStartAreaNode), "Execute", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(LevelGenerationHijackPatches), "PlaceArenaAsStartArea", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(MakerGraphContext), "StartMaking", new Type[2] { typeof(MakerNodeBase), typeof(OnNodeExecuting) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(LevelGenerationHijackPatches), "ScopeToOneGenerationRun", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _installed = true; if (logger != null) { logger.Log("[levelgen] generation hooks installed."); } } catch (Exception arg) { if (logger != null) { logger.LogWarning($"[levelgen] generation hooks could not be installed: {arg}"); } } } private static bool ObserveOrSkipStep(MakerNodeBase __instance, MakerGraphContext context, ref IEnumerator __result) { if (!LevelGenerationHijack.IsArmed || (Object)(object)__instance == (Object)null) { return true; } try { Type type = ((object)__instance).GetType(); int num = (((Object)(object)context != (Object)null) ? (context.ExecutingNodeIndex + 1) : (-1)); if (!LevelGenerationHijack.IsNeutered(type)) { ILogger? logger = LevelGenerationHijack.Logger; if (logger != null) { logger.Log($"[levelgen] step {num}: {type.Name} (native)"); } return true; } if ((Object)(object)context == (Object)null) { ILogger? logger2 = LevelGenerationHijack.Logger; if (logger2 != null) { logger2.LogWarning("[levelgen] " + type.Name + " has no generation context; leaving it to run."); } return true; } __instance.SetContext(context); int executingNodeIndex = context.ExecutingNodeIndex; context.ExecutingNodeIndex = executingNodeIndex + 1; __result = SkippedStep(); ILogger? logger3 = LevelGenerationHijack.Logger; if (logger3 != null) { logger3.Log($"[levelgen] step {num}: {type.Name} (skipped)"); } return false; } catch (Exception arg) { ILogger? logger4 = LevelGenerationHijack.Logger; if (logger4 != null) { logger4.LogWarning($"[levelgen] step hook threw, running the step: {arg}"); } return true; } } private static void ScopeToOneGenerationRun(ref IEnumerator __result) { if (__result == null || !LevelGenerationHijack.IsArenaModeOn) { return; } try { ArenaLevel? arenaLevel = CurrentlyGeneratingLevel(); if (!arenaLevel.HasValue) { return; } if (!LevelGenerationHijack.TryArmForRun(arenaLevel.Value)) { LevelGenerationHijack.LeaveArenaMode($"the players moved on to {arenaLevel.Value}"); return; } } catch (Exception arg) { ILogger? logger = LevelGenerationHijack.Logger; if (logger != null) { logger.LogWarning($"[levelgen] could not identify the generating level, leaving it ordinary: {arg}"); } return; } __result = DisarmWhenFinished(__result); } private static ArenaLevel? CurrentlyGeneratingLevel() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) GameManager instance = StaticInstance.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.currentEnvironment == (Object)null) { return null; } return new ArenaLevel(instance.currentEnvironment.id, instance.currentLevelIndex); } private static bool PlaceArenaAsStartArea(CreateStartAreaNode __instance, ref IEnumerator __result) { if (!LevelGenerationHijack.IsArmed || (Object)(object)__instance == (Object)null) { return true; } try { HijackedArenaRoomSource arenaRooms = LevelGenerationHijack.ArenaRooms; if (arenaRooms == null) { ILogger? logger = LevelGenerationHijack.Logger; if (logger != null) { logger.LogWarning("[levelgen] no arena source installed; generating the level's own start area."); } return true; } MakerGraphContext context = ((MakerNodeBase)__instance).Context; LevelGenerationContext val = (LevelGenerationContext)(object)((context is LevelGenerationContext) ? context : null); if (val == null) { ILogger? logger2 = LevelGenerationHijack.Logger; if (logger2 != null) { logger2.LogWarning("[levelgen] start-area step has no level-generation context; leaving it to generate."); } return true; } Room val2 = arenaRooms.Acquire(); if ((Object)(object)val2 == (Object)null) { return true; } __result = StartAreaFromArena(__instance, val, val2); return false; } catch (Exception arg) { ILogger? logger3 = LevelGenerationHijack.Logger; if (logger3 != null) { logger3.LogWarning($"[levelgen] arena injection threw, generating the level's own start area: {arg}"); } return true; } } private static IEnumerator StartAreaFromArena(CreateStartAreaNode node, LevelGenerationContext context, Room room) { ((MakerNodeBase)node).AddManagedObject((Object)(object)((Component)room).gameObject); context.orderedRooms.Clear(); context.orderedRooms.Add(room); context.spawnPoint = room.GetPlayerSpawnPoint(string.Empty); context.startOutConnectors = ConnectorExt.GetChildConnectorsSorted(((Component)room).gameObject, false); if ((Object)(object)context.spawnPoint == (Object)null) { ILogger? logger = LevelGenerationHijack.Logger; if (logger != null) { logger.LogWarning("[levelgen] the arena room exposes no player spawn point; the level will have nowhere to place the player."); } } ArenaFogRange fog = LevelGenerationHijack.Fog; if (fog != null) { SulfurLevelFog.TryApply(fog.StartDistance, fog.EndDistance, LevelGenerationHijack.Logger); } ILogger? logger2 = LevelGenerationHijack.Logger; if (logger2 != null) { logger2.Log("[levelgen] arena placed as the level's start area."); } yield return null; } private static IEnumerator SkippedStep() { yield return null; } private static IEnumerator DisarmWhenFinished(IEnumerator run) { try { while (run.MoveNext()) { yield return run.Current; } } finally { ILogger? logger = LevelGenerationHijack.Logger; if (logger != null) { logger.Log("[levelgen] generation run ended; hijack released."); } LevelGenerationHijack.Disarm(); } } } public sealed class SulfurArenaHazard { private readonly struct Visit { public float HealthOnEntry { get; } public int Ticks { get; } public Visit(float healthOnEntry) : this(healthOnEntry, 0) { } private Visit(float healthOnEntry, int ticks) { HealthOnEntry = healthOnEntry; Ticks = ticks; } public Visit OneMore() { return new Visit(HealthOnEntry, Ticks + 1); } } private sealed class SludgeDamager : IDamager { private readonly Transform _transform; public string SourceName => "False Gods sludge"; public Unit SourceUnit => null; public Weapon SourceWeapon => null; public Transform Transform => _transform; public bool CreatedByPlayer => false; public SludgeDamager(Transform transform) { _transform = transform; } public void SetOwner(Unit unit) { } } private readonly Func _arenaRoot; private readonly string _volumeParentPath; private readonly string _volumeName; private readonly int _damage; private readonly float _interval; private readonly ILogger _logger; private readonly List _volumes = new List(); private readonly Dictionary _burning = new Dictionary(); private GameObject _knownRoot; private float _sinceLastTick; public SulfurArenaHazard(Func arenaRoot, string volumeParentPath, string volumeName, int damage, float interval, ILogger logger = null) { _arenaRoot = arenaRoot ?? throw new ArgumentNullException("arenaRoot"); _volumeParentPath = volumeParentPath; _volumeName = volumeName; _damage = damage; _interval = Mathf.Max(0.02f, interval); _logger = logger; } public void Advance(float deltaTime) { GameObject val = _arenaRoot(); if ((Object)(object)val == (Object)null) { Forget(); return; } if (val != _knownRoot) { Collect(val); } if (_volumes.Count != 0) { _sinceLastTick += deltaTime; if (!(_sinceLastTick < _interval)) { _sinceLastTick = 0f; Burn(); } } } public void Forget() { _knownRoot = null; _volumes.Clear(); _burning.Clear(); _sinceLastTick = 0f; } private void Collect(GameObject root) { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) _knownRoot = root; _volumes.Clear(); _burning.Clear(); Transform val = (string.IsNullOrEmpty(_volumeParentPath) ? root.transform : root.transform.Find(_volumeParentPath)); if ((Object)(object)val == (Object)null) { ILogger logger = _logger; if (logger != null) { logger.Log("[hazard] no '" + _volumeParentPath + "' in this arena; nothing burns."); } return; } Transform[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); foreach (Transform val2 in componentsInChildren) { if (!string.Equals(((Object)val2).name, _volumeName, StringComparison.Ordinal)) { continue; } SphereCollider component = ((Component)val2).GetComponent(); if (!((Object)(object)component == (Object)null)) { _volumes.Add(component); ILogger logger2 = _logger; if (logger2 != null) { string text = $"[hazard] '{_volumeName}' reaches {WorldRadius(component):0.#} around "; Vector3 val3 = Center(component); logger2.Log(text + ((Vector3)(ref val3)).ToString("0.#")); } } } ILogger logger3 = _logger; if (logger3 != null) { logger3.Log($"[hazard] {_volumes.Count} volume(s) burning for {_damage} every {_interval:0.##}s"); } } private void Burn() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) GameManager instance = StaticInstance.Instance; List list = (((Object)(object)instance != (Object)null) ? instance.Players : null); if (list == null) { return; } for (int i = 0; i < list.Count; i++) { Player val = list[i]; if ((Object)(object)val == (Object)null || (Object)(object)val.playerUnit == (Object)null || !FightingPlayers.IsFighting(val)) { continue; } int instanceID = ((Object)val).GetInstanceID(); if (!Inside(((Component)val).transform.position)) { if (_burning.TryGetValue(instanceID, out var value)) { _burning.Remove(instanceID); float num = Health(val); ILogger logger = _logger; if (logger != null) { logger.Log($"[hazard] a player left the sludge after {value.Ticks} tick(s): " + $"health here {value.HealthOnEntry:0.##} -> {num:0.##}" + ((num < value.HealthOnEntry) ? string.Empty : " (owned by another peer)")); } } continue; } if (!_burning.TryGetValue(instanceID, out var value2)) { value2 = new Visit(Health(val)); ILogger logger2 = _logger; if (logger2 != null) { Vector3 position = ((Component)val).transform.position; logger2.Log("[hazard] a player is standing in the sludge at " + ((Vector3)(ref position)).ToString("0.#") + "."); } } Strike(val); _burning[instanceID] = value2.OneMore(); } } private bool Inside(Vector3 point) { //IL_0022: 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_0028: 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) for (int i = 0; i < _volumes.Count; i++) { SphereCollider val = _volumes[i]; if (!((Object)(object)val == (Object)null)) { float num = WorldRadius(val); Vector3 val2 = Center(val) - point; if (((Vector3)(ref val2)).sqrMagnitude <= num * num) { return true; } } } return false; } private void Strike(Player player) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) try { player.playerUnit.ReceiveDamage((float)_damage, (DamageTypes)7, (IDamager)(object)new SludgeDamager(((Component)player).transform), Data.Default, (Vector3?)null); } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[hazard] the sludge could not burn a player (" + ex.Message + "); skipped."); } } } private static float Health(Player player) { try { EntityStats stats = player.playerUnit.Stats; return (stats == null) ? (-1f) : stats.GetStatus((EntityAttributes)92); } catch (Exception) { return -1f; } } private static Vector3 Center(SphereCollider sphere) { //IL_0007: 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) return ((Component)sphere).transform.TransformPoint(sphere.center); } private static float WorldRadius(SphereCollider sphere) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) Vector3 lossyScale = ((Component)sphere).transform.lossyScale; return sphere.radius * Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Max(Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z))); } } public sealed class SulfurArenaHijackPort : IArenaHijackPort { private const WorldEnvironmentIds CaveEnvironment = (WorldEnvironmentIds)3; private const int FirstLevelIndex = 0; private static readonly ArenaLevel HijackedLevel = new ArenaLevel((WorldEnvironmentIds)3, 0); private readonly ILogger? _logger; public ArenaLevelId ArenaLevel => new ArenaLevelId(3, 0); public bool IsArenaModeOn => LevelGenerationHijack.IsArenaModeOn; public SulfurArenaHijackPort(ILogger? logger) { _logger = logger; } public bool DeclareArenaLevel(ArenaLevelId level) { if (!Enum.IsDefined(typeof(WorldEnvironmentIds), ((ArenaLevelId)(ref level)).Environment)) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[hijack] refusing a boss-arena declaration for unknown environment " + $"{((ArenaLevelId)(ref level)).Environment} (level {((ArenaLevelId)(ref level)).LevelIndex})."); } return false; } LevelGenerationHijack.EnterArenaMode(new ArenaLevel((WorldEnvironmentIds)((ArenaLevelId)(ref level)).Environment, ((ArenaLevelId)(ref level)).LevelIndex)); return true; } public void LeaveArenaMode() { LevelGenerationHijack.LeaveArenaMode(); } public void LoadHijackedArena() { GameManager instance = StaticInstance.Instance; if ((Object)(object)instance == (Object)null) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[hijack] no GameManager; cannot load the cave level."); } return; } LevelGenerationHijack.EnterArenaMode(HijackedLevel); try { ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log($"[hijack] loading {(object)(WorldEnvironmentIds)3} level {0} (native level load)."); } instance.GoToLevel((WorldEnvironmentIds)3, 0, (LoadingMode)0, string.Empty); } catch (Exception arg) { ILogger? logger3 = _logger; if (logger3 != null) { logger3.LogWarning($"[hijack] GoToLevel threw: {arg}"); } } } } public static class SulfurArenaRoom { public const string NavigationLinksPath = "NavigationRoot/NavLinks"; private const string LinkMarkerPrefix = "Link_"; private const string LinkEndChildName = "End"; public static Room Build(GameObject arenaGeometry, Vector3 playerSpawn, ILogger logger = null) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0043: 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_007b: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)arenaGeometry == (Object)null) { throw new ArgumentNullException("arenaGeometry"); } GameObject val = new GameObject("FalseGodsArenaRoom"); val.SetActive(false); RoomLODBase roomLOD = val.AddComponent(); Room obj = val.AddComponent(); obj.roomLOD = roomLOD; obj.disableBloodOccupancyGrid = true; obj.roomSize = (RoomSize)4; obj.doNotFlip = true; obj.doNotBarricade = true; obj.uniquePerLevel = true; obj.uniquePerRun = true; obj.Structure = arenaGeometry; obj.Decoration = new GameObject("Decoration"); obj.Decoration.transform.SetParent(val.transform, false); EmptyEveryBakedList(obj); arenaGeometry.transform.SetParent(val.transform, true); obj.nodeLinks = BuildNavigationLinks(arenaGeometry, logger); GameObject val2 = new GameObject("PlayerSpawn"); val2.transform.SetParent(val.transform, false); val2.transform.position = playerSpawn; val2.AddComponent().identifier = string.Empty; val.SetActive(true); obj.partOfMainFlow = true; obj.roomIndex = 0; obj.disallowEnemySpawn = true; if (logger != null) { logger.Log("[arena-room] arena wrapped as a Room; player spawn at " + $"({playerSpawn.x:0.0}, {playerSpawn.y:0.0}, {playerSpawn.z:0.0})."); } return obj; } private static NodeLink2[] BuildNavigationLinks(GameObject arenaGeometry, ILogger logger) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown Transform val = arenaGeometry.transform.Find("NavigationRoot/NavLinks"); if ((Object)(object)val == (Object)null) { return Array.Empty(); } List list = new List(); int num = 0; foreach (Transform item in val) { Transform val2 = item; if (((Object)val2).name.StartsWith("Link_", StringComparison.Ordinal)) { Transform val3 = val2.Find("End"); if ((Object)(object)val3 == (Object)null) { num++; continue; } NodeLink2 val4 = ((Component)val2).gameObject.AddComponent(); val4.end = val3; val4.oneWay = false; list.Add(val4); } } if ((list.Count > 0 || num > 0) && logger != null) { logger.Log($"[arena-room] {list.Count} navigation link(s) wired" + ((num > 0) ? string.Format("; {0} marker(s) skipped with no '{1}' child", num, "End") : "") + "."); } return list.ToArray(); } private static void EmptyEveryBakedList(Room room) { room.containers = None(room.containers); room.connectors = None(room.connectors); room.NPCSpawns = None(room.NPCSpawns); room.NPCs = None(room.NPCs); room.Interactables = None(room.Interactables); room.pickups = None(room.pickups); room.eventSpawners = None(room.eventSpawners); room.bezierArms = None(room.bezierArms); room.hiddenChests = None(room.hiddenChests); room.randomizeXOnSprites = None(room.randomizeXOnSprites); room.randomChildSubsets = None(room.randomChildSubsets); room.randomChanceSelects = None(room.randomChanceSelects); room.randomlyDisables = None(room.randomlyDisables); room.randomizeDecals = None(room.randomizeDecals); room.serviceStations = None(room.serviceStations); room.triggerSpawners = None(room.triggerSpawners); room.endlessModeSpawnPoints = None(room.endlessModeSpawnPoints); room.nodeLinks = None(room.nodeLinks); room.bakedNPCSpawns = None(room.bakedNPCSpawns); room.bakedEventSpawners = None(room.bakedEventSpawners); room.bakedNavMeshLinks = None(room.bakedNavMeshLinks); room.navMeshAnchors = new List(); } private static T[] None(T[] bakedList) { return Array.Empty(); } } public sealed class SulfurCaveBossPortal { private sealed class FadingSurface { private readonly Material _material; private readonly bool _wasOpaque; public FadingSurface(Material material) { _material = material; _wasOpaque = material.HasProperty("_Surface") && material.GetFloat("_Surface") < 0.5f; if (_wasOpaque) { material.SetFloat("_Surface", 1f); material.SetFloat("_SrcBlend", 5f); material.SetFloat("_DstBlend", 10f); material.SetFloat("_ZWrite", 0f); material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.renderQueue = 3000; } } public void SetAlpha(float alpha) { _material.SetFloat("_Alpha", alpha); } public void Finish() { _material.SetFloat("_Alpha", 1f); if (_wasOpaque) { _material.SetFloat("_Surface", 0f); _material.SetFloat("_SrcBlend", 1f); _material.SetFloat("_DstBlend", 0f); _material.SetFloat("_ZWrite", 1f); _material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); _material.renderQueue = 2000; } } } private sealed class CaveDoorTrigger : MonoBehaviour { private GameObject _player; private bool _used; public Action WalkedThrough { get; set; } private void OnTriggerEnter(Collider other) { if (!_used && !((Object)(object)other == (Object)null)) { if ((Object)(object)_player == (Object)null) { GameManager instance = StaticInstance.Instance; _player = (((Object)(object)instance != (Object)null) ? instance.PlayerObject : null); } if (!((Object)(object)_player == (Object)null) && !((Object)(object)((Component)other).gameObject != (Object)(object)_player)) { _used = true; WalkedThrough?.Invoke(); } } } } private static readonly Vector3 DoorwayPosition = new Vector3(-8.15f, 3.06f, 16.17f); private static readonly Vector3 DoorwayRotation = new Vector3(0f, 348.53f, 0f); private static readonly Vector3 DoorwaySize = new Vector3(5.73f, 6.35f, 1f); private const float DoorwayDepthMultiplier = 3f; private const string DoorDonorKey = "Assets/_Core/Prefabs/LevelGeneration/Chunks/Hub/ChurchHub.prefab"; private const string PortalName = "HedgemazePortal"; private const string PortalLitChild = "ON"; private static readonly (string Path, Vector3 Offset, bool ByDrawnCentre)[] DoorPieces = new(string, Vector3, bool)[3] { ("Shine", Vector3.zero, true), ("HedgeMazeShine", new Vector3(0.01f, 0.02f, 3.25f), true), ("PortalParticleEffects", new Vector3(-0.34f, -0.47f, -1.25f), false) }; private const float PortalRollDegrees = 90f; private const float OpeningSeconds = 1f; private const string TransparentKeyword = "_SURFACE_TYPE_TRANSPARENT"; private const float ProudOfTheWall = 0.1f; private const float StandsIntoTheRoom = 0.2f; private const float SetsDownFromThePanel = 0.2f; private readonly ILogger _logger; private readonly Action _walkThrough; private CousinHelper _watched; private Unit _boss; private GameObject _doorway; private AssetReference _donor; private bool _doorwayKnown; private Vector3 _doorwayAt; private Quaternion _doorwayFacing; private Transform _look; private float _sinceOpened = -1f; private readonly List _fading = new List(); public SulfurCaveBossPortal(Action walkThrough, ILogger logger = null) { _walkThrough = walkThrough ?? throw new ArgumentNullException("walkThrough"); _logger = logger; } public void Watch() { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown AdvanceTheOpening(); if ((Object)(object)_watched != (Object)null) { return; } if ((Object)(object)_boss != (Object)null || _donor != null || _doorwayKnown) { Forget(); } CousinHelper val; try { val = Object.FindAnyObjectByType((FindObjectsInactive)0); } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[cave-door] could not look for the cave boss (" + ex.Message + ")."); } return; } if ((Object)(object)val == (Object)null) { return; } Unit component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[cave-door] the cave boss's helper is not on a unit; no door will open."); } } else { _watched = val; _boss = component; component.onDeath = (OnDeath)Delegate.Combine((Delegate?)(object)component.onDeath, (Delegate?)new OnDeath(BossDied)); FindTheDoorway(val, component); } } private void AdvanceTheOpening() { if (_sinceOpened < 0f || (Object)(object)_look == (Object)null) { return; } _sinceOpened += Time.deltaTime; float num = Mathf.Clamp01(_sinceOpened / 1f); float alpha = num * num * (3f - 2f * num); for (int i = 0; i < _fading.Count; i++) { _fading[i].SetAlpha(alpha); } if (!(num < 1f)) { for (int j = 0; j < _fading.Count; j++) { _fading[j].Finish(); } _fading.Clear(); _sinceOpened = -1f; ILogger logger = _logger; if (logger != null) { logger.Log("[cave-door] the way through has finished opening."); } } } public void Forget() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown if ((Object)(object)_boss != (Object)null) { _boss.onDeath = (OnDeath)Delegate.Remove((Delegate?)(object)_boss.onDeath, (Delegate?)new OnDeath(BossDied)); } _boss = null; _watched = null; _doorwayKnown = false; _look = null; _sinceOpened = -1f; _fading.Clear(); if ((Object)(object)_doorway != (Object)null) { Object.Destroy((Object)(object)_doorway); } _doorway = null; Release(); } private void FindTheDoorway(CousinHelper helper, Unit boss) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: 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) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) Room val = ((Component)helper).GetComponentInParent(); string text = "its own room in the hierarchy"; if ((Object)(object)val == (Object)null) { val = Room.FindClosestRoom(((Component)boss).transform.position, (Room)null, 10f); text = "the closest room to where it stands"; } if ((Object)(object)val == (Object)null) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[cave-door] the cave boss is in this level but its room cannot be found, so no way through will open. The room's own exit still works."); } return; } _doorwayAt = ((Component)val).transform.TransformPoint(DoorwayPosition); _doorwayFacing = ((Component)val).transform.rotation * Quaternion.Euler(DoorwayRotation); Vector3 val2 = ((Component)boss).transform.position - _doorwayAt; bool flag = Vector3.Dot(_doorwayFacing * Vector3.forward, val2) < 0f; if (flag) { _doorwayFacing *= Quaternion.Euler(0f, 180f, 0f); } _doorwayAt += _doorwayFacing * Vector3.forward * 0.2f; _doorwayAt += Vector3.down * 0.2f; _doorwayKnown = true; ILogger logger2 = _logger; if (logger2 != null) { logger2.Log("[cave-door] the cave boss is in this level (" + text + "); a way through will open at " + string.Format("{0} when it falls, facing {1}.", _doorwayAt, flag ? "the room (turned about)" : "the room")); } } private void BossDied(Unit unit) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_016b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_doorway != (Object)null) { return; } if (!_doorwayKnown) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[cave-door] the cave boss is dead, but there was nowhere to put a door; none opened."); } return; } try { _doorway = new GameObject("FalseGodsCaveDoor"); _doorway.transform.SetPositionAndRotation(_doorwayAt, _doorwayFacing); BoxCollider obj = _doorway.AddComponent(); ((Collider)obj).isTrigger = true; float num = DoorwaySize.z * 3f; obj.size = new Vector3(DoorwaySize.x, DoorwaySize.y, num); obj.center = new Vector3(0f, 0f, (num - DoorwaySize.z) * 0.5f); GameManager instance = StaticInstance.Instance; if ((Object)(object)instance != (Object)null) { _doorway.layer = instance.TriggerLayer; } GameObject val = new GameObject("Look"); val.transform.SetParent(_doorway.transform, false); _look = val.transform; AddTheDoor(_look); CollectSurfacesToFade(_look); _sinceOpened = 0f; _doorway.AddComponent().WalkedThrough = _walkThrough; ILogger logger2 = _logger; if (logger2 != null) { logger2.Log("[cave-door] the cave boss is dead; a way through has opened in its room at " + $"{_doorway.transform.position}."); } } catch (Exception ex) { ILogger logger3 = _logger; if (logger3 != null) { logger3.LogWarning("[cave-door] the door could not be opened (" + ex.Message + "); the room's own way out still works."); } } } private void AddTheDoor(Transform doorway) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) GameObject val = LoadDonor(); if ((Object)(object)val == (Object)null) { return; } Transform val2 = FindPortal(val.transform); if ((Object)(object)val2 == (Object)null) { return; } Transform val3 = val2.Find(DoorPieces[0].Path); if ((Object)(object)val3 == (Object)null) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[cave-door] the donor portal has no lit plate to measure the rest against; the way through is unlit."); } return; } Vector3 origin = DrawnCentre(val3); FitToTheDoorway(val3, doorway); int num = 0; for (int i = 0; i < DoorPieces.Length; i++) { if (Clone(val2, DoorPieces[i], origin, doorway)) { num++; } } ILogger logger2 = _logger; if (logger2 != null) { logger2.Log($"[cave-door] {num} of {DoorPieces.Length} piece(s) of the church's portal now stand " + "in the doorway."); } } private Transform FindPortal(Transform donor) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown Transform val = null; Transform[] componentsInChildren = ((Component)donor).GetComponentsInChildren(true); foreach (Transform val2 in componentsInChildren) { if (((Object)val2).name == "HedgemazePortal") { val = val2; break; } } if ((Object)(object)val == (Object)null) { StringBuilder stringBuilder = new StringBuilder(); int num = 0; foreach (Transform item in donor) { Transform val3 = item; if (num++ == 12) { stringBuilder.Append(", ..."); break; } if (num > 1) { stringBuilder.Append(", "); } stringBuilder.Append(((Object)val3).name); } ILogger logger = _logger; if (logger != null) { logger.LogWarning("[cave-door] the donor holds no 'HedgemazePortal'; the way through is unlit. It " + $"holds: {stringBuilder}"); } return null; } Transform val4 = val.Find("ON"); if ((Object)(object)val4 == (Object)null) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[cave-door] the portal has no 'ON' half; the way through is unlit."); } return null; } return val4; } private void FitToTheDoorway(Transform plate, Transform doorway) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_008a: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = ((Component)plate).GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { return; } Bounds bounds = componentsInChildren[0].bounds; for (int i = 1; i < componentsInChildren.Length; i++) { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds); } float y = ((Bounds)(ref bounds)).size.y; float x = ((Bounds)(ref bounds)).size.x; if (!(y <= 0.001f) && !(x <= 0.001f)) { float num = Mathf.Min(DoorwaySize.x / y, DoorwaySize.y / x); doorway.localScale = Vector3.one * num; ILogger logger = _logger; if (logger != null) { logger.Log($"[cave-door] the borrowed portal is {y:0.00} by {x:0.00} on its side and the room " + $"authored {DoorwaySize.x:0.00} by {DoorwaySize.y:0.00}, so it stands at {num:0.00}x " + $"({y * num:0.00} by {x * num:0.00}), inside the panel."); } } } private GameObject LoadDonor() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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: Invalid comparison between Unknown and I4 //IL_004e: Unknown result type (might be due to invalid IL or missing references) try { _donor = new AssetReference("Assets/_Core/Prefabs/LevelGeneration/Chunks/Hub/ChurchHub.prefab"); AsyncOperationHandle val = _donor.LoadAssetAsync(); GameObject val2 = val.WaitForCompletion(); if ((int)val.Status == 1 && (Object)(object)val2 != (Object)null) { return val2; } ILogger logger = _logger; if (logger != null) { logger.LogWarning($"[cave-door] the portal's donor did not load ({val.Status}); the way " + "through is there but unlit."); } } catch (Exception ex) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[cave-door] the portal's donor did not load (" + ex.Message + "); the way through is there but unlit."); } } Release(); return null; } private bool Clone(Transform portal, (string Path, Vector3 Offset, bool ByDrawnCentre) piece, Vector3 origin, Transform doorway) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: 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_00b2: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //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_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) Transform val = portal.Find(piece.Path); if ((Object)(object)val == (Object)null) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[cave-door] the donor portal has no '" + piece.Path + "'; that piece is missing."); } return false; } GameObject val2 = new GameObject("FalseGodsDoorStaging"); val2.SetActive(false); try { GameObject val3 = Object.Instantiate(((Component)val).gameObject, val2.transform); ((Object)val3).name = ((Object)val).name; Collider[] componentsInChildren = val3.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } Vector3 val4 = (piece.ByDrawnCentre ? DrawnCentre(val) : val.position); Vector3 val5 = val.position - val4; Quaternion val6 = Quaternion.Euler(0f, 0f, 90f); val3.transform.SetParent(doorway, false); val3.transform.localRotation = val6 * val.localRotation; val3.transform.localScale = val.localScale; val3.transform.localPosition = val6 * (piece.Offset + val5) + Vector3.forward * 0.1f; val3.SetActive(true); return true; } finally { Object.Destroy((Object)(object)val2); } } private void CollectSurfacesToFade(Transform look) { Renderer[] componentsInChildren = ((Component)look).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Material[] materials = componentsInChildren[i].materials; foreach (Material val in materials) { if (!((Object)(object)val == (Object)null) && val.HasProperty("_Alpha")) { _fading.Add(new FadingSurface(val)); } } } } private static Vector3 DrawnCentre(Transform piece) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = ((Component)piece).GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { return piece.position; } Bounds bounds = componentsInChildren[0].bounds; for (int i = 1; i < componentsInChildren.Length; i++) { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds); } return ((Bounds)(ref bounds)).center; } private void Release() { if (_donor == null) { return; } try { _donor.ReleaseAsset(); } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[cave-door] the embers' donor room would not release (" + ex.Message + ")."); } } _donor = null; } } public sealed class SulfurDevMenuEntry { private const string Label = "FALSE GODS: boss arena"; private const string PreferredChapter = "Caves"; private readonly Action _goToTheArena; private readonly ILogger _logger; private GameObject _row; public SulfurDevMenuEntry(Action goToTheArena, ILogger logger = null) { _goToTheArena = goToTheArena ?? throw new ArgumentNullException("goToTheArena"); _logger = logger; } public void Maintain() { //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Expected O, but got Unknown if ((Object)(object)_row != (Object)null) { return; } ChapterPanel[] array; try { array = Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0); } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[dev-menu] could not look for the level list (" + ex.Message + ")."); } return; } if (array == null || array.Length == 0) { return; } ChapterPanel val = PickPanel(array); Button val2 = FindARow(val); if ((Object)(object)val2 == (Object)null) { return; } try { _row = Object.Instantiate(((Component)val2).gameObject, ((Component)val).transform); ((Object)_row).name = "FalseGodsArenaRow"; _row.transform.SetAsLastSibling(); TextMeshProUGUI componentInChildren = _row.GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)componentInChildren).text = "FALSE GODS: boss arena"; } Button component = _row.GetComponent