public static bool Prefix(ref Vector3 position, EscapePod __instance) { __instance.transform.position = position; __instance.anchorPosition = position; __instance.RespawnPlayer(); return(false); //this means don't run original method }
public void RescueSurvivors(EscapePod e) { shipClass.survivors += e.Survivors; shipClass.Characters.AddRange(e.SurvivorCharacters); Debug.Log("Rescuing from " + e.name); Destroy(e.gameObject); }
public static void Postfix(EscapePod __instance) { if (Config.BASIC_GAME.Equals(DeathRun.config.startLocation)) { return; } if (!DeathRun.saveData.podSave.podGravity || (DeathRun.saveData.podSave.podAnchored && !isRighting())) { __instance.rigidbodyComponent.isKinematic = true; // Make sure pod stays in place (turns off physics effects) } else if (DeathRun.playerIsDead) { __instance.rigidbodyComponent.isKinematic = true; // Make sure pod stays in place (turns off physics effects) wasDead = true; } else { if (wasDead && !DeathRun.playerIsDead) { wasDead = false; if (!DeathRun.saveData.podSave.podAnchored && DeathRun.saveData.podSave.podGravity) { __instance.rigidbodyComponent.isKinematic = false; } } if (frozen) { DeathRun.saveData.podSave.podTransform.copyTo(__instance.transform); // Teleport pod back to where it was at beginning of frame (temporary "frozen" behavior) } } }
public static void Prefix(ref Player __instance, EscapePod value) { NitroxId podId = null; if (value != null) { podId = NitroxEntity.GetId(value.gameObject); } NitroxServiceLocator.LocateService <LocalPlayer>().BroadcastEscapePodChange(Optional.OfNullable(podId)); }
/// <summary> /// Update is being called every frame, this is where our logic is /// </summary> private void Update() { //If we are not connected to the client, then try to reconnect every 5 seconds if (!_connection.Connected && UnityEngine.Time.time > nextReconnect) { _connection.Connect(); nextReconnect = UnityEngine.Time.time + 5f; } try { //If the gameobject is being destroyed, or the run has ended: Stop executing if (_destroying || _runEnded) { return; } //Get the game time from the day and night cycle DayNightCycle cycle = DayNightCycle.main; if (cycle != null) { //Count the timer up by using unity's Deltatime property if (cycle.dayNightSpeed > 0.2f) { Time += UnityEngine.Time.deltaTime; } //Send the ingame time to LiveSplit Server _connection.SendGametime(Time); } //Check if the rocket launch has begun, if so; end the run if (LaunchRocket.isLaunching && !_runEnded) { _runEnded = true; _connection.Split(); return; } //Check when the pod intro cinematic has STARTED and is not currently ACTIVE, that means we have wen't past it EscapePod pod = EscapePod.main; if (pod != null && pod.startedIntroCinematic && !pod.introCinematic.cinematicModeActive && !_runStarted) { _runStarted = true; //Reset the current game time Time = 0; _connection.StartRun(); } } catch (Exception e) { Debug.LogError($"[SubnauticaSplitter] ERROR: {e}"); } }
public static bool Prefix(ref Vector3 position, EscapePod __instance) { if (Config.BASIC_GAME.Equals(DeathRun.config.startLocation)) { return(true); } __instance.transform.position = position; __instance.anchorPosition = position; __instance.RespawnPlayer(); return(false); }
public static bool Prefix(EscapePod __instance, ref Vector3 __result) { DeathRun.playerIsDead = false; if (Config.BASIC_GAME.Equals(DeathRun.config.startLocation)) { DeathRun.saveData.podSave.podGravity = false; DeathRun.saveData.podSave.podSinking = false; DeathRun.saveData.podSave.podAnchored = false; DeathRun.saveData.podSave.spotPicked = true; DeathRun.saveData.startSave = new StartSpot(0, 0, "Safe Shallows"); DeathRunUtils.CenterMessage("DEATH RUN", 10, 2); DeathRunUtils.CenterMessage("Start: \"" + DeathRun.saveData.startSave.message + "\"", 10, 3); CattleLogger.Message("Start: " + DeathRun.saveData.startSave.message); return(true); } int picker = UnityEngine.Random.Range(0, spots.Count); StartSpot spot = spots[picker]; // If a specific spot was specified in the config, use that instead. foreach (StartSpot s in spots) { if (s.message.Equals(DeathRun.config.startLocation)) { spot = s; break; } } DeathRun.saveData.podSave.podGravity = true; // Pod should sink DeathRun.saveData.podSave.podSinking = false; // ... but isn't sinking yet DeathRun.saveData.podSave.podAnchored = false; // ... and hasn't come to rest on the bottom DeathRun.saveData.podSave.spotPicked = true; // But we have picked the spot for it DeathRun.saveData.startSave = spot; // Here's where we started //ErrorMessage.AddMessage("\"" + spot.message + "\""); DeathRunUtils.CenterMessage("DEATH RUN", 10, 2); DeathRunUtils.CenterMessage("Start: \"" + spot.message + "\"", 10, 3); CattleLogger.Message("Start: " + spot.message); __result.x = spot.x; __result.y = spot.y; __result.z = spot.z; return(false); }
private bool IsSwimming(Vector3 playerPosition, Optional <NitroxId> subId) { if (subId.HasValue) { Optional <GameObject> sub = NitroxEntity.GetObjectFrom(subId.Value); SubRoot subroot = null; sub.Value.TryGetComponent <SubRoot>(out subroot); // Set the animation for the remote player to standing instead of swimming if player is not in a flooded subroot // or in a waterpark if (subroot) { if (subroot.IsUnderwater(playerPosition)) { return(true); } if (subroot.isCyclops) { return(false); } // We know that we are in a subroot. But we can also be in a waterpark in a subroot, where we would swim BaseRoot baseRoot = subroot.GetComponentInParent <BaseRoot>(); if (baseRoot) { WaterPark[] waterParks = baseRoot.GetComponentsInChildren <WaterPark>(); foreach (WaterPark waterPark in waterParks) { if (waterPark.IsPointInside(playerPosition)) { return(true); } } return(false); } } Log.Debug($"Trying to find escape pod for {subId}."); EscapePod escapePod = null; sub.Value.TryGetComponent <EscapePod>(out escapePod); if (escapePod) { Log.Debug("Found escape pod for player. Will add him and update animation."); return(false); } } // Player can be above ocean level. float oceanLevel = Ocean.main.GetOceanLevel(); return(playerPosition.y < oceanLevel); }
public override IEnumerator Process(InitialPlayerSync packet, WaitScreen.ManualWaitItem waitScreenItem) { int remotePlayersSynced = 0; foreach (InitialRemotePlayerData playerData in packet.RemotePlayerData) { waitScreenItem.SetProgress(remotePlayersSynced, packet.RemotePlayerData.Count); List <TechType> equippedTechTypes = playerData.EquippedTechTypes.Select(techType => techType.ToUnity()).ToList(); RemotePlayer player = remotePlayerManager.Create(playerData.PlayerContext, equippedTechTypes); if (playerData.SubRootId.HasValue) { Optional <GameObject> sub = NitroxEntity.GetObjectFrom(playerData.SubRootId.Value); if (sub.HasValue) { Log.Debug($"sub value set to {sub.Value}. Try to find subroot"); SubRoot subroot = null; sub.Value.TryGetComponent <SubRoot>(out subroot); if (subroot != null) { Log.Debug("Found subroot for player. Will add him and update animation."); player.SetSubRoot(subroot); // Set the animation for the remote player to standing instead of swimming if player is not in a flooded subroot if (!subroot.IsUnderwater(player.Body.transform.position)) { player.UpdateAnimation(AnimChangeType.UNDERWATER, AnimChangeState.OFF); } } Log.Debug("Trying to find escape pod."); EscapePod escapePod = null; sub.Value.TryGetComponent <EscapePod>(out escapePod); if (escapePod != null) { Log.Debug("Found escape pod for player. Will add him and update animation."); player.UpdateAnimation(AnimChangeType.UNDERWATER, AnimChangeState.OFF); } } else { Log.Error("Could not spawn remote player into subroot/escape pod with id: " + playerData.SubRootId.Value); } } remotePlayersSynced++; yield return(null); } }
public void OnRepair(NitroxId id) { if (escapePodsById.ContainsKey(id)) { EscapePod pod = escapePodsById[id].GetComponent <EscapePod>(); pod.liveMixin.health = pod.liveMixin.maxHealth; pod.animator.SetFloat("lifepod_damage", 1.0f); pod.fixPanelGoal.Trigger(); pod.fixPanelPowerUp.Play(); } else { Log.Warn("No escape pod to be repaired by id " + id); } }
public void SetEscapePod(EscapePod newEscapePod) { if (EscapePod != newEscapePod) { if (newEscapePod) { Attach(newEscapePod.transform, true); } else { Detach(); } EscapePod = newEscapePod; } }
public override void Process(EscapePodChanged packet) { Optional <RemotePlayer> remotePlayer = remotePlayerManager.Find(packet.PlayerId); if (remotePlayer.HasValue) { EscapePod escapePod = null; if (packet.EscapePodId.HasValue) { GameObject sub = NitroxEntity.RequireObjectFrom(packet.EscapePodId.Value); escapePod = sub.GetComponent <EscapePod>(); } remotePlayer.Value.SetEscapePod(escapePod); } }
public static void Prefix(ref Player __instance, EscapePod value) { NitroxId podId = null; if (value != null) { podId = NitroxEntity.GetId(value.gameObject); } // Why only send when podId is empty? // At the moment, SubrootId saves if a player is in an escape pod // Every time you leave an escape pod, BroadcastSubrootChange is called anyway, so this will reduce the load // and some bugs that can occur, due to both pod and base/cyclops use of the same field, will be suppressed if (podId != null) { NitroxServiceLocator.LocateService <LocalPlayer>().BroadcastEscapePodChange(Optional.OfNullable(podId)); } }
private static bool IsValidTarget(LiveMixin liveMixin) { if (!liveMixin) { return(true); } if (liveMixin.weldable) { return(false); } if (!liveMixin.knifeable) { return(false); } EscapePod component = liveMixin.GetComponent <EscapePod>(); return(!component); }
public void OnRepairedByMe(EscapePod pod) { string guid = ""; foreach (KeyValuePair <string, GameObject> dict in escapePodsByGuid) { if (dict.Value.GetGuid() == pod.gameObject.GetGuid()) { guid = dict.Key; // we're looking for serverside guid here break; } } if (!guid.Equals("")) { EscapePodRepair repair = new EscapePodRepair(guid); packetSender.Send(repair); } else { Log.Warn("Couldn't find escape pod guid on repair"); } }
public void OnRepairedByMe(EscapePod pod) { NitroxId id = null; foreach (KeyValuePair <NitroxId, GameObject> dict in escapePodsById) { if (NitroxEntity.GetId(dict.Value) == NitroxEntity.GetId(pod.gameObject)) { id = dict.Key; // we're looking for serverside id here break; } } if (id != null) { EscapePodRepair repair = new EscapePodRepair(id); packetSender.Send(repair); } else { Log.Warn("Couldn't find escape pod id on repair"); } }
public static bool Prefix(EscapePod __instance) { return(!EscapePodManager.SURPRESS_ESCAPE_POD_AWAKE_METHOD); }
public static bool Prefix(EscapePod __instance) { NitroxServiceLocator.LocateService <EscapePodManager>().OnRepairedByMe(__instance); return(true); }
public static bool Prefix(EscapePod __instance) { return(!BroadcastEscapePodsProcessor.SURPRESS_ESCAPE_POD_AWAKE_METHOD); }
static void EscapePod_Awake_Prefix(EscapePod __instance) => __instance.bottomHatchUsed = __instance.topHatchUsed = true;
public static bool Prefix(EscapePod __instance) { if (Config.BASIC_GAME.Equals(DeathRun.config.startLocation)) { return(true); } WorldForces wf = __instance.GetComponent <WorldForces>(); float depth = Ocean.main.GetDepthOf(__instance.gameObject); // Copy our current transform if (!DeathRun.saveData.podSave.podAnchored || isRighting()) { DeathRun.saveData.podSave.podTransform.copyFrom(__instance.transform); } // This block makes sure the pod doesn't sink *during* the opening cinematic etc. if (!DeathRun.saveData.podSave.podSinking) { frozen = false; // This checks if we're holding on the "press any key to continue" screen or intro cinematic if (DeathRunUtils.isIntroStillGoing()) { return(true); } // Otherwise, "turn on gravity" for the pod if (DeathRun.saveData.podSave.podGravity) { DeathRun.saveData.podSave.podSinking = true; wf.underwaterGravity = 9.81f; if (depth <= 0) { wf.aboveWaterGravity = 50f; } else { wf.aboveWaterGravity = 9.81f; } } } // Once we're below the surface, return gravity to normal if (wf.aboveWaterGravity == 50f && depth > 0) { wf.aboveWaterGravity = 9.81f; } // Give player some early feedback the lifepod is sinking if (DeathRun.saveData.podSave.podGravity && (depth > 6) && (DeathRun.saveData.podSave.lastDepth < 6)) { ErrorMessage.AddMessage("The Life Pod is sinking!"); DeathRunUtils.CenterMessage("The Life Pod is sinking!", 6); } int secs = (int)DayNightCycle.main.timePassedAsFloat; if (secs != DeathRun.saveData.podSave.prevSecs) { // Note if we've recently been frozen in place by cut scene or player distance if (frozen || __instance.rigidbodyComponent.isKinematic) { frozenSecs = secs; } // Check when pod hits bottom so we can stop processing it. if (!DeathRun.saveData.podSave.podRepaired && (DeathRun.saveData.podSave.prevSecs > 0) && (secs - frozenSecs > 2) && (depth > 20)) { float dist = Vector3.Distance(DeathRun.saveData.podSave.podPrev.position, DeathRun.saveData.podSave.podTransform.position); if (!DeathRun.saveData.podSave.podAnchored && (dist < 0.5)) { ErrorMessage.AddMessage("The Escape Pod has struck bottom!"); DeathRunUtils.CenterMessage("The Escape Pod has struck bottom!", 6); DeathRun.saveData.podSave.podAnchored = true; float random = UnityEngine.Random.value; float angle; float up = 2; if (random < .10f) { angle = 30; } else if (random < .20f) { angle = 45; } else if (random < .30f) { angle = 60; } else if (random < .40f) { angle = 120; } else if (random < .50f) { angle = 135; up = 3; } else if (random < .60f) { angle = 150; up = 4; } else if (random < .70f) { angle = 170; up = 4; } else if (random < .80f) { angle = 300; } else if (random < .90f) { angle = 315; } else { angle = 330; } __instance.transform.Translate(0, up, 0); if (Player.main.IsInside()) { Player.main.transform.Translate(0, 2, 0); } // Make a copy of our "upright state" DeathRun.saveData.podSave.podStraight.copyFrom(__instance.transform); // Now tip the pod over and copy that __instance.transform.Rotate(Vector3.forward, angle); // Jolt at bottom! DeathRun.saveData.podSave.podTipped.copyFrom(__instance.transform); // If we're supposed to (based on preferences) stay straight up, copy THAT back if (DeathRun.config.podStayUpright) { DeathRun.saveData.podSave.podStraight.copyTo(__instance.transform); } // Finally, store the stable transform we're supposed to use. DeathRun.saveData.podSave.podTransform.copyFrom(__instance.transform); } } DeathRun.saveData.podSave.prevSecs = secs; DeathRun.saveData.podSave.podPrev.copyFrom(DeathRun.saveData.podSave.podTransform); } // If player is away from the pod, stop gravity so that it doesn't fall through the world when the geometry unloads frozen = (Vector3.Distance(__instance.transform.position, Player.main.transform.position) > 20) || (DeathRun.saveData.podSave.podAnchored && !isRighting()); if (frozen) { wf.underwaterGravity = 0.0f; } else { wf.underwaterGravity = 9.81f; } // Once pod is repaired, we give it a little time to right itself and then restore kinematic mode "for safety" if (isRighting()) { if ((DeathRun.saveData.podSave.podRightingTime > 0) && (DayNightCycle.main.timePassedAsFloat > DeathRun.saveData.podSave.podRightingTime + 15)) { DeathRun.saveData.podSave.podRighted = true; __instance.rigidbodyComponent.isKinematic = true; } } DeathRun.saveData.podSave.lastDepth = depth; return(true); }
public static void Postfix(Player __instance) { PlayerTool heldTool = Inventory.main.GetHeldTool(); Vehicle vehicle = __instance.GetVehicle(); Pickupable module = vehicle?.GetSlotItem(vehicle.GetActiveSlotID())?.item; bool builderCheck = heldTool?.pickupable?.GetTechType() == TechType.Builder; bool builderModuleCheck = module != null && TechTypeHandler.TryGetModdedTechType("BuilderModule", out TechType modTechType) && module.GetTechType() == modTechType; string msg1 = $"Attach as target override = {Main.config.AttachToTarget}"; ErrorMessage._Message emsg = ErrorMessage.main.GetExistingMessage(msg1); string msg2 = $"Full Override = {Main.config.FullOverride}"; ErrorMessage._Message emsg2 = ErrorMessage.main.GetExistingMessage(msg2); if (DevConsole.instance != null && !DevConsole.instance.state && (builderCheck || builderModuleCheck)) { if (Input.GetKeyDown(Main.config.AttachToTargetToggle)) { Main.config.AttachToTarget = !Main.config.AttachToTarget; msg1 = $"Attach as target override = {Main.config.AttachToTarget}"; } if (Input.GetKeyDown(Main.config.FullOverrideToggle)) { Main.config.FullOverride = !Main.config.FullOverride; msg2 = $"Full Override = {Main.config.FullOverride}"; } if (emsg != null) { emsg.messageText = msg1; emsg.entry.text = msg1; if (emsg.timeEnd <= Time.time + 1f) { emsg.timeEnd += Time.deltaTime; } } else { ErrorMessage.AddMessage(msg1); } if (emsg2 != null) { emsg2.messageText = msg2; emsg2.entry.text = msg2; if (emsg2.timeEnd <= Time.time + 1f) { emsg2.timeEnd += Time.deltaTime; } } else { ErrorMessage.AddMessage(msg2); } } else if (Main.config.AttachToTarget || Main.config.FullOverride) { Main.config.AttachToTarget = false; Main.config.FullOverride = false; if (emsg != null) { emsg.timeEnd = Time.time; } if (emsg2 != null) { emsg2.timeEnd = Time.time; } } WaterPark waterPark = __instance?.currentWaterPark; if (waterPark?.GetComponentInParent <Creature>() != null) { Vector3 vector3 = __instance.currentWaterPark.transform.position; __instance.SetPosition(vector3); string msg3 = $"Press {GameInput.GetBinding(GameInput.GetPrimaryDevice(), GameInput.Button.Exit, GameInput.BindingSet.Primary)} to exit waterpark if you cant reach the exit."; ErrorMessage._Message emsg3 = ErrorMessage.main.GetExistingMessage(msg3); if (emsg3 != null && emsg3.timeEnd <= Time.time + 1f) { emsg3.timeEnd += Time.deltaTime; } else if (emsg3 is null) { ErrorMessage.AddMessage(msg3); } if (GameInput.GetButtonDown(GameInput.Button.Exit)) { UseableDiveHatch diveHatch = null; Collider[] hitColliders = Physics.OverlapSphere(__instance.transform.position, 3f, 1, QueryTriggerInteraction.UseGlobal); foreach (Collider hitCollider in hitColliders) { UseableDiveHatch hatch = hitCollider.gameObject.GetComponentInParent <UseableDiveHatch>(); if (hatch != null && hatch.isForWaterPark) { diveHatch = hatch; break; } } if (diveHatch != null) { diveHatch.StartCinematicMode(diveHatch.enterCinematicController, __instance); if (diveHatch.enterCustomGoalText != "" && (!diveHatch.customGoalWithLootOnly || Inventory.main.GetTotalItemCount() > 0)) { Debug.Log("OnCustomGoalEvent(" + diveHatch.enterCustomText); GoalManager.main.OnCustomGoalEvent(diveHatch.enterCustomGoalText); } if (diveHatch.secureInventory) { Inventory.Get().SecureItems(true); } } } return; } #if SN1 SubRoot currentSubRoot = __instance.GetCurrentSub(); if (currentSubRoot != null && currentSubRoot is BaseRoot && __instance.playerController.velocity.y < -20f) { RespawnPoint componentInChildren = currentSubRoot.gameObject.GetComponentInChildren <RespawnPoint>(); if (componentInChildren) { __instance.SetPosition(componentInChildren.GetSpawnPosition()); return; } } EscapePod escapePod = __instance.currentEscapePod; if (escapePod != null && __instance.playerController.velocity.y < -20f) { __instance.SetPosition(escapePod.playerSpawn.transform.position, escapePod.playerSpawn.transform.rotation); return; } #elif BZ IInteriorSpace interiorSpace = __instance.currentInterior; if (interiorSpace != null && __instance.playerController.velocity.y < -20f) { RespawnPoint respawnPoint = interiorSpace.GetRespawnPoint(); if (respawnPoint) { __instance.SetPosition(respawnPoint.GetSpawnPosition()); return; } } #endif }
public static bool Prefix(EscapePod __instance, ref Vector3 __result) { string line; var path = @"./QMods/MyEscapePodReposition/config.txt"; System.IO.StreamReader file = new StreamReader(path); line = file.ReadLine(); line = line.Substring(10); Console.WriteLine("Spawn selected: " + line); switch (line) { case "Custom": string customSelection = file.ReadLine(); string[] coords = customSelection.Split(','); __result = new Vector3((float)Convert.ToDouble( coords[0]), (float)Convert.ToDouble(coords[1]), (float)Convert.ToDouble((coords[2]))); break; case "Random": bool isBad = false; Console.WriteLine("Adjusting spawn location due to Aurora vicinity"); do { __result = new Vector3(UnityEngine.Random.Range(-1250f, 1250f), UnityEngine.Random.Range(-1250f, 1250f)); if (__result.x > 543 && __result.x < 1724 && __result.z > -574 && __result.z < 400) { Console.WriteLine("Adjusting spawn again, still too close!"); isBad = true; } else { isBad = false; } } while (isBad); Console.WriteLine("Good random spawn found at " + __result); break; case "Landfall": //randomly on one of the two islands int randInt = UnityEngine.Random.Range(0, 2); if (randInt == 0) { __result = new Vector3(UnityEngine.Random.Range(228f, 401f), 200f, UnityEngine.Random.Range(770f, 1130f)); } else { __result = new Vector3(UnityEngine.Random.Range(-905f, -637f), 200f, UnityEngine.Random.Range(-1157f, -922f)); } break; case "Oasis": //the nice little puddle in the center of the floating island __result = new Vector3(-711, 200, -1075); break; case "Safe Shallows": //use default spawn rules return(true); case "Mountain Island": __result = new Vector3(UnityEngine.Random.Range(228f, 401f), 200f, UnityEngine.Random.Range(770f, 1130f)); break; case "Floating Island": __result = new Vector3(UnityEngine.Random.Range(-905f, -637f), 200f, UnityEngine.Random.Range(-1157f, -922f)); break; case "Dunes": __result = new Vector3(UnityEngine.Random.Range(-1689f, -1248f), 100f, UnityEngine.Random.Range(-10f, 1009f)); break; default: /* Optional */ Console.WriteLine("Defaulting to random"); __result = new Vector3(UnityEngine.Random.Range(-1250f, 1250f), 200f, UnityEngine.Random.Range(-1250f, 1250f)); break; } Console.WriteLine("Spawn Coordinates:"); Console.WriteLine(__result); return(false); }
public static void Postfix(Player __instance) { PlayerTool heldTool = Inventory.main.GetHeldTool(); bool builderCheck = heldTool != null && heldTool.pickupable.GetTechType() == TechType.Builder; string msg2 = $"Full Override = {Main.FullOverride}"; ErrorMessage._Message emsg2 = ErrorMessage.main.GetExistingMessage(msg2); if (DevConsole.instance != null && !DevConsole.instance.state && (builderCheck)) { if (Input.GetKeyDown(KeyCode.G)) { Main.FullOverride = !Main.FullOverride; msg2 = $"Full Override = {Main.FullOverride}"; } if (emsg2 != null) { emsg2.messageText = msg2; emsg2.entry.text = msg2; if (emsg2.timeEnd <= Time.time + 1f) { emsg2.timeEnd += Time.deltaTime; } } else { ErrorMessage.AddMessage(msg2); } } else if (Main.FullOverride) { Main.FullOverride = false; if (emsg2 != null) { emsg2.timeEnd = Time.time; } } SubRoot currentSubRoot = __instance.GetCurrentSub(); if (currentSubRoot != null && currentSubRoot is BaseRoot && __instance.playerController.velocity.y < -20f) { RespawnPoint componentInChildren = currentSubRoot.gameObject.GetComponentInChildren <RespawnPoint>(); if (componentInChildren) { __instance.SetPosition(componentInChildren.GetSpawnPosition()); return; } } EscapePod escapePod = __instance.currentEscapePod; if (escapePod != null && __instance.playerController.velocity.y < -20f) { __instance.SetPosition(escapePod.playerSpawn.transform.position, escapePod.playerSpawn.transform.rotation); return; } }