Merge pull request #595 from misternebula/dev

0.25.0
This commit is contained in:
_nebula 2023-02-08 12:27:23 +00:00 committed by GitHub
commit 33bd827b04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 1070 additions and 739 deletions

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<GameDir>C:\Program Files\Epic Games\OuterWilds</GameDir>
<OwmlDir>$(AppData)\OuterWildsModManager\OWML</OwmlDir>
<UnityAssetsDir>$(SolutionDir)\qsb-unityproject\Assets</UnityAssetsDir>
</PropertyGroup>

View File

@ -60,7 +60,6 @@ internal class GhostPartyPathDirectorPatches : QSBPatch
var ghostBrain = __instance._dispatchedGhosts[i].GetWorldObject<QSBGhostBrain>();
if (ghostBrain.GetCurrentActionName() == GhostAction.Name.PartyPath)
{
// BUG: breaks on client cuz cast
var partyPathAction = (QSBPartyPathAction)ghostBrain.GetCurrentAction();
if (partyPathAction.hasReachedEndOfPath)
{
@ -105,7 +104,6 @@ internal class GhostPartyPathDirectorPatches : QSBPatch
var num = Random.Range(0, __instance._ghostSpawns.Length);
ghostBrain2.AttachedObject.transform.position = __instance._ghostSpawns[num].spawnTransform.position;
ghostBrain2.AttachedObject.transform.eulerAngles = Vector3.up * __instance._ghostSpawns[num].spawnTransform.eulerAngles.y;
// BUG: breaks on client cuz cast
((QSBPartyPathAction)ghostBrain2.GetCurrentAction()).StartFollowPath();
__instance._ghostSpawns[num].spawnDoor.Open();
__instance._ghostSpawns[num].spawnDoorTimer = Time.timeSinceLevelLoad + 4f;

View File

@ -200,7 +200,6 @@ internal class GhostZone2DirectorPatches : QSBPatch
DebugLog.DebugWrite($"- fade light down");
QSBGhostZone2Director.ElevatorsStatus[j].elevatorPair.elevator.topLight.FadeTo(0f, 0.2f);
DebugLog.DebugWrite($"- get action");
// BUG: breaks on client cuz cast
QSBGhostZone2Director.ElevatorsStatus[j].elevatorAction = (QSBElevatorWalkAction)__instance._elevators[j].ghost.GetWorldObject<QSBGhostBrain>().GetAction(GhostAction.Name.ElevatorWalk);
DebugLog.DebugWrite($"- CallToUseElevator on action");
QSBGhostZone2Director.ElevatorsStatus[j].elevatorAction.CallToUseElevator();

View File

@ -102,6 +102,11 @@ public class RaftTransformSync : UnsectoredRigidbodySync, ILinkedNetworkBehaviou
playerBody.SetPosition(AttachedTransform.FromRelPos(relPos));
playerBody.SetRotation(AttachedTransform.FromRelRot(relRot));
if (!Physics.autoSyncTransforms)
{
Physics.SyncTransforms();
}
}
}
else

View File

@ -37,4 +37,8 @@ public static class OWEvents
public const string StartShipIgnition = nameof(StartShipIgnition);
public const string CompleteShipIgnition = nameof(CompleteShipIgnition);
public const string CancelShipIgnition = nameof(CancelShipIgnition);
public const string ProbeEnterQuantumMoon = nameof(ProbeEnterQuantumMoon);
public const string ProbeExitQuantumMoon = nameof(ProbeExitQuantumMoon);
public const string EnterCloak = nameof(EnterCloak);
public const string ExitCloak = nameof(ExitCloak);
}

View File

@ -8,4 +8,6 @@ public enum EnterLeaveType
ExitPlatform,
EnterShip,
ExitShip,
EnterCloak,
ExitCloak
}

View File

@ -20,6 +20,8 @@ internal class EnterLeaveMessage : QSBMessage<EnterLeaveType>
GlobalMessenger.AddListener(OWEvents.PlayerExitQuantumMoon, () => Handler(EnterLeaveType.ExitMoon));
GlobalMessenger.AddListener(OWEvents.EnterShip, () => Handler(EnterLeaveType.EnterShip));
GlobalMessenger.AddListener(OWEvents.ExitShip, () => Handler(EnterLeaveType.ExitShip));
GlobalMessenger.AddListener(OWEvents.EnterCloak, () => Handler(EnterLeaveType.EnterCloak));
GlobalMessenger.AddListener(OWEvents.ExitCloak, () => Handler(EnterLeaveType.ExitCloak));
}
private static void Handler(EnterLeaveType type, int objectId = -1)
@ -62,6 +64,12 @@ internal class EnterLeaveMessage : QSBMessage<EnterLeaveType>
case EnterLeaveType.ExitMoon:
player.IsInMoon = false;
break;
case EnterLeaveType.EnterCloak:
player.IsInCloak = true;
break;
case EnterLeaveType.ExitCloak:
player.IsInCloak = false;
break;
case EnterLeaveType.EnterPlatform:
CustomNomaiRemoteCameraPlatform.CustomPlatformList[ObjectId]
.OnRemotePlayerEnter(From);

View File

@ -17,6 +17,8 @@ public class PlayerInformationMessage : QSBMessage
private bool TranslatorEquipped;
private bool ProbeActive;
private ClientState ClientState;
private float FieldOfView;
private bool IsInShip;
public PlayerInformationMessage()
{
@ -30,6 +32,8 @@ public class PlayerInformationMessage : QSBMessage
TranslatorEquipped = player.TranslatorEquipped;
ProbeActive = player.ProbeActive;
ClientState = player.State;
FieldOfView = PlayerData.GetGraphicSettings().fieldOfView;
IsInShip = player.IsInShip;
}
public override void Serialize(NetworkWriter writer)
@ -44,6 +48,8 @@ public class PlayerInformationMessage : QSBMessage
writer.Write(TranslatorEquipped);
writer.Write(ProbeActive);
writer.Write(ClientState);
writer.Write(FieldOfView);
writer.Write(IsInShip);
}
public override void Deserialize(NetworkReader reader)
@ -58,6 +64,8 @@ public class PlayerInformationMessage : QSBMessage
TranslatorEquipped = reader.Read<bool>();
ProbeActive = reader.Read<bool>();
ClientState = reader.Read<ClientState>();
FieldOfView = reader.ReadFloat();
IsInShip = reader.ReadBool();
}
public override void OnReceiveRemote()
@ -74,11 +82,16 @@ public class PlayerInformationMessage : QSBMessage
player.SignalscopeEquipped = SignalscopeEquipped;
player.TranslatorEquipped = TranslatorEquipped;
player.ProbeActive = ProbeActive;
player.IsInShip = IsInShip;
if (QSBPlayerManager.LocalPlayer.IsReady && player.IsReady)
{
player.UpdateObjectsFromStates();
}
Delay.RunWhen(
() => player.Camera != null,
() => player.Camera.fieldOfView = FieldOfView);
player.State = ClientState;
}
else

View File

@ -0,0 +1,20 @@
using QSB.Messaging;
using QSB.Utility;
namespace QSB.Player.Messages;
internal class UpdateFOVMessage : QSBMessage<float>
{
static UpdateFOVMessage()
=> GlobalMessenger<GraphicSettings>.AddListener(
"GraphicSettingsUpdated",
(GraphicSettings settings) => new UpdateFOVMessage(settings.fieldOfView).Send());
private UpdateFOVMessage(float fov) : base(fov) { }
public override void OnReceiveRemote()
{
var player = QSBPlayerManager.GetPlayer(From);
player.Camera.fieldOfView = Data;
}
}

View File

@ -31,6 +31,8 @@ public partial class PlayerInfo
public bool IsInMoon { get; set; }
public bool IsInShrine { get; set; }
public bool IsInEyeShuttle { get; set; }
public bool IsInShip { get; set; }
public bool IsInCloak { get; set; }
public IQSBQuantumObject EntangledObject { get; set; }
public QSBPlayerAudioController AudioController { get; set; }
public bool IsLocalPlayer => TransformSync.isLocalPlayer; // if TransformSync is ever null, i give permission for nebula to make fun of me about it for the rest of time - johncorby

View File

@ -0,0 +1,15 @@
using HarmonyLib;
using QSB.Patches;
namespace QSB.QuantumSync.Patches.Client;
[HarmonyPatch(typeof(EyeProxyQuantumMoon))]
internal class ClientEyeProxyQuantumMoonPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnNonServerClientConnect;
[HarmonyPrefix]
[HarmonyPatch(nameof(EyeProxyQuantumMoon.ChangeQuantumState))]
public static bool ChangeQuantumState()
=> false;
}

View File

@ -0,0 +1,20 @@
using HarmonyLib;
using QSB.Patches;
namespace QSB.QuantumSync.Patches.Client;
[HarmonyPatch(typeof(QuantumMoon))]
internal class ClientQuantumMoonPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnNonServerClientConnect;
[HarmonyPostfix]
[HarmonyPatch(nameof(QuantumMoon.Start))]
public static void Start(QuantumMoon __instance)
=> __instance.SetSurfaceState(-1);
[HarmonyPrefix]
[HarmonyPatch(nameof(QuantumMoon.ChangeQuantumState))]
public static bool ChangeQuantumState()
=> false;
}

