using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using FalseGods.Application.Arena; using FalseGods.Application.Combat; using FalseGods.Application.Presentation; using FalseGods.Application.ReadyGate; using FalseGods.Application.Replication; using FalseGods.Core.Arena; using FalseGods.Core.Arena.Events; using FalseGods.Core.Bosses; using FalseGods.Core.Bosses.Combat; using FalseGods.Core.Bosses.Events; using FalseGods.Core.Encounters; using FalseGods.Core.Simulation; using FalseGods.Integration.Sulfur.Arena; using FalseGods.Integration.Sulfur.Combat; using FalseGods.Integration.Sulfur.Navigation; using FalseGods.Integration.Sulfur.Presentation; using FalseGods.Integration.Sulfur.Simulation; using FalseGods.Plugin.Diagnostics; using FalseGods.Protocol.Arena; using FalseGods.Protocol.Wire; using FalseGods.RuntimeContracts.Arena; using FalseGods.RuntimeContracts.Diagnostics; using FalseGods.RuntimeContracts.Integration; using FalseGods.RuntimeContracts.Multiplayer; using FalseGods.RuntimeContracts.Presentation; using FalseGods.RuntimeContracts.Transport; using FalseGods.UnityRuntime.Arena; using FalseGods.UnityRuntime.Presentation; using Microsoft.CodeAnalysis; using UnityEngine; [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.Plugin")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+6e5740a80f810ab422551028733810b527fb614d")] [assembly: AssemblyProduct("FalseGods.Plugin")] [assembly: AssemblyTitle("FalseGods.Plugin")] [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.Plugin { internal sealed class ClientBossController : IDisposable { private sealed class HitReportSink : IBossDamageSink { private readonly ClientHitReporter _reporter; private readonly EncounterId _encounter; public HitReportSink(ClientHitReporter reporter, EncounterId encounter) { //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) _reporter = reporter; _encounter = encounter; } public void ApplyWeaponDamage(float amount) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) _reporter.ReportHit(_encounter, amount, (WorldPosition?)null); } } private const float OriginEpsilon = 0.05f; private readonly ILogger? _logger; private readonly IFalseGodsIntegration _integration; private readonly string _contentDirectory; private readonly ClientEncounterFlow _controlFlow; private readonly ClientHitReporter _hitReporter; private readonly IDamagePort _damagePort; private readonly SulfurLocalPlayer _localPlayer; private readonly IBattlefieldCleanupPort _battlefield; private readonly IBossArmPort _rageArms; private readonly IBossVoicePort _voice; private readonly IArenaAtmospherePort _atmosphere; private readonly IBossRewardPort _reward; private readonly Func _levelWillBringTheArena; private readonly IBossPresencePort _presence; private ReplicationReceiver _receiver; private IDisposable? _hitBinding; private BossPresentation? _presentation; private EncounterId? _encounter; private int _presentedEvents; private int _presentedArenaEvents; private bool _waitingForCameraLogged; private BundleArenaRealization? _realization; private ArenaLoadFlow? _arenaFlow; private LoadedArena? _loadedArena; private ArenaPresentation? _arenaPresentation; private EncounterId? _arenaEncounter; private bool _lateJoinArenaFailed; private bool _arenaSnapshotReplayed; private bool _openingPlayed; private bool _waitingForOwnArenaLogged; private bool _ownsArena; public HijackedArenaContent? LevelArena { get; set; } public bool IsUp => _presentation != null; public ClientBossController(ILogger logger, MonoBehaviour host, IFalseGodsIntegration integration, IArenaAtmospherePort atmosphere, Func levelWillBringTheArena) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown //IL_0131: 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_0148: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown _logger = logger; _integration = integration ?? throw new ArgumentNullException("integration"); _atmosphere = atmosphere ?? throw new ArgumentNullException("atmosphere"); _levelWillBringTheArena = levelWillBringTheArena ?? throw new ArgumentNullException("levelWillBringTheArena"); _contentDirectory = Path.GetDirectoryName(typeof(ClientBossController).Assembly.Location) ?? "."; _receiver = new ReplicationReceiver(integration.Channel, integration.Session); _hitReporter = new ClientHitReporter(integration.Channel, integration.Session, logger); _damagePort = (IDamagePort)new SulfurDamagePort(logger); _localPlayer = new SulfurLocalPlayer(); _battlefield = (IBattlefieldCleanupPort)new SulfurBattlefieldCleanup(logger); _rageArms = (IBossArmPort)new SulfurBossArmPort(host, logger); _reward = (IBossRewardPort)new SulfurBossReward(logger); _presence = (IBossPresencePort)new SulfurBossPresence((Func)delegate { BossPresentation? presentation = _presentation; return (presentation == null) ? null : presentation.CollisionCollider; }, logger); _voice = (IBossVoicePort)new SulfurBossVoice(((Component)host).transform, logger); _voice.Warm(); _atmosphere.Warm(); _controlFlow = new ClientEncounterFlow(integration.Channel, integration.Session) { OnEnterArena = HandleEnterArena, OnAborted = delegate(EncounterAborted aborted) { //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) ILogger? logger3 = _logger; if (logger3 != null) { logger3.Log($"Host aborted {aborted.Encounter} at the gate ({aborted.Reason}); tearing the local arena down."); } TeardownArena(); }, OnEnded = delegate(EncounterEnded ended) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) ILogger? logger3 = _logger; if (logger3 != null) { logger3.Log($"Host ended {ended.Encounter}; discarding the encounter."); } DiscardEncounter(); }, OnBossHitPlayer = HandleBossHitPlayer }; ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log("Client encounter composition ready: listening for the host's announcements and streams."); } } public void Tick(float deltaSeconds) { //IL_0030: 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_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_0073: 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_0082: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: 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_0196: 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_01b4: Unknown result type (might be due to invalid IL or missing references) _controlFlow.Tick(deltaSeconds); TryRealizeFromBaseline(); BossSnapshot latestBossSnapshot = _receiver.LatestBossSnapshot; if (latestBossSnapshot == null) { return; } if (_encounter.HasValue && latestBossSnapshot.Encounter != _encounter.Value) { ResetForNewEncounter(latestBossSnapshot.Encounter); return; } SimVector2 position; if (_presentation == null) { position = latestBossSnapshot.Position; float x = ((SimVector2)(ref position)).X; float positionHeight = latestBossSnapshot.PositionHeight; position = latestBossSnapshot.Position; if (!TryRaisePresentation(x, positionHeight, ((SimVector2)(ref position)).Z, latestBossSnapshot.Encounter)) { return; } } ReplayArenaSnapshotOnce(); IReadOnlyList appliedBossEvents = _receiver.AppliedBossEvents; while (_presentedEvents < appliedBossEvents.Count) { IBossWireEvent val = appliedBossEvents[_presentedEvents]; _presentation.Handle(WirePresentationMapping.ToEvent(latestBossSnapshot.Boss, val)); if (val is BossRelocatedEvent) { ClearOurOwnFloor(); } else { BossEnragedEvent val2 = (BossEnragedEvent)(object)((val is BossEnragedEvent) ? val : null); if (val2 != null && val2.Enraged) { IBossVoicePort voice = _voice; position = latestBossSnapshot.Position; float x2 = ((SimVector2)(ref position)).X; float positionHeight2 = latestBossSnapshot.PositionHeight; position = latestBossSnapshot.Position; voice.Roar(new ArenaWorldPoint(x2, positionHeight2, ((SimVector2)(ref position)).Z)); } else if (val is BossBeganEvent) { PlayTheOpening(latestBossSnapshot, withCeremony: true); } else if (val is BossDefeatedEvent) { _atmosphere.StopBattleMusic(); _presence.HideHealthBar(); IBossRewardPort reward = _reward; LoadedArena? loadedArena = _loadedArena; ArenaWorldPoint? val3 = ((loadedArena != null) ? loadedArena.RewardDrop : ((ArenaWorldPoint?)null)); ? val4; if (!val3.HasValue) { position = latestBossSnapshot.Position; float x3 = ((SimVector2)(ref position)).X; float positionHeight3 = latestBossSnapshot.PositionHeight; position = latestBossSnapshot.Position; val4 = new ArenaWorldPoint(x3, positionHeight3, ((SimVector2)(ref position)).Z); } else { val4 = val3.GetValueOrDefault(); } reward.DropReward((ArenaWorldPoint)val4); } } _presentedEvents++; } CatchUpOnTheOpening(latestBossSnapshot); IReadOnlyList appliedArenaEvents = _receiver.AppliedArenaEvents; while (_presentedArenaEvents < appliedArenaEvents.Count) { ArenaPresentation? arenaPresentation = _arenaPresentation; if (arenaPresentation != null) { arenaPresentation.Handle(WirePresentationMapping.ToEvent(appliedArenaEvents[_presentedArenaEvents])); } _presentedArenaEvents++; } PresentationState val5 = WirePresentationMapping.ToState(latestBossSnapshot); _presentation.Apply(val5); _presence.ReportHealth(val5.HealthFraction); CarryTheHostsArms(latestBossSnapshot); _presentation.Render(deltaSeconds); } private void CarryTheHostsArms(BossSnapshot snapshot) { //IL_0027: 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_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_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_0067: Unknown result type (might be due to invalid IL or missing references) if (!snapshot.Enraged) { _rageArms.Release(); return; } _rageArms.Adopt(2); IBossArmPort rageArms = _rageArms; SimVector2 position = snapshot.Position; float x = ((SimVector2)(ref position)).X; float positionHeight = snapshot.PositionHeight; position = snapshot.Position; rageArms.Follow(new ArmPlacement(new ArenaWorldPoint(x, positionHeight, ((SimVector2)(ref position)).Z), snapshot.Facing, 3.1f, 1f, 1.5f, 1.5f)); } private void PlayTheOpening(BossSnapshot snapshot, bool withCeremony) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0032: Unknown result type (might be due to invalid IL or missing references) _openingPlayed = true; if (withCeremony) { IBossVoicePort voice = _voice; SimVector2 position = snapshot.Position; float x = ((SimVector2)(ref position)).X; float positionHeight = snapshot.PositionHeight; position = snapshot.Position; voice.Roar(new ArenaWorldPoint(x, positionHeight, ((SimVector2)(ref position)).Z)); _atmosphere.SetRoomDepth(10f, 72f, 1f, 3f); ILogger? logger = _logger; if (logger != null) { logger.Log("[opening] the host's boss began; roaring and opening the room here."); } } else { _atmosphere.SetRoomDepth(10f, 72f, 0f, 0f); ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log("[opening] the fight was already under way; opening the room without the ceremony."); } } _atmosphere.StartBattleMusic(); _presence.ShowHealthBar(); } private void CatchUpOnTheOpening(BossSnapshot snapshot) { if (!_openingPlayed && snapshot.Begun) { PlayTheOpening(snapshot, withCeremony: false); } } private void ClearOurOwnFloor() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) LoadedArena loadedArena = _loadedArena; if (loadedArena != null) { int num = _battlefield.SweepCorpses(loadedArena.Origin, 120f); ILogger? logger = _logger; if (logger != null) { logger.Log($"[cleanup] the host's boss moved on; {num} body/bodies going into the floor here."); } } } public void Dispose() { _controlFlow.Dispose(); _receiver.Dispose(); _hitBinding?.Dispose(); _hitBinding = null; _presence.Withdraw(); BossPresentation? presentation = _presentation; if (presentation != null) { presentation.Dispose(); } _presentation = null; _openingPlayed = false; _atmosphere.StopBattleMusic(); TeardownArena(); ILogger? logger = _logger; if (logger != null) { logger.Log("Client encounter composition torn down; nothing remains."); } } private ClientLoadOutcome HandleEnterArena(EnterArena enter) { //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_00c3: 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) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: 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_0049: Unknown result type (might be due to invalid IL or missing references) TeardownArena(); _lateJoinArenaFailed = false; ClientLoadOutcome val = RealizeArenaAt(enter.Origin, enter.Encounter); if (val.NotYet) { if (!_waitingForOwnArenaLogged) { _waitingForOwnArenaLogged = true; ILogger? logger = _logger; if (logger != null) { logger.Log($"The host announced {enter.Encounter}, but this peer's own arena is still being " + "built by the level (" + val.FailureReason + "); waiting for it rather than loading a second copy."); } } return val; } _waitingForOwnArenaLogged = false; if (val.Manifest == null) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning($"Arena load for {enter.Encounter} failed: {val.FailureReason}. Reporting ArenaLoadFailed."); } return val; } ILogger? logger3 = _logger; if (logger3 != null) { object arg = enter.Encounter; WorldPosition origin = enter.Origin; object arg2 = ((WorldPosition)(ref origin)).X; origin = enter.Origin; string text = $"Arena for {arg} ready at ({arg2:0.0}, {((WorldPosition)(ref origin)).Y:0.0}, "; origin = enter.Origin; logger3.Log(text + $"{((WorldPosition)(ref origin)).Z:0.0}); reporting ArenaReady."); } _openingPlayed = false; _atmosphere.SetRoomDepth(4f, 10f, 0f, 0f); return val; } private ClientLoadOutcome RealizeArenaAt(WorldPosition origin, EncounterId encounter) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_008e: 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_00af: Expected O, but got Unknown //IL_00af: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_001a: 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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) HijackedArenaContent levelArena = LevelArena; if (levelArena != null && levelArena.IsLive) { return AdoptLevelArena(levelArena, origin, encounter); } if (_levelWillBringTheArena()) { return ClientLoadOutcome.Deferred("this peer's level is still building the arena it declared"); } BundleArenaRealization realization = new BundleArenaRealization(Path.Combine(_contentDirectory, "falsegods-poc-room.bundle"), Path.Combine(_contentDirectory, "arena-content-PocRoom.artifact"), "PocRoom", _logger); ArenaLoadFlow val = new ArenaLoadFlow((IArenaAssetProvider)(object)realization, (IArenaRealization)(object)realization, (INavigationPort)new AstarNavigationPort((Func)(() => realization.CurrentRoot), _logger), (IVanillaAssetProvider)new SulfurVanillaAssetProvider((Func)(() => realization.CurrentRoot), _logger)); ArenaPrepareResult val2 = val.Prepare(); if (!val2.Success) { val.Teardown(); return ClientLoadOutcome.Failed(val2.FailureReason ?? "prepare failed"); } ArenaRealizeResult val3 = val.Realize(new ArenaWorldPoint(((WorldPosition)(ref origin)).X, ((WorldPosition)(ref origin)).Y, ((WorldPosition)(ref origin)).Z)); if (!val3.Success || val3.Manifest == null || val3.Arena == null) { return ClientLoadOutcome.Failed(val3.FailureReason ?? "realize failed"); } _ownsArena = true; _realization = realization; _arenaFlow = val; _loadedArena = val3.Arena; _arenaPresentation = new ArenaPresentation(realization, _logger); _arenaEncounter = encounter; _arenaSnapshotReplayed = false; return ClientLoadOutcome.Ready(val3.Manifest); } private ClientLoadOutcome AdoptLevelArena(HijackedArenaContent levelArena, WorldPosition origin, EncounterId encounter) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown //IL_00ec: 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) ArenaRealizeResult realized = levelArena.Realized; BundleArenaRealization realization = levelArena.Realization; if (((realized != null) ? realized.Manifest : null) == null || realized.Arena == null || realization == null) { return ClientLoadOutcome.Failed("the level's arena is standing but reported no load result"); } ArenaWorldPoint origin2 = realized.Arena.Origin; if (!SameOrigin(origin2, origin)) { return ClientLoadOutcome.Failed($"the level's arena stands at ({((ArenaWorldPoint)(ref origin2)).X:0.0}, {((ArenaWorldPoint)(ref origin2)).Y:0.0}, " + $"{((ArenaWorldPoint)(ref origin2)).Z:0.0}) but the host announced ({((WorldPosition)(ref origin)).X:0.0}, {((WorldPosition)(ref origin)).Y:0.0}, " + $"{((WorldPosition)(ref origin)).Z:0.0})"); } _ownsArena = false; _realization = realization; _arenaFlow = null; _loadedArena = realized.Arena; _arenaPresentation = new ArenaPresentation(realization, _logger); _arenaEncounter = encounter; _arenaSnapshotReplayed = false; ILogger? logger = _logger; if (logger != null) { logger.Log($"Adopting the arena the hijacked level left standing for {encounter}; " + "no second copy loaded, and the level keeps it when the encounter ends."); } return ClientLoadOutcome.Ready(realized.Manifest); } private static bool SameOrigin(ArenaWorldPoint standing, WorldPosition announced) { if (Math.Abs(((ArenaWorldPoint)(ref standing)).X - ((WorldPosition)(ref announced)).X) <= 0.05f && Math.Abs(((ArenaWorldPoint)(ref standing)).Y - ((WorldPosition)(ref announced)).Y) <= 0.05f) { return Math.Abs(((ArenaWorldPoint)(ref standing)).Z - ((WorldPosition)(ref announced)).Z) <= 0.05f; } return false; } private void TryRealizeFromBaseline() { //IL_0052: 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_002e: 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_0042: 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_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_015f: Unknown result type (might be due to invalid IL or missing references) EncounterBaseline baseline = _receiver.Baseline; if (baseline == null || _lateJoinArenaFailed) { return; } if (_loadedArena != (LoadedArena)null) { EncounterId? arenaEncounter = _arenaEncounter; EncounterId encounter = baseline.Encounter; if (arenaEncounter.HasValue && arenaEncounter.GetValueOrDefault() == encounter) { return; } } ClientLoadOutcome val = RealizeArenaAt(baseline.ArenaOrigin, baseline.Encounter); if (val.NotYet) { return; } if (val.Manifest == null) { _lateJoinArenaFailed = true; ILogger? logger = _logger; if (logger != null) { logger.LogWarning("Late-join arena load failed: " + val.FailureReason + ". The boss puppet will not be shown for this encounter."); } } else if (!string.Equals(val.Manifest.ArenaId, baseline.ArenaId, StringComparison.Ordinal) || val.Manifest.ArenaVersion != baseline.ArenaVersion || val.Manifest.ContentHash != baseline.ContentHash) { _lateJoinArenaFailed = true; ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning("Late-join arena content does not match the host's baseline " + $"({val.Manifest.ArenaId} v{val.Manifest.ArenaVersion} vs {baseline.ArenaId} " + $"v{baseline.ArenaVersion}); tearing it down and showing nothing."); } TeardownArena(); } else { ILogger? logger3 = _logger; if (logger3 != null) { logger3.Log($"Late join: arena for {baseline.Encounter} realized from the baseline's origin and " + "content-verified against it."); } } } private void ReplayArenaSnapshotOnce() { if (_arenaSnapshotReplayed || _arenaPresentation == null) { return; } ArenaSnapshot latestArenaSnapshot = _receiver.LatestArenaSnapshot; if (latestArenaSnapshot != null) { _arenaSnapshotReplayed = true; IReadOnlyList readOnlyList = WirePresentationMapping.ToEvents(latestArenaSnapshot); for (int i = 0; i < readOnlyList.Count; i++) { _arenaPresentation.Handle(readOnlyList[i]); } } } private bool TryRaisePresentation(float x, float height, float z, EncounterId encounter) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) if (_loadedArena != null) { EncounterId? arenaEncounter = _arenaEncounter; if (arenaEncounter.HasValue && !(arenaEncounter.GetValueOrDefault() != encounter)) { ILogger? logger = _logger; Vector3 val = new Vector3(x, height, z); ArenaWorldPoint bossSpawn = _loadedArena.BossSpawn; _presentation = new BossPresentation(logger, val, ((ArenaWorldPoint)(ref bossSpawn)).Y); if (_loadedArena.BossSize > 0f) { _presentation.SpriteScale = _loadedArena.BossSize; } _presence.Declare(); _encounter = encounter; _presentedEvents = 0; _presentedArenaEvents = 0; _waitingForCameraLogged = false; _hitBinding = BossWeaponDamage.Bind(((Component)_presentation.HitCollider).gameObject, (IBossDamageSink)(object)new HitReportSink(_hitReporter, encounter), _logger); ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log($"Client boss puppet raised for {encounter} at ({x:0.0}, {height:0.0}, {z:0.0}), " + "where the host says it stands; host-driven. Your weapons report hits to the host."); } return true; } } if (!_waitingForCameraLogged) { _waitingForCameraLogged = true; ILogger? logger3 = _logger; if (logger3 != null) { logger3.Log($"Host boss state for {encounter} arrived before a matching local arena; waiting."); } } return false; } private void ResetForNewEncounter(EncounterId next) { //IL_0011: 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_004d: Expected O, but got Unknown //IL_00c8: 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_00d8: 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) ILogger? logger = _logger; if (logger != null) { logger.Log($"Host started {next}; discarding the previous encounter's stream and visuals."); } _receiver.Dispose(); _receiver = new ReplicationReceiver(_integration.Channel, _integration.Session); _hitBinding?.Dispose(); _hitBinding = null; _presence.Withdraw(); BossPresentation? presentation = _presentation; if (presentation != null) { presentation.Dispose(); } _presentation = null; _encounter = null; _presentedEvents = 0; _presentedArenaEvents = 0; _openingPlayed = false; _atmosphere.StopBattleMusic(); if (_arenaEncounter.HasValue) { EncounterId? arenaEncounter = _arenaEncounter; if (!arenaEncounter.HasValue || arenaEncounter.GetValueOrDefault() != next) { TeardownArena(); } } } private void DiscardEncounter() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown _receiver.Dispose(); _receiver = new ReplicationReceiver(_integration.Channel, _integration.Session); _hitBinding?.Dispose(); _hitBinding = null; _presence.Withdraw(); BossPresentation? presentation = _presentation; if (presentation != null) { presentation.Dispose(); } _presentation = null; _encounter = null; _presentedEvents = 0; _presentedArenaEvents = 0; _openingPlayed = false; _atmosphere.StopBattleMusic(); TeardownArena(); } private void HandleBossHitPlayer(BossHitPlayer hit) { //IL_0017: 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_0045: Unknown result type (might be due to invalid IL or missing references) int num = default(int); if (hit.Amount > 0 && _encounter.HasValue && !(hit.Encounter != _encounter.Value) && _localPlayer.TryGetLocalParticipantIndex(ref num)) { _damagePort.ApplyDamage(new ParticipantId(num), hit.Amount); ILogger? logger = _logger; if (logger != null) { logger.Log($"Boss hit you for {hit.Amount} (host-authoritative); applied to your local player."); } } } private void TeardownArena() { _arenaPresentation = null; if (_ownsArena) { ArenaLoadFlow? arenaFlow = _arenaFlow; if (arenaFlow != null) { arenaFlow.Teardown(); } } _ownsArena = false; _arenaFlow = null; _realization = null; _loadedArena = null; _arenaEncounter = null; _arenaSnapshotReplayed = false; } } [BepInPlugin("ryuka.sulfur.false_gods", "False Gods", "0.4.0")] public sealed class FalseGodsPlugin : BaseUnityPlugin { private sealed class TrackedPlayer { private readonly TargetMotionTracker _tracker; private SimVector2 _lastPosition; private bool _hasLastPosition; public SimVector2 SmoothedVelocity => _tracker.SmoothedVelocity; public TrackedPlayer(float smoothingSeconds) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown _tracker = new TargetMotionTracker(smoothingSeconds); } public void Observe(PlayerAim player, float deltaSeconds) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //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_001f: 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_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_0067: 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_007e: Unknown result type (might be due to invalid IL or missing references) SimVector2 val = default(SimVector2); if (((PlayerAim)(ref player)).VelocityKnown) { val = ((PlayerAim)(ref player)).Velocity; } else if (_hasLastPosition) { SimVector2 position = ((PlayerAim)(ref player)).Position; float num = (((SimVector2)(ref position)).X - ((SimVector2)(ref _lastPosition)).X) / deltaSeconds; position = ((PlayerAim)(ref player)).Position; ((SimVector2)(ref val))..ctor(num, (((SimVector2)(ref position)).Z - ((SimVector2)(ref _lastPosition)).Z) / deltaSeconds); } else { val = SimVector2.Zero; } _lastPosition = ((PlayerAim)(ref player)).Position; _hasLastPosition = true; _tracker.Observe(val, deltaSeconds); } } private enum CompositionRole { SinglePlayer, Host, Client } public const string PluginGuid = "ryuka.sulfur.false_gods"; public const string PluginName = "False Gods"; public const string PluginVersion = "0.4.0"; private const int TestBossDefinition = 1; private const float VolleySpreadMin = 1.4f; private const float VolleySpreadMax = 4.2f; private const float VolleyLiftHeight = 5f; private const float VolleyLiftSeconds = 0.5f; private const float VolleyHoldMin = 0.5f; private const float VolleyHoldMax = 1.5f; private const int VolleyHoldSalt = 9973; private const float VolleyFlightSeconds = 1.2f; private const float VolleyApex = 4f; private const float VolleyCratesPerSecond = 10f; private const float VolleyFireInterval = 0.1f; private const float VolleyLeadFraction = 1f; private const float VolleyLeadShare = 0.5f; private const float VolleyLeadSmoothingSeconds = 0.4f; private const int CrateHitDamage = 10; private const float CrateContactRadius = 1.2f; private const float CrateSplashRadius = 2.5f; private const float CrateKnockbackSpeed = 12f; private const float CrateKnockbackLift = 4f; private ConfigEntry _maxClientHitDamage; private int _nextVolleySeed = 1; private IThrownCratePort _crates; private SulfurCarriedLoadMirror? _carriedLoads; private readonly List _playersToThrowAt = new List(); private readonly List _volleyAims = new List(); private readonly Dictionary _playerSpeeds = new Dictionary(); private readonly HashSet _playersSeen = new HashSet(); private readonly List _forgottenPlayers = new List(); private IPlayerMotionPort _playerMotion; private BepInExLogger _log; private IArenaHijackPort _hijack; private ArenaLevelFlow? _levelFlow; private IFalseGodsIntegration? _levelFlowIntegration; private IDisposable? _spawnOwnership; private IFalseGodsIntegration? _spawnOwnershipIntegration; private CrateCommandFlow? _crateFlow; private IFalseGodsIntegration? _crateFlowIntegration; private HijackedArenaContent _levelArena; private SulfurArenaHazard _hazard; private LocalEncounterController _boss; private IBossVoicePort _voice; private IArenaAtmospherePort _atmosphere; private SulfurCaveBossPortal _caveDoor; private SulfurDevMenuEntry _devMenuRow; private int _raisedForRun; private bool _warmedThisArena; private const int WarmCrateCount = 2; private const float WarmDropHeight = 3f; private ClientBossController? _client; private IFalseGodsIntegration? _clientIntegration; private int _nextEncounter = 1; private EncounterId _currentEncounter; private void Awake() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Expected O, but got Unknown //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Expected O, but got Unknown //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01de: 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_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Expected O, but got Unknown //IL_026f: Expected O, but got Unknown //IL_026f: Expected O, but got Unknown //IL_026f: Expected O, but got Unknown //IL_026f: Expected O, but got Unknown //IL_026f: Expected O, but got Unknown _maxClientHitDamage = ((BaseUnityPlugin)this).Config.Bind("Multiplayer", "MaxClientHitDamage", 1000f, "Host only: the largest single hit a multiplayer client may report against the boss. A sanity ceiling on a forged message, not a substitute for rate limiting - set it above any legitimate single weapon hit. The host clamps to this; the simulation still decides weak-point, phase, and death. Read once at load."); _log = new BepInExLogger(((BaseUnityPlugin)this).Logger); SulfurCrateImpact val = new SulfurCrateImpact(10, 1.2f, 2.5f, 12f, 4f, (ILogger)(object)_log); val.Hit = delegate { _boss?.CratesHitSomebody(); }; SulfurThrownCratePort val2 = (SulfurThrownCratePort)(object)(_crates = (IThrownCratePort)new SulfurThrownCratePort((ILogger)(object)_log, (IThrownCrateImpact)(object)val)); val2.Died = delegate(int crateId, CrateDeath death) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.ReportDestroyed(crateId, death); } }; val2.Exploded = delegate(ArenaWorldPoint at, bool airburst) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) _boss?.ExplosionAt(at, airburst); }; _carriedLoads = new SulfurCarriedLoadMirror(val2, (ILogger)(object)_log); _playerMotion = (IPlayerMotionPort)new SulfurPlayerMotionPort(); LevelGenerationHijackPatches.Install((ILogger)(object)_log); _levelArena = new HijackedArenaContent(Path.GetDirectoryName(typeof(FalseGodsPlugin).Assembly.Location) ?? ".", (ILogger)(object)_log); _hazard = new SulfurArenaHazard((Func)delegate { BundleArenaRealization? realization = _levelArena.Realization; return (realization == null) ? null : realization.CurrentRoot; }, "VisualRoot/VanillaProps", "PoolBlocker", 5, 0.25f, (ILogger)(object)_log); LevelGenerationHijack.ArenaRooms = _levelArena.CreateRoomSource(); LevelGenerationHijack.Fog = new ArenaFogRange(4f, 10f); _hijack = (IArenaHijackPort)new SulfurArenaHijackPort((ILogger)(object)_log); _voice = (IBossVoicePort)new SulfurBossVoice(((Component)this).transform, (ILogger)(object)_log); _atmosphere = (IArenaAtmospherePort)new SulfurArenaAtmosphere((MonoBehaviour)(object)this, (ILogger)(object)_log); _caveDoor = new SulfurCaveBossPortal((Action)GoToArenaLevel, (ILogger)(object)_log); _devMenuRow = new SulfurDevMenuEntry((Action)GoToArenaLevel, (ILogger)(object)_log); _boss = new LocalEncounterController((ILogger)(object)_log, (IMinionSpawnPort)new SulfurMinionSpawnPort((MonoBehaviour)(object)this, (ILogger)(object)_log, false), (IMinionSpawnPort)new SulfurMinionSpawnPort((MonoBehaviour)(object)this, (ILogger)(object)_log, true), (IBossArmPort)new SulfurBossArmPort((MonoBehaviour)(object)this, (ILogger)(object)_log), (IBattlefieldCleanupPort)new SulfurBattlefieldCleanup((ILogger)(object)_log), _voice, _atmosphere, (IBossRewardPort)new SulfurBossReward((ILogger)(object)_log), _playerMotion, _crates, (ICarrierPort)new SulfurCarrierPort((MonoBehaviour)(object)this, _crates, (ILogger)(object)_log, (Action)delegate(ArenaWorldPoint at, CratePileId pile, int count, float radius) { //IL_000b: 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) CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.BroadcastTaken(at, pile, count, radius); } }, (Action)delegate(ArenaWorldPoint from, ArenaWorldPoint at, CratePileId pile, int count, int seed, int explosives) { //IL_000b: 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_000d: Unknown result type (might be due to invalid IL or missing references) CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.BroadcastSetDown(from, at, pile, count, seed, explosives); } }), delegate(ArenaWorldPoint at, CratePileId pile, bool explosive) { //IL_000b: 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) CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.BroadcastDropped(at, pile, explosive); } }, LaunchCrateVolley, _maxClientHitDamage.Value) { LevelArena = _levelArena }; FalseGodsIntegrations.Changed += OnIntegrationChanged; ((BaseUnityPlugin)this).Logger.LogMessage((object)("False Gods 0.4.0 loaded. Beat the cave boss and walk into the way through that opens in its room; the arena's own boss is started by walking into it. Multiplayer integration: " + ((FalseGodsIntegrations.Current != null) ? "registered" : "none (single-player)") + ".")); } private void Update() { WarmContentWhileTheScreenIsBlack(); _caveDoor.Watch(); _devMenuRow.Maintain(); MaintainArenaLevelFlow(FalseGodsIntegrations.Current); MaintainSpawnOwnership(FalseGodsIntegrations.Current); MaintainCrateFlow(FalseGodsIntegrations.Current); TrackPlayerMotion(Time.deltaTime); _crates.Advance(Time.deltaTime); IFalseGodsIntegration current = FalseGodsIntegrations.Current; CompositionRole compositionRole = EvaluateRole(current); if (compositionRole != CompositionRole.Client) { _hazard.Advance(Time.deltaTime); } if (compositionRole == CompositionRole.Client) { RunClientComposition(current); return; } TearDownClientComposition(); RunLocalComposition(current, compositionRole); } private void MaintainCrateFlow(IFalseGodsIntegration? integration) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown if (integration == null || !integration.Session.IsActive) { if (_crateFlow != null) { _crateFlow.Dispose(); _crateFlow = null; _crateFlowIntegration = null; SulfurCarriedLoadMirror? carriedLoads = _carriedLoads; if (carriedLoads != null) { carriedLoads.Clear(); } } return; } if (_crateFlow != null && _crateFlowIntegration != integration) { _crateFlow.Dispose(); _crateFlow = null; _crateFlowIntegration = null; } if (_crateFlow != null) { return; } _crateFlow = new CrateCommandFlow(integration.Channel, integration.Session) { OnDropped = delegate(ArenaWorldPoint at, CratePileId pile, bool explosive) { //IL_0006: 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_0022: 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) _crates.Drop(at, pile, explosive); _log.Log($"[crate] host dropped one on {pile} at ({((ArenaWorldPoint)(ref at)).X:0.0}, {((ArenaWorldPoint)(ref at)).Y:0.0}, {((ArenaWorldPoint)(ref at)).Z:0.0}); " + $"{_crates.RestingOn(pile)} resting on that pile here."); }, OnThrown = delegate(ArenaWorldPoint from, ArenaWorldPoint to, float seconds, float apex) { //IL_0006: 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) _crates.Throw(from, to, seconds, apex); _log.Log($"[crate] host threw one from ({((ArenaWorldPoint)(ref from)).X:0.0}, {((ArenaWorldPoint)(ref from)).Y:0.0}, {((ArenaWorldPoint)(ref from)).Z:0.0}) to " + $"({((ArenaWorldPoint)(ref to)).X:0.0}, {((ArenaWorldPoint)(ref to)).Y:0.0}, {((ArenaWorldPoint)(ref to)).Z:0.0}); {_crates.InFlight} in the air here."); }, OnTaken = delegate(ArenaWorldPoint at, CratePileId pile, int count, float radius) { //IL_0006: 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_001d: 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_0051: Unknown result type (might be due to invalid IL or missing references) int num = _crates.TakeFrom(pile, count, at, radius); SulfurCarriedLoadMirror? carriedLoads2 = _carriedLoads; if (carriedLoads2 != null) { carriedLoads2.PickedUp(at, count); } _log.Log($"[carrier] host collected {count} off {pile}; {num} taken here, " + $"{_crates.RestingOn(pile)} left on it."); }, OnSetDown = delegate(ArenaWorldPoint from, ArenaWorldPoint at, CratePileId pile, int count, int seed, int explosives) { //IL_0006: 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_0008: 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_0044: 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) int num = _crates.TossRing(from, at, pile, count, seed, explosives); SulfurCarriedLoadMirror? carriedLoads2 = _carriedLoads; if (carriedLoads2 != null) { carriedLoads2.PutDown(from); } _log.Log($"[carrier] host put {count} down on {pile} (seed {seed}, {explosives} that go " + $"off); {num} laid out here, {_crates.RestingOn(pile)} on that pile."); }, OnVolleyFired = delegate(CratePileId pile, IReadOnlyList aims, CrateVolleyShape shape) { //IL_0006: 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_0026: Unknown result type (might be due to invalid IL or missing references) int num = _crates.LaunchVolley(pile, aims, shape); _log.Log($"[crate] host fired a volley of {((CrateVolleyShape)(ref shape)).Count} off {pile} (seed {((CrateVolleyShape)(ref shape)).Seed}) " + $"spread over {aims.Count} player(s); {num} lifted here."); }, OnDestroyed = delegate(int crateId, CrateDeath death) { //IL_0007: 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) bool flag = _crates.Destroy(crateId, death); _log.Log($"[crate] host settled that crate {crateId} was {Describe(death)}; " + (flag ? "destroyed here too." : "this peer no longer had it.")); }, OnDestroyRequested = delegate(int crateId, CrateDeath death) { //IL_0007: 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_002c: Unknown result type (might be due to invalid IL or missing references) bool flag = _crates.Destroy(crateId, death); CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.BroadcastDestroyed(crateId, death); } _log.Log($"[crate] a client's player {Describe(death)} crate {crateId}; " + (flag ? "destroyed here and settled for everyone." : "the host no longer had it.")); } }; _crateFlowIntegration = integration; } private static string Describe(CrateDeath death) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if ((int)death != 0) { return "burst on a player"; } return "shot"; } private void MaintainSpawnOwnership(IFalseGodsIntegration? integration) { if (integration != _spawnOwnershipIntegration) { _spawnOwnership?.Dispose(); _spawnOwnership = ((integration != null) ? integration.Spawns.DeclareHostAuthoritative((object)this) : null); _spawnOwnershipIntegration = integration; FightingPlayers.AskedOf((integration != null) ? integration.Lives : null); OurDestructibles.ClaimedWith((integration != null) ? integration.Destructibles : null); if (integration != null && _spawnOwnership == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"The session layer would not carry our runtime spawns; the boss's minions will appear on the host only."); } } } private void MaintainArenaLevelFlow(IFalseGodsIntegration? integration) { //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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00bd: 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) if (integration == null || !integration.Session.IsActive) { if (_levelFlow != null) { TearDownArenaLevelFlow(); } return; } if (_levelFlow != null && _levelFlowIntegration != integration) { TearDownArenaLevelFlow(); } if (_levelFlow == null) { _levelFlow = new ArenaLevelFlow(integration.Channel, integration.Session, integration.Roster) { OnDeclared = ApplyArenaLevelDeclaration, OnRequested = HandleArenaLevelRequest }; _levelFlowIntegration = integration; ReconcileArenaLevelOnJoiningSession(integration); } ArenaLevelDeclared declaration = _levelFlow.Declaration; if (declaration != (ArenaLevelDeclared)null && declaration.IsBossArena && !_hijack.IsArenaModeOn && (int)integration.Session.Role == 0) { _levelFlow.Declare(declaration.Level, false); } _levelFlow.Tick(); } private void ReconcileArenaLevelOnJoiningSession(IFalseGodsIntegration integration) { //IL_0006: 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) if ((int)integration.Session.Role == 0) { if (_hijack.IsArenaModeOn) { ArenaLevelFlow? levelFlow = _levelFlow; if (levelFlow != null) { levelFlow.Declare(_hijack.ArenaLevel, true); } } } else if (_hijack.IsArenaModeOn) { ((BaseUnityPlugin)this).Logger.LogMessage((object)"Joined a session: the host decides which level is the boss arena, so the local declaration is dropped until it says so."); _hijack.LeaveArenaMode(); } } private void TearDownArenaLevelFlow() { ArenaLevelFlow? levelFlow = _levelFlow; if (levelFlow != null) { levelFlow.Dispose(); } _levelFlow = null; _levelFlowIntegration = null; } private void GoToArenaLevel() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_0056: 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) ArenaLevelFlow levelFlow = _levelFlow; if (levelFlow == null) { _hijack.LoadHijackedArena(); return; } IFalseGodsIntegration current = FalseGodsIntegrations.Current; if (current != null && (int)current.Session.Role == 0) { levelFlow.Declare(_hijack.ArenaLevel, true); _hijack.LoadHijackedArena(); } else { levelFlow.Request(_hijack.ArenaLevel); ((BaseUnityPlugin)this).Logger.LogMessage((object)"Asked the host to take the session to the boss arena; the host leads the transition."); } } private void ApplyArenaLevelDeclaration(ArenaLevelDeclared declaration) { //IL_001b: 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) if (!declaration.IsBossArena) { _hijack.LeaveArenaMode(); } else if (!_hijack.DeclareArenaLevel(declaration.Level)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)($"The host declared {declaration.Level} a boss arena, but this build does not " + "recognise that level; it will generate normally here.")); } } private void HandleArenaLevelRequest(ArenaLevelRequested request) { //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_000d: 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_003a: 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) ArenaLevelId arenaLevel = _hijack.ArenaLevel; if (request.Level != arenaLevel) { ((BaseUnityPlugin)this).Logger.LogWarning((object)($"A session peer asked for a boss arena at {request.Level}, but this build's " + $"arena is {arenaLevel}; ignoring the request.")); return; } ((BaseUnityPlugin)this).Logger.LogMessage((object)"A session peer asked for the boss arena; declaring it and leading the transition."); ArenaLevelFlow? levelFlow = _levelFlow; if (levelFlow != null) { levelFlow.Declare(arenaLevel, true); } _hijack.LoadHijackedArena(); } private void LaunchCrateVolley(CratePileId pile, int count) { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_00ec: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Camera.main == (Object)null) { return; } int num = _nextVolleySeed++; float num2 = SeededRandom.Range(num, 9973, 0.5f, 1.5f); float num3 = (0.5f + num2 + 1.2f) * 1f; List list = BuildVolleyAims(num3); if (list.Count == 0) { _log.Log("[crate] nobody to throw at — every player is down or out of the level."); return; } CrateVolleyShape val = default(CrateVolleyShape); ((CrateVolleyShape)(ref val))..ctor(num, count, 1.4f, 4.2f, 5f, 0.5f, num2, 1.2f, 4f, 0.5f, 0.1f); int num4 = _crates.LaunchVolley(pile, (IReadOnlyList)list, val); if (num4 > 0) { CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.BroadcastVolley(pile, (IReadOnlyList)list, val); } _log.Log($"[crate] volley of {num4} lifted off {pile}; {_crates.RestingOn(pile)} left there. " + $"Hold {num2:0.00}s, then {10f:0.#}/s for {(float)num4 * 0.1f:0.00}s; " + $"spread over {list.Count} player(s), led {num3:0.00}s. Shoot them for loot."); } else { _log.Log($"[crate] {pile} is empty - the boss has no ammunition. Nothing has been carried to it " + "yet."); } } private List BuildVolleyAims(float airtime) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_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_0054: 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_0062: 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_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_0087: 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) _playerMotion.ReadPlayersToThrowAt((IList)_playersToThrowAt); _volleyAims.Clear(); for (int i = 0; i < _playersToThrowAt.Count; i++) { PlayerAim val = _playersToThrowAt[i]; if (_playerSpeeds.TryGetValue(((PlayerAim)(ref val)).Index, out TrackedPlayer value)) { SimVector2 val2 = LeadAim.Predict(((PlayerAim)(ref val)).Position, value.SmoothedVelocity, airtime); List volleyAims = _volleyAims; SimVector2 position = ((PlayerAim)(ref val)).Position; float x = ((SimVector2)(ref position)).X; float height = ((PlayerAim)(ref val)).Height; position = ((PlayerAim)(ref val)).Position; volleyAims.Add(new CrateVolleyAim(new ArenaWorldPoint(x, height, ((SimVector2)(ref position)).Z), new ArenaWorldPoint(((SimVector2)(ref val2)).X, ((PlayerAim)(ref val)).Height, ((SimVector2)(ref val2)).Z))); } } return _volleyAims; } private void TrackPlayerMotion(float deltaSeconds) { //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_007e: Unknown result type (might be due to invalid IL or missing references) if (deltaSeconds <= 0f) { return; } _playerMotion.ReadPlayersToThrowAt((IList)_playersToThrowAt); _playersSeen.Clear(); for (int i = 0; i < _playersToThrowAt.Count; i++) { PlayerAim player = _playersToThrowAt[i]; _playersSeen.Add(((PlayerAim)(ref player)).Index); if (!_playerSpeeds.TryGetValue(((PlayerAim)(ref player)).Index, out TrackedPlayer value)) { value = new TrackedPlayer(0.4f); _playerSpeeds[((PlayerAim)(ref player)).Index] = value; } value.Observe(player, deltaSeconds); } if (_playerSpeeds.Count == _playersSeen.Count) { return; } _forgottenPlayers.Clear(); foreach (int key in _playerSpeeds.Keys) { if (!_playersSeen.Contains(key)) { _forgottenPlayers.Add(key); } } for (int j = 0; j < _forgottenPlayers.Count; j++) { _playerSpeeds.Remove(_forgottenPlayers[j]); } } private void OnDestroy() { FalseGodsIntegrations.Changed -= OnIntegrationChanged; IArenaHijackPort hijack = _hijack; if (hijack != null) { hijack.LeaveArenaMode(); } if (_boss != null && _boss.IsActiveEncounter) { _boss.Drop(); } TearDownClientComposition(); TearDownArenaLevelFlow(); _spawnOwnership?.Dispose(); _spawnOwnership = null; _spawnOwnershipIntegration = null; CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.Dispose(); } _crateFlow = null; _crateFlowIntegration = null; SulfurCaveBossPortal caveDoor = _caveDoor; if (caveDoor != null) { caveDoor.Forget(); } ((IDisposable)_atmosphere)?.Dispose(); } private CompositionRole EvaluateRole(IFalseGodsIntegration? integration) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (integration == null || !integration.Session.IsActive) { return CompositionRole.SinglePlayer; } if ((int)integration.Session.Role != 0) { return CompositionRole.Client; } return CompositionRole.Host; } private void RunLocalComposition(IFalseGodsIntegration? integration, CompositionRole role) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) DropWithTheArena(); RaiseWithTheArena(integration, role); bool flag = role == CompositionRole.Host && _boss.IsUp; if (flag && !_boss.HasReplication && _boss.CurrentManifest != (ArenaManifest)null) { _boss.SetHosting(BuildHostReplication(integration, _boss.CurrentManifest, _boss.CurrentOrigin), integration); } else if (!flag && _boss.HasReplication) { _boss.SetHosting(null, null); } _boss.Tick(Time.deltaTime); } private void DropWithTheArena() { if (_boss.IsUp && !_levelArena.IsLive) { ((BaseUnityPlugin)this).Logger.LogMessage((object)"The level took the arena with it; the fight there is over."); _boss.Drop(); } } private void RaiseWithTheArena(IFalseGodsIntegration? integration, CompositionRole role) { int arenaRunsFinished = LevelGenerationHijack.ArenaRunsFinished; if (arenaRunsFinished != 0 && arenaRunsFinished != _raisedForRun && _levelArena.IsLive) { _raisedForRun = arenaRunsFinished; if (_boss.IsActiveEncounter) { _boss.Drop(); } _crates.Clear(); ((BaseUnityPlugin)this).Logger.LogMessage((object)"The boss arena is standing; raising the boss in it. It waits, untouchable, until a player walks into the room."); Raise(integration, role); } } private void WarmContentWhileTheScreenIsBlack() { if (!_levelArena.IsLive) { _warmedThisArena = false; } else if (!_warmedThisArena) { _warmedThisArena = true; _crates.Prepare(); MakeTheFirstOnesNow(); } } private void MakeTheFirstOnesNow() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //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_00b0: Unknown result type (might be due to invalid IL or missing references) ArenaRealizeResult? realized = _levelArena.Realized; object obj; if (realized == null) { obj = null; } else { LoadedArena arena = realized.Arena; obj = ((arena != null) ? arena.CrateSources : null); } IReadOnlyList readOnlyList = (IReadOnlyList)obj; if (readOnlyList == null || readOnlyList.Count == 0) { return; } ArenaWorldPoint at = readOnlyList[0]; ArenaWorldPoint val = default(ArenaWorldPoint); ((ArenaWorldPoint)(ref val))..ctor(((ArenaWorldPoint)(ref at)).X, ((ArenaWorldPoint)(ref at)).Y + 3f, ((ArenaWorldPoint)(ref at)).Z); int num = 0; for (int i = 0; i < 2; i++) { if (_crates.Drop(val, CratePileId.Source(0), false)) { num++; } } _log.Log($"[crate] {num} made at the first production point while the level was still loading, so the " + "first one of the fight is not the first one ever built."); _boss.WarmTheVillage(at); } private void Raise(IFalseGodsIntegration? integration, CompositionRole role) { //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_0023: Unknown result type (might be due to invalid IL or missing references) _currentEncounter = new EncounterId(_nextEncounter++); _boss.Raise(_currentEncounter, (role == CompositionRole.Host) ? integration : null); } private void RunClientComposition(IFalseGodsIntegration integration) { if (_boss.IsActiveEncounter) { _boss.Drop(); } if (_client != null && _clientIntegration != integration) { TearDownClientComposition(); } if (_client == null) { _client = new ClientBossController((ILogger)(object)_log, (MonoBehaviour)(object)this, integration, _atmosphere, () => _hijack.IsArenaModeOn && !_levelArena.IsLive) { LevelArena = _levelArena }; _clientIntegration = integration; } _client.Tick(Time.deltaTime); } private void TearDownClientComposition() { _client?.Dispose(); _client = null; _clientIntegration = null; } private EncounterHostReplication BuildHostReplication(IFalseGodsIntegration integration, ArenaManifest manifest, WorldPosition arenaOrigin) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0030: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown return new EncounterHostReplication(new ReplicationSender(integration.Channel, integration.Session), integration.Session, integration.Roster, _currentEncounter, new DefinitionId(1), manifest, arenaOrigin); } private void OnIntegrationChanged() { ((BaseUnityPlugin)this).Logger.LogMessage((object)((FalseGodsIntegrations.Current != null) ? "Multiplayer integration registered; the host/client composition activates with the session." : "Multiplayer integration revoked; returning to the single-player composition.")); } } internal sealed class HijackedArenaContent { private static readonly ArenaWorldPoint LevelOrigin = new ArenaWorldPoint(0f, 0f, 0f); private readonly string _contentDirectory; private readonly ILogger _logger; private BundleArenaRealization? _realization; private ArenaLoadFlow? _flow; private ArenaRealizeResult? _realized; public bool IsLive { get { if (_realization != null) { return (Object)(object)_realization.CurrentRoot != (Object)null; } return false; } } public ArenaRealizeResult? Realized { get { if (!IsLive) { return null; } return _realized; } } public BundleArenaRealization? Realization { get { if (!IsLive) { return null; } return _realization; } } public static ArenaWorldPoint Origin => LevelOrigin; public HijackedArenaContent(string contentDirectory, ILogger logger) { _contentDirectory = contentDirectory ?? throw new ArgumentNullException("contentDirectory"); _logger = logger; } public HijackedArenaRoomSource CreateRoomSource() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown return new HijackedArenaRoomSource((Func)Load, (Func)delegate { BundleArenaRealization? realization = _realization; return (realization == null) ? null : realization.CurrentRoot; }, (Action)Release, _logger); } private HijackedArenaLoad Load() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0061: 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_0082: Expected O, but got Unknown //IL_0082: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) Release(); BundleArenaRealization realization = new BundleArenaRealization(Path.Combine(_contentDirectory, "falsegods-poc-room.bundle"), Path.Combine(_contentDirectory, "arena-content-PocRoom.artifact"), "PocRoom", _logger); _realization = realization; _flow = new ArenaLoadFlow((IArenaAssetProvider)(object)realization, (IArenaRealization)(object)realization, (INavigationPort)new NativeLevelNavigationPort(_logger), (IVanillaAssetProvider)new SulfurVanillaAssetProvider((Func)(() => realization.CurrentRoot), _logger)); ArenaPrepareResult val = _flow.Prepare(); if (!val.Success) { return HijackedArenaLoad.Failed("arena content did not prepare: " + val.FailureReason); } ArenaRealizeResult val2 = _flow.Realize(LevelOrigin); if (!val2.Success || val2.Arena == null) { return HijackedArenaLoad.Failed("arena load failed: " + val2.FailureReason); } _realized = val2; return HijackedArenaLoad.Loaded(val2.Arena.PlayerSpawn); } private void Release() { ArenaLoadFlow? flow = _flow; if (flow != null) { flow.Teardown(); } _flow = null; _realization = null; _realized = null; } } internal sealed class LocalEncounterController { private sealed class LocalRoster : IPlayerRoster { public static readonly LocalRoster Instance = new LocalRoster(); public static readonly SessionPeerId LocalPeer = new SessionPeerId(0); private readonly IReadOnlyList _members = (IReadOnlyList)(object)new SessionPeerId[1] { LocalPeer }; public IReadOnlyList Members => _members; } private sealed class WeaponSink : IBossDamageSink { private readonly LocalEncounterController _owner; public WeaponSink(LocalEncounterController owner) { _owner = owner; } public void ApplyWeaponDamage(float amount) { _owner.OnWeaponDamage(amount); } } internal const float EyeToFootDrop = 1.6f; internal const string BundleFileName = "falsegods-poc-room.bundle"; internal const string ArtifactFileName = "arena-content-PocRoom.artifact"; internal const string ArenaPrefabName = "PocRoom"; internal const float DefaultMaxClientHitDamage = 1000f; private const string PhaseTwoGroup = "phase_2"; private const float GateTimeoutSeconds = 30f; private static readonly SupplyLineShape Supply = new SupplyLineShape(0.35f, 14, 40); private static readonly SupplyEscalation Escalation = new SupplyEscalation((SupplyStep[])(object)new SupplyStep[5] { new SupplyStep(0.8f, 6, 7, 0.01f), new SupplyStep(0.6f, 6, 8, 0.02f), new SupplyStep(0.4f, 7, 9, 0.03f), new SupplyStep(0.2f, 7, 10, 0.04f), new SupplyStep(0f, 8, 10, 0.05f) }); private const float ProductionDropHeight = 3f; private const float ExitBarrelDelaySeconds = 0.5f; private const float ExitBarrelFlightSeconds = 1.6f; private const float ExitBarrelApexHeight = 9f; private const float CarrierReplacementRoundTrips = 1f; private const float StarvationRoundTrips = 1.5f; private const float FutilitySeconds = 30f; private const float RageDamageMultiplier = 2.5f; private const float RageCostsHealthFraction = 0.2f; private const int ExplosiveRollSeed = 20873; private const float AirburstOnTheBoss = 20f; private const float OpeningSeconds = 1.9f; private const float CarrierHandlingSeconds = 0.75f; private const float VolleyEverySeconds = 2f; private const int MaxCratesPerVolley = 16; private const float AssumedCarrierWalkSpeed = 5.13f; private static readonly IReadOnlyList Itinerary = (IReadOnlyList)(object)new BossStation[5] { new BossStation(0, 1f, default(MinionBandId)), new BossStation(1, 0.8f, MinionBands.Vanguard), new BossStation(0, 0.6f, default(MinionBandId)), new BossStation(1, 0.4f, MinionBands.Warband), new BossStation(0, 0.2f, MinionBands.Coven) }; private readonly ILogger _logger; private readonly ISimulationClock _clock; private readonly IEncounterParticipantQuery _participants; private readonly IDamagePort _damagePort; private readonly SulfurLocalPlayer _localPlayer; private readonly string _contentDirectory; private readonly float _maxClientHitDamage; private readonly IMinionSpawnPort _minionSpawns; private readonly IMinionSpawnPort _emergencyMinions; private readonly IBossArmPort _rageArms; private readonly IBattlefieldCleanupPort _battlefield; private readonly IBossVoicePort _voice; private readonly IArenaAtmospherePort _atmosphere; private readonly IBossRewardPort _reward; private readonly IPlayerMotionPort _players; private readonly List _atTheDoor = new List(); private readonly IBossPresencePort _presence; private readonly StarvationWatch _starvation = new StarvationWatch(); private int _pileLastSeen; private readonly IThrownCratePort _crates; private readonly ICarrierPort _carriers; private readonly Action? _announceProduced; private readonly Action? _throwVolley; private SupplyLine? _supply; private int[]? _restingAtSource; private float _sinceVolley; private float _measuredRoundTripSeconds = 1f; private float _walkSpeedInUse = 5.13f; private int _lastReportedThroughput = -1; private float _blastDamage; private float _blastRadius; private int _produced; private int _barrelsMade; private bool _cratesHitSomebody; private float _untilTheExitBarrel = -1f; private BossSimulation? _boss; private BossPresenter? _presenter; private BossPresentation? _presentation; private ArenaSimulation? _arena; private EncounterCoordinator? _coordinator; private ArenaPresentation? _arenaPresentation; private BundleArenaRealization? _realization; private ArenaLoadFlow? _flow; private EncounterHostReplication? _replication; private IDisposable? _damageBinding; private HostHitIntake? _hitIntake; private IFalseGodsIntegration? _hostIntegration; private ReplicationSender? _hostSender; private HostEncounterGate? _hostGate; private ArenaRealizeResult? _pendingStart; private bool _ownsArena; private ArenaManifest? _manifest; private LoadedArena? _arenaContent; private EncounterId _encounter; private WorldPosition _originWire; private BossActivity _lastReportedActivity = (BossActivity)4; private int _lastReportedPending = -1; public HijackedArenaContent? LevelArena { get; set; } public bool IsUp => _presentation != null; public bool IsActiveEncounter { get { if (!IsUp) { return _hostGate != null; } return true; } } public bool HasReplication => _replication != null; public ArenaManifest? CurrentManifest => _manifest; public WorldPosition CurrentOrigin => _originWire; public LocalEncounterController(ILogger logger, IMinionSpawnPort minions, IMinionSpawnPort emergencyMinions, IBossArmPort rageArms, IBattlefieldCleanupPort battlefield, IBossVoicePort voice, IArenaAtmospherePort atmosphere, IBossRewardPort reward, IPlayerMotionPort players, IThrownCratePort crates, ICarrierPort carriers, Action? announceProduced = null, Action? throwVolley = null, float maxClientHitDamage = 1000f) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown _throwVolley = throwVolley; _logger = logger; _minionSpawns = minions ?? throw new ArgumentNullException("minions"); _emergencyMinions = emergencyMinions ?? throw new ArgumentNullException("emergencyMinions"); _rageArms = rageArms ?? throw new ArgumentNullException("rageArms"); _battlefield = battlefield ?? throw new ArgumentNullException("battlefield"); _voice = voice ?? throw new ArgumentNullException("voice"); _atmosphere = atmosphere ?? throw new ArgumentNullException("atmosphere"); _reward = reward ?? throw new ArgumentNullException("reward"); _players = players ?? throw new ArgumentNullException("players"); _crates = crates ?? throw new ArgumentNullException("crates"); _carriers = carriers ?? throw new ArgumentNullException("carriers"); _announceProduced = announceProduced; _maxClientHitDamage = maxClientHitDamage; _clock = (ISimulationClock)new SulfurSimulationClock(); _participants = (IEncounterParticipantQuery)new SulfurParticipantQuery(); _damagePort = (IDamagePort)new SulfurDamagePort(logger); _localPlayer = new SulfurLocalPlayer(); _presence = (IBossPresencePort)new SulfurBossPresence((Func)delegate { BossPresentation? presentation = _presentation; return (presentation == null) ? null : presentation.CollisionCollider; }, logger); _contentDirectory = Path.GetDirectoryName(typeof(LocalEncounterController).Assembly.Location) ?? "."; } public void CratesHitSomebody() { _cratesHitSomebody = true; } public void WarmTheVillage(ArenaWorldPoint at) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _carriers.Warm(at); } public void ExplosionAt(ArenaWorldPoint at, bool pickedOutOfTheAir) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) BossTakesItsShareOfTheBlast(at, pickedOutOfTheAir); } public void SetHosting(EncounterHostReplication? replication, IFalseGodsIntegration? integration) { //IL_0083: 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_00b0: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) if (_replication != replication) { _replication = replication; ILogger logger = _logger; if (logger != null) { logger.Log((replication != null) ? "Host replication attached: encounter state and events now broadcast to the session." : "Host replication detached: encounter continues locally only."); } } if (replication == null || integration == null) { if (_hitIntake != null) { _hitIntake.Dispose(); _hitIntake = null; ILogger logger2 = _logger; if (logger2 != null) { logger2.Log("Client hits are no longer accepted: this encounter is not hosted."); } } } else { if (_hitIntake != null) { return; } _hitIntake = new HostHitIntake(integration.Channel, integration.Roster, _encounter, _maxClientHitDamage, (Action)OnWeaponDamage, (Action)delegate(string message) { ILogger logger4 = _logger; if (logger4 != null) { logger4.Log(message); } }); ILogger logger3 = _logger; if (logger3 != null) { logger3.Log($"Client hits accepted for {_encounter}; the simulation still decides what they cost."); } } } public bool Raise(EncounterId encounter, IFalseGodsIntegration? hostIntegration) { //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_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Expected O, but got Unknown //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown //IL_01b2: Expected O, but got Unknown //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Expected O, but got Unknown //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0227: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) if (IsActiveEncounter) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("An encounter is already up or gating; drop it first."); } return false; } _encounter = encounter; _hostIntegration = hostIntegration; _voice.Warm(); _atmosphere.Warm(); IThrownCratePort crates = _crates; IThrownCratePort obj = ((crates is SulfurThrownCratePort) ? crates : null); if (obj != null) { ((SulfurThrownCratePort)obj).ReadBlast(ref _blastDamage, ref _blastRadius); } if (_crates.Prepare()) { ILogger logger2 = _logger; if (logger2 != null) { logger2.Log("[crate] destructible content loaded ahead of the fight."); } } HijackedArenaContent levelArena = LevelArena; if (levelArena != null && levelArena.IsLive) { ArenaRealizeResult realized = levelArena.Realized; if (((realized != null) ? realized.Manifest : null) == null || realized.Arena == null) { ILogger logger3 = _logger; if (logger3 != null) { logger3.LogWarning("The level's arena is standing but reported no load result; cannot raise in it."); } return false; } _ownsArena = false; _realization = levelArena.Realization; _flow = null; return RaiseInArena(realized, HijackedArenaContent.Origin); } Camera main = Camera.main; if ((Object)(object)main == (Object)null) { ILogger logger4 = _logger; if (logger4 != null) { logger4.LogWarning("Cannot start the encounter: no main camera. Load a level and stand in it first."); } return false; } _ownsArena = true; _realization = new BundleArenaRealization(Path.Combine(_contentDirectory, "falsegods-poc-room.bundle"), Path.Combine(_contentDirectory, "arena-content-PocRoom.artifact"), "PocRoom", _logger); BundleArenaRealization realizationForNav = _realization; _flow = new ArenaLoadFlow((IArenaAssetProvider)(object)_realization, (IArenaRealization)(object)_realization, (INavigationPort)new AstarNavigationPort((Func)(() => realizationForNav.CurrentRoot), _logger), (IVanillaAssetProvider)new SulfurVanillaAssetProvider((Func)(() => realizationForNav.CurrentRoot), _logger)); ArenaPrepareResult val = _flow.Prepare(); if (!val.Success || val.Artifact == null) { Abort("arena content did not prepare: " + val.FailureReason); return false; } Vector3 position = ((Component)main).transform.position; ArenaWorldPoint val2 = default(ArenaWorldPoint); ((ArenaWorldPoint)(ref val2))..ctor(position.x, position.y - 1.6f, position.z); ArenaWorldPoint val3; try { val3 = ArenaPlacement.OriginForPlayerFoot(val.Artifact, val2); } catch (InvalidOperationException ex) { Abort("arena placement refused: " + ex.Message); return false; } ArenaRealizeResult val4 = _flow.Realize(val3); if (!val4.Success || val4.Manifest == null || val4.Arena == null) { Abort("arena load failed: " + val4.FailureReason); return false; } return RaiseInArena(val4, val3); } private bool RaiseInArena(ArenaRealizeResult realized, ArenaWorldPoint origin) { //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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0106: 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_0116: 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_0119: Invalid comparison between Unknown and I4 //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0081: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) _manifest = realized.Manifest; _originWire = new WorldPosition(((ArenaWorldPoint)(ref origin)).X, ((ArenaWorldPoint)(ref origin)).Y, ((ArenaWorldPoint)(ref origin)).Z); if (_hostIntegration != null) { _hostSender = new ReplicationSender(_hostIntegration.Channel, _hostIntegration.Session); _hostGate = new HostEncounterGate(_hostIntegration.Channel, _hostIntegration.Session, _hostIntegration.Roster, _hostSender, _encounter, realized.Manifest, _originWire, 30f); _pendingStart = realized; _hostGate.Open(); ILogger logger = _logger; if (logger != null) { logger.Log($"Encounter {_encounter}: arena realized and EnterArena broadcast; waiting for every " + $"session peer's ArenaReady (timeout {30f:0}s)."); } return true; } EncounterReadyGate val = new EncounterReadyGate(realized.Manifest, (IPlayerRoster)(object)LocalRoster.Instance); GateStatus val2 = val.SubmitReady(LocalRoster.LocalPeer, realized.Manifest); if ((int)val2 != 1) { Abort($"ready gate did not resolve locally: {val2}/{val.AbortReason}"); return false; } StartBoss(realized); return true; } public void Tick(float deltaSeconds) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) if (_hostGate != null && _pendingStart != (ArenaRealizeResult)null) { _hostGate.Tick(deltaSeconds); GateStatus status = _hostGate.Status; if ((int)status != 1) { if ((int)status == 2) { ILogger logger = _logger; if (logger != null) { logger.LogWarning($"Encounter {_encounter} aborted at the gate: {_hostGate.AbortReason} " + "(outstanding: [" + _hostGate.DescribeOutstanding() + "]). Clients were told; releasing the local arena."); } CleanupGate(); ReleaseArena(); } return; } ArenaRealizeResult pendingStart = _pendingStart; _pendingStart = null; _hostGate.Dispose(); _hostGate = null; ILogger logger2 = _logger; if (logger2 != null) { logger2.Log("Ready gate resolved for every session peer; starting the encounter."); } StartBoss(pendingStart); } else if (_boss != null && _presenter != null && _presentation != null) { WatchTheDoor(); _boss.Advance(); ReportActivityChange(); if (!_boss.IsOutsideTheFight && !_boss.IsDead) { AdvanceSupplyLine(deltaSeconds); AdvanceStarvation(deltaSeconds); CarryTheArmsWithTheBoss(); FireWhateverWasBrought(deltaSeconds); } AdvanceTheLastBarrel(deltaSeconds); _presence.ReportHealth(_boss.HealthFraction); Present(); _presentation.Render(deltaSeconds); } } private void AdvanceTheLastBarrel(float deltaSeconds) { //IL_0076: 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) if (_untilTheExitBarrel < 0f) { return; } _untilTheExitBarrel -= deltaSeconds; if (_untilTheExitBarrel > 0f) { return; } _untilTheExitBarrel = -1f; LoadedArena? arenaContent = _arenaContent; ArenaWorldPoint? val = ((arenaContent != null) ? arenaContent.ExitBlast : ((ArenaWorldPoint?)null)); if (!val.HasValue) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[exit] the room authored no place for the boss's last barrel to land, so the way out stays shut."); } return; } bool flag = _crates.ThrowExplosive(BossStandsAt(), val.Value, 1.6f, 9f, (Action)OpenTheWayOut); ILogger logger2 = _logger; if (logger2 != null) { logger2.Log(flag ? "[exit] the boss throws one last barrel at the rock over the doorway." : "[exit] the boss's last barrel could not be thrown; opening the way out directly instead."); } if (!flag) { OpenTheWayOut(); } } private void OpenTheWayOut() { if (_arena != null && !_arena.IsExitUnlocked) { _arena.UnlockExit(); ILogger logger = _logger; if (logger != null) { logger.Log("[exit] the rock is blown out of the doorway; the way out is open."); } } } private void WatchTheDoor() { //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_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_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_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) LoadedArena? arenaContent = _arenaContent; ArenaWorldPoint? val = ((arenaContent != null) ? arenaContent.StartTrigger : ((ArenaWorldPoint?)null)); if (_boss == null || _boss.HasBegun || !val.HasValue) { return; } ArenaWorldPoint value = val.Value; float startTriggerRadius = _arenaContent.StartTriggerRadius; _players.ReadPlayersToThrowAt((IList)_atTheDoor); for (int i = 0; i < _atTheDoor.Count; i++) { PlayerAim val2 = _atTheDoor[i]; SimVector2 position = ((PlayerAim)(ref val2)).Position; float num = ((SimVector2)(ref position)).X - ((ArenaWorldPoint)(ref value)).X; float num2 = ((PlayerAim)(ref val2)).Height - ((ArenaWorldPoint)(ref value)).Y; position = ((PlayerAim)(ref val2)).Position; float num3 = ((SimVector2)(ref position)).Z - ((ArenaWorldPoint)(ref value)).Z; if (!(num * num + num2 * num2 + num3 * num3 > startTriggerRadius * startTriggerRadius)) { ILogger logger = _logger; if (logger != null) { logger.Log($"[opening] player {((PlayerAim)(ref val2)).Index} reached the room; the fight starts."); } _boss.Begin(); break; } } } private void AdvanceSupplyLine(float deltaSeconds) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_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_00c5: 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_011e: 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_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) LoadedArena? arenaContent = _arenaContent; IReadOnlyList readOnlyList = ((arenaContent != null) ? arenaContent.CrateSources : null); if (_supply == null || readOnlyList == null || readOnlyList.Count == 0) { return; } for (int i = 0; i < _restingAtSource.Length; i++) { _restingAtSource[i] = _crates.RestingOn(CratePileId.Source(i)); } AdvanceCarriers(deltaSeconds, readOnlyList); _supply.Advance(deltaSeconds, (IReadOnlyList)_restingAtSource); SupplyEscalation escalation = Escalation; BossSimulation? boss = _boss; SupplyStep val = escalation.At((boss != null) ? boss.HealthFraction : 1f); IReadOnlyList readOnlyList2 = _supply.DrainProductionRequests(); ArenaWorldPoint val4 = default(ArenaWorldPoint); for (int j = 0; j < readOnlyList2.Count; j++) { int num = readOnlyList2[j]; if (num >= readOnlyList.Count) { continue; } CratePileId val2 = CratePileId.Source(num); ArenaWorldPoint val3 = readOnlyList[num]; ((ArenaWorldPoint)(ref val4))..ctor(((ArenaWorldPoint)(ref val3)).X, ((ArenaWorldPoint)(ref val3)).Y + 3f, ((ArenaWorldPoint)(ref val3)).Z); bool flag = SeededRandom.Unit01(20873, _produced++) < (double)((SupplyStep)(ref val)).ExplosiveChance; if (!_crates.Drop(val4, val2, flag)) { continue; } _announceProduced?.Invoke(val4, val2, flag); if (flag) { _barrelsMade++; ILogger logger = _logger; if (logger != null) { logger.Log($"[supply] source {num} produced a BARREL ({_barrelsMade} of {_produced} " + $"produced so far, at {((SupplyStep)(ref val)).ExplosiveChance:P1} this step)."); } } else { ILogger logger2 = _logger; if (logger2 != null) { logger2.Log($"[supply] source {num} produced one; {_crates.RestingOn(val2)} resting there."); } } } } private void FireWhateverWasBrought(float deltaSeconds) { //IL_0029: 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_006b: Unknown result type (might be due to invalid IL or missing references) _sinceVolley += deltaSeconds; if (_boss != null && !(_sinceVolley < 2f) && CanThrow(_boss.Activity) && TryGetSupplyPile(out var pile, out var _)) { int num = _crates.RestingOn(pile); if (num > 0) { _sinceVolley = 0f; _throwVolley?.Invoke(pile, Math.Min(num, 16)); } } } private static bool CanThrow(BossActivity activity) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 if ((int)activity != 4 && (int)activity != 5 && (int)activity != 6) { return (int)activity != 7; } return false; } private void AdvanceCarriers(float deltaSeconds, IReadOnlyList sources) { //IL_0025: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (_boss != null && TryGetSupplyPile(out var pile, out var at)) { SupplyStep step = Escalation.At(_boss.HealthFraction); _carriers.Advance(deltaSeconds, ((SupplyStep)(ref step)).Carriers, ((SupplyStep)(ref step)).LoadPerCarrier, _measuredRoundTripSeconds * 1f, sources, at, pile); AdoptMeasuredWalkSpeed(); ReportSupplyStepChange(step); } } private void AdoptMeasuredWalkSpeed() { float observedWalkSpeed = _carriers.ObservedWalkSpeed; if (!(observedWalkSpeed <= 0f) && _arenaContent != null && !(Math.Abs(observedWalkSpeed - _walkSpeedInUse) < 0.01f)) { float measuredRoundTripSeconds = _measuredRoundTripSeconds; _walkSpeedInUse = observedWalkSpeed; _measuredRoundTripSeconds = EstimateRoundTripSeconds(_arenaContent.CrateSources, _arenaContent.CratePiles, observedWalkSpeed); _lastReportedThroughput = -1; ILogger logger = _logger; if (logger != null) { logger.Log($"[supply] carriers actually walk {observedWalkSpeed:0.00} m/s, so a round trip is " + $"{_measuredRoundTripSeconds:0.0}s, not {measuredRoundTripSeconds:0.0}s."); } } } private void ReportSupplyStepChange(SupplyStep step) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (((SupplyStep)(ref step)).Throughput != _lastReportedThroughput) { _lastReportedThroughput = ((SupplyStep)(ref step)).Throughput; float num = SupplyEscalation.RatePerSecond(step, _measuredRoundTripSeconds); ILogger logger = _logger; if (logger != null) { logger.Log($"[supply] the village steps up: {((SupplyStep)(ref step)).Carriers} carrier(s) hauling " + $"{((SupplyStep)(ref step)).LoadPerCarrier} each = {((SupplyStep)(ref step)).Throughput} in transit, about {num:0.0} crate(s)/s over a " + $"{_measuredRoundTripSeconds:0.0}s round trip."); } } } private static float EstimateRoundTripSeconds(IReadOnlyList sources, IReadOnlyList piles, float walkSpeed) { //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_0040: 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: 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_0063: 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) if (sources.Count == 0 || piles.Count == 0 || walkSpeed <= 0f) { return 1f; } float num = 0f; int num2 = 0; for (int i = 0; i < sources.Count; i++) { for (int j = 0; j < piles.Count; j++) { ArenaWorldPoint val = sources[i]; float x = ((ArenaWorldPoint)(ref val)).X; val = piles[j]; float num3 = x - ((ArenaWorldPoint)(ref val)).X; val = sources[i]; float z = ((ArenaWorldPoint)(ref val)).Z; val = piles[j]; float num4 = z - ((ArenaWorldPoint)(ref val)).Z; num += (float)Math.Sqrt(num3 * num3 + num4 * num4); num2++; } } return num / (float)num2 * 2f / walkSpeed + 1.5f; } private bool TryGetSupplyPile(out CratePileId pile, out ArenaWorldPoint at) { //IL_0001: 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_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_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_0093: 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) pile = CratePileId.Loose; at = default(ArenaWorldPoint); LoadedArena? arenaContent = _arenaContent; IReadOnlyList readOnlyList = ((arenaContent != null) ? arenaContent.CratePiles : null); if (_boss == null || readOnlyList == null || readOnlyList.Count == 0) { return false; } int stationIndex = _boss.StationIndex; int num; if (stationIndex < 0 || stationIndex >= Itinerary.Count) { num = 0; } else { BossStation val = Itinerary[stationIndex]; num = ((BossStation)(ref val)).AnchorIndex; } int num2 = num; int num3 = ((num2 < readOnlyList.Count) ? num2 : (readOnlyList.Count - 1)); pile = CratePileId.Delivery(num3); at = readOnlyList[num3]; return true; } public void Drop() { BroadcastEndedIfHosting(); CleanupGate(); HostHitIntake? hitIntake = _hitIntake; if (hitIntake != null) { hitIntake.Dispose(); } _hitIntake = null; _minionSpawns.DespawnAll(); _emergencyMinions.DespawnAll(); _rageArms.LowerAll(); _atmosphere.StopBattleMusic(); _starvation.Reset(); _pileLastSeen = 0; _carriers.DismissAll(); _supply = null; _restingAtSource = null; _arenaContent = null; _damageBinding?.Dispose(); _damageBinding = null; _presence.Withdraw(); BossPresentation? presentation = _presentation; if (presentation != null) { presentation.Dispose(); } _presentation = null; _presenter = null; _boss = null; _arenaPresentation = null; EncounterCoordinator? coordinator = _coordinator; if (coordinator != null) { coordinator.BeginExit(); } _coordinator = null; _arena = null; bool ownsArena = _ownsArena; ReleaseArena(); _replication = null; _hostIntegration = null; ILogger logger = _logger; if (logger != null) { logger.Log(ownsArena ? "Encounter torn down; arena navigation restored and nothing remains." : "Encounter torn down; the level's arena is left standing, as it belongs to the level."); } } private void StartBoss(ArenaRealizeResult realized) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00ae: 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_00d0: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0148: 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_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0175: 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_018b: Expected O, but got Unknown //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Expected O, but got Unknown //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Expected O, but got Unknown //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Expected O, but got Unknown //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0415: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Unknown result type (might be due to invalid IL or missing references) ArenaManifest manifest = realized.Manifest; LoadedArena arena = realized.Arena; _arena = new ArenaSimulation(); _coordinator = new EncounterCoordinator(_encounter, _arena, new MechanismGroupId("phase_2")); IReadOnlyList readOnlyList = ToBossAnchors(arena.BossAnchors); BossDefinition val = new BossDefinition(50000, 0.5f, 0f, 2f, 1.5f, 0.4f, 2f, 3, 20, 2f, 5f, (readOnlyList.Count > 0) ? Itinerary : null, 0.45f, 0.6f, 0.6f, 1.9f, false, 2.5f, 0.2f); _boss = new BossSimulation(new BossInstanceId(1), val, _clock, (IAuthoritativeRandom)new SeededAuthoritativeRandom(Environment.TickCount), _participants, readOnlyList); _arenaContent = arena; ArenaWorldPoint bossSpawn = arena.BossSpawn; bool hasValue = arena.StartTrigger.HasValue; _boss.Spawn(new SimVector2(((ArenaWorldPoint)(ref bossSpawn)).X, ((ArenaWorldPoint)(ref bossSpawn)).Z), ((ArenaWorldPoint)(ref bossSpawn)).Y, hasValue); _atmosphere.SetRoomDepth(4f, 10f, 0f, 0f); ILogger logger = _logger; SimVector2 position = _boss.Position; float x = ((SimVector2)(ref position)).X; float positionHeight = _boss.PositionHeight; position = _boss.Position; _presentation = new BossPresentation(logger, new Vector3(x, positionHeight, ((SimVector2)(ref position)).Z), ((ArenaWorldPoint)(ref bossSpawn)).Y); if (arena.BossSize > 0f) { _presentation.SpriteScale = arena.BossSize; } _presenter = new BossPresenter((IEncounterPresentation)(object)_presentation); _arenaPresentation = new ArenaPresentation(_realization, _logger); _presence.Declare(); if (_hostIntegration != null && _hostSender != null) { SetHosting(new EncounterHostReplication(_hostSender, _hostIntegration.Session, _hostIntegration.Roster, _encounter, new DefinitionId(1), manifest, _originWire), _hostIntegration); } _damageBinding = BossWeaponDamage.Bind(((Component)_presentation.HitCollider).gameObject, (IBossDamageSink)(object)new WeaponSink(this), _logger); _coordinator.Begin(); Present(); _presentation.Render(0f); string text = (_ownsArena ? $"{arena.NavWalkableNodes} walkable nav node(s) applied" : "navigation built by the level itself"); object obj; if (!hasValue) { obj = "in the fight already — the room authored no start trigger"; } else { ArenaWorldPoint value = arena.StartTrigger.Value; string text2 = $"waiting, untouchable, for a player to reach ({((ArenaWorldPoint)(ref value)).X:0.0}, "; value = arena.StartTrigger.Value; object arg = ((ArenaWorldPoint)(ref value)).Y; value = arena.StartTrigger.Value; obj = text2 + $"{arg:0.0}, {((ArenaWorldPoint)(ref value)).Z:0.0}) within " + $"{arena.StartTriggerRadius:0.#}m"; } string text3 = (string)obj; ILogger logger2 = _logger; if (logger2 != null) { logger2.Log($"Encounter {_encounter} started: arena '{manifest.ArenaId}' at " + $"({((WorldPosition)(ref _originWire)).X:0.0}, {((WorldPosition)(ref _originWire)).Y:0.0}, {((WorldPosition)(ref _originWire)).Z:0.0}), {text}, " + $"boss at ({((ArenaWorldPoint)(ref bossSpawn)).X:0.0}, {((ArenaWorldPoint)(ref bossSpawn)).Y:0.0}, {((ArenaWorldPoint)(ref bossSpawn)).Z:0.0}) on " + "the arena floor, " + text3 + ". Shoot or melee it; it strikes back through its room, not itself."); } _supply = ((arena.CrateSources.Count <= 0) ? ((SupplyLine)null) : new SupplyLine(Supply, arena.CrateSources.Count)); _restingAtSource = ((arena.CrateSources.Count > 0) ? new int[arena.CrateSources.Count] : null); _sinceVolley = 0f; _walkSpeedInUse = 5.13f; _measuredRoundTripSeconds = EstimateRoundTripSeconds(arena.CrateSources, arena.CratePiles, _walkSpeedInUse); _lastReportedThroughput = -1; _produced = 0; _barrelsMade = 0; ReportAuthoredBossContent(arena); } private void ReportActivityChange() { //IL_00a1: 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_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_0082: 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) if (_boss == null) { return; } if (_boss.PendingStationIndex != _lastReportedPending) { _lastReportedPending = _boss.PendingStationIndex; if (_lastReportedPending >= 0) { ILogger logger = _logger; if (logger != null) { logger.Log($"[boss-activity] station {_lastReportedPending} reached at {_boss.Health}/" + $"{_boss.MaxHealth} hp; leaving now (was {_boss.Activity})."); } } } if (_boss.Activity != _lastReportedActivity) { _lastReportedActivity = _boss.Activity; string arg = ((_boss.PendingStationIndex >= 0) ? $", waiting to move to station {_boss.PendingStationIndex}" : string.Empty); ILogger logger2 = _logger; if (logger2 != null) { logger2.Log($"[boss-activity] {_boss.Activity} at station {_boss.StationIndex} " + $"({_boss.Health}/{_boss.MaxHealth} hp){arg}"); } } } private void AdvanceStarvation(float deltaSeconds) { //IL_001b: 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_0070: Invalid comparison between Unknown and I4 //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Invalid comparison between Unknown and I4 //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Invalid comparison between Unknown and I4 //IL_0122: Unknown result type (might be due to invalid IL or missing references) if (_boss == null || !TryGetSupplyPile(out var pile, out var _)) { return; } int num = _crates.RestingOn(pile); bool flag = num > _pileLastSeen; _pileLastSeen = num; bool cratesHitSomebody = _cratesHitSomebody; _cratesHitSomebody = false; StarvationChange val = _starvation.Advance(deltaSeconds, flag, _measuredRoundTripSeconds * 1.5f, _emergencyMinions.Alive, cratesHitSomebody, 30f); if ((int)val != 1) { if ((int)val == 2) { ILogger logger = _logger; if (logger != null) { logger.Log("[rage] delivering again and its band is dead; the boss goes back to throwing."); } _boss.SetEnraged(false); } return; } int num2 = _emergencyMinions.SizeOf(MinionBands.Emergency); ILogger logger2 = _logger; if (logger2 != null) { logger2.Log(((int)_starvation.Reason == 1) ? ($"[rage] nothing it threw has hurt anybody for {_starvation.SinceHit:0.#}s: the boss " + $"comes at you itself. Summoning {num2}.") : ($"[rage] nothing delivered for {_starvation.SinceDelivery:0.#}s: the boss comes at " + $"you. Summoning {num2}; it settles when they are dead AND the route runs.")); } _boss.SetEnraged(true); _voice.Roar(BossStandsAt()); SummonEmergencyBand(); RaiseRageArms(); } private void SummonEmergencyBand() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) LoadedArena? arenaContent = _arenaContent; IReadOnlyList readOnlyList = ((arenaContent != null) ? arenaContent.MinionSpawns : null); if (readOnlyList == null || readOnlyList.Count == 0) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[rage] the room authored no minion spawn points, so the boss has nobody to send; it will stay enraged until it is supplied again."); } } else { _emergencyMinions.Summon(MinionBands.Emergency, RotatedByOne(readOnlyList)); } } private static IReadOnlyList RotatedByOne(IReadOnlyList places) { //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) if (places.Count < 2) { return places; } ArenaWorldPoint[] array = (ArenaWorldPoint[])(object)new ArenaWorldPoint[places.Count]; for (int i = 0; i < array.Length; i++) { array[i] = places[(i + 1) % places.Count]; } return array; } private void ClearTheFloorOnRelocation(IReadOnlyList bossEvents) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) LoadedArena arenaContent = _arenaContent; if (arenaContent == null) { return; } for (int i = 0; i < bossEvents.Count; i++) { IBossDomainEvent obj = bossEvents[i]; BossRelocated val = (BossRelocated)(object)((obj is BossRelocated) ? obj : null); if (val != null) { int num = _battlefield.SweepCorpses(arenaContent.Origin, 120f); ILogger logger = _logger; if (logger != null) { logger.Log($"[cleanup] station {val.StationIndex}: {num} body/bodies cleared from the " + "floor, and the gore with them."); } break; } } } private void PlayTheOpening(IReadOnlyList bossEvents) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < bossEvents.Count; i++) { if (bossEvents[i] is BossBegan) { _voice.Roar(BossStandsAt()); _atmosphere.SetRoomDepth(10f, 72f, 1f, 3f); _atmosphere.StartBattleMusic(); _presence.ShowHealthBar(); ILogger logger = _logger; if (logger != null) { logger.Log($"[opening] the boss roars; the room opens to {72f:0}m after " + $"{1f:0.#}s, and the fight runs in {1.9f:0.#}s."); } break; } } } private void AnswerARageEnding(IReadOnlyList bossEvents) { for (int i = 0; i < bossEvents.Count; i++) { IBossDomainEvent obj = bossEvents[i]; BossEnraged val = (BossEnraged)(object)((obj is BossEnraged) ? obj : null); if (val == null || val.Enraged) { continue; } _rageArms.LowerAll(); if (_starvation.Enraged) { ILogger logger = _logger; if (logger != null) { logger.Log("[rage] the boss has spent its temper; it stops for now, and starts going hungry again from here."); } _starvation.Reset(); _pileLastSeen = 0; } break; } } private void EndTheFightWithTheBoss(IReadOnlyList bossEvents) { //IL_0062: 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) for (int i = 0; i < bossEvents.Count; i++) { if (bossEvents[i] is BossDied) { _atmosphere.StopBattleMusic(); _presence.HideHealthBar(); IBossRewardPort reward = _reward; LoadedArena? arenaContent = _arenaContent; reward.DropReward((ArenaWorldPoint)(((??)((arenaContent != null) ? arenaContent.RewardDrop : ((ArenaWorldPoint?)null))) ?? BossStandsAt())); _carriers.Disband(); _rageArms.LowerAll(); _starvation.Reset(); _pileLastSeen = 0; _supply = null; _untilTheExitBarrel = 0.5f; ILogger logger = _logger; if (logger != null) { logger.Log("[fight] the boss is dead: the supply line has stopped and its villagers have gone back to their own lives."); } break; } } } private void BossTakesItsShareOfTheBlast(ArenaWorldPoint at, bool pickedOutOfTheAir) { //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) if (_boss == null || _boss.IsDead || _blastRadius <= 0f) { return; } ArenaWorldPoint val = BossStandsAt(); float num = ((ArenaWorldPoint)(ref val)).X - ((ArenaWorldPoint)(ref at)).X; float num2 = ((ArenaWorldPoint)(ref val)).Y - ((ArenaWorldPoint)(ref at)).Y; float num3 = ((ArenaWorldPoint)(ref val)).Z - ((ArenaWorldPoint)(ref at)).Z; float num4 = (float)Math.Sqrt(num * num + num2 * num2 + num3 * num3); if (pickedOutOfTheAir) { float num5 = _blastDamage * 20f; ILogger logger = _logger; if (logger != null) { logger.Log($"[crate] a barrel was caught in the air {num4:0.#}m out; the boss takes " + $"{num5:0.#} for it ({20f:0}x, no falloff)."); } OnWeaponDamage(num5); } else { if (num4 >= _blastRadius) { return; } float num6 = _blastDamage * (1f - num4 / _blastRadius); if (!(num6 <= 0f)) { ILogger logger2 = _logger; if (logger2 != null) { logger2.Log($"[crate] a barrel went off {num4:0.#}m from the boss; its share is {num6:0.#}."); } OnWeaponDamage(num6); } } } private ArenaWorldPoint BossStandsAt() { //IL_0041: 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_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_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_0039: Unknown result type (might be due to invalid IL or missing references) if (_boss != null) { SimVector2 position = _boss.Position; float x = ((SimVector2)(ref position)).X; float positionHeight = _boss.PositionHeight; position = _boss.Position; return new ArenaWorldPoint(x, positionHeight, ((SimVector2)(ref position)).Z); } return default(ArenaWorldPoint); } private void RaiseRageArms() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) _rageArms.Raise(2, ArmsAroundTheBoss()); } private void CarryTheArmsWithTheBoss() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (_rageArms.Raised > 0) { _rageArms.Follow(ArmsAroundTheBoss()); } } private ArmPlacement ArmsAroundTheBoss() { //IL_0001: 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_0012: 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_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_0036: Unknown result type (might be due to invalid IL or missing references) ArenaWorldPoint val = BossStandsAt(); BossSimulation? boss = _boss; SimVector2 val2 = (SimVector2)((boss != null) ? boss.Facing : default(SimVector2)); return new ArmPlacement(val, val2, 3.1f, 1f, 1.5f, 1.5f); } private void Summon(SummonRequest request) { //IL_003a: 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_0091: Unknown result type (might be due to invalid IL or missing references) LoadedArena? arenaContent = _arenaContent; IReadOnlyList readOnlyList = ((arenaContent != null) ? arenaContent.MinionSpawns : null); if (readOnlyList == null || readOnlyList.Count == 0) { ILogger logger = _logger; if (logger != null) { logger.LogWarning($"[minion] station {request.StationIndex} calls up the {request.Band} band, but " + "the room authored no minion spawn points; nothing summoned."); } return; } ILogger logger2 = _logger; if (logger2 != null) { logger2.Log($"[minion] station {request.StationIndex} calls up the {request.Band} band."); } _minionSpawns.Summon(request.Band, readOnlyList); } private static IReadOnlyList ToBossAnchors(IReadOnlyList authored) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_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_0030: 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_003c: 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) BossAnchor[] array = (BossAnchor[])(object)new BossAnchor[authored.Count]; for (int i = 0; i < authored.Count; i++) { int num = i; ArenaWorldPoint val = authored[i]; float x = ((ArenaWorldPoint)(ref val)).X; val = authored[i]; SimVector2 val2 = new SimVector2(x, ((ArenaWorldPoint)(ref val)).Z); val = authored[i]; array[num] = new BossAnchor(val2, ((ArenaWorldPoint)(ref val)).Y); } return array; } private void ReportAuthoredBossContent(LoadedArena arena) { string text = ((arena.BossSize > 0f) ? $"size {arena.BossSize:0.##} (authored)" : "size: none authored, presentation default in use"); if (arena.BossAnchors.Count == 0) { ILogger logger = _logger; if (logger != null) { logger.Log("[boss-content] " + text + "; no authored anchors — the boss has no room-authored places to stand."); } return; } ILogger logger2 = _logger; if (logger2 != null) { logger2.Log($"[boss-content] {text}; {arena.BossAnchors.Count} authored anchor(s): " + $"{Describe(arena.BossAnchors)}; {arena.MinionSpawns.Count} minion spawn point(s)"); } ILogger logger3 = _logger; if (logger3 != null) { logger3.Log($"[supply-content] {arena.CrateSources.Count} crate source(s): " + $"{Describe(arena.CrateSources)}; {arena.CratePiles.Count} delivery pile(s): " + $"{Describe(arena.CratePiles)}; round trip about {_measuredRoundTripSeconds:0.0}s at " + $"{_walkSpeedInUse:0.##} m/s"); } if (arena.CratePiles.Count > 0 && arena.CratePiles.Count < arena.BossAnchors.Count) { ILogger logger4 = _logger; if (logger4 != null) { logger4.LogWarning($"[supply-content] the room authored {arena.CratePiles.Count} pile(s) for " + $"{arena.BossAnchors.Count} anchor(s); anchors past the last pile are supplied by it."); } } } private static string Describe(IReadOnlyList points) { //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_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_0073: 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) if (points.Count == 0) { return "none"; } StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < points.Count; i++) { StringBuilder stringBuilder2 = stringBuilder.Append((i == 0) ? string.Empty : ", "); object[] obj = new object[4] { i, null, null, null }; ArenaWorldPoint val = points[i]; obj[1] = ((ArenaWorldPoint)(ref val)).X; val = points[i]; obj[2] = ((ArenaWorldPoint)(ref val)).Y; val = points[i]; obj[3] = ((ArenaWorldPoint)(ref val)).Z; stringBuilder2.Append(string.Format("#{0} ({1:0.0}, {2:0.0}, {3:0.0})", obj)); } return stringBuilder.ToString(); } private void OnWeaponDamage(float amount) { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) if (_boss == null || _boss.IsDead) { return; } if (_boss.IsOutsideTheFight) { ILogger logger = _logger; if (logger != null) { logger.Log("[weapon-damage] refused: the fight has not started (" + (_boss.HasBegun ? "the boss is still roaring" : "nobody has walked in yet") + "); " + $"health stays {_boss.Health}."); } return; } if (_boss.IsRelocating) { ILogger logger2 = _logger; if (logger2 != null) { logger2.Log($"[weapon-damage] refused: the boss is {_boss.Activity} (invulnerable while it moves); " + $"health stays {_boss.Health}."); } return; } int num = WeaponDamage.ToSimAmount(amount); if (num != 0) { int health = _boss.Health; BossPhase phase = _boss.Phase; bool isEnraged = _boss.IsEnraged; _boss.ApplyDamage(num); Present(); ILogger logger3 = _logger; if (logger3 != null) { logger3.Log($"[weapon-damage] raw={num} (game {amount:0.##}) enraged={isEnraged} " + $"health {health}->{_boss.Health} (-{health - _boss.Health}) " + string.Format("phase {0}->{1}{2}", phase, _boss.Phase, _boss.IsDead ? " DEAD" : string.Empty)); } } } private void Present() { //IL_0110: 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) if (_boss == null || _presenter == null || _arena == null || _coordinator == null) { return; } IReadOnlyList readOnlyList = _boss.DrainEvents(); _presenter.Present(_boss, readOnlyList); _coordinator.Process(readOnlyList); ClearTheFloorOnRelocation(readOnlyList); PlayTheOpening(readOnlyList); AnswerARageEnding(readOnlyList); EndTheFightWithTheBoss(readOnlyList); IReadOnlyList readOnlyList2 = _boss.DrainDamageRequests(); if (readOnlyList2.Count > 0) { ApplyOrDeferPlayerDamage(readOnlyList2); } IReadOnlyList readOnlyList3 = _boss.DrainSummonRequests(); for (int i = 0; i < readOnlyList3.Count; i++) { Summon(readOnlyList3[i]); } IReadOnlyList readOnlyList4 = _arena.DrainEvents(); for (int j = 0; j < readOnlyList4.Count; j++) { ArenaPresentation? arenaPresentation = _arenaPresentation; if (arenaPresentation != null) { arenaPresentation.Handle(ArenaPresentationMapping.ToEvent(readOnlyList4[j])); } } EncounterHostReplication? replication = _replication; if (replication != null) { replication.Publish(_boss, readOnlyList, _arena, readOnlyList4, _coordinator.Phase, new SimulationTick(_clock.Tick)); } } private void ApplyOrDeferPlayerDamage(IReadOnlyList requests) { //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_0019: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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: Expected O, but got Unknown //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) if (_hostIntegration == null) { for (int i = 0; i < requests.Count; i++) { _damagePort.ApplyDamage(requests[i].Target, requests[i].Amount); } return; } int num = default(int); _localPlayer.TryGetLocalParticipantIndex(ref num); SessionPeerId val2 = default(SessionPeerId); for (int j = 0; j < requests.Count; j++) { DamageRequest val = requests[j]; IParticipantPeerMap players = _hostIntegration.Players; ParticipantId target = val.Target; if (players.TryGetRemotePeer(((ParticipantId)(ref target)).Value, ref val2)) { ReplicationSender? hostSender = _hostSender; if (hostSender != null) { hostSender.SendBossHitPlayer(new BossHitPlayer(_encounter, val.Amount), val2); } continue; } target = val.Target; if (((ParticipantId)(ref target)).Value == num) { _damagePort.ApplyDamage(val.Target, val.Amount); continue; } ILogger logger = _logger; if (logger != null) { target = val.Target; logger.Log($"[boss-damage] hit on participant {((ParticipantId)(ref target)).Value} maps to no session peer " + "or the local player; dropped."); } } } private void ReleaseArena() { if (_ownsArena) { ArenaLoadFlow? flow = _flow; if (flow != null) { flow.Teardown(); } } _flow = null; _realization = null; _manifest = null; _ownsArena = false; } private void Abort(string reason) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("Encounter not started (" + reason + "). Nothing was placed; the fail-closed path tore down whatever had been acquired."); } CleanupGate(); ReleaseArena(); _arena = null; _coordinator = null; _hostIntegration = null; } private void BroadcastEndedIfHosting() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown if (_hostSender == null || _hostIntegration == null) { return; } try { if (_hostIntegration.Session.IsActive && (int)_hostIntegration.Session.Role == 0) { _hostSender.BroadcastEnded(new EncounterEnded(_encounter, new SimulationTick(_clock.Tick))); } } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("EncounterEnded broadcast failed (" + ex.Message + "); clients will fall back to session-end cleanup."); } } } private void CleanupGate() { HostEncounterGate? hostGate = _hostGate; if (hostGate != null) { hostGate.Dispose(); } _hostGate = null; _hostSender = null; _pendingStart = null; } } } namespace FalseGods.Plugin.Diagnostics { internal sealed class BepInExLogger : ILogger { private readonly ManualLogSource _log; public BepInExLogger(ManualLogSource log) { _log = log; } public void Log(string message) { _log.LogInfo((object)message); } public void LogWarning(string message) { _log.LogWarning((object)message); } } }