diff --git a/EpicRerouter/EpicRerouter.csproj b/EpicRerouter/EpicRerouter.csproj
index 3cff5ff9..f52659e0 100644
--- a/EpicRerouter/EpicRerouter.csproj
+++ b/EpicRerouter/EpicRerouter.csproj
@@ -4,6 +4,6 @@
-
+
diff --git a/MirrorWeaver/MirrorWeaver.csproj b/MirrorWeaver/MirrorWeaver.csproj
index 61a05999..6e06d15e 100644
--- a/MirrorWeaver/MirrorWeaver.csproj
+++ b/MirrorWeaver/MirrorWeaver.csproj
@@ -4,7 +4,7 @@
-
+
diff --git a/QSB/Animation/Player/AnimationSync.cs b/QSB/Animation/Player/AnimationSync.cs
index ec837038..d79b8773 100644
--- a/QSB/Animation/Player/AnimationSync.cs
+++ b/QSB/Animation/Player/AnimationSync.cs
@@ -39,6 +39,7 @@ public class AnimationSync : PlayerSyncObject
///
/// This wipes the NetworkAnimator's fields, so it assumes the parameters have changed.
/// Basically just forces it to set all its dirty flags.
+ /// BUG: this doesnt work for other players because its only called by the host.
///
private void SendInitialState(uint to) => NetworkAnimator.Invoke("Awake");
diff --git a/QSB/DeathSync/Patches/DeathPatches.cs b/QSB/DeathSync/Patches/DeathPatches.cs
index 2b1fe4a1..59fa30a3 100644
--- a/QSB/DeathSync/Patches/DeathPatches.cs
+++ b/QSB/DeathSync/Patches/DeathPatches.cs
@@ -3,7 +3,6 @@ using QSB.DeathSync.Messages;
using QSB.Messaging;
using QSB.Patches;
using QSB.Player;
-using QSB.Utility;
using System.Linq;
using UnityEngine;
@@ -14,96 +13,47 @@ public class DeathPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
+ ///
+ /// don't take damage from impact in ship
+ ///
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerResources), nameof(PlayerResources.OnImpact))]
- public static bool PlayerResources_OnImpact(PlayerResources __instance, ImpactData impact) =>
- // don't take damage from impact in ship
- !PlayerState.IsInsideShip();
+ public static bool PlayerResources_OnImpact(PlayerResources __instance, ImpactData impact)
+ {
+ if (QSBCore.ShipDamage)
+ {
+ return true;
+ }
+
+ return !PlayerState.IsInsideShip();
+ }
///
/// don't insta-die from impact in ship
///
[HarmonyPrefix]
- [HarmonyPatch(typeof(HighSpeedImpactSensor), nameof(HighSpeedImpactSensor.FixedUpdate))]
- public static bool HighSpeedImpactSensor_FixedUpdate(HighSpeedImpactSensor __instance)
+ [HarmonyPatch(typeof(HighSpeedImpactSensor), nameof(HighSpeedImpactSensor.HandlePlayerInsideShip))]
+ public static bool HighSpeedImpactSensor_HandlePlayerInsideShip(HighSpeedImpactSensor __instance)
{
- if (__instance._isPlayer && (PlayerState.IsAttached() || PlayerState.IsInsideShuttle() || PlayerState.UsingNomaiRemoteCamera()))
+ if (QSBCore.ShipDamage)
{
- return false;
+ return true;
}
- if (__instance._dieNextUpdate && !__instance._dead)
+ var shipCenter = Locator.GetShipTransform().position + Locator.GetShipTransform().up * 2f;
+ var distanceFromShip = Vector3.Distance(__instance._body.GetPosition(), shipCenter);
+ if (distanceFromShip > 8f)
{
- __instance._dead = true;
- __instance._dieNextUpdate = false;
- if (__instance.gameObject.CompareTag("Player"))
- {
- Locator.GetDeathManager().SetImpactDeathSpeed(__instance._impactSpeed);
- Locator.GetDeathManager().KillPlayer(DeathType.Impact);
- }
- else if (__instance.gameObject.CompareTag("Ship"))
- {
- __instance.GetComponent().Explode();
- }
+ __instance._body.SetPosition(shipCenter);
}
- if (__instance._isPlayer && PlayerState.IsInsideShip())
+ if (!__instance._dead)
{
- var shipCenter = Locator.GetShipTransform().position + Locator.GetShipTransform().up * 2f;
- var distanceFromShip = Vector3.Distance(__instance._body.GetPosition(), shipCenter);
- if (distanceFromShip > 8f)
+ var a = __instance._body.GetVelocity() - Locator.GetShipBody().GetPointVelocity(__instance._body.GetPosition());
+ if (a.sqrMagnitude > __instance._sqrCheckSpeedThreshold)
{
- __instance._body.SetPosition(shipCenter);
- }
-
- if (!__instance._dead)
- {
- var a = __instance._body.GetVelocity() - Locator.GetShipBody().GetPointVelocity(__instance._body.GetPosition());
- if (a.sqrMagnitude > __instance._sqrCheckSpeedThreshold)
- {
- __instance._impactSpeed = a.magnitude;
- __instance._body.AddVelocityChange(-a);
- }
- }
-
- return false;
- }
-
- var passiveReferenceFrame = __instance._sectorDetector.GetPassiveReferenceFrame();
- if (!__instance._dead && passiveReferenceFrame != null)
- {
- var relativeVelocity = __instance._body.GetVelocity() - passiveReferenceFrame.GetOWRigidBody().GetPointVelocity(__instance._body.GetPosition());
- if (relativeVelocity.sqrMagnitude > __instance._sqrCheckSpeedThreshold)
- {
- var hitCount = Physics.RaycastNonAlloc(__instance.transform.TransformPoint(__instance._localOffset), relativeVelocity, __instance._raycastHits, relativeVelocity.magnitude * Time.deltaTime + __instance._radius, OWLayerMask.physicalMask, QueryTriggerInteraction.Ignore);
- for (var i = 0; i < hitCount; i++)
- {
- if (__instance._raycastHits[i].rigidbody.mass > 10f && !__instance._raycastHits[i].rigidbody.Equals(__instance._body.GetRigidbody()))
- {
- var owRigidbody = __instance._raycastHits[i].rigidbody.GetComponent();
- if (owRigidbody == null)
- {
- DebugLog.ToConsole("Rigidbody does not have attached OWRigidbody!!!", OWML.Common.MessageType.Error);
- Debug.Break();
- }
- else
- {
- relativeVelocity = __instance._body.GetVelocity() - owRigidbody.GetPointVelocity(__instance._body.GetPosition());
- var a2 = Vector3.Project(relativeVelocity, __instance._raycastHits[i].normal);
- if (a2.sqrMagnitude > __instance._sqrCheckSpeedThreshold)
- {
- __instance._body.AddVelocityChange(-a2);
- __instance._impactSpeed = a2.magnitude;
- if (!PlayerState.IsInsideTheEye())
- {
- __instance._dieNextUpdate = true;
- }
-
- break;
- }
- }
- }
- }
+ __instance._impactSpeed = a.magnitude;
+ __instance._body.AddVelocityChange(-a);
}
}
@@ -141,15 +91,10 @@ public class DeathPatches : QSBPatch
Achievements.Earn(Achievements.Type.EARLY_ADOPTER);
}
- if (PlayerState.InDreamWorld())
+ if (PlayerState.InDreamWorld() && deathType != DeathType.Dream && deathType != DeathType.DreamExplosion && deathType != DeathType.Supernova && deathType != DeathType.TimeLoop && deathType != DeathType.Meditation)
{
- // exit dream world either way to prevent goof with respawn
- // TODO: test
Locator.GetDreamWorldController().ExitDreamWorld(deathType);
- if (deathType != DeathType.Dream && deathType != DeathType.DreamExplosion && deathType != DeathType.Supernova && deathType != DeathType.TimeLoop && deathType != DeathType.Meditation)
- {
- return;
- }
+ return;
}
if (!@this._isDying)
diff --git a/QSB/EchoesOfTheEye/AlarmTotemSync/AlarmTotemManager.cs b/QSB/EchoesOfTheEye/AlarmTotemSync/AlarmTotemManager.cs
index b50b1e90..992f79ee 100644
--- a/QSB/EchoesOfTheEye/AlarmTotemSync/AlarmTotemManager.cs
+++ b/QSB/EchoesOfTheEye/AlarmTotemSync/AlarmTotemManager.cs
@@ -1,8 +1,9 @@
using Cysharp.Threading.Tasks;
using QSB.EchoesOfTheEye.AlarmTotemSync.WorldObjects;
+using QSB.Utility;
using QSB.WorldSync;
+using System.Linq;
using System.Threading;
-using UnityEngine;
namespace QSB.EchoesOfTheEye.AlarmTotemSync;
@@ -11,18 +12,12 @@ public class AlarmTotemManager : WorldObjectManager
public override WorldObjectScene WorldObjectScene => WorldObjectScene.SolarSystem;
public override bool DlcOnly => true;
- private QSBAlarmSequenceController _qsbAlarmSequenceController;
+ public static AlarmBell[] AlarmBells;
public override async UniTask BuildWorldObjects(OWScene scene, CancellationToken ct)
{
- // QSBWorldSync.Init();
+ QSBWorldSync.Init();
QSBWorldSync.Init();
-
- _qsbAlarmSequenceController = new GameObject(nameof(QSBAlarmSequenceController))
- .AddComponent();
- DontDestroyOnLoad(_qsbAlarmSequenceController.gameObject);
+ AlarmBells = QSBWorldSync.GetUnityObjects().Where(x => x._lightController).SortDeterministic().ToArray();
}
-
- public override void UnbuildWorldObjects() =>
- Destroy(_qsbAlarmSequenceController.gameObject);
}
diff --git a/QSB/EchoesOfTheEye/AlarmTotemSync/Messages/SetVisibleMessage.cs b/QSB/EchoesOfTheEye/AlarmTotemSync/Messages/SetVisibleMessage.cs
new file mode 100644
index 00000000..fd8ad1a4
--- /dev/null
+++ b/QSB/EchoesOfTheEye/AlarmTotemSync/Messages/SetVisibleMessage.cs
@@ -0,0 +1,37 @@
+using QSB.EchoesOfTheEye.AlarmTotemSync.WorldObjects;
+using QSB.Messaging;
+
+namespace QSB.EchoesOfTheEye.AlarmTotemSync.Messages;
+
+public class SetVisibleMessage : QSBWorldObjectMessage
+{
+ public SetVisibleMessage(bool visible) : base(visible) { }
+
+ public override void OnReceiveRemote()
+ {
+ if (WorldObject.AttachedObject._isPlayerVisible == Data)
+ {
+ return;
+ }
+
+ WorldObject.AttachedObject._isPlayerVisible = Data;
+ if (Data)
+ {
+ Locator.GetAlarmSequenceController().IncreaseAlarmCounter();
+ WorldObject.AttachedObject._secondsConcealed = 0f;
+ WorldObject.AttachedObject._simTotemMaterials[0] = WorldObject.AttachedObject._simAlarmMaterial;
+ WorldObject.AttachedObject._simTotemRenderer.sharedMaterials = WorldObject.AttachedObject._simTotemMaterials;
+ WorldObject.AttachedObject._simVisionConeRenderer.SetColor(WorldObject.AttachedObject._simAlarmColor);
+ GlobalMessenger.FireEvent("AlarmTotemTriggered");
+ }
+ else
+ {
+ Locator.GetAlarmSequenceController().DecreaseAlarmCounter();
+ WorldObject.AttachedObject._secondsConcealed = 0f;
+ WorldObject.AttachedObject._simTotemMaterials[0] = WorldObject.AttachedObject._origSimEyeMaterial;
+ WorldObject.AttachedObject._simTotemRenderer.sharedMaterials = WorldObject.AttachedObject._simTotemMaterials;
+ WorldObject.AttachedObject._simVisionConeRenderer.SetColor(WorldObject.AttachedObject._simVisionConeRenderer.GetOriginalColor());
+ WorldObject.AttachedObject._pulseLightController.FadeTo(0f, 0.5f);
+ }
+ }
+}
diff --git a/QSB/EchoesOfTheEye/AlarmTotemSync/Messages/TotemEnabledMessage.cs b/QSB/EchoesOfTheEye/AlarmTotemSync/Messages/TotemEnabledMessage.cs
deleted file mode 100644
index 446c3f0e..00000000
--- a/QSB/EchoesOfTheEye/AlarmTotemSync/Messages/TotemEnabledMessage.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using QSB.EchoesOfTheEye.AlarmTotemSync.WorldObjects;
-using QSB.Messaging;
-
-namespace QSB.EchoesOfTheEye.AlarmTotemSync.Messages;
-
-public class TotemEnabledMessage : QSBWorldObjectMessage
-{
- public TotemEnabledMessage(bool enabled) : base(enabled) { }
-
- public override void OnReceiveRemote() =>
- WorldObject.SetEnabled(Data);
-}
diff --git a/QSB/EchoesOfTheEye/AlarmTotemSync/Messages/TotemVisibleForMessage.cs b/QSB/EchoesOfTheEye/AlarmTotemSync/Messages/TotemVisibleForMessage.cs
deleted file mode 100644
index e8624afb..00000000
--- a/QSB/EchoesOfTheEye/AlarmTotemSync/Messages/TotemVisibleForMessage.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using QSB.EchoesOfTheEye.AlarmTotemSync.WorldObjects;
-using QSB.Messaging;
-using System.Collections.Generic;
-
-namespace QSB.EchoesOfTheEye.AlarmTotemSync.Messages;
-
-public class TotemVisibleForMessage : QSBWorldObjectMessage>
-{
- public TotemVisibleForMessage(List visibleFor) : base(visibleFor) { }
-
- public override void OnReceiveRemote()
- {
- WorldObject.VisibleFor.Clear();
- WorldObject.VisibleFor.AddRange(Data);
- }
-}
diff --git a/QSB/EchoesOfTheEye/AlarmTotemSync/Messages/TotemVisibleMessage.cs b/QSB/EchoesOfTheEye/AlarmTotemSync/Messages/TotemVisibleMessage.cs
deleted file mode 100644
index 947302e9..00000000
--- a/QSB/EchoesOfTheEye/AlarmTotemSync/Messages/TotemVisibleMessage.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using QSB.EchoesOfTheEye.AlarmTotemSync.WorldObjects;
-using QSB.Messaging;
-
-namespace QSB.EchoesOfTheEye.AlarmTotemSync.Messages;
-
-public class TotemVisibleMessage : QSBWorldObjectMessage
-{
- public TotemVisibleMessage(bool visible) : base(visible) { }
- public override void OnReceiveLocal() => OnReceiveRemote();
- public override void OnReceiveRemote() => WorldObject.SetVisible(From, Data);
-}
diff --git a/QSB/EchoesOfTheEye/AlarmTotemSync/Patches/AlarmSequenceControllerPatches.cs b/QSB/EchoesOfTheEye/AlarmTotemSync/Patches/AlarmSequenceControllerPatches.cs
new file mode 100644
index 00000000..d51aa386
--- /dev/null
+++ b/QSB/EchoesOfTheEye/AlarmTotemSync/Patches/AlarmSequenceControllerPatches.cs
@@ -0,0 +1,93 @@
+using HarmonyLib;
+using QSB.Patches;
+using UnityEngine;
+
+namespace QSB.EchoesOfTheEye.AlarmTotemSync.Patches;
+
+[HarmonyPatch(typeof(AlarmSequenceController))]
+public class AlarmSequenceControllerPatches : QSBPatch
+{
+ public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
+
+ [HarmonyPrefix]
+ [HarmonyPatch(nameof(AlarmSequenceController.IncreaseAlarmCounter))]
+ private static bool IncreaseAlarmCounter(AlarmSequenceController __instance)
+ {
+ __instance._alarmCounter++;
+ if (__instance._alarmCounter == 1)
+ {
+ __instance.PlayChimes();
+ }
+ __instance.enabled = true;
+ return false;
+ }
+
+ [HarmonyPrefix]
+ [HarmonyPatch(nameof(AlarmSequenceController.DecreaseAlarmCounter))]
+ private static bool DecreaseAlarmCounter(AlarmSequenceController __instance)
+ {
+ __instance._alarmCounter--;
+ if (__instance._alarmCounter < 0)
+ {
+ __instance._alarmCounter = 0;
+ Debug.LogError("Something went wrong, alarm counter should never drop below zero!");
+ }
+ return false;
+ }
+
+ [HarmonyPrefix]
+ [HarmonyPatch(nameof(AlarmSequenceController.StopChimes))]
+ private static bool StopChimes(AlarmSequenceController __instance)
+ {
+ __instance._playing = false;
+ __instance._stopRequested = false;
+ __instance._animationStarted = false;
+ foreach (var alarmBell in AlarmTotemManager.AlarmBells)
+ {
+ alarmBell.StopAnimation();
+ }
+ return false;
+ }
+
+ [HarmonyPrefix]
+ [HarmonyPatch(nameof(AlarmSequenceController.Update))]
+ private static bool Update(AlarmSequenceController __instance)
+ {
+ __instance.UpdateWakeFraction();
+ if (__instance._playing)
+ {
+ __instance.UpdateChimes();
+ }
+ __instance.UpdatePulse();
+ if (!__instance._playing && __instance._alarmCounter == 0 && __instance._pulse <= 0.01f)
+ {
+ __instance._pulse = 0f;
+ __instance._targetPulse = 0f;
+ __instance.enabled = false;
+ }
+ return false;
+ }
+
+ [HarmonyPrefix]
+ [HarmonyPatch(nameof(AlarmSequenceController.PlaySingleChime))]
+ private static bool PlaySingleChime(AlarmSequenceController __instance)
+ {
+ foreach (var alarmBell in AlarmTotemManager.AlarmBells)
+ {
+ alarmBell.PlaySingleChime(__instance._chimeIndex);
+ }
+ if (!__instance._animationStarted && !__instance._dreamWorldController.IsInDream())
+ {
+ foreach (var alarmBell in AlarmTotemManager.AlarmBells)
+ {
+ alarmBell.PlayAnimation();
+ }
+ __instance._animationStarted = true;
+ }
+ if (__instance._dreamWorldController.IsInDream() && !__instance._dreamWorldController.IsExitingDream())
+ {
+ Locator.GetDreamWorldAudioController().PlaySingleAlarmChime(__instance._chimeIndex, __instance._volumeCurve.Evaluate(__instance._wakeFraction));
+ }
+ return false;
+ }
+}
diff --git a/QSB/EchoesOfTheEye/AlarmTotemSync/Patches/AlarmTotemPatches.cs b/QSB/EchoesOfTheEye/AlarmTotemSync/Patches/AlarmTotemPatches.cs
index 93169d62..8b84d710 100644
--- a/QSB/EchoesOfTheEye/AlarmTotemSync/Patches/AlarmTotemPatches.cs
+++ b/QSB/EchoesOfTheEye/AlarmTotemSync/Patches/AlarmTotemPatches.cs
@@ -1,8 +1,11 @@
using HarmonyLib;
+using QSB.AuthoritySync;
using QSB.EchoesOfTheEye.AlarmTotemSync.Messages;
using QSB.EchoesOfTheEye.AlarmTotemSync.WorldObjects;
using QSB.Messaging;
using QSB.Patches;
+using QSB.Player;
+using QSB.Utility;
using QSB.WorldSync;
using UnityEngine;
@@ -12,27 +15,58 @@ public class AlarmTotemPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
- /*
[HarmonyPrefix]
[HarmonyPatch(typeof(AlarmTotem), nameof(AlarmTotem.OnSectorOccupantAdded))]
- private static void OnSectorOccupantAdded(AlarmTotem __instance, SectorDetector sectorDetector)
+ private static bool OnSectorOccupantAdded(AlarmTotem __instance, SectorDetector sectorDetector)
{
- if (sectorDetector.GetOccupantType() == DynamicOccupant.Player && QSBWorldSync.AllObjectsReady)
+ if (!QSBWorldSync.AllObjectsReady)
{
- __instance.GetWorldObject()
- .SendMessage(new TotemEnabledMessage(true));
+ return true;
}
+
+ if (sectorDetector.GetOccupantType() == DynamicOccupant.Player)
+ {
+ __instance.enabled = true;
+ var qsbAlarmTotem = __instance.GetWorldObject();
+ qsbAlarmTotem.RequestOwnership();
+ }
+ return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(AlarmTotem), nameof(AlarmTotem.OnSectorOccupantRemoved))]
- private static void OnSectorOccupantRemoved(AlarmTotem __instance, SectorDetector sectorDetector)
+ private static bool OnSectorOccupantRemoved(AlarmTotem __instance, SectorDetector sectorDetector)
{
- if (sectorDetector.GetOccupantType() == DynamicOccupant.Player && QSBWorldSync.AllObjectsReady)
+ if (!QSBWorldSync.AllObjectsReady)
{
- __instance.GetWorldObject()
- .SendMessage(new TotemEnabledMessage(false));
+ return true;
}
+
+ if (sectorDetector.GetOccupantType() == DynamicOccupant.Player)
+ {
+ __instance.enabled = false;
+ var qsbAlarmTotem = __instance.GetWorldObject();
+ qsbAlarmTotem.ReleaseOwnership();
+ Delay.RunFramesLater(10, () =>
+ {
+ // no one else took ownership, so we can safely turn stuff off
+ // ie turn off when no one else is there
+ if (qsbAlarmTotem.Owner == 0)
+ {
+ __instance._pulseLightController.SetIntensity(0f);
+ __instance._simTotemMaterials[0] = __instance._origSimEyeMaterial;
+ __instance._simTotemRenderer.sharedMaterials = __instance._simTotemMaterials;
+ __instance._simVisionConeRenderer.SetColor(__instance._simVisionConeRenderer.GetOriginalColor());
+ if (__instance._isPlayerVisible)
+ {
+ __instance._isPlayerVisible = false;
+ __instance._secondsConcealed = 0f;
+ Locator.GetAlarmSequenceController().DecreaseAlarmCounter();
+ }
+ }
+ });
+ }
+ return false;
}
[HarmonyPrefix]
@@ -43,45 +77,87 @@ public class AlarmTotemPatches : QSBPatch
{
return true;
}
-
var qsbAlarmTotem = __instance.GetWorldObject();
- var isLocallyVisible = qsbAlarmTotem.IsLocallyVisible;
- qsbAlarmTotem.IsLocallyVisible = __instance.CheckPlayerVisible();
- if (qsbAlarmTotem.IsLocallyVisible && !isLocallyVisible)
+ if (qsbAlarmTotem.Owner != QSBPlayerManager.LocalPlayerId)
{
- qsbAlarmTotem.SendMessage(new TotemVisibleMessage(true));
- }
- else if (isLocallyVisible && !qsbAlarmTotem.IsLocallyVisible)
- {
- qsbAlarmTotem.SendMessage(new TotemVisibleMessage(false));
+ return false;
}
var isPlayerVisible = __instance._isPlayerVisible;
- __instance._isPlayerVisible = qsbAlarmTotem.VisibleFor.Count > 0;
- if (__instance._isPlayerVisible && !isPlayerVisible)
+ __instance._isPlayerVisible = __instance.CheckPlayerVisible();
+ if (!isPlayerVisible && __instance._isPlayerVisible)
{
Locator.GetAlarmSequenceController().IncreaseAlarmCounter();
+ __instance._secondsConcealed = 0f;
__instance._simTotemMaterials[0] = __instance._simAlarmMaterial;
__instance._simTotemRenderer.sharedMaterials = __instance._simTotemMaterials;
__instance._simVisionConeRenderer.SetColor(__instance._simAlarmColor);
- if (__instance._isTutorialTotem)
- {
- GlobalMessenger.FireEvent("TutorialAlarmTotemTriggered");
- }
+ GlobalMessenger.FireEvent("AlarmTotemTriggered");
+ qsbAlarmTotem.SendMessage(new SetVisibleMessage(true));
}
else if (isPlayerVisible && !__instance._isPlayerVisible)
{
Locator.GetAlarmSequenceController().DecreaseAlarmCounter();
+ __instance._secondsConcealed = 0f;
__instance._simTotemMaterials[0] = __instance._origSimEyeMaterial;
__instance._simTotemRenderer.sharedMaterials = __instance._simTotemMaterials;
__instance._simVisionConeRenderer.SetColor(__instance._simVisionConeRenderer.GetOriginalColor());
__instance._pulseLightController.FadeTo(0f, 0.5f);
+ qsbAlarmTotem.SendMessage(new SetVisibleMessage(false));
}
-
return false;
}
- */
+
+ [HarmonyPrefix]
+ [HarmonyPatch(typeof(AlarmTotem), nameof(AlarmTotem.CheckPlayerVisible))]
+ private static bool CheckPlayerVisible(AlarmTotem __instance, out bool __result)
+ {
+ if (!__instance._isFaceOpen)
+ {
+ __result = false;
+ return false;
+ }
+ foreach (var player in QSBPlayerManager.PlayerList)
+ {
+ var position = player.Camera.transform.position;
+ if (__instance.CheckPointInVisionCone(position) && !__instance.CheckLineOccluded(__instance._sightOrigin.position, position))
+ {
+ if (player.LightSensor.IsIlluminated())
+ {
+ __result = true;
+ return false;
+ }
+ if (player.AssignedSimulationLantern == null)
+ {
+ continue;
+ }
+ var lanternController = player.AssignedSimulationLantern.AttachedObject.GetLanternController();
+ if (lanternController.IsHeldByPlayer())
+ {
+ if (lanternController.IsConcealed())
+ {
+ if (!__instance._hasConcealedFromAlarm)
+ {
+ __instance._secondsConcealed += Time.deltaTime;
+ if (__instance._secondsConcealed > 1f)
+ {
+ __instance._hasConcealedFromAlarm = true;
+ GlobalMessenger.FireEvent("ConcealFromAlarmTotem");
+ }
+ }
+ __result = false;
+ return false;
+ }
+ __result = true;
+ return false;
+ }
+ }
+ }
+ __result = false;
+ return false;
+ }
+
[HarmonyPrefix]
[HarmonyPatch(typeof(AlarmBell), nameof(AlarmBell.OnEntry))]
diff --git a/QSB/EchoesOfTheEye/AlarmTotemSync/QSBAlarmSequenceController.cs b/QSB/EchoesOfTheEye/AlarmTotemSync/QSBAlarmSequenceController.cs
deleted file mode 100644
index d81c178d..00000000
--- a/QSB/EchoesOfTheEye/AlarmTotemSync/QSBAlarmSequenceController.cs
+++ /dev/null
@@ -1,245 +0,0 @@
-using UnityEngine;
-
-namespace QSB.EchoesOfTheEye.AlarmTotemSync;
-
-///
-/// copied and modified from base game
-///
-public class QSBAlarmSequenceController : MonoBehaviour
-{
- private const int CHIME_COUNT = 3;
-
- [SerializeField]
- private float _wakeDuration = 5f;
-
- [SerializeField]
- private float _recoveryDuration = 2f;
-
- [Header("Audio")]
- [SerializeField]
- private float _audioLingerTime = 3f;
-
- [SerializeField]
- private AnimationCurve _volumeCurve;
-
- [Header("Pulse")]
- [SerializeField]
- private float _pulseAttackLength = 0.2f;
-
- [SerializeField]
- private float _pulseHoldLength = 0.1f;
-
- [SerializeField]
- private float _pulseCooldownLength = 1f;
-
- private DreamWorldController _dreamWorldController;
-
- private AlarmBell _activeBell;
-
- private int _alarmCounter;
-
- private float _wakeFraction;
-
- private float _targetPulse;
-
- private float _pulse;
-
- private bool _playing;
-
- private bool _animationStarted;
-
- private bool _stopRequested;
-
- private float _stopTime;
-
- private int _chimeIndex;
-
- private float _lastChimeTime;
-
- private float _chimeInterval;
-
- private void Awake()
- {
- // Locator.RegisterAlarmSequenceController(this);
- GlobalMessenger.AddListener("ExitDreamWorld", OnExitDreamWorld);
- }
-
- private void Start()
- {
- _dreamWorldController = Locator.GetDreamWorldController();
- enabled = false;
- }
-
- private void OnDestroy()
- {
- GlobalMessenger.RemoveListener("ExitDreamWorld", OnExitDreamWorld);
- }
-
- public void RegisterDreamEyeMaskController(DreamEyeMaskController dreamEyeMaskController) { }
-
- public float GetPulseIntensity() => _pulse;
-
- public bool IsAlarmWakingPlayer() => _alarmCounter > 0 && !PlayerState.IsResurrected();
-
- public void IncreaseAlarmCounter()
- {
- if (!_dreamWorldController.IsInDream() || _dreamWorldController.IsExitingDream())
- {
- return;
- }
-
- _alarmCounter++;
- if (_alarmCounter == 1)
- {
- PlayChimes();
- }
-
- enabled = true;
- }
-
- public void DecreaseAlarmCounter()
- {
- if (!_dreamWorldController.IsInDream() || _dreamWorldController.IsExitingDream())
- {
- return;
- }
-
- _alarmCounter--;
- if (_alarmCounter < 0)
- {
- _alarmCounter = 0;
- Debug.LogError("Something went wrong, alarm counter should never drop below zero!");
- }
- }
-
- private void PlayChimes()
- {
- if (Locator.GetDreamWorldController().GetDreamCampfire() != null)
- {
- _activeBell = Locator.GetDreamWorldController().GetDreamCampfire().GetAlarmBell();
- }
-
- _playing = true;
- _chimeInterval = 1f;
- _lastChimeTime = 0f;
- _stopRequested = false;
- }
-
- private void StopChimes()
- {
- _playing = false;
- _stopRequested = false;
- _animationStarted = false;
- if (_activeBell != null)
- {
- _activeBell.StopAnimation();
- _activeBell = null;
- }
- }
-
- private void Update()
- {
- if (_dreamWorldController.IsInDream() && !_dreamWorldController.IsExitingDream())
- {
- UpdateWakeFraction();
- }
-
- if (_playing)
- {
- UpdateChimes();
- }
-
- UpdatePulse();
- if (!_playing && _alarmCounter == 0 && _pulse <= 0.01f)
- {
- _pulse = 0f;
- _targetPulse = 0f;
- enabled = false;
- }
- }
-
- private void UpdateWakeFraction()
- {
- if (_alarmCounter > 0)
- {
- _wakeFraction = Mathf.MoveTowards(_wakeFraction, 1f, Time.deltaTime / _wakeDuration);
- if (_wakeFraction >= 1f && !PlayerState.IsResurrected())
- {
- _dreamWorldController.ExitDreamWorld(DreamWakeType.Alarm);
- }
- }
- else if (_wakeFraction > 0f)
- {
- _wakeFraction = Mathf.MoveTowards(_wakeFraction, 0f, Time.deltaTime / _recoveryDuration);
- if (_wakeFraction <= 0f)
- {
- StopChimes();
- }
- }
- }
-
- private void UpdateChimes()
- {
- if (Time.time > _lastChimeTime + _chimeInterval)
- {
- if (!PlayerState.IsResurrected())
- {
- PlaySingleChime();
- }
-
- _targetPulse = 1f;
- _lastChimeTime = Time.time;
- _chimeInterval = Mathf.Max(_chimeInterval - 0.08f, 0.4f);
- _chimeIndex++;
- _chimeIndex = _chimeIndex >= CHIME_COUNT ? 0 : _chimeIndex;
- }
-
- if (_stopRequested && Time.time > _stopTime)
- {
- StopChimes();
- }
- }
-
- private void UpdatePulse()
- {
- if (Time.time > _lastChimeTime + _pulseAttackLength + _pulseHoldLength)
- {
- var num = _pulseCooldownLength * _chimeInterval;
- _targetPulse = Mathf.MoveTowards(_targetPulse, 0f, 1f / num * Time.deltaTime);
- _pulse = _targetPulse;
- return;
- }
-
- _pulse = Mathf.MoveTowards(_pulse, _targetPulse, 1f / _pulseAttackLength * Time.deltaTime);
- }
-
- private void PlaySingleChime()
- {
- if (_activeBell != null)
- {
- _activeBell.PlaySingleChime(_chimeIndex);
- if (!_animationStarted && !_dreamWorldController.IsInDream())
- {
- _activeBell.PlayAnimation();
- _animationStarted = true;
- }
- }
-
- if (_dreamWorldController.IsInDream() && !_dreamWorldController.IsExitingDream())
- {
- Locator.GetDreamWorldAudioController().PlaySingleAlarmChime(_chimeIndex, _volumeCurve.Evaluate(_wakeFraction));
- }
- }
-
- private void OnExitDreamWorld()
- {
- if (_playing)
- {
- _stopRequested = true;
- _stopTime = Time.time + _audioLingerTime;
- }
-
- _alarmCounter = 0;
- _wakeFraction = 0f;
- }
-}
diff --git a/QSB/EchoesOfTheEye/AlarmTotemSync/WorldObjects/QSBAlarmTotem.cs b/QSB/EchoesOfTheEye/AlarmTotemSync/WorldObjects/QSBAlarmTotem.cs
index 69ff7f9b..b8a3affd 100644
--- a/QSB/EchoesOfTheEye/AlarmTotemSync/WorldObjects/QSBAlarmTotem.cs
+++ b/QSB/EchoesOfTheEye/AlarmTotemSync/WorldObjects/QSBAlarmTotem.cs
@@ -1,83 +1,17 @@
-using Cysharp.Threading.Tasks;
+using QSB.AuthoritySync;
using QSB.EchoesOfTheEye.AlarmTotemSync.Messages;
using QSB.Messaging;
-using QSB.Player;
-using QSB.WorldSync;
-using System.Collections.Generic;
-using System.Threading;
namespace QSB.EchoesOfTheEye.AlarmTotemSync.WorldObjects;
-///
-/// TODO: make this not NRE (by not doing enable sync) and then readd it back in
-///
-public class QSBAlarmTotem : WorldObject
+public class QSBAlarmTotem : AuthWorldObject
{
- public readonly List VisibleFor = new();
- public bool IsLocallyVisible;
+ public override bool CanOwn => AttachedObject.enabled;
public override void SendInitialState(uint to)
{
- this.SendMessage(new TotemEnabledMessage(AttachedObject.enabled) { To = to });
- this.SendMessage(new TotemVisibleForMessage(VisibleFor) { To = to });
- }
+ base.SendInitialState(to);
- public override async UniTask Init(CancellationToken ct) =>
- QSBPlayerManager.OnRemovePlayer += OnPlayerLeave;
-
- public override void OnRemoval() =>
- QSBPlayerManager.OnRemovePlayer -= OnPlayerLeave;
-
- private void OnPlayerLeave(PlayerInfo player) =>
- VisibleFor.QuickRemove(player.PlayerId);
-
- public void SetVisible(uint playerId, bool visible)
- {
- if (visible)
- {
- VisibleFor.SafeAdd(playerId);
- }
- else
- {
- VisibleFor.QuickRemove(playerId);
- }
- }
-
- public void SetEnabled(bool enabled)
- {
- if (AttachedObject.enabled == enabled)
- {
- return;
- }
-
- if (!enabled &&
- AttachedObject._sector &&
- AttachedObject._sector.ContainsOccupant(DynamicOccupant.Player))
- {
- // local player is in sector, do not disable
- return;
- }
-
- AttachedObject.enabled = enabled;
-
- if (!enabled)
- {
- AttachedObject._simTotemMaterials[0] = AttachedObject._origSimEyeMaterial;
- AttachedObject._simTotemRenderer.sharedMaterials = AttachedObject._simTotemMaterials;
- AttachedObject._simVisionConeRenderer.SetColor(AttachedObject._simVisionConeRenderer.GetOriginalColor());
- AttachedObject._pulseLightController.SetIntensity(0f);
- /*
- if (AttachedObject._isPlayerVisible)
- {
- AttachedObject._isPlayerVisible = false;
- Locator.GetAlarmSequenceController().DecreaseAlarmCounter();
- }
- */
- if (IsLocallyVisible)
- {
- IsLocallyVisible = false;
- this.SendMessage(new TotemVisibleMessage(false));
- }
- }
+ this.SendMessage(new SetVisibleMessage(AttachedObject._isPlayerVisible) { To = to });
}
}
diff --git a/QSB/EchoesOfTheEye/DreamWorld/Messages/DreamWorldFakePlayer.cs b/QSB/EchoesOfTheEye/DreamWorld/Messages/DreamWorldFakePlayer.cs
new file mode 100644
index 00000000..10661e10
--- /dev/null
+++ b/QSB/EchoesOfTheEye/DreamWorld/Messages/DreamWorldFakePlayer.cs
@@ -0,0 +1,114 @@
+using HarmonyLib;
+using QSB.Animation.Player;
+using QSB.Messaging;
+using QSB.Patches;
+using QSB.Player;
+using QSB.Utility;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace QSB.EchoesOfTheEye.DreamWorld.Messages;
+
+public class DreamWorldFakePlayer : MonoBehaviour
+{
+ private static readonly List _instances = new();
+
+ public static void Create(PlayerInfo player)
+ {
+ var go = new GameObject($"player {player} DreamWorldFakePlayer");
+ go.SetActive(false);
+ go.AddComponent()._player = player;
+ go.SetActive(true);
+ }
+
+ public static void Destroy(PlayerInfo player)
+ {
+ foreach (var dreamWorldFakePlayer in _instances)
+ {
+ if (dreamWorldFakePlayer._player == player)
+ {
+ Destroy(dreamWorldFakePlayer.gameObject);
+ }
+ }
+ }
+
+ private PlayerInfo _player;
+
+ private void Awake()
+ {
+ _instances.SafeAdd(this);
+ QSBPlayerManager.OnRemovePlayer += OnRemovePlayer;
+
+ transform.parent = _player.TransformSync.ReferenceTransform;
+ transform.localPosition = _player.TransformSync.transform.position;
+ transform.localRotation = _player.TransformSync.transform.rotation;
+
+ #region fake player
+
+ var fakePlayer = _player.Body.transform.Find("REMOTE_Traveller_HEA_Player_v2").gameObject.InstantiateInactive();
+ fakePlayer.transform.SetParent(transform, false);
+
+ Destroy(fakePlayer.GetComponent());
+ Destroy(fakePlayer.GetComponent());
+
+ var REMOTE_ItemCarryTool = fakePlayer.transform.Find(
+ // TODO : kill me for my sins
+ "Traveller_Rig_v01:Traveller_Trajectory_Jnt/" +
+ "Traveller_Rig_v01:Traveller_ROOT_Jnt/" +
+ "Traveller_Rig_v01:Traveller_Spine_01_Jnt/" +
+ "Traveller_Rig_v01:Traveller_Spine_02_Jnt/" +
+ "Traveller_Rig_v01:Traveller_Spine_Top_Jnt/" +
+ "Traveller_Rig_v01:Traveller_RT_Arm_Clavicle_Jnt/" +
+ "Traveller_Rig_v01:Traveller_RT_Arm_Shoulder_Jnt/" +
+ "Traveller_Rig_v01:Traveller_RT_Arm_Elbow_Jnt/" +
+ "Traveller_Rig_v01:Traveller_RT_Arm_Wrist_Jnt/" +
+ "REMOTE_ItemCarryTool"
+ ).gameObject;
+ Destroy(REMOTE_ItemCarryTool);
+
+ fakePlayer.SetActive(true);
+
+ #endregion
+ }
+
+ private void OnDestroy()
+ {
+ _instances.QuickRemove(this);
+ QSBPlayerManager.OnRemovePlayer -= OnRemovePlayer;
+ }
+
+ private void OnRemovePlayer(PlayerInfo player)
+ {
+ if (player != _player)
+ {
+ return;
+ }
+ Destroy(gameObject);
+ }
+}
+
+public class DreamWorldFakePlayerPatch : QSBPatch
+{
+ public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
+
+ ///
+ /// do this early to create the fake player BEFORE teleporting
+ ///
+ [HarmonyPatch(typeof(DreamWorldController), nameof(DreamWorldController.EnterDreamWorld))]
+ [HarmonyPrefix]
+ private static void EnterDreamWorld()
+ {
+ if (Locator.GetToolModeSwapper().GetItemCarryTool().GetHeldItemType() == ItemType.DreamLantern)
+ {
+ new DreamWorldFakePlayerMessage().Send();
+ }
+ }
+}
+
+public class DreamWorldFakePlayerMessage : QSBMessage
+{
+ public override void OnReceiveRemote()
+ {
+ DreamWorldFakePlayer.Create(QSBPlayerManager.GetPlayer(From));
+ }
+}
diff --git a/QSB/EchoesOfTheEye/DreamWorld/Messages/EnterDreamWorldMessage.cs b/QSB/EchoesOfTheEye/DreamWorld/Messages/EnterDreamWorldMessage.cs
index b0c1dbd9..7bd9b6ad 100644
--- a/QSB/EchoesOfTheEye/DreamWorld/Messages/EnterDreamWorldMessage.cs
+++ b/QSB/EchoesOfTheEye/DreamWorld/Messages/EnterDreamWorldMessage.cs
@@ -1,7 +1,5 @@
-using QSB.EchoesOfTheEye.DreamLantern;
-using QSB.EchoesOfTheEye.DreamLantern.WorldObjects;
+using QSB.EchoesOfTheEye.DreamLantern.WorldObjects;
using QSB.EchoesOfTheEye.Ghosts.WorldObjects;
-using QSB.ItemSync.WorldObjects.Items;
using QSB.Messaging;
using QSB.Player;
using QSB.Player.TransformSync;
diff --git a/QSB/EchoesOfTheEye/DreamWorld/Messages/ExitDreamWorldMessage.cs b/QSB/EchoesOfTheEye/DreamWorld/Messages/ExitDreamWorldMessage.cs
index b1302cf8..373e25d3 100644
--- a/QSB/EchoesOfTheEye/DreamWorld/Messages/ExitDreamWorldMessage.cs
+++ b/QSB/EchoesOfTheEye/DreamWorld/Messages/ExitDreamWorldMessage.cs
@@ -50,5 +50,8 @@ internal class ExitDreamWorldMessage : QSBMessage
ghost.GetEffects().OnSectorOccupantsUpdated();
}
}
+
+ Locator.GetAlarmSequenceController().OnExitDreamWorld();
+ DreamWorldFakePlayer.Destroy(player);
}
}
diff --git a/QSB/GetAttachedOWRigidbodyPatch.cs b/QSB/GetAttachedOWRigidbodyPatch.cs
index 7ee82ab1..2d045faa 100644
--- a/QSB/GetAttachedOWRigidbodyPatch.cs
+++ b/QSB/GetAttachedOWRigidbodyPatch.cs
@@ -4,9 +4,6 @@ using UnityEngine;
namespace QSB;
-///
-/// TODO: TEST THIS. see if things horribly break. this could be huge.
-///
[HarmonyPatch(typeof(OWExtensions))]
public class GetAttachedOWRigidbodyPatch : QSBPatch
{
diff --git a/QSB/Menus/MenuManager.cs b/QSB/Menus/MenuManager.cs
index 007e5910..22c78780 100644
--- a/QSB/Menus/MenuManager.cs
+++ b/QSB/Menus/MenuManager.cs
@@ -42,7 +42,7 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
private const int _titleButtonIndex = 2;
private float _connectPopupOpenTime;
- private const string UpdateChangelog = "QSB Version 0.22.0\r\nFixed lots of bugs, and added lots of SFX and VFX stuff.";
+ private const string UpdateChangelog = "QSB Version 0.23.0\r\nA lot of small improvements and bug fixes.";
private Action PopupClose;
diff --git a/QSB/ModelShip/Messages/UseFlightConsoleMessage.cs b/QSB/ModelShip/Messages/UseFlightConsoleMessage.cs
index 464e7f3b..f4abfe95 100644
--- a/QSB/ModelShip/Messages/UseFlightConsoleMessage.cs
+++ b/QSB/ModelShip/Messages/UseFlightConsoleMessage.cs
@@ -74,6 +74,9 @@ internal class UseFlightConsoleMessage : QSBMessage
// Client messes up its position when they start flying it
// We can just recall it immediately so its in the right place.
var console = QSBWorldSync.GetUnityObject();
- console.RespawnModelShip(false);
+ if (console._modelShipBody) // for when model ship is destroyed
+ {
+ console.RespawnModelShip(false);
+ }
}
}
diff --git a/QSB/Player/PlayerHUDMarker.cs b/QSB/Player/PlayerHUDMarker.cs
index ebcc7e04..02e33c3c 100644
--- a/QSB/Player/PlayerHUDMarker.cs
+++ b/QSB/Player/PlayerHUDMarker.cs
@@ -1,4 +1,5 @@
-using QSB.Utility;
+using QSB.ServerSettings;
+using QSB.Utility;
using UnityEngine;
namespace QSB.Player;
@@ -34,6 +35,11 @@ public class PlayerHUDMarker : HUDDistanceMarker
return false;
}
+ if (!ServerSettingsManager.ShowPlayerNames)
+ {
+ return false;
+ }
+
return _player.IsReady &&
!_player.IsDead &&
_player.Visible &&
diff --git a/QSB/Player/PlayerInfo.cs b/QSB/Player/PlayerInfo.cs
index 06715acd..c6a0fe42 100644
--- a/QSB/Player/PlayerInfo.cs
+++ b/QSB/Player/PlayerInfo.cs
@@ -22,6 +22,7 @@ public partial class PlayerInfo
public uint PlayerId { get; }
public string Name { get; set; }
public PlayerHUDMarker HudMarker { get; set; }
+ public PlayerMapMarker MapMarker { get; set; }
public PlayerTransformSync TransformSync { get; }
public ClientState State { get; set; }
public EyeState EyeState { get; set; }
diff --git a/QSB/Player/PlayerMapMarker.cs b/QSB/Player/PlayerMapMarker.cs
index 6904b095..417b7040 100644
--- a/QSB/Player/PlayerMapMarker.cs
+++ b/QSB/Player/PlayerMapMarker.cs
@@ -1,4 +1,5 @@
-using QSB.Utility;
+using QSB.ServerSettings;
+using QSB.Utility;
using UnityEngine;
namespace QSB.Player;
@@ -31,6 +32,7 @@ public class PlayerMapMarker : MonoBehaviour
public void Init(PlayerInfo player)
{
_player = player;
+ _player.MapMarker = this;
_hasBeenSetUpForInit = true;
}
@@ -57,6 +59,11 @@ public class PlayerMapMarker : MonoBehaviour
return false;
}
+ if (!ServerSettingsManager.ShowPlayerNames)
+ {
+ return false;
+ }
+
var playerScreenPos = Locator.GetActiveCamera().WorldToScreenPoint(transform.position);
var isInfrontOfCamera = playerScreenPos.z > 0f;
@@ -82,4 +89,9 @@ public class PlayerMapMarker : MonoBehaviour
_canvasMarker.SetVisibility(shouldBeVisible);
}
}
+
+ public void Remove()
+ {
+ // TODO
+ }
}
\ No newline at end of file
diff --git a/QSB/Player/TransformSync/PlayerTransformSync.cs b/QSB/Player/TransformSync/PlayerTransformSync.cs
index ee2bc73d..c030693c 100644
--- a/QSB/Player/TransformSync/PlayerTransformSync.cs
+++ b/QSB/Player/TransformSync/PlayerTransformSync.cs
@@ -54,6 +54,7 @@ public class PlayerTransformSync : SectoredTransformSync
QSBPatch.Remote = false;
base.OnStopClient();
Player.HudMarker?.Remove();
+ Player.MapMarker?.Remove();
QSBPlayerManager.PlayerList.Remove(Player);
DebugLog.DebugWrite($"Remove Player : {Player}", MessageType.Info);
}
diff --git a/QSB/PlayerBodySetup/Remote/ShaderReplacer.cs b/QSB/PlayerBodySetup/Remote/ShaderReplacer.cs
index 69f05fbb..338b436b 100644
--- a/QSB/PlayerBodySetup/Remote/ShaderReplacer.cs
+++ b/QSB/PlayerBodySetup/Remote/ShaderReplacer.cs
@@ -29,11 +29,18 @@ public static class ShaderReplacer
// preserve override tag and render queue (for Standard shader)
// keywords and properties are already preserved
- var renderType = material.GetTag("RenderType", false);
- var renderQueue = material.renderQueue;
- material.shader = replacementShader;
- material.SetOverrideTag("RenderType", renderType);
- material.renderQueue = renderQueue;
+ if (material.renderQueue != material.shader.renderQueue)
+ {
+ var renderType = material.GetTag("RenderType", false);
+ var renderQueue = material.renderQueue;
+ material.shader = replacementShader;
+ material.SetOverrideTag("RenderType", renderType);
+ material.renderQueue = renderQueue;
+ }
+ else
+ {
+ material.shader = replacementShader;
+ }
}
}
}
diff --git a/QSB/QSB.csproj b/QSB/QSB.csproj
index 8bfae7dd..177373de 100644
--- a/QSB/QSB.csproj
+++ b/QSB/QSB.csproj
@@ -59,7 +59,7 @@
-
+
diff --git a/QSB/QSBCore.cs b/QSB/QSBCore.cs
index 32ff5fa1..48e9137c 100644
--- a/QSB/QSBCore.cs
+++ b/QSB/QSBCore.cs
@@ -4,9 +4,11 @@ using OWML.Common;
using OWML.ModHelper;
using QSB.Localization;
using QSB.Menus;
+using QSB.Messaging;
using QSB.Patches;
using QSB.QuantumSync;
using QSB.SaveSync;
+using QSB.ServerSettings;
using QSB.Utility;
using QSB.WorldSync;
using System;
@@ -56,6 +58,8 @@ public class QSBCore : ModBehaviour
Application.version.Split('.').Take(3).Join(delimiter: ".");
public static bool DLCInstalled => EntitlementsManager.IsDlcOwned() == EntitlementsManager.AsyncOwnershipStatus.Owned;
public static bool IncompatibleModsAllowed { get; private set; }
+ public static bool ShowPlayerNames { get; private set; }
+ public static bool ShipDamage { get; private set; }
public static GameVendor GameVendor { get; private set; } = GameVendor.None;
public static bool IsStandalone => GameVendor is GameVendor.Epic or GameVendor.Steam;
public static IProfileManager ProfileManager => IsStandalone
@@ -247,6 +251,14 @@ public class QSBCore : ModBehaviour
{
DefaultServerIP = config.GetSettingsValue("defaultServerIP");
IncompatibleModsAllowed = config.GetSettingsValue("incompatibleModsAllowed");
+ ShowPlayerNames = config.GetSettingsValue("showPlayerNames");
+ ShipDamage = config.GetSettingsValue("shipDamage");
+
+ if (IsHost)
+ {
+ ServerSettingsManager.ServerShowPlayerNames = ShowPlayerNames;
+ new ServerSettingsMessage().Send();
+ }
}
private void Update()
diff --git a/QSB/QSBNetworkManager.cs b/QSB/QSBNetworkManager.cs
index 28a05a52..9d920dbf 100644
--- a/QSB/QSBNetworkManager.cs
+++ b/QSB/QSBNetworkManager.cs
@@ -315,7 +315,11 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
Destroy(GetComponent());
Destroy(GetComponent());
Destroy(GetComponent());
- QSBPlayerManager.PlayerList.ForEach(player => player.HudMarker?.Remove());
+ QSBPlayerManager.PlayerList.ForEach(player =>
+ {
+ player.HudMarker?.Remove();
+ player.MapMarker?.Remove();
+ });
QSBWorldSync.RemoveWorldObjects();
@@ -397,7 +401,11 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
DebugLog.DebugWrite("OnStopServer", MessageType.Info);
Destroy(GetComponent());
DebugLog.ToConsole("Server stopped!", MessageType.Info);
- QSBPlayerManager.PlayerList.ForEach(player => player.HudMarker?.Remove());
+ QSBPlayerManager.PlayerList.ForEach(player =>
+ {
+ player.HudMarker?.Remove();
+ player.MapMarker?.Remove();
+ });
base.OnStopServer();
}
diff --git a/QSB/SaveSync/Messages/RequestGameStateMessage.cs b/QSB/SaveSync/Messages/RequestGameStateMessage.cs
index 42a24547..da49e43c 100644
--- a/QSB/SaveSync/Messages/RequestGameStateMessage.cs
+++ b/QSB/SaveSync/Messages/RequestGameStateMessage.cs
@@ -1,6 +1,7 @@
using QSB.ConversationSync.Messages;
using QSB.Messaging;
using QSB.Player;
+using QSB.ServerSettings;
using QSB.Utility;
namespace QSB.SaveSync.Messages;
@@ -21,6 +22,7 @@ internal class RequestGameStateMessage : QSBMessage
}
new GameStateMessage(From).Send();
+ new ServerSettingsMessage().Send();
var gameSave = PlayerData._currentGameSave;
diff --git a/QSB/ServerSettings/ServerSettingsManager.cs b/QSB/ServerSettings/ServerSettingsManager.cs
new file mode 100644
index 00000000..505f0ba2
--- /dev/null
+++ b/QSB/ServerSettings/ServerSettingsManager.cs
@@ -0,0 +1,10 @@
+using QSB.Utility;
+using UnityEngine;
+
+namespace QSB.ServerSettings;
+
+internal class ServerSettingsManager : MonoBehaviour, IAddComponentOnStart
+{
+ public static bool ServerShowPlayerNames;
+ public static bool ShowPlayerNames => (ServerShowPlayerNames || QSBCore.IsHost) && QSBCore.ShowPlayerNames;
+}
diff --git a/QSB/ServerSettings/ServerSettingsMessage.cs b/QSB/ServerSettings/ServerSettingsMessage.cs
new file mode 100644
index 00000000..1b88b00c
--- /dev/null
+++ b/QSB/ServerSettings/ServerSettingsMessage.cs
@@ -0,0 +1,27 @@
+using Mirror;
+using QSB.Messaging;
+
+namespace QSB.ServerSettings;
+
+internal class ServerSettingsMessage : QSBMessage
+{
+ private bool _showPlayerNames;
+
+ public ServerSettingsMessage()
+ => _showPlayerNames = QSBCore.ShowPlayerNames;
+
+ public override void Serialize(NetworkWriter writer)
+ {
+ base.Serialize(writer);
+ writer.Write(_showPlayerNames);
+ }
+
+ public override void Deserialize(NetworkReader reader)
+ {
+ base.Deserialize(reader);
+ _showPlayerNames = reader.ReadBool();
+ }
+
+ public override void OnReceiveRemote()
+ => ServerSettingsManager.ServerShowPlayerNames = _showPlayerNames;
+}
diff --git a/QSB/TimeSync/Patches/TimePatches.cs b/QSB/TimeSync/Patches/TimePatches.cs
index 3b807a19..66d7899c 100644
--- a/QSB/TimeSync/Patches/TimePatches.cs
+++ b/QSB/TimeSync/Patches/TimePatches.cs
@@ -4,6 +4,7 @@ using QSB.Messaging;
using QSB.Patches;
using QSB.TimeSync.Messages;
using QSB.Utility;
+using UnityEngine;
namespace QSB.TimeSync.Patches;
diff --git a/QSB/TimeSync/WakeUpSync.cs b/QSB/TimeSync/WakeUpSync.cs
index 8366a995..26479397 100644
--- a/QSB/TimeSync/WakeUpSync.cs
+++ b/QSB/TimeSync/WakeUpSync.cs
@@ -8,6 +8,7 @@ using QSB.Messaging;
using QSB.Player;
using QSB.Player.Messages;
using QSB.TimeSync.Messages;
+using QSB.TimeSync.Patches;
using QSB.Utility;
using QSB.WorldSync;
using System;
@@ -46,7 +47,6 @@ public class WakeUpSync : NetworkBehaviour
{
OWTime.SetTimeScale(1f);
OWTime.SetMaxDeltaTime(0.06666667f);
- OWTime.SetFixedTimestep(0.01666667f);
Locator.GetActiveCamera().enabled = true;
CurrentState = State.NotLoaded;
CurrentReason = null;
@@ -214,7 +214,6 @@ public class WakeUpSync : NetworkBehaviour
CurrentState = State.FastForwarding;
CurrentReason = reason;
OWTime.SetMaxDeltaTime(0.033333335f);
- OWTime.SetFixedTimestep(0.033333335f);
TimeSyncUI.TargetTime = _serverTime;
TimeSyncUI.Start(TimeSyncType.FastForwarding, reason);
}
@@ -245,7 +244,6 @@ public class WakeUpSync : NetworkBehaviour
{
OWTime.SetTimeScale(1f);
OWTime.SetMaxDeltaTime(0.06666667f);
- OWTime.SetFixedTimestep(0.01666667f);
Locator.GetActiveCamera().enabled = true;
CurrentState = State.Loaded;
CurrentReason = null;
diff --git a/QSB/Translations/zh_CN.json b/QSB/Translations/zh_CN.json
new file mode 100644
index 00000000..d64142b0
--- /dev/null
+++ b/QSB/Translations/zh_CN.json
@@ -0,0 +1,126 @@
+{
+ "Language": "CHINESE_SIMPLE",
+ "MainMenuHost": "开启多人游戏",
+ "MainMenuConnect": "连接至多人游戏",
+ "PauseMenuDisconnect": "断开连接",
+ "PauseMenuStopHosting": "关闭服务器",
+ "PublicIPAddress": "公共IP地址\n\n(您的多人存档数据将被覆盖)",
+ "ProductUserID": "用户ID\n\n(您的多人存档数据将被覆盖)",
+ "Connect": "连接",
+ "Cancel": "取消",
+ "HostExistingOrNewOrCopy": "您想使用一个现有的多人探险存档,或是开启一个新的存档,还是把现有的单人探险存档复制到多人探险存档?",
+ "HostNewOrCopy": "您想开启一个新的存档,还是把现有的单人探险存档复制到多人探险存档?",
+ "HostExistingOrNew": "您想使用一个现有的多人探险存档,还是开启一个新的存档?",
+ "ExistingSave": "现有存档",
+ "NewSave": "新建存档",
+ "CopySave": "复制存档",
+ "DisconnectAreYouSure": "您确定要断开连接吗?\n将会退出至主菜单。",
+ "Yes": "是",
+ "No": "否",
+ "StopHostingAreYouSure": "您确定要停止服务器吗?\n将会与所有人断开连接并且使他们退出至主菜单。",
+ "CopyProductUserIDToClipboard": "开启服务器\n其他玩家需要使用您的用户ID连接至服务器,用户ID是:\n{0}\n您想要复制到剪切板吗?",
+ "Connecting": "连接中……",
+ "OK": "好的",
+ "ServerRefusedConnection": "服务器拒绝了您的连接\n{0}",
+ "ClientDisconnectWithError": "客户端发生错误导致连接断开\n{0}",
+ "QSBVersionMismatch": "QSB版本号不匹配。(客户端:{0},服务端:{1})",
+ "OWVersionMismatch": "《星际拓荒》版本号不匹配。(客户端:{0},服务端:{1})",
+ "DLCMismatch": "DLC安装情况不匹配。(客户端:{0},服务端:{1})",
+ "GameProgressLimit": "游戏中时间太久了。",
+ "AddonMismatch": "插件不匹配(客户端:{0}插件,服务端:{1}插件)",
+ "IncompatibleMod": "使用了不兼容/不允许的模组,检测到的第一个模组是{0}",
+ "PlayerJoinedTheGame": "{0}加入了游戏!",
+ "PlayerWasKicked": "{0}被踢出了游戏。",
+ "KickedFromServer": "被踢出了游戏,理由是:{0}",
+ "RespawnPlayer": "复活玩家",
+ "TimeSyncTooFarBehind": "{0}\n快进以匹配服务器时间……",
+ "TimeSyncWaitingForStartOfServer": "等待服务器开始……",
+ "TimeSyncTooFarAhead": "{0}\n暂停等待以匹配服务器时间……",
+ "TimeSyncWaitForAllToReady": "等待开始轮回……",
+ "TimeSyncWaitForAllToDie": "等待轮回结束……",
+ "GalaxyMapEveryoneNotPresent": "现在还不是时候。需要所有人见证这个时刻。",
+ "YouAreDead": "你死了。",
+ "WaitingForRespawn": "等待某人将你复活……",
+ "WaitingForAllToDie": "等待{0}死亡……",
+ "AttachToShip": "固定在飞船上",
+ "DetachFromShip": "取消固定",
+ "DeathMessages": {
+ "Default": [
+ "{0}死了",
+ "{0}被杀了"
+ ],
+ "Impact": [
+ "{0}忘记使用推进器了",
+ "{0}拥抱了地面",
+ "{0}狠狠的撞上了地面",
+ "{0}爆炸了",
+ "{0}因为撞击而死",
+ "{0}撞击地面过猛"
+ ],
+ "Asphyxiation": [
+ "{0}忘记了需要呼吸",
+ "{0}窒息了",
+ "{0}窒息而死",
+ "{0}忘记了怎么呼吸",
+ "{0}忘记检查氧气了",
+ "{0}把空气用完了",
+ "{0}把氧气用完了",
+ "{0}不再需要呼吸了"
+ ],
+ "Energy": [
+ "{0}被烹饪了"
+ ],
+ "Supernova": [
+ "{0}没有时间了",
+ "{0}被烧掉了",
+ "{0}被超新星烤熟了",
+ "{0}升华了",
+ "{0}遗忘了时间"
+ ],
+ "Digestion": [
+ "{0}被吃掉了",
+ "{0}发现了一条鱼",
+ "{0}遇到了邪恶生物",
+ "{0}惹错了鱼",
+ "{0}被消化了",
+ "{0}因为消化系统而死"
+ ],
+ "Crushed": [
+ "{0}被压死了",
+ "{0}被压扁了",
+ "{0}埋葬了自己",
+ "{0}没能及时逃离",
+ "{0}想在沙子中游泳",
+ "{0}小看了沙子的力量",
+ "{0}卡在沙子下面了"
+ ],
+ "Lava": [
+ "{0}在岩浆中死去",
+ "{0}融化了",
+ "{0}尝试在岩浆中游泳",
+ "{0}掉进了岩浆",
+ "{0}因为岩浆而死",
+ "{0}在岩浆中游泳",
+ "{0}被岩浆烧毁"
+ ],
+ "BlackHole": [
+ "{0}尝试追寻自己的记忆"
+ ],
+ "DreamExplosion": [
+ "{0}爆炸了",
+ "{0}是第一个吃螃蟹的人",
+ "{0}被炸死了",
+ "{0}被炸了",
+ "{0}因为爆炸而死",
+ "{0}使用了错误的文物"
+ ],
+ "CrushedByElevator": [
+ "{0}被粉碎了",
+ "{0}被挤扁了",
+ "{0}被电梯撞击",
+ "{0}站在了电梯下",
+ "{0}变成了一个平板人",
+ "{0}被电梯挤扁了"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/QSB/default-config.json b/QSB/default-config.json
index f78c880c..852343c8 100644
--- a/QSB/default-config.json
+++ b/QSB/default-config.json
@@ -1,7 +1,29 @@
{
"enabled": true,
"settings": {
- "defaultServerIP": "localhost",
- "incompatibleModsAllowed": false
+ "defaultServerIP": {
+ "title": "Last Entered IP/ID",
+ "type": "text",
+ "value": "localhost",
+ "tooltip": "Used if you leave the connect prompt blank."
+ },
+ "incompatibleModsAllowed": {
+ "title": "Incompatible Mods Allowed",
+ "type": "toggle",
+ "value": false,
+ "tooltip": "Kicks players if they have certain mods."
+ },
+ "showPlayerNames": {
+ "title": "Show Player Names",
+ "type": "toggle",
+ "value": true,
+ "tooltip": "Shows player names in the HUD and the map view."
+ },
+ "shipDamage": {
+ "title": "Ship Damage",
+ "type": "toggle",
+ "value": true,
+ "tooltip": "Take impact damage when inside the ship."
+ }
}
}
\ No newline at end of file
diff --git a/QSB/manifest.json b/QSB/manifest.json
index c49e7688..d78fe58b 100644
--- a/QSB/manifest.json
+++ b/QSB/manifest.json
@@ -8,7 +8,7 @@
},
"uniqueName": "Raicuparta.QuantumSpaceBuddies",
"version": "0.23.0",
- "owmlVersion": "2.7.0",
+ "owmlVersion": "2.8.0",
"dependencies": [ "_nebula.MenuFramework", "JohnCorby.VanillaFix" ],
"pathsToPreserve": [ "debugsettings.json", "storage.json" ]
}
diff --git a/README.md b/README.md
index e0980867..71fc9180 100644
--- a/README.md
+++ b/README.md
@@ -170,7 +170,7 @@ The template for this file is this :
### Authors
-- [\_nebula](https://github.com/misternebula) - Developer of v0.3 onwards
+- [\_nebula](https://github.com/misternebula) - Developer of v0.3.0 onwards
- [JohnCorby](https://github.com/JohnCorby) - Co-developer of v0.13.0 onwards.
- [AmazingAlek](https://github.com/amazingalek) - Developer of v0.1.0 - v0.7.1.
- [Raicuparta](https://github.com/Raicuparta) - Developer of v0.1.0 - v0.2.0.
@@ -179,9 +179,10 @@ The template for this file is this :
- [Chris Yeninas](https://github.com/PhantomGamers) - Help with project files and GitHub workflows.
- [Tlya](https://github.com/Tllya) - Russian translation.
-- [Xen](https://github.com/xen-42) - French translation.
+- [Xen](https://github.com/xen-42) - French translation, and help with particle effects and sounds.
- [ShoosGun](https://github.com/ShoosGun) - Portuguese translation.
- [DertolleDude](https://github.com/DertolleDude) - German translation.
+- [SakuradaYuki](https://github.com/SakuradaYuki) - Chinese translation.
### Special Thanks
- Thanks to Logan Ver Hoef for help with the game code, and for helping make the damn game in the first place.
diff --git a/TRANSLATING.md b/TRANSLATING.md
index ce4437c2..9cdf25b1 100644
--- a/TRANSLATING.md
+++ b/TRANSLATING.md
@@ -10,13 +10,13 @@ QSB can only be translated to the languages Outer Wilds supports - so if you don
- Russian
- Portuguese (Brazil)
- German
+- Chinese (Simplified)
### Un-translated languages :
- Spanish (Latin American)
- Italian
- Polish
- Japanese
-- Chinese (Simplified)
- Korean
- Turkish
@@ -38,4 +38,4 @@ Once you are happy with it, go to [this page](https://github.com/misternebula/qu
Scroll down to the "Propose new file" box. In the title box (default "Create new file") write something along the lines of "Add translation for (language)".
-Press the big green "Propose new file", and we'll review it soon!
\ No newline at end of file
+Press the big green "Propose new file", and we'll review it soon!