View File

@ -1,25 +0,0 @@
using HarmonyLib;
using QSB.Patches;
namespace QSB.QuantumSync.Patches;
[HarmonyPatch]
public class ClientQuantumPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnNonServerClientConnect;
[HarmonyPostfix]
[HarmonyPatch(typeof(QuantumMoon), nameof(QuantumMoon.Start))]
public static void QuantumMoon_Start(QuantumMoon __instance)
=> __instance.SetSurfaceState(-1);
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumMoon), nameof(QuantumMoon.ChangeQuantumState))]
public static bool QuantumMoon_ChangeQuantumState()
=> false;
[HarmonyPrefix]
[HarmonyPatch(typeof(EyeProxyQuantumMoon), nameof(EyeProxyQuantumMoon.ChangeQuantumState))]
public static bool EyeProxyQuantumMoon_ChangeQuantumState()
=> false;
}

View File

@ -0,0 +1,68 @@
using HarmonyLib;
using QSB.Patches;
using QSB.Player;
using QSB.QuantumSync.WorldObjects;
using QSB.WorldSync;
namespace QSB.QuantumSync.Patches.Common;
[HarmonyPatch(typeof(MultiStateQuantumObject))]
public class MultiStateQuantumObjectPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(nameof(MultiStateQuantumObject.Start))]
public static bool Start(MultiStateQuantumObject __instance)
{
if (!QSBWorldSync.AllObjectsReady)
{
return true;
}
var qsbObj = __instance.GetWorldObject<QSBMultiStateQuantumObject>();
if (qsbObj.ControllingPlayer == 0)
{
return true;
}
foreach (var state in qsbObj.QuantumStates)
{
if (!state.IsMeantToBeEnabled)
{
state.SetVisible(false);
}
}
if (__instance._sector == null)
{
__instance.CheckEnabled();
}
if (__instance._collapseOnStart)
{
__instance.Collapse(true);
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(nameof(MultiStateQuantumObject.ChangeQuantumState))]
public static bool ChangeQuantumState(MultiStateQuantumObject __instance)
{
if (!QSBWorldSync.AllObjectsReady)
{
return true;
}
var qsbObj = __instance.GetWorldObject<QSBMultiStateQuantumObject>();
if (qsbObj.ControllingPlayer == 0 && qsbObj.CurrentState == -1)
{
return true;
}
var isInControl = qsbObj.ControllingPlayer == QSBPlayerManager.LocalPlayerId;
return isInControl;
}
}

View File

@ -0,0 +1,120 @@
using HarmonyLib;
using QSB.Messaging;
using QSB.Patches;
using QSB.Player;
using QSB.ShipSync;
using QSB.Utility;
using System.Linq;
using UnityEngine;
namespace QSB.QuantumSync.Patches.Common;
[HarmonyPatch(typeof(QuantumMoon))]
internal class QuantumMoonPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(nameof(QuantumMoon.CheckPlayerFogProximity))]
public static bool CheckPlayerFogProximity(QuantumMoon __instance)
{
var playerDistance = Vector3.Distance(__instance.transform.position, Locator.GetPlayerCamera().transform.position);
var fogOffset = (__instance._stateIndex == 5) ? __instance._eyeStateFogOffset : 0f;
var distanceFromFog = playerDistance - (__instance._fogRadius + fogOffset);
var fogAlpha = 0f;
if (!__instance._isPlayerInside)
{
fogAlpha = Mathf.InverseLerp(__instance._fogThickness + __instance._fogRolloffDistance, __instance._fogThickness, distanceFromFog);
if (distanceFromFog < 0f) // inside fog
{
var playersWhoCanSeeMoon = QuantumManager.IsVisibleUsingCameraFrustum((ShapeVisibilityTracker)__instance._visibilityTracker, true).PlayersWhoCanSee;
var shipInFog = GetShipInFog(__instance);
var anyoneInMoon = QSBPlayerManager.PlayerList.Any(x => x.IsInMoon && !x.IsLocalPlayer);
// this probably breaks in really obscure cases, but it should be good enough...
if (playersWhoCanSeeMoon.Any(x => !(shipInFog && x.IsInShip) && !GetTransformInFog(__instance, x.CameraBody.transform)) || __instance.IsLockedByProbeSnapshot() || anyoneInMoon)
{
/* Either :
* - The moon is locked with a snapshot
* OR
* - Someone else is in the moon
* OR
* - If the ship is in the fog :
* - there are people outside the ship who can see the moon, and who are not in the fog
* - If the ship is not in the fog
* - There are people who can see the moon, who are not in the fog
*/
__instance._isPlayerInside = true;
__instance.SetSurfaceState(__instance._stateIndex);
Locator.GetShipLogManager().RevealFact(__instance._revealFactID);
GlobalMessenger.FireEvent(OWEvents.PlayerEnterQuantumMoon);
}
else
{
__instance.Collapse(true);
}
}
}
else if (__instance._isPlayerInside)
{
fogAlpha = Mathf.InverseLerp(-__instance._fogThickness - __instance._fogRolloffDistance, -__instance._fogThickness, distanceFromFog);
if (distanceFromFog >= 0f)
{
if (__instance._stateIndex != 5)
{
__instance._isPlayerInside = false;
if (!__instance.IsLockedByProbeSnapshot() && !QuantumManager.IsVisibleUsingCameraFrustum((ShapeVisibilityTracker)__instance._visibilityTracker, true).FoundPlayers)
{
__instance.Collapse(true);
}
__instance.SetSurfaceState(-1);
GlobalMessenger.FireEvent(OWEvents.PlayerExitQuantumMoon);
}
else
{
var vector = Locator.GetPlayerTransform().position - __instance.transform.position;
Locator.GetPlayerBody().SetVelocity(__instance._moonBody.GetPointVelocity(Locator.GetPlayerTransform().position) - (vector.normalized * 5f));
var d = 80f;
Locator.GetPlayerBody().SetPosition(__instance.transform.position + (__instance._vortexReturnPivot.up * d));
if (!Physics.autoSyncTransforms)
{
Physics.SyncTransforms();
}
var component = Locator.GetPlayerCamera().GetComponent<PlayerCameraController>();
component.SetDegreesY(component.GetMinDegreesY());
__instance._vortexAudio.SetLocalVolume(0f);
__instance._collapseToIndex = 1;
__instance.Collapse(true);
}
}
}
__instance._playerFogBubble.SetFogAlpha(fogAlpha);
__instance._shipLandingCamFogBubble.SetFogAlpha(fogAlpha);
return false;
}
public static bool GetShipInFog(QuantumMoon moon)
{
if (ShipManager.Instance.IsShipWrecked)
{
return false;
}
var distance = Vector3.Distance(moon.transform.position, Locator.GetShipTransform().position);
var fogOffset = (moon._stateIndex == 5) ? moon._eyeStateFogOffset : 0f;
var distanceFromFog = distance - (moon._fogRadius + fogOffset);
return distanceFromFog < 10f; // to account for ship size
}
public static bool GetTransformInFog(QuantumMoon moon, Transform transform)
{
var distance = Vector3.Distance(moon.transform.position, transform.position);
var fogOffset = (moon._stateIndex == 5) ? moon._eyeStateFogOffset : 0f;
var distanceFromFog = distance - (moon._fogRadius + fogOffset);
return distanceFromFog < 0f;
}
}

View File

@ -0,0 +1,56 @@
using HarmonyLib;
using QSB.Messaging;
using QSB.Patches;
using QSB.QuantumSync.Messages;
using QSB.QuantumSync.WorldObjects;
using QSB.WorldSync;
using System.Linq;
namespace QSB.QuantumSync.Patches.Common;
[HarmonyPatch(typeof(QuantumObject))]
public class QuantumObjectPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(nameof(QuantumObject.IsLockedByPlayerContact))]
public static bool IsLockedByPlayerContact(out bool __result, QuantumObject __instance)
{
var playersEntangled = QuantumManager.GetEntangledPlayers(__instance);
__result = playersEntangled.Count() != 0 && __instance.IsIlluminated();
return false;
}
[HarmonyPostfix]
[HarmonyPatch(nameof(QuantumObject.SetIsQuantum))]
public static void SetIsQuantum(QuantumObject __instance)
{
if (QSBWorldSync.AllObjectsReady)
{
__instance.GetWorldObject<IQSBQuantumObject>().SendMessage(new SetIsQuantumMessage(__instance.IsQuantum()));
}
}
[HarmonyPrefix]
[HarmonyPatch(nameof(QuantumObject.OnProbeSnapshot))]
public static bool OnProbeSnapshot()
{
return false;
}
[HarmonyPrefix]
[HarmonyPatch(nameof(QuantumObject.OnProbeSnapshotRemoved))]
public static bool OnProbeSnapshotRemoved()
{
return false;
}
[HarmonyPrefix]
[HarmonyPatch(nameof(QuantumObject.IsLockedByProbeSnapshot))]
public static bool IsLockedByProbeSnapshot(QuantumObject __instance, ref bool __result)
{
__result = __instance._visibleInProbeSnapshot;
return false;
}
}

