Merge branch 'dev' into meteors

# Conflicts:
#	QSB/Events/QSBEventManager.cs
This commit is contained in:
JohnCorby 2021-11-18 23:07:49 -08:00
commit 04420e2d8d
15 changed files with 381 additions and 180 deletions

View File

@ -1,6 +1,7 @@
using QSB.ClientServerStateSync;
using QSB.Events;
using QSB.Messaging;
using QSB.Patches;
using QSB.Utility;
namespace QSB.DeathSync.Events
@ -29,6 +30,8 @@ namespace QSB.DeathSync.Events
switch (message.EnumValue)
{
case EndLoopReason.AllPlayersDead:
QSBPatchManager.DoUnpatchType(QSBPatchTypes.RespawnTime);
Locator.GetDeathManager().KillPlayer(DeathType.TimeLoop);
if (QSBCore.IsHost)
{

View File

@ -1,6 +1,7 @@
using QSB.ClientServerStateSync;
using QSB.Events;
using QSB.Player;
using QSB.RespawnSync;
using QSB.Utility;
namespace QSB.DeathSync.Events

View File

@ -1,166 +0,0 @@
using HarmonyLib;
using OWML.Utils;
using QSB.Patches;
namespace QSB.DeathSync.Patches
{
[HarmonyPatch]
internal class RespawnPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerRecoveryPoint), nameof(PlayerRecoveryPoint.OnGainFocus))]
public static bool PlayerRecoveryPoint_OnGainFocus(
PlayerResources ____playerResources,
bool ____refuelsPlayer,
bool ____healsPlayer,
SingleInteractionVolume ____interactVolume
)
{
if (____playerResources == null)
{
____playerResources = Locator.GetPlayerTransform().GetComponent<PlayerResources>();
}
var isAtFullHealth = ____playerResources.GetHealthFraction() == 1f;
var isAtFullFuel = ____playerResources.GetFuelFraction() == 1f;
var canBeRefueled = false;
var canBeHealed = false;
if (!isAtFullFuel && ____refuelsPlayer)
{
canBeRefueled = true;
}
if (!isAtFullHealth && ____healsPlayer)
{
canBeHealed = true;
}
var showRespawnPrompt = false;
var uitextType = UITextType.None;
if (canBeHealed && canBeRefueled)
{
// Heal and refuel
uitextType = UITextType.RefillPrompt_0;
____interactVolume.SetKeyCommandVisible(true);
}
else if (canBeHealed)
{
// Heal
uitextType = UITextType.RefillPrompt_2;
____interactVolume.SetKeyCommandVisible(true);
}
else if (canBeRefueled)
{
// Refuel
uitextType = UITextType.RefillPrompt_4;
____interactVolume.SetKeyCommandVisible(true);
}
else if (RespawnManager.Instance.RespawnNeeded)
{
showRespawnPrompt = true;
}
else if (____refuelsPlayer && ____healsPlayer)
{
// Fuel and health full
uitextType = UITextType.RefillPrompt_7;
____interactVolume.SetKeyCommandVisible(false);
}
else if (____refuelsPlayer)
{
// Fuel full
uitextType = UITextType.RefillPrompt_8;
____interactVolume.SetKeyCommandVisible(false);
}
else if (____healsPlayer)
{
// Health full
uitextType = UITextType.RefillPrompt_9;
____interactVolume.SetKeyCommandVisible(false);
}
if (showRespawnPrompt)
{
____interactVolume.GetValue<ScreenPrompt>("_screenPrompt").SetText($"<CMD> Respawn Player");
____interactVolume.GetValue<ScreenPrompt>("_noCommandIconPrompt").SetText("Respawn Player");
}
if (uitextType != UITextType.None)
{
____interactVolume.ChangePrompt(uitextType);
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerRecoveryPoint), nameof(PlayerRecoveryPoint.OnPressInteract))]
public static bool PlayerRecoveryPoint_OnPressInteract(
PlayerRecoveryPoint __instance,
PlayerResources ____playerResources,
ref bool ____recovering,
bool ____refuelsPlayer,
bool ____healsPlayer,
PlayerAudioController ____playerAudioController,
SingleInteractionVolume ____interactVolume
)
{
var playerNeedsRefueling = ____playerResources.GetFuelFraction() != 1f;
var playerNeedsHealing = ____playerResources.GetHealthFraction() != 1f;
var canBeInteractedWith = false;
if (playerNeedsRefueling && ____refuelsPlayer)
{
canBeInteractedWith = true;
}
if (playerNeedsHealing && ____healsPlayer)
{
canBeInteractedWith = true;
}
if (RespawnManager.Instance.RespawnNeeded)
{
canBeInteractedWith = true;
}
if (canBeInteractedWith)
{
if (RespawnManager.Instance.RespawnNeeded && !playerNeedsRefueling && !playerNeedsHealing)
{
RespawnManager.Instance.RespawnSomePlayer();
return false;
}
____playerResources.StartRefillResources(____refuelsPlayer, ____healsPlayer);
if (____playerAudioController != null)
{
if (playerNeedsRefueling && ____refuelsPlayer)
{
____playerAudioController.PlayRefuel();
}
if (playerNeedsHealing && ____healsPlayer)
{
____playerAudioController.PlayMedkit();
}
}
____recovering = true;
__instance.enabled = true;
}
else
{
____interactVolume.ResetInteraction();
}
return false;
}
}
}

