using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak;
using Peak.Network;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;
using Zorro.Core;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LateJoinWithYourFriends")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LateJoinWithYourFriends")]
[assembly: AssemblyTitle("LateJoinWithYourFriends")]
[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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace LateJoinWithYourFriends
{
[BepInPlugin("com.daedo.latejoinwithyourfriends", "Late Join With Your Friends", "1.2.0")]
public class Plugin : BaseUnityPlugin
{
private sealed class SavedPosition
{
public string Room;
public string Scene;
public int Segment;
public Vector3 Position;
public DateTime SavedAtUtc;
}
[HarmonyPatch(typeof(CharacterSpawner), "SpawnDeadAtBaseCamp")]
private static class SpawnDeadAtBaseCampPatch
{
private static void Prefix(ref bool andRevive)
{
if (Enabled.Value && !((Object)(object)Instance == (Object)null) && !(VoidBiome.VoidBiomeActive & andRevive))
{
Instance.StartReviveRoutine(andRevive);
andRevive = false;
}
}
}
[HarmonyPatch(typeof(CharacterClimbing), "StopAnyClimbing")]
private static class StopAnyClimbingPatch
{
private static bool Prefix(Character ___character)
{
return (Object)(object)___character != (Object)null;
}
}
[HarmonyPatch(typeof(CharacterSpawner), "ReconnectingPlayerSpawn")]
private static class ReconnectingPlayerSpawnPatch
{
private static void Prefix(Segment currentMapStage, ref ReconnectData reconnectData, ref bool canRevive)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Invalid comparison between Unknown and I4
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
if (!Enabled.Value)
{
return;
}
if ((int)currentMapStage != 6 && !IsSanePosition(reconnectData.position))
{
Log.LogWarning((object)$"Host stored an invalid reconnect position ({reconnectData.position}); using a safe spawn point instead.");
reconnectData.position = ((Component)SpawnPoint.LocalSpawnPoint).transform.position;
if ((int)currentMapStage != 0)
{
reconnectData.mapSegment = (Segment)0;
}
}
if (HandleReconnects.Value && !reconnectData.dead)
{
Arm(canRevive);
canRevive = false;
}
}
}
[HarmonyPatch(typeof(CharacterSpawner), "DeathOnArrival")]
private static class DeathOnArrivalPatch
{
private static void Finalizer()
{
if (armed)
{
armed = false;
if (!(Time.realtimeSinceStartup - armedAt > 30f) && !((Object)(object)Instance == (Object)null))
{
Instance.StartReviveRoutine(armedCampWouldRevive);
}
}
}
}
private static ConfigEntry<bool> ReturnToLastPosition;
private static ConfigEntry<float> ReturnSaveIntervalSeconds;
private static ConfigEntry<float> ReturnMaxAgeMinutes;
private const float ReturnMinDistance = 8f;
private const float ReturnDecisionTimeout = 45f;
private bool returnEligible;
private bool returnPending;
private float returnPendingSince;
private bool wasInRoom;
private Character lastLocalCharacter;
private float saveTimer;
internal static Plugin Instance;
internal static ManualLogSource Log;
private static ConfigEntry<bool> Enabled;
private static ConfigEntry<SpawnTarget> Target;
private static ConfigEntry<bool> WakeUpAnimation;
private static ConfigEntry<bool> PoofEffect;
private static ConfigEntry<bool> HandleReconnects;
private static ConfigEntry<bool> ApplyRevivePenalty;
private static ConfigEntry<float> StableGroundSeconds;
private static ConfigEntry<float> PreferredTargetWaitSeconds;
private static bool armed;
private static bool armedCampWouldRevive;
private static float armedAt;
private Coroutine routine;
private const float FogSafetyMargin = 20f;
private const float RagdollGraceSeconds = 3f;
private const float RagdollBrokenConfirmSeconds = 1.5f;
private const float LieDownRadius = 1.6f;
private const float LieDownClearance = 0.9f;
private const float LaunchSpeed = 25f;
private const float LaunchGuardSeconds = 15f;
private static string LastPositionFile => Path.Combine(Paths.ConfigPath, "com.daedo.latejoinwithyourfriends.lastpos.txt");
private void BindReturnConfig()
{
ReturnToLastPosition = ((BaseUnityPlugin)this).Config.Bind<bool>("Return To Last Position", "Enabled", true, "If you leave (or the game crashes) and rejoin the same room, go back to where you were. Only if the group is still on the same part of the map, the fog hasn't reached it and there is still ground. Players who were dead stay dead.");
ReturnSaveIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Return To Last Position", "SaveIntervalSeconds", 10f, "How often to save your position, in seconds (only while alive and standing on the ground).");
ReturnMaxAgeMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("Return To Last Position", "MaxAgeMinutes", 30f, "How many minutes the saved position stays valid.");
}
private void Update()
{
if (!Enabled.Value || !ReturnToLastPosition.Value)
{
return;
}
bool flag = PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null;
if (flag && !wasInRoom)
{
returnEligible = true;
returnPending = false;
lastLocalCharacter = null;
}
wasInRoom = flag;
if (!flag)
{
return;
}
Character localCharacter = Character.localCharacter;
if ((Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter != (Object)(object)lastLocalCharacter)
{
lastLocalCharacter = localCharacter;
if (returnEligible)
{
EvaluateReturn();
if (returnPending)
{
((MonoBehaviour)this).StartCoroutine(ReturnWhenSpawnedAlive(localCharacter));
}
}
}
if (returnPending && Time.realtimeSinceStartup - returnPendingSince > 45f)
{
Log.LogInfo((object)"Did not return to the saved position in time (still dead); continuing normally.");
returnPending = false;
}
if (!returnEligible && !returnPending)
{
saveTimer += Time.unscaledDeltaTime;
if (!(saveTimer < Mathf.Max(2f, ReturnSaveIntervalSeconds.Value)))
{
saveTimer = 0f;
TrySavePosition(localCharacter);
}
}
}
private static void TrySavePosition(Character c)
{
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Expected I4, but got Unknown
if ((Object)(object)c == (Object)null || (Object)(object)c.data == (Object)null || c.data.dead || c.data.passedOut || c.data.fullyPassedOut || c.warping || !c.data.isGrounded || c.data.isClimbingAnything || (Object)(object)Singleton<MapHandler>.Instance == (Object)null || VoidBiome.VoidBiomeActive)
{
return;
}
Scene activeScene = SceneManager.GetActiveScene();
string name = ((Scene)(ref activeScene)).name;
if (name == "Airport" || name == "Title")
{
return;
}
Vector3 center = c.Center;
if (!IsSanePosition(center))
{
return;
}
try
{
string contents = string.Join("\n", "room=" + PhotonNetwork.CurrentRoom.Name, "scene=" + name, "segment=" + (int)MapHandler.CurrentSegmentNumber, "x=" + center.x.ToString("R", CultureInfo.InvariantCulture), "y=" + center.y.ToString("R", CultureInfo.InvariantCulture), "z=" + center.z.ToString("R", CultureInfo.InvariantCulture), "savedAtUtc=" + DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture));
string text = LastPositionFile + ".tmp";
File.WriteAllText(text, contents);
if (File.Exists(LastPositionFile))
{
File.Delete(LastPositionFile);
}
File.Move(text, LastPositionFile);
}
catch (Exception ex)
{
Log.LogWarning((object)("Could not save position: " + ex.Message));
}
}
private static SavedPosition ReadSave()
{
//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
try
{
if (!File.Exists(LastPositionFile))
{
return null;
}
SavedPosition savedPosition = new SavedPosition();
float num = 0f;
float num2 = 0f;
float num3 = 0f;
string[] array = File.ReadAllLines(LastPositionFile);
foreach (string text in array)
{
int num4 = text.IndexOf('=');
if (num4 > 0)
{
string text2 = text.Substring(0, num4);
string text3 = text.Substring(num4 + 1);
switch (text2)
{
case "room":
savedPosition.Room = text3;
break;
case "scene":
savedPosition.Scene = text3;
break;
case "segment":
savedPosition.Segment = int.Parse(text3, CultureInfo.InvariantCulture);
break;
case "x":
num = float.Parse(text3, CultureInfo.InvariantCulture);
break;
case "y":
num2 = float.Parse(text3, CultureInfo.InvariantCulture);
break;
case "z":
num3 = float.Parse(text3, CultureInfo.InvariantCulture);
break;
case "savedAtUtc":
savedPosition.SavedAtUtc = new DateTime(long.Parse(text3, CultureInfo.InvariantCulture), DateTimeKind.Utc);
break;
}
}
}
savedPosition.Position = new Vector3(num, num2, num3);
return string.IsNullOrEmpty(savedPosition.Room) ? null : savedPosition;
}
catch (Exception ex)
{
Log.LogWarning((object)("Saved position is unreadable; ignoring it: " + ex.Message));
return null;
}
}
private static SavedPosition LoadMatchingSave(out string problem)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
SavedPosition savedPosition = ReadSave();
if (savedPosition == null)
{
problem = "no saved position";
return null;
}
if (PhotonNetwork.CurrentRoom == null || savedPosition.Room != PhotonNetwork.CurrentRoom.Name)
{
problem = "saved position is from another room";
return null;
}
string scene = savedPosition.Scene;
Scene activeScene = SceneManager.GetActiveScene();
if (scene != ((Scene)(ref activeScene)).name)
{
problem = "saved position is from another map";
return null;
}
double totalMinutes = (DateTime.UtcNow - savedPosition.SavedAtUtc).TotalMinutes;
if (totalMinutes > (double)ReturnMaxAgeMinutes.Value)
{
problem = $"saved position is too old ({totalMinutes:0} min)";
return null;
}
problem = null;
return savedPosition;
}
private static bool TryGetReturnPosition(out Vector3 position, out string problem)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_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_0046: Invalid comparison between Unknown and I4
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//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_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
position = default(Vector3);
SavedPosition savedPosition = LoadMatchingSave(out problem);
if (savedPosition == null)
{
return false;
}
if ((Object)(object)Singleton<MapHandler>.Instance == (Object)null)
{
problem = "map not loaded yet";
return false;
}
if (VoidBiome.VoidBiomeActive)
{
problem = "the group is in the Void";
return false;
}
Segment currentSegmentNumber = MapHandler.CurrentSegmentNumber;
if ((int)currentSegmentNumber != savedPosition.Segment)
{
problem = $"the group has left that segment ({(object)(Segment)(byte)savedPosition.Segment} -> {currentSegmentNumber})";
return false;
}
if (!IsSanePosition(savedPosition.Position))
{
problem = $"invalid saved position {savedPosition.Position}";
return false;
}
if (IsInFog(savedPosition.Position))
{
problem = "covered by fog";
return false;
}
LayerMask allPhysicalExceptCharacter = HelperFunctions.AllPhysicalExceptCharacter;
RaycastHit val = default(RaycastHit);
if (!Physics.Raycast(savedPosition.Position + Vector3.up, Vector3.down, ref val, 4f, LayerMask.op_Implicit(allPhysicalExceptCharacter), (QueryTriggerInteraction)1))
{
problem = "no ground at that spot";
return false;
}
position = ((RaycastHit)(ref val)).point + Vector3.up * 1.2f;
return true;
}
private bool TryConsumeReturnPosition(out Vector3 position)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
position = default(Vector3);
if (!Enabled.Value || !ReturnToLastPosition.Value)
{
return false;
}
if (returnEligible)
{
EvaluateReturn();
}
if (!returnPending)
{
return false;
}
returnPending = false;
if (TryGetReturnPosition(out position, out var problem))
{
return true;
}
Log.LogInfo((object)("Cannot return to the saved position: " + problem + "."));
return false;
}
private void EvaluateReturn()
{
returnEligible = false;
returnPending = LoadMatchingSave(out var problem) != null;
returnPendingSince = Time.realtimeSinceStartup;
Log.LogInfo((object)(returnPending ? "Found a saved position for this room." : ("No usable saved position: " + problem + ".")));
}
private IEnumerator ReturnWhenSpawnedAlive(Character self)
{
float stable = 0f;
while (returnPending && (Object)(object)self != (Object)null)
{
if (self.data.dead)
{
yield break;
}
stable = ((self.warping || self.data.passedOut) ? 0f : (stable + Time.deltaTime));
if (stable >= 3f)
{
break;
}
yield return null;
}
if (!returnPending || (Object)(object)self == (Object)null || self.data.dead || routine != null)
{
yield break;
}
returnPending = false;
if (!TryGetReturnPosition(out var position, out var problem))
{
Log.LogInfo((object)("Cannot return to the saved position: " + problem + "."));
yield break;
}
float num = Vector3.Distance(self.Center, position);
if (num < 8f)
{
Log.LogInfo((object)$"Already close to the saved position ({num:0} m); nothing to do.");
yield break;
}
Log.LogInfo((object)$"Returning to last saved position: {position} ({num:0} m away).");
((MonoBehaviourPun)self).photonView.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { position, false });
((MonoBehaviour)this).StartCoroutine(DampLaunchAfterSpawn(self));
((MonoBehaviour)this).StartCoroutine(WatchAfterSpawn(self, position));
}
private void Awake()
{
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "When joining a run in progress, spawn alive instead of staying dead until the next statue.");
Target = ((BaseUnityPlugin)this).Config.Bind<SpawnTarget>("General", "SpawnTarget", SpawnTarget.Host, "Where to spawn: Host (falls back to the highest living scout if the host is dead), Highest (highest living scout), Lowest (lowest living scout) or MapStart (starting point of the current biome; if the fog has already covered it, spawns next to the highest living scout).");
WakeUpAnimation = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "WakeUpAnimation", true, "Spawn passed out and wake up, like at the start of a run. Skipped on uneven ground.");
PoofEffect = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PoofEffect", false, "Play the revive smoke and sound when spawning. When off, you appear without any effect (for everyone, even players without the mod).");
HandleReconnects = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HandleReconnects", true, "Also applies when you reconnect and the game would kill you for being too far behind. Players who were already dead stay dead.");
ApplyRevivePenalty = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ApplyRevivePenalty", false, "Apply the revive penalty (curse/hunger) when spawning.");
StableGroundSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "StableGroundSeconds", 0.5f, "How long the target must stand on solid ground (not climbing or falling) before you spawn next to them.");
PreferredTargetWaitSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "PreferredTargetWaitSeconds", 20f, "How long to wait for the chosen target to be on the ground before accepting any living scout on the ground.");
BindReturnConfig();
new Harmony("com.daedo.latejoinwithyourfriends").PatchAll();
Log.LogInfo((object)$"Late Join With Your Friends v1.2.0 loaded (target: {Target.Value}).");
}
private static void Arm(bool campWouldRevive)
{
armed = true;
armedCampWouldRevive = campWouldRevive;
armedAt = Time.realtimeSinceStartup;
}
private void StartReviveRoutine(bool campWouldRevive)
{
if (routine != null)
{
((MonoBehaviour)this).StopCoroutine(routine);
}
routine = ((MonoBehaviour)this).StartCoroutine(ReviveNearTargetRoutine(campWouldRevive));
}
private IEnumerator ReviveNearTargetRoutine(bool campWouldRevive)
{
float waitedForDeath = 0f;
while (waitedForDeath < 15f && ((Object)(object)Character.localCharacter == (Object)null || !Character.localCharacter.data.dead))
{
waitedForDeath += Time.unscaledDeltaTime;
yield return null;
}
Character self = Character.localCharacter;
if ((Object)(object)self == (Object)null || !self.data.dead)
{
Log.LogWarning((object)"Local character did not die on arrival; nothing to do.");
routine = null;
yield break;
}
yield return (object)new WaitForSeconds(0.5f);
string text = RagdollProblem(self);
float t = 0f;
while (text != null && t < 1.5f)
{
yield return null;
if ((Object)(object)self == (Object)null)
{
routine = null;
yield break;
}
text = RagdollProblem(self);
t += Time.deltaTime;
}
if (text != null)
{
Log.LogError((object)("Ragdoll broken before revive (" + text + "); staying dead. Rejoin to fix it."));
routine = null;
yield break;
}
if (TryConsumeReturnPosition(out var back))
{
Log.LogInfo((object)$"Returning to last saved position: {back}.");
yield return ReviveAt(self, back, ApplyRevivePenalty.Value, -1, WakeUpAnimation.Value);
((MonoBehaviour)this).StartCoroutine(WatchAfterSpawn(self, back));
routine = null;
yield break;
}
SpawnTarget mode = Target.Value;
Vector3 start;
if (mode == SpawnTarget.MapStart)
{
if (TryMapStartPosition(out start, out var problem))
{
Log.LogInfo((object)$"Joined a run in progress; spawning at the map start: {start}.");
yield return ReviveAt(self, start, ApplyRevivePenalty.Value, -1, WakeUpAnimation.Value);
((MonoBehaviour)this).StartCoroutine(WatchAfterSpawn(self, start));
routine = null;
yield break;
}
Log.LogWarning((object)("Map start unavailable (" + problem + "); spawning next to the highest living scout."));
mode = SpawnTarget.Highest;
}
Log.LogInfo((object)$"Joined a run in progress; looking for a target ({mode}).");
Dictionary<Character, float> groundedSince = new Dictionary<Character, float>();
float waited = 0f;
Character lastPreferred = null;
Character val2;
while (true)
{
if ((Object)(object)self == (Object)null || !PhotonNetwork.InRoom)
{
routine = null;
yield break;
}
if (!self.data.dead)
{
Log.LogInfo((object)"Already revived by other means; cancelling.");
routine = null;
yield break;
}
List<Character> list = AliveScouts(self);
if (list.Count == 0)
{
FallbackWhenNobodyAlive(self, campWouldRevive);
routine = null;
yield break;
}
float now = Time.time;
foreach (Character item in list)
{
if (IsStandingStill(item))
{
if (!groundedSince.ContainsKey(item))
{
groundedSince[item] = now;
}
}
else
{
groundedSince.Remove(item);
}
}
Character val = PreferredTarget(list, mode);
if ((Object)(object)val != (Object)(object)lastPreferred)
{
Log.LogInfo((object)("Target: " + Describe(val) + "."));
lastPreferred = val;
}
val2 = null;
if (IsReady(val, groundedSince, now))
{
val2 = val;
}
else if (waited >= PreferredTargetWaitSeconds.Value)
{
val2 = ByHeight(list.Where((Character c) => IsReady(c, groundedSince, now)), mode).FirstOrDefault();
}
if ((Object)(object)val2 != (Object)null)
{
break;
}
waited += Time.deltaTime;
yield return null;
}
start = SpawnPointNear(val2);
Log.LogInfo((object)$"Spawning next to {Describe(val2)} at {start}.");
yield return ReviveAt(self, start, ApplyRevivePenalty.Value, -1, WakeUpAnimation.Value);
((MonoBehaviour)this).StartCoroutine(WatchAfterSpawn(self, start));
routine = null;
}
private static List<Character> AliveScouts(Character self)
{
return Character.AllCharacters.Where((Character c) => (Object)(object)c != (Object)null && (Object)(object)c != (Object)(object)self && c.IsPlayerControlled && (Object)(object)c.data != (Object)null && !c.data.dead && !c.data.fullyPassedOut).ToList();
}
private static Character PreferredTarget(List<Character> alive, SpawnTarget mode)
{
if (mode == SpawnTarget.Host)
{
Player masterClient = PhotonNetwork.MasterClient;
Character val = default(Character);
if (PlayerHandler.TryGetCharacter((masterClient != null) ? masterClient.ActorNumber : (-1), ref val) && alive.Contains(val))
{
return val;
}
}
return ByHeight(alive, mode).First();
}
private static IEnumerable<Character> ByHeight(IEnumerable<Character> scouts, SpawnTarget mode)
{
if (mode != SpawnTarget.Lowest)
{
return scouts.OrderByDescending((Character c) => c.Center.y);
}
return scouts.OrderBy((Character c) => c.Center.y);
}
private static Vector3 MapStartAnchor()
{
//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_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Expected I4, but got Unknown
//IL_0039: 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_007d: Unknown result type (might be due to invalid IL or missing references)
Campfire previousCampfire = MapHandler.PreviousCampfire;
Transform val = (((Object)(object)previousCampfire != (Object)null) ? ((Component)previousCampfire).transform : ((Component)SpawnPoint.LocalSpawnPoint).transform);
Segment currentSegmentNumber = MapHandler.CurrentSegmentNumber;
Log.LogInfo((object)($"Map start: segment {currentSegmentNumber}, biome {MapHandler.GetBiomeForSegment((int)currentSegmentNumber)}, " + string.Format("{0} at {1}.", ((Object)(object)previousCampfire != (Object)null) ? "biome start campfire" : "plane", val.position)));
return val.position;
}
private static Vector3 MapStartPosition()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: 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_0038: 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_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
if (VoidBiome.VoidBiomeActive)
{
return VoidBiome.instance.GetSpawnPosition(NetCode.Session.SeatNumber);
}
Vector3 val = MapStartAnchor();
if (!TryGroundNear(val, out var position))
{
return val + CharacterSpawner.RandomBaseCampOffset;
}
return position;
}
private static bool TryMapStartPosition(out Vector3 position, out string problem)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
problem = null;
if (VoidBiome.VoidBiomeActive)
{
position = VoidBiome.instance.GetSpawnPosition(NetCode.Session.SeatNumber);
return true;
}
Vector3 val = MapStartAnchor();
if (IsInFog(val))
{
position = default(Vector3);
problem = "covered by fog";
return false;
}
if (!TryGroundNear(val, out position))
{
problem = "no ground near the campfire";
return false;
}
return true;
}
private static bool IsInFog(Vector3 position)
{
//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)
OrbFogHandler instance = Singleton<OrbFogHandler>.Instance;
if ((Object)(object)instance == (Object)null || !OrbFogHandler.IsFoggingCurrentSegment)
{
return false;
}
FogSphere componentInChildren = ((Component)instance).GetComponentInChildren<FogSphere>();
if ((Object)(object)componentInChildren == (Object)null || !((Component)componentInChildren).gameObject.activeInHierarchy)
{
return false;
}
float num = Vector3.Distance(componentInChildren.fogPoint, position);
Log.LogInfo((object)$"Fog: radius {instance.currentSize:0}, point {num:0} from center (moving: {instance.isMoving}).");
return num > instance.currentSize - 20f;
}
private static bool IsSanePosition(Vector3 p)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: 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)
if (!IsFinite(p))
{
return false;
}
if (Mathf.Abs(p.x) < 1500f && p.y > -300f && p.y < 1300f && p.z > -2000f)
{
return p.z < 4000f;
}
return false;
}
private static bool IsFinite(Vector3 p)
{
//IL_0000: 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_001a: 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_0034: 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)
if (!float.IsNaN(p.x) && !float.IsNaN(p.y) && !float.IsNaN(p.z) && !float.IsInfinity(p.x) && !float.IsInfinity(p.y))
{
return !float.IsInfinity(p.z);
}
return false;
}
internal static string RagdollProblem(Character c)
{
//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_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_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)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//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)
Vector3 center = c.Center;
if (!IsFinite(center))
{
return $"invalid center {center}";
}
foreach (Bodypart part in c.refs.ragdoll.partList)
{
Rigidbody val = (((Object)(object)part != (Object)null) ? part.Rig : null);
if (!((Object)(object)val == (Object)null))
{
Quaternion rotation = val.rotation;
float num = rotation.x * rotation.x + rotation.y * rotation.y + rotation.z * rotation.z + rotation.w * rotation.w;
if (!IsFinite(val.position) || float.IsNaN(num) || Mathf.Abs(num - 1f) > 0.05f)
{
return $"{((Object)part).name}: corrupted rotation/position (norm {num:0.000}, pos {val.position})";
}
float num2 = Vector3.Distance(val.position, center);
if (num2 > 25f)
{
return $"{((Object)part).name}: {num2:0.0} m from center";
}
Vector3 linearVelocity = val.linearVelocity;
float magnitude = ((Vector3)(ref linearVelocity)).magnitude;
if (magnitude > 300f)
{
return $"{((Object)part).name}: speed {magnitude:0} m/s";
}
}
}
return null;
}
private static bool TryGroundNear(Vector3 anchor, out Vector3 position)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: 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_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: 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_0089: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: 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_00ca: 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_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
LayerMask allPhysicalExceptCharacter = HelperFunctions.AllPhysicalExceptCharacter;
Vector3? val = null;
RaycastHit val3 = default(RaycastHit);
for (int i = 0; i < 24; i++)
{
Vector2 insideUnitCircle = Random.insideUnitCircle;
Vector2 val2 = ((Vector2)(ref insideUnitCircle)).normalized * Random.Range(1.75f, 2.5f);
if (!Physics.Raycast(anchor + new Vector3(val2.x, 4f, val2.y), Vector3.down, ref val3, 10f, LayerMask.op_Implicit(allPhysicalExceptCharacter), (QueryTriggerInteraction)1) || ((RaycastHit)(ref val3)).normal.y < 0.6f || Mathf.Abs(((RaycastHit)(ref val3)).point.y - anchor.y) > 3f)
{
continue;
}
Vector3 val4 = ((RaycastHit)(ref val3)).point + Vector3.up * 1.2f;
if (!Physics.CheckSphere(val4, 0.4f, LayerMask.op_Implicit(allPhysicalExceptCharacter), (QueryTriggerInteraction)1))
{
if (!val.HasValue)
{
val = val4;
}
if (!WakeUpAnimation.Value || SafeToLieDown(val4, out var _))
{
position = val4;
return true;
}
}
}
position = val.GetValueOrDefault();
return val.HasValue;
}
private static bool SafeToLieDown(Vector3 standPosition, out string problem)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: 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_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: 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_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//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_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
LayerMask allPhysicalExceptCharacter = HelperFunctions.AllPhysicalExceptCharacter;
RaycastHit val = default(RaycastHit);
if (!Physics.Raycast(standPosition + Vector3.up * 0.5f, Vector3.down, ref val, 4f, LayerMask.op_Implicit(allPhysicalExceptCharacter), (QueryTriggerInteraction)1))
{
problem = "no ground below";
return false;
}
if (((RaycastHit)(ref val)).normal.y < 0.85f)
{
problem = $"slope of {Vector3.Angle(((RaycastHit)(ref val)).normal, Vector3.up):0}°";
return false;
}
if (Physics.CheckSphere(((RaycastHit)(ref val)).point + Vector3.up * 1.05f, 0.9f, LayerMask.op_Implicit(allPhysicalExceptCharacter), (QueryTriggerInteraction)1))
{
problem = "obstacle where the body would lie";
return false;
}
RaycastHit val3 = default(RaycastHit);
for (int i = 0; i < 8; i++)
{
float num = (float)i * MathF.PI / 4f;
Vector3 val2 = new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)) * 1.6f;
if (!Physics.Raycast(((RaycastHit)(ref val)).point + val2 + Vector3.up * 1.5f, Vector3.down, ref val3, 3f, LayerMask.op_Implicit(allPhysicalExceptCharacter), (QueryTriggerInteraction)1) || Mathf.Abs(((RaycastHit)(ref val3)).point.y - ((RaycastHit)(ref val)).point.y) > 0.6f)
{
problem = "ledge or step too close";
return false;
}
}
problem = null;
return true;
}
private IEnumerator DampLaunchAfterSpawn(Character self)
{
WaitForFixedUpdate fixedStep = new WaitForFixedUpdate();
float elapsed = 0f;
int damped = 0;
while (elapsed < 15f && (Object)(object)self != (Object)null && !self.data.dead)
{
yield return fixedStep;
elapsed += Time.fixedDeltaTime;
if ((Object)(object)self == (Object)null || self.warping)
{
continue;
}
float num = 0f;
foreach (Bodypart part in self.refs.ragdoll.partList)
{
Rigidbody val = (((Object)(object)part != (Object)null) ? part.Rig : null);
if ((Object)(object)val != (Object)null)
{
float num2 = num;
Vector3 linearVelocity = val.linearVelocity;
num = Mathf.Max(num2, ((Vector3)(ref linearVelocity)).magnitude);
}
}
if (num < 25f)
{
continue;
}
foreach (Bodypart part2 in self.refs.ragdoll.partList)
{
Rigidbody val2 = (((Object)(object)part2 != (Object)null) ? part2.Rig : null);
if (!((Object)(object)val2 == (Object)null))
{
val2.linearVelocity = Vector3.zero;
val2.angularVelocity = Vector3.zero;
}
}
if (damped++ == 0)
{
Log.LogWarning((object)$"Physics spike of {num:0} m/s after spawning; holding the character in place.");
}
}
if (damped > 1)
{
Log.LogInfo((object)$"Anti-launch guard triggered {damped} times.");
}
}
private IEnumerator WatchAfterSpawn(Character self, Vector3 spawn)
{
//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)
float elapsed = 0f;
bool reported = false;
Vector3 last = spawn;
bool lastInFog = false;
float lastCold = 0f;
float brokenFor = 0f;
while (elapsed < 90f && (Object)(object)self != (Object)null && !self.data.dead)
{
elapsed += Time.deltaTime;
string text = ((elapsed >= 3f && !self.warping) ? RagdollProblem(self) : null);
if (text == null)
{
if (brokenFor > 0f)
{
Log.LogInfo((object)$"Ragdoll back to normal after {brokenFor:0.0} s.");
}
brokenFor = 0f;
}
else
{
if (brokenFor == 0f)
{
Log.LogWarning((object)("Ragdoll looks wrong (" + text + "); checking whether it persists."));
}
brokenFor += Time.deltaTime;
if (brokenFor >= 1.5f)
{
Log.LogError((object)("Ragdoll broken after spawning (" + text + "); moving to the death zone. Rejoin to fix it."));
((MonoBehaviourPun)self).photonView.RPC("RPCA_Die", (RpcTarget)0, Array.Empty<object>());
yield break;
}
}
if (!self.warping)
{
last = self.Center;
lastInFog = self.data.isInFog;
lastCold = self.refs.afflictions.GetCurrentStatus((STATUSTYPE)2);
bool flag = elapsed < 20f && last.y < spawn.y - 30f;
bool flag2 = elapsed < 10f && Vector2.Distance(new Vector2(last.x, last.z), new Vector2(spawn.x, spawn.z)) > 40f;
if (flag || flag2 || (!VoidBiome.VoidBiomeActive && !IsSanePosition(last)))
{
Character val = ByHeight(AliveScouts(self), SpawnTarget.Highest).FirstOrDefault();
Log.LogWarning((object)(string.Format("{0} from the spawn point ({1} -> {2}); ", flag ? "Fell" : "Flung", spawn, last) + (((Object)(object)val != (Object)null) ? ("moving next to " + Describe(val) + ".") : "no living scout to move to.")));
if ((Object)(object)val != (Object)null)
{
((MonoBehaviourPun)self).photonView.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2]
{
SpawnPointNear(val),
false
});
}
yield break;
}
}
if (!reported && elapsed >= 5f)
{
reported = true;
Log.LogInfo((object)$"5 s after spawning: position {last}, grounded: {self.data.isGrounded}, in fog: {lastInFog}.");
}
yield return null;
}
if ((Object)(object)self != (Object)null && self.data.dead)
{
Log.LogWarning((object)$"Died {elapsed:0} s after spawning near {last} (cold: {lastCold:0.00}, in fog: {lastInFog}).");
}
}
private static IEnumerator ReviveAt(Character self, Vector3 position, bool applyStatus, int statueSegment, bool wakeUp)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (statueSegment > -1 || PoofEffect.Value)
{
((MonoBehaviourPun)self).photonView.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[3] { position, applyStatus, statueSegment });
}
else
{
((MonoBehaviourPun)self).photonView.RPC("ReviveCharacter", (RpcTarget)0, new object[1] { applyStatus });
((MonoBehaviourPun)self).photonView.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { position, false });
self.refs.stats.justDied = false;
self.refs.stats.justRevived = true;
self.refs.stats.Record(true, position.y);
}
if ((Object)(object)Instance != (Object)null)
{
((MonoBehaviour)Instance).StartCoroutine(Instance.DampLaunchAfterSpawn(self));
}
if (!wakeUp)
{
yield break;
}
if (!SafeToLieDown(position, out var problem))
{
Log.LogInfo((object)("Skipping the wake-up animation: " + problem + "."));
yield break;
}
yield return null;
while ((Object)(object)self != (Object)null && self.warping)
{
yield return null;
}
if ((Object)(object)self != (Object)null)
{
AccessTools.Method(typeof(Character), "StartPassedOutOnTheBeach", (Type[])null, (Type[])null)?.Invoke(self, null);
}
}
private static bool IsStandingStill(Character c)
{
if (c.data.isGrounded && !c.data.isClimbingAnything)
{
return !c.warping;
}
return false;
}
private static bool IsReady(Character c, Dictionary<Character, float> groundedSince, float now)
{
if (groundedSince.TryGetValue(c, out var value))
{
return now - value >= StableGroundSeconds.Value;
}
return false;
}
private static Vector3 SpawnPointNear(Character target)
{
//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_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_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_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: 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_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: 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: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: 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_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: 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)
Vector3 center = target.Center;
LayerMask allPhysicalExceptCharacter = HelperFunctions.AllPhysicalExceptCharacter;
for (int i = 0; i < 12; i++)
{
Vector2 insideUnitCircle = Random.insideUnitCircle;
Vector2 val = ((Vector2)(ref insideUnitCircle)).normalized * Random.Range(1f, 1.75f);
Vector3 val2 = center + new Vector3(val.x, 1f, val.y);
if (!Physics.Linecast(center, val2, LayerMask.op_Implicit(allPhysicalExceptCharacter), (QueryTriggerInteraction)1) && !Physics.CheckSphere(val2, 0.5f, LayerMask.op_Implicit(allPhysicalExceptCharacter), (QueryTriggerInteraction)1) && Physics.Raycast(val2, Vector3.down, 4f, LayerMask.op_Implicit(allPhysicalExceptCharacter), (QueryTriggerInteraction)1))
{
return val2;
}
}
return center + Vector3.up * 2f;
}
private void FallbackWhenNobodyAlive(Character self, bool campWouldRevive)
{
if (campWouldRevive && !VoidBiome.VoidBiomeActive)
{
Log.LogInfo((object)"Nobody alive; reviving at the campfire like vanilla.");
((MonoBehaviour)this).StartCoroutine(ReviveAtBaseCampRoutine(self));
}
else
{
Log.LogInfo((object)"Nobody alive; staying dead until the next statue (vanilla behavior).");
}
}
private static IEnumerator ReviveAtBaseCampRoutine(Character self)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: 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_0029: Unknown result type (might be due to invalid IL or missing references)
Vector3 position = MapStartPosition();
RespawnChest val = MapHandler.PreviousScoutStatue ?? MapHandler.BaseCampScoutStatue;
int statueSegment = ((!((Object)(object)val != (Object)null)) ? (-1) : ((int)val.SegmentNumber));
return ReviveAt(self, position, applyStatus: true, statueSegment, wakeUp: true);
}
private static string Describe(Character c)
{
if ((Object)(object)c == (Object)null)
{
return "nobody";
}
PhotonView photonView = ((MonoBehaviourPun)c).photonView;
object obj;
if (photonView == null)
{
obj = null;
}
else
{
Player owner = photonView.Owner;
obj = ((owner != null) ? owner.NickName : null);
}
if (obj == null)
{
obj = ((Object)c).name;
}
string text = (string)obj;
PhotonView photonView2 = ((MonoBehaviourPun)c).photonView;
if (photonView2 != null)
{
Player owner2 = photonView2.Owner;
if (((owner2 != null) ? new bool?(owner2.IsMasterClient) : ((bool?)null)) == true)
{
return text + " (host)";
}
}
return text;
}
}
public enum SpawnTarget
{
Host,
Highest,
Lowest,
MapStart
}
}