View File

@ -0,0 +1,71 @@
using HarmonyLib;
using QSB.Patches;
using QSB.Player;
using QSB.QuantumSync.WorldObjects;
using QSB.WorldSync;
using System.Linq;
namespace QSB.QuantumSync.Patches.Common;
[HarmonyPatch(typeof(QuantumShrine))]
public class QuantumShrinePatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(nameof(QuantumShrine.IsPlayerInDarkness))]
public static bool IsPlayerInDarkness(QuantumShrine __instance, out bool __result)
{
foreach (var lamp in __instance._lamps)
{
if (lamp.intensity > 0f)
{
__result = false;
return false;
}
}
var playersInMoon = QSBPlayerManager.PlayerList.Where(x => x.IsInMoon).ToList();
if (playersInMoon.Any(player => !player.IsInShrine))
{
__result = false;
return false;
}
if (playersInMoon.Any(player => player.FlashLight != null && player.FlashLight.FlashlightOn))
{
__result = false;
return false;
}
if (playersInMoon.Count == 0)
{
__result = false;
return false;
}
if (QSBPlayerManager.LocalPlayer != null
&& QSBPlayerManager.LocalPlayer.IsInShrine
&& PlayerState.IsFlashlightOn())
{
__result = false;
return false;
}
// BUG : make this *really* check for all players - check other probes and other jetpacks!
__result = __instance._gate.GetOpenFraction() == 0f
&& !__instance._isProbeInside
&& Locator.GetThrusterLightTracker().GetLightRange() <= 0f;
return false;
}
[HarmonyPrefix]
[HarmonyPatch(nameof(QuantumShrine.ChangeQuantumState))]
public static bool ChangeQuantumState(QuantumShrine __instance)
{
var shrineWorldObject = __instance.GetWorldObject<QSBSocketedQuantumObject>();
var isInControl = shrineWorldObject.ControllingPlayer == QSBPlayerManager.LocalPlayerId;
return isInControl;
}
}

View File

@ -0,0 +1,57 @@
using HarmonyLib;
using QSB.Messaging;
using QSB.Patches;
using QSB.Player;
using QSB.QuantumSync.Messages;
using QSB.QuantumSync.WorldObjects;
using QSB.WorldSync;
using System.Linq;
using UnityEngine;
namespace QSB.QuantumSync.Patches.Common;
[HarmonyPatch(typeof(QuantumShuffleObject))]
internal class QuantumShuffleObjectPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(nameof(QuantumShuffleObject.ChangeQuantumState))]
public static bool ChangeQuantumState(
QuantumShuffleObject __instance,
ref bool __result)
{
QSBQuantumShuffleObject shuffleWorldObject = default;
if (QSBWorldSync.AllObjectsReady)
{
shuffleWorldObject = __instance.GetWorldObject<QSBQuantumShuffleObject>();
if (shuffleWorldObject.ControllingPlayer != QSBPlayerManager.LocalPlayerId)
{
return false;
}
}
__instance._indexList.Clear();
__instance._indexList = Enumerable.Range(0, __instance._localPositions.Length).ToList();
for (var i = 0; i < __instance._indexList.Count; ++i)
{
var random = Random.Range(i, __instance._indexList.Count);
var temp = __instance._indexList[i];
__instance._indexList[i] = __instance._indexList[random];
__instance._indexList[random] = temp;
}
for (var j = 0; j < __instance._shuffledObjects.Length; j++)
{
__instance._shuffledObjects[j].localPosition = __instance._localPositions[__instance._indexList[j]];
}
if (QSBWorldSync.AllObjectsReady)
{
shuffleWorldObject.SendMessage(new QuantumShuffleMessage(__instance._indexList.ToArray()));
__result = true;
}
return false;
}
}

View File

@ -0,0 +1,59 @@
using HarmonyLib;
using QSB.Messaging;
using QSB.Patches;
using QSB.Player;
using QSB.QuantumSync.Messages;
using QSB.QuantumSync.WorldObjects;
using QSB.WorldSync;
namespace QSB.QuantumSync.Patches.Common;
[HarmonyPatch(typeof(QuantumSkeletonTower))]
internal class QuantumSkeletonTowerPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(nameof(QuantumSkeletonTower.ChangeQuantumState))]
public static bool ChangeQuantumState(QuantumSkeletonTower __instance, ref bool __result)
{
if (!QSBWorldSync.AllObjectsReady)
{
return true;
}
var qsbQuantumSkeletonTower = __instance.GetWorldObject<QSBQuantumSkeletonTower>();
if (qsbQuantumSkeletonTower.ControllingPlayer != QSBPlayerManager.LocalPlayerId)
{
return false;
}
if (__instance._waitForPlayerToLookAtTower)
{
__result = false;
return false;
}
if (__instance._index < __instance._towerSkeletons.Length)
{
for (var i = 0; i < __instance._pointingSkeletons.Length; i++)
{
if (__instance._pointingSkeletons[i].gameObject.activeInHierarchy &&
(!__instance._pointingSkeletons[i].IsVisible() || !__instance._pointingSkeletons[i].IsIlluminated()))
{
__instance._pointingSkeletons[i].gameObject.SetActive(false);
__instance._towerSkeletons[__instance._index].SetActive(true);
__instance._index++;
__instance._waitForPlayerToLookAtTower = true;
qsbQuantumSkeletonTower.SendMessage(new MoveSkeletonMessage(i));
__result = true;
return false;
}
}
}
__result = false;
return false;
}
}

View File

@ -0,0 +1,14 @@
using HarmonyLib;
using QSB.Patches;
namespace QSB.QuantumSync.Patches.Common;
[HarmonyPatch(typeof(QuantumSocketCollapseTrigger))]
internal class QuantumSocketCollapseTriggerPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(nameof(QuantumSocketCollapseTrigger.OnTriggerEnter))]
public static bool OnTriggerEnter() => false;
}

View File

@ -0,0 +1,50 @@
using HarmonyLib;
using OWML.Common;
using QSB.Messaging;
using QSB.Patches;
using QSB.Player;
using QSB.QuantumSync.Messages;
using QSB.QuantumSync.WorldObjects;
using QSB.Utility;
using QSB.WorldSync;
using System.Linq;
namespace QSB.QuantumSync.Patches.Common;
[HarmonyPatch(typeof(QuantumState))]
public class QuantumStatePatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPostfix]
[HarmonyPatch(nameof(QuantumState.SetVisible))]
public static void SetVisible(QuantumState __instance, bool visible)
{
if (!QSBWorldSync.AllObjectsReady)
{
return;
}
if (!visible)
{
return;
}
var allMultiStates = QSBWorldSync.GetWorldObjects<QSBMultiStateQuantumObject>();
var stateObject = __instance.GetWorldObject<QSBQuantumState>();
var owner = allMultiStates.FirstOrDefault(x => x.QuantumStates.Contains(stateObject));
if (owner == default)
{
DebugLog.ToConsole($"Error - Could not find QSBMultiStateQuantumObject for state {__instance.name}", MessageType.Error);
return;
}
if (owner.ControllingPlayer != QSBPlayerManager.LocalPlayerId)
{
return;
}
var stateIndex = owner.QuantumStates.IndexOf(stateObject);
owner.SendMessage(new MultiStateChangeMessage(stateIndex));
}
}

View File