View File

@ -7,6 +7,7 @@ using QSB.WorldSync;
using QSB.Utility;
using System.Linq;
using UnityEngine;
using QSB.RespawnSync;
namespace QSB.DeathSync
{

View File

@ -31,6 +31,7 @@ using QSB.Utility;
using QSB.Utility.Events;
using System.Collections.Generic;
using QSB.MeteorSync.Events;
using QSB.RespawnSync.Events;
namespace QSB.Events
{

View File

@ -38,6 +38,7 @@ namespace QSB.Patches
public static event Action<QSBPatchTypes> OnUnpatchType;
private static List<QSBPatch> _patchList = new List<QSBPatch>();
private static List<QSBPatchTypes> _patchedTypes = new List<QSBPatchTypes>();
public static Dictionary<QSBPatchTypes, Harmony> TypeToInstance = new Dictionary<QSBPatchTypes, Harmony>();
@ -69,7 +70,6 @@ namespace QSB.Patches
new InputPatches(),
new TimePatches(),
new MapPatches(),
new RespawnPatches(),
new LauncherPatches(),
new SolanumPatches(),
new SatelliteProjectorPatches(),
@ -92,6 +92,12 @@ namespace QSB.Patches
public static void DoPatchType(QSBPatchTypes type)
{
if (_patchedTypes.Contains(type))
{
DebugLog.ToConsole($"Warning - Tried to patch type {type}, when it has already been patched!", MessageType.Warning);
return;
}
OnPatchType?.SafeInvoke(type);
//DebugLog.DebugWrite($"Patch block {Enum.GetName(typeof(QSBPatchTypes), type)}", MessageType.Info);
foreach (var patch in _patchList.Where(x => x.Type == type))
@ -100,6 +106,7 @@ namespace QSB.Patches
try
{
patch.DoPatches(TypeToInstance[type]);
_patchedTypes.Add(type);
}
catch (Exception ex)
{
@ -110,9 +117,16 @@ namespace QSB.Patches
public static void DoUnpatchType(QSBPatchTypes type)
{
if (!_patchedTypes.Contains(type))
{
DebugLog.ToConsole($"Warning - Tried to unpatch type {type}, when it is either unpatched or was never patched.", MessageType.Warning);
return;
}
OnUnpatchType?.SafeInvoke(type);
//DebugLog.DebugWrite($"Unpatch block {Enum.GetName(typeof(QSBPatchTypes), type)}", MessageType.Info);
TypeToInstance[type].UnpatchSelf();
_patchedTypes.Remove(type);
}
}
}

View File

@ -16,7 +16,7 @@ namespace QSB.Player
_markerTarget = new GameObject().transform;
_markerTarget.parent = transform;
_markerTarget.localPosition = Vector3.up * 2;
_markerTarget.localPosition = Vector3.up * 0.25f;
}
public void Init(PlayerInfo player)

View File

@ -62,7 +62,7 @@ namespace QSB.Player
return default;
}
DebugLog.DebugWrite($"Create Player : id<{id}> Stacktrace :\r\n{Environment.StackTrace}", MessageType.Info);
DebugLog.DebugWrite($"Create Player : id<{id}>", MessageType.Info);
player = new PlayerInfo(id);
PlayerList.Add(player);
OnAddPlayer?.Invoke(id);
@ -71,7 +71,7 @@ namespace QSB.Player
public static void RemovePlayer(uint id)
{
DebugLog.DebugWrite($"Remove Player : id<{id}> Stacktrace :\r\n{Environment.StackTrace}", MessageType.Info);
DebugLog.DebugWrite($"Remove Player : id<{id}>", MessageType.Info);
PlayerList.RemoveAll(x => x.PlayerId == id);
}
@ -140,6 +140,8 @@ namespace QSB.Player
public static void ChangePlayerVisibility(uint playerId, bool visible)
{
var player = GetPlayer(playerId);
player.Visible = visible;
if (player.Body == null)
{
DebugLog.ToConsole($"Warning - Player {playerId} has a null player model!", MessageType.Warning);
@ -150,8 +152,6 @@ namespace QSB.Player
{
renderer.enabled = visible;
}
player.Visible = visible;
}
public static PlayerInfo GetClosestPlayerToWorldPoint(Vector3 worldPoint, bool includeLocalPlayer) => includeLocalPlayer

View File

@ -88,13 +88,14 @@
<Compile Include="ConversationSync\ConversationManager.cs" />
<Compile Include="DeathSync\EndLoopReason.cs" />
<Compile Include="DeathSync\Events\EndLoopEvent.cs" />
<Compile Include="DeathSync\Events\PlayerRespawnEvent.cs" />
<Compile Include="RespawnSync\Events\PlayerRespawnEvent.cs" />
<Compile Include="DeathSync\Events\StartLoopEvent.cs" />
<Compile Include="DeathSync\Patches\MapPatches.cs" />
<Compile Include="DeathSync\Events\PlayerDeathMessage.cs" />
<Compile Include="DeathSync\Patches\DeathPatches.cs" />
<Compile Include="DeathSync\Patches\RespawnPatches.cs" />
<Compile Include="DeathSync\RespawnManager.cs" />
<Compile Include="RespawnSync\RespawnHUDMarker.cs" />
<Compile Include="RespawnSync\RespawnManager.cs" />
<Compile Include="RespawnSync\ShipRecoveryPoint.cs" />
<Compile Include="EchoesOfTheEye\AirlockSync\AirlockManager.cs" />
<Compile Include="EchoesOfTheEye\AirlockSync\WorldObjects\QSBGhostAirlock.cs" />
<Compile Include="ElevatorSync\WorldObjects\QSBElevator.cs" />
@ -325,6 +326,7 @@
<Compile Include="Utility\DebugGUI.cs" />
<Compile Include="Utility\Events\DebugEvent.cs" />
<Compile Include="Utility\Events\DebugEventEnum.cs" />
<Compile Include="Utility\UIHelper.cs" />
<Compile Include="Utility\ZOverride.cs" />
<Compile Include="Utility\Extensions.cs" />
<Compile Include="Utility\GlobalMessenger4Args.cs" />

View File

@ -4,7 +4,6 @@ using OWML.ModHelper.Input;
using QSB.Animation.NPC;
using QSB.CampfireSync;
using QSB.ConversationSync;
using QSB.DeathSync;
using QSB.EchoesOfTheEye.AirlockSync;
using QSB.EchoesOfTheEye.LightSensorSync;
using QSB.ElevatorSync;
@ -33,6 +32,7 @@ using QuantumUNET;
using QuantumUNET.Components;
using System.Linq;
using UnityEngine;
using QSB.RespawnSync;
/*
Copyright (C) 2020 - 2021

View File

@ -3,7 +3,7 @@ using QSB.Events;
using QSB.Messaging;
using QSB.Player;
namespace QSB.DeathSync.Events
namespace QSB.RespawnSync.Events
{
internal class PlayerRespawnEvent : QSBEvent<PlayerMessage>
{

View File

@ -0,0 +1,54 @@
using QSB.Player;
using QSB.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace QSB.RespawnSync
{
public class RespawnHUDMarker : HUDDistanceMarker
{
private bool _isReady;
public override void InitCanvasMarker()
{
_markerRadius = 0.2f;
_markerTarget = transform;
_markerLabel = "RESPAWN PLAYER";
_isReady = true;
base.InitCanvasMarker();
}
private void Update()
{
if (!_isReady)
{
return;
}
if (_canvasMarker != null)
{
var isVisible = _canvasMarker.IsVisible();
if (RespawnManager.Instance.RespawnNeeded != isVisible)
{
_isVisible = RespawnManager.Instance.RespawnNeeded;
_canvasMarker.SetVisibility(_isVisible);
}
}
if (_isVisible && _canvasMarker != null)
{
var color = (Mathf.Sin(Time.unscaledTime * 10f) > 0f)
? Color.white
: new Color(1f, 1f, 1f, 0.1f);
_canvasMarker._mainTextField.color = color;
_canvasMarker._offScreenIndicator._textField.color = color;
}
}
}
}

View File

@ -6,8 +6,9 @@ using QSB.Utility;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Networking;
namespace QSB.DeathSync
namespace QSB.RespawnSync
{
internal class RespawnManager : MonoBehaviour
{
@ -17,18 +18,83 @@ namespace QSB.DeathSync
private List<PlayerInfo> _playersPendingRespawn = new List<PlayerInfo>();
private NotificationData _previousNotification;
private GameObject _owRecoveryPoint;
private GameObject _qsbRecoveryPoint;
private void Start()
{
Instance = this;
QSBSceneManager.OnSceneLoaded += OnSceneLoaded;
QSBSceneManager.OnSceneLoaded += (OWScene old, OWScene newScene, bool inUniverse)
=> QSBCore.UnityEvents.RunWhen(
() => Locator.GetMarkerManager() != null,
() => Init(newScene, inUniverse));
QSBNetworkManager.Instance.OnClientConnected += OnConnected;
QSBNetworkManager.Instance.OnClientDisconnected += OnDisconnected;
}
private void OnSceneLoaded(OWScene oldScene, OWScene newScene, bool inUniverse)
private void OnConnected()
{
if (QSBSceneManager.IsInUniverse)
{
Init(QSBSceneManager.CurrentScene, true);
}
}
private void OnDisconnected(NetworkError error)
{
_owRecoveryPoint?.SetActive(true);
_qsbRecoveryPoint?.SetActive(false);
}
private void Init(OWScene newScene, bool inUniverse)
{
QSBPlayerManager.ShowAllPlayers();
QSBPlayerManager.PlayerList.ForEach(x => x.IsDead = false);
_playersPendingRespawn.Clear();
if (newScene != OWScene.SolarSystem)
{
return;
}
if (_owRecoveryPoint == null)
{
_owRecoveryPoint = GameObject.Find("Systems_Supplies/PlayerRecoveryPoint");
}
if (_owRecoveryPoint == null)
{
DebugLog.ToConsole($"Error - Couldn't find the ship's PlayerRecoveryPoint!", OWML.Common.MessageType.Error);
return;
}
_owRecoveryPoint.SetActive(false);
var Systems_Supplies = _owRecoveryPoint.gameObject.transform.parent;
if (_qsbRecoveryPoint == null)
{
_qsbRecoveryPoint = new GameObject("QSBPlayerRecoveryPoint");
_qsbRecoveryPoint.SetActive(false);
_qsbRecoveryPoint.transform.parent = Systems_Supplies;
_qsbRecoveryPoint.transform.localPosition = new Vector3(2.46f, 1.957f, 1.156f);
_qsbRecoveryPoint.transform.localRotation = Quaternion.Euler(0, 6.460001f, 0f);
_qsbRecoveryPoint.layer = 21;
var boxCollider = _qsbRecoveryPoint.AddComponent<BoxCollider>();
boxCollider.isTrigger = true;
boxCollider.size = new Vector3(1.3f, 1.01f, 0.47f);
var multiInteract = _qsbRecoveryPoint.AddComponent<MultiInteractReceiver>();
multiInteract._usableInShip = true;
multiInteract._interactRange = 1.5f;
_qsbRecoveryPoint.AddComponent<ShipRecoveryPoint>();
_qsbRecoveryPoint.AddComponent<RespawnHUDMarker>();
}
_qsbRecoveryPoint.SetActive(true);
}
public void TriggerRespawnMap()

View File

@ -0,0 +1,211 @@
using QSB.Utility;
using UnityEngine;
namespace QSB.RespawnSync
{
internal class ShipRecoveryPoint : MonoBehaviour
{
private MultipleInteractionVolume _interactVolume;
private PlayerResources _playerResources;
private PlayerAudioController _playerAudioController;
private bool _recovering;
private int _refillIndex;
private int _respawnIndex;
private bool _wearingSuit;
private void Awake()
{
_interactVolume = this.GetRequiredComponent<MultipleInteractionVolume>();
_interactVolume.OnPressInteract += OnPressInteract;
_interactVolume.OnGainFocus += OnGainFocus;
var respawnPlayerText = UIHelper.AddToUITable("Respawn Player");
_refillIndex = _interactVolume.AddInteraction(InputLibrary.interact, InputMode.Character, UITextType.None, true, true);
_respawnIndex = _interactVolume.AddInteraction(InputLibrary.interactSecondary, InputMode.Character, (UITextType)respawnPlayerText, true, true);
GlobalMessenger.AddListener("SuitUp", new Callback(OnSuitUp));
GlobalMessenger.AddListener("RemoveSuit", new Callback(OnRemoveSuit));
}
private void Start()
{
_playerResources = Locator.GetPlayerTransform().GetComponent<PlayerResources>();
_playerAudioController = Locator.GetPlayerAudioController();
}
private void OnDestroy()
{
_interactVolume.OnPressInteract -= OnPressInteract;
_interactVolume.OnGainFocus -= OnGainFocus;
GlobalMessenger.RemoveListener("SuitUp", new Callback(OnSuitUp));
GlobalMessenger.RemoveListener("RemoveSuit", new Callback(OnRemoveSuit));
}
private void OnSuitUp()
=> _wearingSuit = true;
private void OnRemoveSuit()
=> _wearingSuit = false;
private void OnGainFocus()
{
if (_playerResources == null)
{
_playerResources = Locator.GetPlayerTransform().GetComponent<PlayerResources>();
}
if (RespawnManager.Instance.RespawnNeeded)
{
_interactVolume.EnableSingleInteraction(true, _respawnIndex);
_interactVolume.SetKeyCommandVisible(true, _respawnIndex);
_interactVolume.GetInteractionAt(_respawnIndex).cachedScreenPrompt.SetDisplayState(ScreenPrompt.DisplayState.Attention);
}
else
{
_interactVolume.EnableSingleInteraction(false, _respawnIndex);
_interactVolume.SetKeyCommandVisible(false, _respawnIndex);
_interactVolume.GetInteractionAt(_respawnIndex).cachedScreenPrompt.SetDisplayState(ScreenPrompt.DisplayState.GrayedOut);
}
var needsHealing = _playerResources.GetHealthFraction() != 1f;
var needsRefueling = _playerResources.GetFuelFraction() != 1f;
UITextType uitextType;
bool keyCommandVisible;
if (needsHealing && needsRefueling)
{
uitextType = UITextType.RefillPrompt_0;
keyCommandVisible = true;
}
else if (needsHealing)
{
uitextType = UITextType.RefillPrompt_2;
keyCommandVisible = true;
}
else if (needsRefueling)
{
uitextType = UITextType.RefillPrompt_4;
keyCommandVisible = true;
}
else
{
uitextType = UITextType.RefillPrompt_7;
keyCommandVisible = false;
}
if (uitextType != UITextType.None)
{
_interactVolume.ChangePrompt(uitextType, _refillIndex);
}
if (_wearingSuit)
{
_interactVolume.EnableSingleInteraction(true, _refillIndex);
_interactVolume.SetKeyCommandVisible(keyCommandVisible, _refillIndex);
_interactVolume.GetInteractionAt(_refillIndex).cachedScreenPrompt.SetDisplayState(ScreenPrompt.DisplayState.Normal);
}
else
{
_interactVolume.EnableSingleInteraction(false, _refillIndex);
_interactVolume.SetKeyCommandVisible(false, _refillIndex);
_interactVolume.GetInteractionAt(_refillIndex).cachedScreenPrompt.SetDisplayState(ScreenPrompt.DisplayState.GrayedOut);
}
}
private void OnPressInteract(IInputCommands inputCommand)
{
if (inputCommand == _interactVolume.GetInteractionAt(_refillIndex).inputCommand)
{
if (!_wearingSuit)
{
return;
}
HandleRecovery();
}
else if (inputCommand == _interactVolume.GetInteractionAt(_respawnIndex).inputCommand)
{
if (!RespawnManager.Instance.RespawnNeeded)
{
return;
}
RespawnManager.Instance.RespawnSomePlayer();
}
else
{
// the fuck????
}
}
private void HandleRecovery()
{
var needsRefueling = _playerResources.GetFuelFraction() != 1f;
var needsHealing = _playerResources.GetHealthFraction() != 1f;
var flag4 = false;
if (needsRefueling)
{
flag4 = true;
}
if (needsHealing)
{
flag4 = true;
}
if (flag4)
{
_playerResources.StartRefillResources(true, true);
if (_playerAudioController != null)
{
if (needsRefueling)
{
_playerAudioController.PlayRefuel();
}
if (needsHealing)
{
_playerAudioController.PlayMedkit();
}
}
_recovering = true;
enabled = true;
return;
}
_interactVolume.ResetInteraction();
}
private void Update()
{
if (_recovering)
{
var doneRecovering = true;
if (_playerResources.GetFuelFraction() < 1f)
{
doneRecovering = false;
}
if (_playerResources.GetHealthFraction() < 1f)
{
doneRecovering = false;
}
if (doneRecovering)
{
_playerResources.StopRefillResources();
_recovering = false;
}
}
if (!_recovering)
{
enabled = false;
}
}
}
}

14
QSB/Utility/UIHelper.cs Normal file
View File

@ -0,0 +1,14 @@
using System.Linq;
namespace QSB.Utility
{
internal static class UIHelper
{
public static int AddToUITable(string text)
{
var instance = UnityEngine.Object.FindObjectOfType<TextTranslation>().m_table;
instance.Insert_UI(instance.theUITable.Keys.Max() + 1, text);
return instance.theUITable.Keys.Max();
}
}
}