@ -0,0 +1,162 @@
using HarmonyLib;
using OWML.Common;
using QSB.Messaging;
using QSB.Patches;
using QSB.Player;
using QSB.QuantumSync.Messages;
using QSB.QuantumSync.WorldObjects;
using QSB.Utility;
using QSB.WorldSync;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace QSB.QuantumSync.Patches.Common;
[HarmonyPatch(typeof(SocketedQuantumObject))]
public class SocketedQuantumObjectPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(nameof(SocketedQuantumObject.ChangeQuantumState))]
public static bool ChangeQuantumState(
SocketedQuantumObject __instance,
ref bool __result,
bool skipInstantVisibilityCheck)
{
if (QSBWorldSync.AllObjectsReady)
{
var socketedWorldObject = __instance.GetWorldObject<QSBSocketedQuantumObject>();
if (socketedWorldObject.ControllingPlayer != QSBPlayerManager.LocalPlayerId)
{
return false;
}
}
foreach (var socket in __instance._childSockets)
{
if (socket.IsOccupied())
{
__result = false;
return false;
}
}
if (__instance._socketList.Count <= 1)
{
DebugLog.ToConsole($"Error - Not enough quantum sockets in list for {__instance.name}!", MessageType.Error);
__result = false;
return false;
}
var list = new List<QuantumSocket>();
foreach (var socket in __instance._socketList)
{
if (!socket.IsOccupied() && socket.IsActive())
{
list.Add(socket);
}
}
if (list.Count == 0)
{
__result = false;
return false;
}
if (__instance._recentlyObscuredSocket != null)
{
__instance.MoveToSocket(__instance._recentlyObscuredSocket);
__instance._recentlyObscuredSocket = null;
__result = true;
return false;
}
var occupiedSocket = __instance._occupiedSocket;
for (var i = 0; i < 20; i++)
{
var index = Random.Range(0, list.Count);
__instance.MoveToSocket(list[index]);
if (skipInstantVisibilityCheck)
{
__result = true;
return false;
}
bool socketNotSuitable;
var isSocketIlluminated = __instance.CheckIllumination();
var playersEntangled = QuantumManager.GetEntangledPlayers(__instance);
if (playersEntangled.Count() != 0)
{
// socket not suitable if illuminated
socketNotSuitable = isSocketIlluminated;
}
else
{
var checkVisInstant = __instance.CheckVisibilityInstantly();
if (isSocketIlluminated)
{
// socket not suitable if object is visible
socketNotSuitable = checkVisInstant;
}
else
{
// socket not suitable if player is inside object
socketNotSuitable = playersEntangled.Any(x => __instance.CheckPointInside(x.CameraBody.transform.position));
}
}
if (!socketNotSuitable)
{
__result = true;
return false;
}
list.RemoveAt(index);
if (list.Count == 0)
{
break;
}
}
__instance.MoveToSocket(occupiedSocket);
__result = false;
return false;
}
[HarmonyPostfix]
[HarmonyPatch(nameof(SocketedQuantumObject.MoveToSocket))]
public static void MoveToSocket(SocketedQuantumObject __instance, QuantumSocket socket)
{
if (!QSBWorldSync.AllObjectsReady)
{
return;
}
if (socket == null)
{
DebugLog.ToConsole($"Error - Trying to move {__instance.name} to a null socket!", MessageType.Error);
return;
}
var objectWorldObject = __instance.GetWorldObject<QSBSocketedQuantumObject>();
var socketWorldObject = socket.GetWorldObject<QSBQuantumSocket>();
if (objectWorldObject == null)
{
DebugLog.ToConsole($"Worldobject is null for {__instance.name}!");
return;
}
if (objectWorldObject.ControllingPlayer != QSBPlayerManager.LocalPlayerId)
{
return;
}
objectWorldObject.SendMessage(new SocketStateChangeMessage(
socketWorldObject.ObjectId,
__instance.transform.localRotation));
}
}

View File

@ -0,0 +1,24 @@
using HarmonyLib;
using QSB.Patches;
using QSB.Player;
using System.Linq;
using UnityEngine;
namespace QSB.QuantumSync.Patches.Common.Visibility;
[HarmonyPatch(typeof(RendererVisibilityTracker))]
internal class VisibilityRendererVisibilityTrackerPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(typeof(RendererVisibilityTracker), nameof(RendererVisibilityTracker.IsVisibleUsingCameraFrustum))]
public static bool RendererVisibilityTracker_IsVisibleUsingCameraFrustum(RendererVisibilityTracker __instance, out bool __result)
{
__result = QSBPlayerManager.GetPlayersWithCameras()
.Any(x => GeometryUtility.TestPlanesAABB(x.Camera.GetFrustumPlanes(), __instance._renderer.bounds))
&& (!__instance._checkFrustumOcclusion || QSBPlayerManager.GetPlayersWithCameras()
.Any(x => !__instance.IsOccludedFromPosition(x.Camera.transform.position)));
return false;
}
}

View File

@ -0,0 +1,21 @@
using HarmonyLib;
using QSB.Patches;
using QSB.Utility;
namespace QSB.QuantumSync.Patches.Common.Visibility;
[HarmonyPatch(typeof(Shape))]
internal class VisibilityShapePatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPostfix]
[HarmonyPatch(nameof(Shape.OnEnable))]
public static void OnEnable(Shape __instance)
=> __instance.RaiseEvent(nameof(__instance.OnShapeActivated), __instance);
[HarmonyPostfix]
[HarmonyPatch(nameof(Shape.OnDisable))]
public static void OnDisable(Shape __instance)
=> __instance.RaiseEvent(nameof(__instance.OnShapeDeactivated), __instance);
}

View File

@ -0,0 +1,26 @@
using HarmonyLib;
using QSB.Patches;
namespace QSB.QuantumSync.Patches.Common.Visibility;
[HarmonyPatch(typeof(ShapeVisibilityTracker))]
internal class VisibilityShapeVisibilityTrackerPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(nameof(ShapeVisibilityTracker.IsVisibleUsingCameraFrustum))]
public static bool IsVisibleUsingCameraFrustum(ShapeVisibilityTracker __instance, out bool __result)
{
__result = QuantumManager.IsVisibleUsingCameraFrustum(__instance, false).FoundPlayers;
return false;
}
[HarmonyPrefix]
[HarmonyPatch(nameof(ShapeVisibilityTracker.IsVisible))]
public static bool IsVisible(ShapeVisibilityTracker __instance, out bool __result)
{
__result = QuantumManager.IsVisible(__instance, false);
return false;
}
}

View File

@ -0,0 +1,76 @@
using HarmonyLib;
using QSB.Patches;
using QSB.Player;
using System.Linq;
namespace QSB.QuantumSync.Patches.Common.Visibility;
[HarmonyPatch(typeof(VisibilityObject))]
internal class VisibilityVisibilityObjectPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(nameof(VisibilityObject.CheckIllumination))]
public static bool CheckIllumination(VisibilityObject __instance, out bool __result)
{
if (!__instance._checkIllumination)
{
__result = true;
return false;
}
var point = __instance.transform.TransformPoint(__instance._localIlluminationOffset);
var (localFlashlight, playerFlashlights) = QSBPlayerManager.GetPlayerFlashlights();
if (localFlashlight.CheckIlluminationAtPoint(point, __instance._illuminationRadius))
{
__result = true;
return false;
}
if (playerFlashlights.Any(x => x.CheckIlluminationAtPoint(point, __instance._illuminationRadius)))
{
__result = true;
return false;
}
var (localProbe, playerProbes) = QSBPlayerManager.GetPlayerProbes();
if (localProbe != null
&& localProbe.IsLaunched()
&& localProbe.CheckIlluminationAtPoint(point, __instance._illuminationRadius))
{
__result = true;
return false;
}
if (playerProbes.Any(x => x.IsLaunched() && x.CheckIlluminationAtPoint(point, __instance._illuminationRadius)))
{
__result = true;
return false;
}
if (QSBPlayerManager.GetThrusterLightTrackers()
.Any(x => x.CheckIlluminationAtPoint(point, __instance._illuminationRadius)))
{
__result = true;
return false;
}
if (__instance._lightSources != null)
{
foreach (var light in __instance._lightSources)
{
if (light.intensity > 0f && light.range > 0f)
{
__result = true;
return false;
}
}
}
__result = false;
return false;
}
}

View File

@ -1,494 +0,0 @@
using HarmonyLib;
using OWML.Common;
using QSB.Messaging;
using QSB.Patches;
using QSB.Player;
using QSB.QuantumSync.Messages;
using QSB.QuantumSync.WorldObjects;
using QSB.Utility;
using QSB.WorldSync;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace QSB.QuantumSync.Patches;
[HarmonyPatch]
public class QuantumPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumSocketCollapseTrigger), nameof(QuantumSocketCollapseTrigger.OnTriggerEnter))]
public static bool QuantumSocketCollapseTrigger_OnTriggerEnter() => false;
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumObject), nameof(QuantumObject.IsLockedByPlayerContact))]
public static bool QuantumObject_IsLockedByPlayerContact(out bool __result, QuantumObject __instance)
{
var playersEntangled = QuantumManager.GetEntangledPlayers(__instance);
__result = playersEntangled.Count() != 0 && __instance.IsIlluminated();
return false;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(QuantumObject), nameof(QuantumObject.SetIsQuantum))]
public static void QuantumObject_SetIsQuantum(QuantumObject __instance)
{
if (QSBWorldSync.AllObjectsReady)
{
__instance.GetWorldObject<IQSBQuantumObject>().SendMessage(new SetIsQuantumMessage(__instance.IsQuantum()));
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(SocketedQuantumObject), nameof(SocketedQuantumObject.ChangeQuantumState))]
public static bool SocketedQuantumObject_ChangeQuantumState(
SocketedQuantumObject __instance,
ref bool __result,
bool skipInstantVisibilityCheck)
{
if (QSBWorldSync.AllObjectsReady)
{
var socketedWorldObject = __instance.GetWorldObject<QSBSocketedQuantumObject>();
if (socketedWorldObject.ControllingPlayer != QSBPlayerManager.LocalPlayerId)
{
return false;
}
}
foreach (var socket in __instance._childSockets)
{
if (socket.IsOccupied())
{
__result = false;
return false;
}
}
if (__instance._socketList.Count <= 1)
{
DebugLog.ToConsole($"Error - Not enough quantum sockets in list for {__instance.name}!", MessageType.Error);
__result = false;
return false;
}
var list = new List<QuantumSocket>();
foreach (var socket in __instance._socketList)
{
if (!socket.IsOccupied() && socket.IsActive())
{
list.Add(socket);
}
}
if (list.Count == 0)
{
__result = false;
return false;
}
if (__instance._recentlyObscuredSocket != null)
{
__instance.MoveToSocket(__instance._recentlyObscuredSocket);
__instance._recentlyObscuredSocket = null;
__result = true;
return false;
}
var occupiedSocket = __instance._occupiedSocket;
for (var i = 0; i < 20; i++)
{
var index = Random.Range(0, list.Count);
__instance.MoveToSocket(list[index]);
if (skipInstantVisibilityCheck)
{
__result = true;
return false;
}
bool socketNotSuitable;
var isSocketIlluminated = __instance.CheckIllumination();
var playersEntangled = QuantumManager.GetEntangledPlayers(__instance);
if (playersEntangled.Count() != 0)
{
// socket not suitable if illuminated
socketNotSuitable = isSocketIlluminated;
}
else
{
var checkVisInstant = __instance.CheckVisibilityInstantly();
if (isSocketIlluminated)
{
// socket not suitable if object is visible
socketNotSuitable = checkVisInstant;
}
else
{
// socket not suitable if player is inside object
socketNotSuitable = playersEntangled.Any(x => __instance.CheckPointInside(x.CameraBody.transform.position));
}
}
if (!socketNotSuitable)
{
__result = true;
return false;
}
list.RemoveAt(index);
if (list.Count == 0)
{
break;
}
}
__instance.MoveToSocket(occupiedSocket);
__result = false;
return false;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(SocketedQuantumObject), nameof(SocketedQuantumObject.MoveToSocket))]
public static void SocketedQuantumObject_MoveToSocket(SocketedQuantumObject __instance, QuantumSocket socket)
{
if (!QSBWorldSync.AllObjectsReady)
{
return;
}
if (socket == null)
{
DebugLog.ToConsole($"Error - Trying to move {__instance.name} to a null socket!", MessageType.Error);
return;
}
var objectWorldObject = __instance.GetWorldObject<QSBSocketedQuantumObject>();
var socketWorldObject = socket.GetWorldObject<QSBQuantumSocket>();
if (objectWorldObject == null)
{
DebugLog.ToConsole($"Worldobject is null for {__instance.name}!");
return;
}
if (objectWorldObject.ControllingPlayer != QSBPlayerManager.LocalPlayerId)
{
return;
}
objectWorldObject.SendMessage(new SocketStateChangeMessage(
socketWorldObject.ObjectId,
__instance.transform.localRotation));
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumShuffleObject), nameof(QuantumShuffleObject.ChangeQuantumState))]
public static bool QuantumShuffleObject_ChangeQuantumState(
QuantumShuffleObject __instance,
ref bool __result)
{
QSBQuantumShuffleObject shuffleWorldObject = default;
if (QSBWorldSync.AllObjectsReady)
{
shuffleWorldObject = __instance.GetWorldObject<QSBQuantumShuffleObject>();
if (shuffleWorldObject.ControllingPlayer != QSBPlayerManager.LocalPlayerId)
{
return false;
}
}
__instance._indexList.Clear();
__instance._indexList = Enumerable.Range(0, __instance._localPositions.Length).ToList();
for (var i = 0; i < __instance._indexList.Count; ++i)
{
var random = Random.Range(i, __instance._indexList.Count);
var temp = __instance._indexList[i];
__instance._indexList[i] = __instance._indexList[random];
__instance._indexList[random] = temp;
}
for (var j = 0; j < __instance._shuffledObjects.Length; j++)
{
__instance._shuffledObjects[j].localPosition = __instance._localPositions[__instance._indexList[j]];
}
if (QSBWorldSync.AllObjectsReady)
{
shuffleWorldObject.SendMessage(new QuantumShuffleMessage(__instance._indexList.ToArray()));
__result = true;
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(MultiStateQuantumObject), nameof(MultiStateQuantumObject.Start))]
public static bool MultiStateQuantumObject_Start(MultiStateQuantumObject __instance)
{
if (!QSBWorldSync.AllObjectsReady)
{
return true;
}
var qsbObj = __instance.GetWorldObject<QSBMultiStateQuantumObject>();
if (qsbObj.ControllingPlayer == 0)
{
return true;
}
foreach (var state in qsbObj.QuantumStates)
{
if (!state.IsMeantToBeEnabled)
{
state.SetVisible(false);
}
}
if (__instance._sector == null)
{
__instance.CheckEnabled();
}
if (__instance._collapseOnStart)
{
__instance.Collapse(true);
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(MultiStateQuantumObject), nameof(MultiStateQuantumObject.ChangeQuantumState))]
public static bool MultiStateQuantumObject_ChangeQuantumState(MultiStateQuantumObject __instance)
{
if (!QSBWorldSync.AllObjectsReady)
{
return true;
}
var qsbObj = __instance.GetWorldObject<QSBMultiStateQuantumObject>();
if (qsbObj.ControllingPlayer == 0 && qsbObj.CurrentState == -1)
{
return true;
}
var isInControl = qsbObj.ControllingPlayer == QSBPlayerManager.LocalPlayerId;
return isInControl;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(QuantumState), nameof(QuantumState.SetVisible))]
public static void QuantumState_SetVisible(QuantumState __instance, bool visible)
{
if (!QSBWorldSync.AllObjectsReady)
{
return;
}
if (!visible)
{
return;
}
var allMultiStates = QSBWorldSync.GetWorldObjects<QSBMultiStateQuantumObject>();
var stateObject = __instance.GetWorldObject<QSBQuantumState>();
var owner = allMultiStates.FirstOrDefault(x => x.QuantumStates.Contains(stateObject));
if (owner == default)
{
DebugLog.ToConsole($"Error - Could not find QSBMultiStateQuantumObject for state {__instance.name}", MessageType.Error);
return;
}
if (owner.ControllingPlayer != QSBPlayerManager.LocalPlayerId)
{
return;
}
var stateIndex = owner.QuantumStates.IndexOf(stateObject);
owner.SendMessage(new MultiStateChangeMessage(stateIndex));
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumShrine), nameof(QuantumShrine.IsPlayerInDarkness))]
public static bool QuantumShrine_IsPlayerInDarkness(QuantumShrine __instance, out bool __result)
{
foreach (var lamp in __instance._lamps)
{
if (lamp.intensity > 0f)
{
__result = false;
return false;
}
}
var playersInMoon = QSBPlayerManager.PlayerList.Where(x => x.IsInMoon).ToList();
if (playersInMoon.Any(player => !player.IsInShrine))
{
__result = false;
return false;
}
if (playersInMoon.Any(player => player.FlashLight != null && player.FlashLight.FlashlightOn))
{
__result = false;
return false;
}
if (playersInMoon.Count == 0)
{
__result = false;
return false;
}
if (QSBPlayerManager.LocalPlayer != null
&& QSBPlayerManager.LocalPlayer.IsInShrine
&& PlayerState.IsFlashlightOn())
{
__result = false;
return false;
}
// BUG : make this *really* check for all players - check other probes and other jetpacks!
__result = __instance._gate.GetOpenFraction() == 0f
&& !__instance._isProbeInside
&& Locator.GetThrusterLightTracker().GetLightRange() <= 0f;
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumShrine), nameof(QuantumShrine.ChangeQuantumState))]
public static bool QuantumShrine_ChangeQuantumState(QuantumShrine __instance)
{
var shrineWorldObject = __instance.GetWorldObject<QSBSocketedQuantumObject>();
var isInControl = shrineWorldObject.ControllingPlayer == QSBPlayerManager.LocalPlayerId;
return isInControl;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumMoon), nameof(QuantumMoon.CheckPlayerFogProximity))]
public static bool QuantumMoon_CheckPlayerFogProximity(QuantumMoon __instance)
{
var playerDistance = Vector3.Distance(__instance.transform.position, Locator.GetPlayerCamera().transform.position);
var fogOffset = (__instance._stateIndex != 5) ? 0f : __instance._eyeStateFogOffset;
var distanceFromFog = playerDistance - (__instance._fogRadius + fogOffset);
var fogAlpha = 0f;
if (!__instance._isPlayerInside)
{
fogAlpha = Mathf.InverseLerp(__instance._fogThickness + __instance._fogRolloffDistance, __instance._fogThickness, distanceFromFog);
if (distanceFromFog < 0f)
{
if (__instance.IsLockedByProbeSnapshot() || QuantumManager.IsVisibleUsingCameraFrustum((ShapeVisibilityTracker)__instance._visibilityTracker, true).FoundPlayers)
{
__instance._isPlayerInside = true;
__instance.SetSurfaceState(__instance._stateIndex);
Locator.GetShipLogManager().RevealFact(__instance._revealFactID);
GlobalMessenger.FireEvent(OWEvents.PlayerEnterQuantumMoon);
}
else
{
__instance.Collapse(true);
}
}
}
else if (__instance._isPlayerInside)
{
fogAlpha = Mathf.InverseLerp(-__instance._fogThickness - __instance._fogRolloffDistance, -__instance._fogThickness, distanceFromFog);
if (distanceFromFog >= 0f)
{
if (__instance._stateIndex != 5)
{
__instance._isPlayerInside = false;
if (!__instance.IsLockedByProbeSnapshot() && !QuantumManager.IsVisibleUsingCameraFrustum((ShapeVisibilityTracker)__instance._visibilityTracker, true).FoundPlayers)
{
__instance.Collapse(true);
}
__instance.SetSurfaceState(-1);
GlobalMessenger.FireEvent(OWEvents.PlayerExitQuantumMoon);
}
else
{
var vector = Locator.GetPlayerTransform().position - __instance.transform.position;
Locator.GetPlayerBody().SetVelocity(__instance._moonBody.GetPointVelocity(Locator.GetPlayerTransform().position) - (vector.normalized * 5f));
var d = 80f;
Locator.GetPlayerBody().SetPosition(__instance.transform.position + (__instance._vortexReturnPivot.up * d));
if (!Physics.autoSyncTransforms)
{
Physics.SyncTransforms();
}
var component = Locator.GetPlayerCamera().GetComponent<PlayerCameraController>();
component.SetDegreesY(component.GetMinDegreesY());
__instance._vortexAudio.SetLocalVolume(0f);
__instance._collapseToIndex = 1;
__instance.Collapse(true);
}
}
}
__instance._playerFogBubble.SetFogAlpha(fogAlpha);
__instance._shipLandingCamFogBubble.SetFogAlpha(fogAlpha);
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumSkeletonTower), nameof(QuantumSkeletonTower.ChangeQuantumState))]
public static bool QuantumSkeletonTower_ChangeQuantumState(QuantumSkeletonTower __instance, ref bool __result)
{
if (!QSBWorldSync.AllObjectsReady)
{
return true;
}
var qsbQuantumSkeletonTower = __instance.GetWorldObject<QSBQuantumSkeletonTower>();
if (qsbQuantumSkeletonTower.ControllingPlayer != QSBPlayerManager.LocalPlayerId)
{
return false;
}
if (__instance._waitForPlayerToLookAtTower)
{
__result = false;
return false;
}
if (__instance._index < __instance._towerSkeletons.Length)
{
for (var i = 0; i < __instance._pointingSkeletons.Length; i++)
{
if (__instance._pointingSkeletons[i].gameObject.activeInHierarchy &&
(!__instance._pointingSkeletons[i].IsVisible() || !__instance._pointingSkeletons[i].IsIlluminated()))
{
__instance._pointingSkeletons[i].gameObject.SetActive(false);
__instance._towerSkeletons[__instance._index].SetActive(true);
__instance._index++;
__instance._waitForPlayerToLookAtTower = true;
qsbQuantumSkeletonTower.SendMessage(new MoveSkeletonMessage(i));
__result = true;
return false;
}
}
}
__result = false;
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumObject), nameof(QuantumObject.OnProbeSnapshot))]
public static bool OnProbeSnapshot()
{
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumObject), nameof(QuantumObject.OnProbeSnapshotRemoved))]
public static bool OnProbeSnapshotRemoved()
{
return false;
}
}

View File

@ -1,121 +0,0 @@
using HarmonyLib;
using QSB.Patches;
using QSB.Player;
using QSB.Utility;
using System.Linq;
using UnityEngine;
namespace QSB.QuantumSync.Patches;
[HarmonyPatch]
public class QuantumVisibilityPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPostfix]
[HarmonyPatch(typeof(Shape), nameof(Shape.OnEnable))]
public static void Shape_OnEnable(Shape __instance)
=> __instance.RaiseEvent(nameof(__instance.OnShapeActivated), __instance);
[HarmonyPostfix]
[HarmonyPatch(typeof(Shape), nameof(Shape.OnDisable))]
public static void Shape_OnDisable(Shape __instance)
=> __instance.RaiseEvent(nameof(__instance.OnShapeDeactivated), __instance);
// ShapeVisibilityTracker patches
[HarmonyPrefix]
[HarmonyPatch(typeof(ShapeVisibilityTracker), nameof(ShapeVisibilityTracker.IsVisibleUsingCameraFrustum))]
public static bool ShapeVisibilityTracker_IsVisibleUsingCameraFrustum(ShapeVisibilityTracker __instance, out bool __result)
{
__result = QuantumManager.IsVisibleUsingCameraFrustum(__instance, false).FoundPlayers;
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShapeVisibilityTracker), nameof(ShapeVisibilityTracker.IsVisible))]
public static bool ShapeVisibilityTracker_IsVisible(ShapeVisibilityTracker __instance, out bool __result)
{
__result = QuantumManager.IsVisible(__instance, false);
return false;
}
// RendererVisibilityTracker patches - probably not needed as i don't think RendererVisibilityTracker is ever used?
[HarmonyPrefix]
[HarmonyPatch(typeof(RendererVisibilityTracker), nameof(RendererVisibilityTracker.IsVisibleUsingCameraFrustum))]
public static bool RendererVisibilityTracker_IsVisibleUsingCameraFrustum(RendererVisibilityTracker __instance, out bool __result)
{
__result = QSBPlayerManager.GetPlayersWithCameras()
.Any(x => GeometryUtility.TestPlanesAABB(x.Camera.GetFrustumPlanes(), __instance._renderer.bounds))
&& (!__instance._checkFrustumOcclusion || QSBPlayerManager.GetPlayersWithCameras()
.Any(x => !__instance.IsOccludedFromPosition(x.Camera.transform.position)));
return false;
}
// VisibilityObject
[HarmonyPrefix]
[HarmonyPatch(typeof(VisibilityObject), nameof(VisibilityObject.CheckIllumination))]
public static bool VisibilityObject_CheckIllumination(VisibilityObject __instance, out bool __result)
{
if (!__instance._checkIllumination)
{
__result = true;
return false;
}
var point = __instance.transform.TransformPoint(__instance._localIlluminationOffset);
var (localFlashlight, playerFlashlights) = QSBPlayerManager.GetPlayerFlashlights();
if (localFlashlight.CheckIlluminationAtPoint(point, __instance._illuminationRadius))
{
__result = true;
return false;
}
if (playerFlashlights.Any(x => x.CheckIlluminationAtPoint(point, __instance._illuminationRadius)))
{
__result = true;
return false;
}
var (localProbe, playerProbes) = QSBPlayerManager.GetPlayerProbes();
if (localProbe != null
&& localProbe.IsLaunched()
&& localProbe.CheckIlluminationAtPoint(point, __instance._illuminationRadius))
{
__result = true;
return false;
}
if (playerProbes.Any(x => x.IsLaunched() && x.CheckIlluminationAtPoint(point, __instance._illuminationRadius)))
{
__result = true;
return false;
}
if (QSBPlayerManager.GetThrusterLightTrackers()
.Any(x => x.CheckIlluminationAtPoint(point, __instance._illuminationRadius)))
{
__result = true;
return false;
}
if (__instance._lightSources != null)
{
foreach (var light in __instance._lightSources)
{
if (light.intensity > 0f && light.range > 0f)
{
__result = true;
return false;
}
}
}
__result = false;
return false;
}
}

View File

@ -0,0 +1,50 @@
using HarmonyLib;
using QSB.Messaging;
using QSB.Patches;
using QSB.QuantumSync.Messages;
using QSB.QuantumSync.WorldObjects;
using QSB.WorldSync;
using UnityEngine;
namespace QSB.QuantumSync.Patches.Server;
[HarmonyPatch(typeof(EyeProxyQuantumMoon))]
public class ServerEyeProxyQuantumMoonPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnServerClientConnect;
[HarmonyPrefix]
[HarmonyPatch(typeof(EyeProxyQuantumMoon), nameof(EyeProxyQuantumMoon.ChangeQuantumState))]
public static bool EyeProxyQuantumMoon_ChangeQuantumState(EyeProxyQuantumMoon __instance, ref bool __result, bool skipInstantVisibilityCheck)
{
if (!QSBWorldSync.AllObjectsReady)
{
return true;
}
var qsbEyeProxyQuantumMoon = __instance.GetWorldObject<QSBEyeProxyQuantumMoon>();
if (TimeLoop.GetSecondsRemaining() > 0f && Random.value > 0.3f)
{
__instance._moonStateRoot.SetActive(false);
qsbEyeProxyQuantumMoon.SendMessage(new EyeProxyMoonStateChangeMessage(false, -1f));
__result = true;
return false;
}
__instance._moonStateRoot.SetActive(true);
for (var i = 0; i < 20; i++)
{
var angle = Random.Range(0f, 360f);
__instance.transform.localEulerAngles = new Vector3(0f, angle, 0f);
if (skipInstantVisibilityCheck || !__instance.CheckVisibilityInstantly())
{
qsbEyeProxyQuantumMoon.SendMessage(new EyeProxyMoonStateChangeMessage(true, angle));
__result = true;
return false;
}
}
__result = true;
return false;
}
}

View File

@ -3,60 +3,17 @@ using QSB.Messaging;
using QSB.Patches;
using QSB.Player;
using QSB.QuantumSync.Messages;
using QSB.QuantumSync.WorldObjects;
using QSB.WorldSync;
using QSB.QuantumSync.Patches.Common;
using System.Linq;
using UnityEngine;
namespace QSB.QuantumSync.Patches;
namespace QSB.QuantumSync.Patches.Server;
[HarmonyPatch]
public class ServerQuantumPatches : QSBPatch
[HarmonyPatch(typeof(QuantumMoon))]
public class ServerQuantumMoonPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnServerClientConnect;
[HarmonyPrefix]
[HarmonyPatch(typeof(EyeProxyQuantumMoon), nameof(EyeProxyQuantumMoon.ChangeQuantumState))]
public static bool EyeProxyQuantumMoon_ChangeQuantumState(EyeProxyQuantumMoon __instance, ref bool __result, bool skipInstantVisibilityCheck)
{
if (!QSBWorldSync.AllObjectsReady)
{
return true;
}
var qsbEyeProxyQuantumMoon = __instance.GetWorldObject<QSBEyeProxyQuantumMoon>();
if (TimeLoop.GetSecondsRemaining() > 0f && Random.value > 0.3f)
{
__instance._moonStateRoot.SetActive(false);
qsbEyeProxyQuantumMoon.SendMessage(new EyeProxyMoonStateChangeMessage(false, -1f));
__result = true;
return false;
}
__instance._moonStateRoot.SetActive(true);
for (var i = 0; i < 20; i++)
{
var angle = Random.Range(0f, 360f);
__instance.transform.localEulerAngles = new Vector3(0f, angle, 0f);
if (skipInstantVisibilityCheck || !__instance.CheckVisibilityInstantly())
{
qsbEyeProxyQuantumMoon.SendMessage(new EyeProxyMoonStateChangeMessage(true, angle));
__result = true;
return false;
}
}
__result = true;
return false;
}
/*
* This patch used to be different, but that one completely broke Solanum's NomaiTextLines.
* I have no idea why, and I fixed it by just writing this patch again.
* The patches did the same thing.
* ¯\_()_/¯
*/
[HarmonyPrefix]
[HarmonyPatch(typeof(QuantumMoon), nameof(QuantumMoon.ChangeQuantumState))]
public static bool ChangeQuantumState(QuantumMoon __instance, bool skipInstantVisibilityCheck, out bool __result)
@ -77,7 +34,7 @@ public class ServerQuantumPatches : QSBPatch
}
// If any of the players outside the shrine can see the moon
if (playersNotInQuantumShrine.Any(playersWhoCanSeeQuantumMoon.Contains))
if (playersNotInQuantumShrine.Any(x => playersWhoCanSeeQuantumMoon.Contains(x) && !QuantumMoonPatches.GetTransformInFog(Locator.GetQuantumMoon(), x.CameraBody.transform)))
{
__result = false;
return false;
@ -253,4 +210,4 @@ public class ServerQuantumPatches : QSBPatch
GlobalMessenger<OWRigidbody>.FireEvent("QuantumMoonChangeState", __instance._moonBody);
}
}
}

View File

@ -130,7 +130,7 @@ internal class QuantumManager : WorldObjectManager
{
foreach (var quantumObject in QSBWorldSync.GetWorldObjects<IQSBQuantumObject>())
{
if (quantumObject.ControllingPlayer == QSBPlayerManager.LocalPlayerId)
if (quantumObject.ControllingPlayer == QSBPlayerManager.LocalPlayerId || quantumObject.HostControls)
{
quantumObject.OnTakeProbeSnapshot(player, cameraId);
}
@ -141,7 +141,7 @@ internal class QuantumManager : WorldObjectManager
{
foreach (var quantumObject in QSBWorldSync.GetWorldObjects<IQSBQuantumObject>())
{
if (quantumObject.ControllingPlayer == QSBPlayerManager.LocalPlayerId)
if (quantumObject.ControllingPlayer == QSBPlayerManager.LocalPlayerId || quantumObject.HostControls)
{
quantumObject.OnRemoveProbeSnapshot(player);
}

View File

@ -6,6 +6,7 @@ namespace QSB.QuantumSync.WorldObjects;
public interface IQSBQuantumObject : IWorldObject
{
bool HostControls { get; }
uint ControllingPlayer { get; set; }
bool IsEnabled { get; }

View File

@ -2,7 +2,7 @@
internal class QSBEyeProxyQuantumMoon : QSBQuantumObject<EyeProxyQuantumMoon>
{
protected override bool HostControls => true;
public override bool HostControls => true;
public override void SendInitialState(uint to)
{

View File

@ -7,7 +7,7 @@ namespace QSB.QuantumSync.WorldObjects;
internal class QSBQuantumMoon : QSBQuantumObject<QuantumMoon>
{
protected override bool HostControls => true;
public override bool HostControls => true;
public override void SendInitialState(uint to)
{

View File

@ -25,7 +25,7 @@ internal abstract class QSBQuantumObject<T> : WorldObject<T>, IQSBQuantumObject
/// whether the controlling player is always the host <br/>
/// also means this object is considered always enabled
/// </summary>
protected virtual bool HostControls => false;
public virtual bool HostControls => false;
public uint ControllingPlayer { get; set; }
public bool IsEnabled { get; private set; }
@ -330,6 +330,8 @@ internal abstract class QSBQuantumObject<T> : WorldObject<T>, IQSBQuantumObject
label += $"{tracker.name}:\r\n IsVisible:{tracker.IsVisible()}\r\n VisibleUsingCamera:{tracker.IsVisibleUsingCameraFrustum()}\r\n";
}
label += $"VisibleInProbeSnapshot:{AttachedObject._visibleInProbeSnapshot}\r\n";
return label;
}
}

View File

@ -165,19 +165,18 @@ internal class ShipManager : WorldObjectManager
public void AddPlayerToShip(PlayerInfo player)
{
player.IsInShip = true;
_playersInShip.Add(player);
UpdateElectricalComponent();
}
public void RemovePlayerFromShip(PlayerInfo player)
{
player.IsInShip = false;
_playersInShip.Remove(player);
UpdateElectricalComponent();
}
public bool IsPlayerInShip(PlayerInfo player)
=> _playersInShip.Contains(player);
private void UpdateElectricalComponent()
{
var electricalSystem = ShipElectricalComponent._electricalSystem;

View File

@ -74,6 +74,11 @@ public class ShipTransformSync : SectoredRigidbodySync
playerBody.SetPosition(AttachedTransform.FromRelPos(relPos));
playerBody.SetRotation(AttachedTransform.FromRelRot(relRot));
if (!Physics.autoSyncTransforms)
{
Physics.SyncTransforms();
}
}
}
else

View File

@ -75,6 +75,11 @@ public class OccasionalTransformSync : UnsectoredRigidbodySync
AttachedRigidbody.SetAngularVelocity(ReferenceRigidbody.FromRelAngVel(AngularVelocity));
Move();
if (!Physics.autoSyncTransforms)
{
Physics.SyncTransforms();
}
}
private readonly List<MoveData> _toMove = new();
@ -125,4 +130,4 @@ public class OccasionalTransformSync : UnsectoredRigidbodySync
_toMove.Clear();
}
}
}

View File

@ -342,6 +342,9 @@ public abstract class SyncBase : QSBNetworkTransform
return;
}
DebugGUI.DrawLabel(AttachedTransform, ToString());
if (DebugActions.WorldObjectSelection == null)
{
DebugGUI.DrawLabel(AttachedTransform, ToString());
}
}
}

View File

@ -21,7 +21,7 @@ public class TeleportingPlanetsPatch : QSBPatch
{
if (__instance.TryGetComponent<AstroObject>(out var astroObject) && astroObject._name != AstroObject.Name.ProbeCannon)
{
DebugLog.ToAll($"AHHHHHHHHH!!!!!!!!!\n{Environment.StackTrace}", MessageType.Error);
DebugLog.ToAll($"AHHHHHHHHH!!!!!!!!!\n{__instance.name}\n{Environment.StackTrace}", MessageType.Error);
}
}
}

View File

@ -0,0 +1,46 @@
using QSB.Messaging;
using QSB.Player.Messages;
using QSB.Player.TransformSync;
using QSB.Player;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using QSB.Utility;
namespace QSB.Tools.ProbeTool.Messages;
internal class ProbeEnterLeaveMessage : QSBMessage<ProbeEnterLeaveType>
{
static ProbeEnterLeaveMessage()
{
GlobalMessenger.AddListener(OWEvents.ProbeEnterQuantumMoon, () => Handler(ProbeEnterLeaveType.EnterQuantumMoon));
GlobalMessenger.AddListener(OWEvents.ProbeExitQuantumMoon, () => Handler(ProbeEnterLeaveType.ExitQuantumMoon));
// TODO : add cloak messages
}
private static void Handler(ProbeEnterLeaveType type)
{
new ProbeEnterLeaveMessage(type).Send();
}
public ProbeEnterLeaveMessage(ProbeEnterLeaveType type) : base(type) { }
public override void OnReceiveRemote()
{
var player = QSBPlayerManager.GetPlayer(From);
switch (Data)
{
case ProbeEnterLeaveType.EnterQuantumMoon:
DebugLog.DebugWrite($"{player} probe enter QM");
player.Probe.InsideQuantumMoon = true;
break;
case ProbeEnterLeaveType.ExitQuantumMoon:
DebugLog.DebugWrite($"{player} probe exit QM");
player.Probe.InsideQuantumMoon = false;
break;
}
}
}

View File

@ -0,0 +1,9 @@
namespace QSB.Tools.ProbeTool;
public enum ProbeEnterLeaveType
{
EnterQuantumMoon,
ExitQuantumMoon,
EnterCloak,
ExitCloak
}

View File

@ -1,4 +1,5 @@
using UnityEngine;
using QSB.Player;
using UnityEngine;
namespace QSB.Tools.ProbeTool;
@ -10,22 +11,21 @@ public class QSBProbeCamera : MonoBehaviour
private OWCamera _camera;
private RenderTexture _snapshotTexture;
private NoiseImageEffect _noiseEffect;
private static OWCamera _lastSnapshotCamera;
private Quaternion _origLocalRotation;
private Quaternion _origParentLocalRotation;
private Vector2 _cameraRotation = Vector2.zero;
private QuantumMoon _quantumMoon;
private SandLevelController _sandLevelController;
private PlayerInfo owner;
public event ProbeCamera.RotateCameraEvent OnRotateCamera;
private void Awake()
{
_origLocalRotation = transform.localRotation;
_origParentLocalRotation = transform.parent.localRotation;
_camera = this.GetRequiredComponent<OWCamera>();
_camera.enabled = false;
_noiseEffect = GetComponent<NoiseImageEffect>();
//this._snapshotTexture = ProbeCamera.GetSharedSnapshotTexture();
}
private void OnDestroy()
@ -33,11 +33,8 @@ public class QSBProbeCamera : MonoBehaviour
private void Start()
{
var astroObject = Locator.GetAstroObject(AstroObject.Name.QuantumMoon);
if (astroObject != null)
{
_quantumMoon = astroObject.GetComponent<QuantumMoon>();
}
var probe = GetComponentInParent<QSBSurveyorProbe>();
owner = probe.GetOwner();
}
public static OWCamera GetLastSnapshotCamera() =>
@ -53,19 +50,13 @@ public class QSBProbeCamera : MonoBehaviour
=> _sandLevelController = sandLevelController;
public bool HasInterference() =>
_id != ProbeCamera.ID.PreLaunch
//&& ((this._quantumMoon != null && this._quantumMoon.IsPlayerInside() != this._quantumMoon.IsProbeInside())
|| (_sandLevelController != null && _sandLevelController.IsPointBuried(transform.position));
//|| (Locator.GetCloakFieldController() != null && Locator.GetCloakFieldController().isPlayerInsideCloak != Locator.GetCloakFieldController().isProbeInsideCloak));
(_id != ProbeCamera.ID.PreLaunch && owner.IsInMoon != owner.Probe.InsideQuantumMoon)
|| (_sandLevelController != null && _sandLevelController.IsPointBuried(transform.position))
|| (Locator.GetCloakFieldController() != null && owner.IsInCloak != owner.Probe.InsideCloak);
public RenderTexture TakeSnapshot()
{
_lastSnapshotCamera = _camera;
if (_noiseEffect != null)
{
_noiseEffect.enabled = HasInterference();
}
_camera.targetTexture = _snapshotTexture;
_camera.Render();
return _snapshotTexture;

View File

@ -21,6 +21,9 @@ public class QSBSurveyorProbe : MonoBehaviour, ILightSource
public event SurveyorProbeEvent OnTakeSnapshot;
public event RetrieveEvent OnStartRetrieveProbe;
public bool InsideQuantumMoon;
public bool InsideCloak;
private GameObject _detectorObj;
private RulesetDetector _rulesetDetector;
private SingularityWarpEffect _warpEffect;
@ -113,6 +116,8 @@ public class QSBSurveyorProbe : MonoBehaviour, ILightSource
_owner = player;
}
public PlayerInfo GetOwner() => _owner;
private void OnWarpComplete() => Deactivate();
public bool IsRetrieving()

View File

@ -18,30 +18,30 @@
"Yes": "ДА",
"No": "НЕТ",
"StopHostingAreYouSure": "Вы уверены, что хотите прекратить хостинг?\nЭто отключит всех игроков от игры и отправит их в главное меню.",
"CopyProductUserIDToClipboard": "Начинаю хостинг.\nИгроки будут использовать ваш ID игрока :\n{0}\nЖелаете скопировать его в буфер обмена?",
"CopyProductUserIDToClipboard": "Начинаю хостинг.\nИгроки будут использовать ваш ID продукта :\n{0}\nЖелаете скопировать его в буфер обмена?",
"Connecting": "ПОДКЛЮЧЕНИЕ...",
"OK": "ЛАДНО",
"ServerRefusedConnection": "Сервер отказал в подключении.\n{0}",
"ClientDisconnectWithError": "Клиент отключён с ошибкой!\n{0}",
"QSBVersionMismatch": "Версия QSB различается. (Клиент:{0}, Сервер:{1})",
"OWVersionMismatch": "Версия Outer Wilds различается. (Клиент:{0}, Сервер:{1})",
"DLCMismatch": "Состояние DLC отличается. (Клиент:{0}, Сервер:{1})",
"DLCMismatch": "Состояние присутствия DLC отличается. (Клиент:{0}, Сервер:{1})",
"GameProgressLimit": "Игра продолжалась слишком долго.",
"AddonMismatch": "Аддоны различаются. (Клиент:{0} аддонов, Сервер:{1} Аддонов)",
"IncompatibleMod": "Используется несовместимый/неразрешенный мод. Первый из них - {0}",
"AddonMismatch": "Аддоны различаются. (Клиент:{0} аддонов, Сервер:{1} аддонов)",
"IncompatibleMod": "Используется несовместимый(ые)/неразрешенный(ые) мод(ы). Первый из них - {0}",
"PlayerJoinedTheGame": "{0} подключился!",
"PlayerWasKicked": "{0} был отключён.",
"KickedFromServer": "Отключён от сервера. Причина : {0}",
"RespawnPlayer": "Возродить игрока",
"TimeSyncTooFarBehind": "{0}\nБыстрая перемотка, что-бы соответствовать времени сервера...",
"TimeSyncWaitingForStartOfServer": "Ожидаю запуск сервера...",
"TimeSyncTooFarAhead": "{0}\nПауза, что-бы соответствовать времени сервера...",
"TimeSyncWaitForAllToReady": "Ожидаю начало цикла...",
"TimeSyncWaitForAllToDie": "Ожидаю конец цикла...",
"GalaxyMapEveryoneNotPresent": "Ещё не время. Все должны быть здесь, что-бы начать.",
"TimeSyncTooFarBehind": "{0}\nБыстрая перемотка, чтобы соответствовать времени сервера...",
"TimeSyncWaitingForStartOfServer": "Ожидание запуска сервера...",
"TimeSyncTooFarAhead": "{0}\nПауза, чтобы соответствовать времени сервера...",
"TimeSyncWaitForAllToReady": "Ожидание начала цикла...",
"TimeSyncWaitForAllToDie": "Ожидание конца цикла...",
"GalaxyMapEveryoneNotPresent": "Ещё не время. Все должны быть здесь, чтобы начать.",
"YouAreDead": "Вы погибли.",
"WaitingForRespawn": "Ожидаю, пока кто-нибудь возрадит вас...",
"WaitingForAllToDie": "Ждём пока {0} игрок(а)(ов) умрут...",
"WaitingForRespawn": "Ожидание, пока кто-нибудь возрадит вас...",
"WaitingForAllToDie": "Ожидание смерти {0} игрока(ов)...",
"AttachToShip": "Зацепиться на корабль",
"DetachFromShip": "Отцепиться от корабля",
"DeathMessages": {

View File

@ -136,8 +136,17 @@ internal class DebugGUI : MonoBehaviour, IAddComponentOnStart
}
WriteLine(1, $"Selected WorldObject : {(DebugActions.WorldObjectSelection == null ? "All" : DebugActions.WorldObjectSelection.Name)}");
WriteLine(1, $"Invincible : {Locator.GetDeathManager()._invincible}");
WriteLine(1, $"Tool Mode : {Locator.GetToolModeSwapper().GetToolMode()}");
if (Locator.GetDeathManager() != null)
{
WriteLine(1, $"Invincible : {Locator.GetDeathManager()._invincible}");
}
if (Locator.GetToolModeSwapper() != null)
{
WriteLine(1, $"Tool Mode : {Locator.GetToolModeSwapper().GetToolMode()}");
}
WriteLine(1, $"Input Mode Stack :");
foreach (var item in OWInput.GetInputModeStack())
{
@ -158,7 +167,7 @@ internal class DebugGUI : MonoBehaviour, IAddComponentOnStart
WriteLine(2, $"Dead : {player.IsDead}");
WriteLine(2, $"Ready : {player.IsReady}");
WriteLine(2, $"Suited Up : {player.SuitedUp}");
WriteLine(2, $"In Suited Up State : {player.AnimationSync.InSuitedUpState}");
WriteLine(2, $"In Suited Up State : {player.AnimationSync?.InSuitedUpState}");
WriteLine(2, $"InDreamWorld : {player.InDreamWorld}");
if (player.IsReady && QSBWorldSync.AllObjectsReady)

View File

@ -7,7 +7,7 @@
"body": "- Disable *all* other mods. (Can heavily affect performance)\n- Make sure you are not running any other network-intensive applications."
},
"uniqueName": "Raicuparta.QuantumSpaceBuddies",
"version": "0.24.4",
"version": "0.25.0",
"owmlVersion": "2.9.0",
"dependencies": [ "_nebula.MenuFramework", "JohnCorby.VanillaFix" ],
"pathsToPreserve": [ "debugsettings.json" ],