diff --git a/QSB/EchoesOfTheEye/Ghosts/Messages/ChangeNodeMapMessage.cs b/QSB/EchoesOfTheEye/Ghosts/Messages/ChangeNodeMapMessage.cs new file mode 100644 index 00000000..11d19724 --- /dev/null +++ b/QSB/EchoesOfTheEye/Ghosts/Messages/ChangeNodeMapMessage.cs @@ -0,0 +1,20 @@ +using QSB.EchoesOfTheEye.Ghosts.WorldObjects; +using QSB.Messaging; +using QSB.WorldSync; + +namespace QSB.EchoesOfTheEye.Ghosts.Messages; + +internal class ChangeNodeMapMessage : QSBWorldObjectMessage +{ + public ChangeNodeMapMessage(int nodeMapIndex) : base(nodeMapIndex) { } + + public override void OnReceiveRemote() + { + var nodeMap = Data.GetWorldObject().AttachedObject; + + WorldObject.AttachedObject._nodeMap = nodeMap; + WorldObject.AttachedObject.transform.parent = nodeMap.transform; + WorldObject.AttachedObject._nodeRoot = nodeMap.transform; + WorldObject.AttachedObject.OnNodeMapChanged.Invoke(); + } +} diff --git a/QSB/EchoesOfTheEye/Ghosts/Messages/Zone2ElevatorStateMessage.cs b/QSB/EchoesOfTheEye/Ghosts/Messages/Zone2ElevatorStateMessage.cs new file mode 100644 index 00000000..c51ba9cc --- /dev/null +++ b/QSB/EchoesOfTheEye/Ghosts/Messages/Zone2ElevatorStateMessage.cs @@ -0,0 +1,65 @@ +using QSB.Messaging; +using QSB.Utility; +using QSB.WorldSync; + +namespace QSB.EchoesOfTheEye.Ghosts.Messages; + +internal class Zone2ElevatorStateMessage : QSBMessage<(int index, Zone2ElevatorState state)> +{ + public Zone2ElevatorStateMessage(int index, Zone2ElevatorState state) : base((index, state)) { } + + public override void OnReceiveRemote() + { + var zoneDirector = QSBWorldSync.GetUnityObject(); + + if (Data.state == Zone2ElevatorState.TutorialElevator) + { + DebugLog.DebugWrite($"TUTORIAL ELEVATOR"); + zoneDirector._ghostTutorialElevator.GoToDestination(1); + return; + } + + if (QSBGhostZone2Director.ElevatorsStatus == null) + { + QSBGhostZone2Director.ElevatorsStatus = new QSBGhostZone2Director.ElevatorStatus[zoneDirector._elevators.Length]; + for (var j = 0; j < zoneDirector._elevators.Length; j++) + { + QSBGhostZone2Director.ElevatorsStatus[j].elevatorPair = zoneDirector._elevators[j]; + QSBGhostZone2Director.ElevatorsStatus[j].activated = false; + QSBGhostZone2Director.ElevatorsStatus[j].deactivated = false; + QSBGhostZone2Director.ElevatorsStatus[j].lightsDeactivated = false; + } + } + + if (Data.state == Zone2ElevatorState.LightsExtinguished) + { + DebugLog.DebugWrite($"LIGHTS EXTINGUISHED"); + + foreach (var elevator in QSBGhostZone2Director.ElevatorsStatus) + { + elevator.elevatorPair.elevator.topLight.FadeTo(0, 0.2f); + } + + return; + } + + var elevatorStatus = QSBGhostZone2Director.ElevatorsStatus[Data.index]; + + switch (Data.state) + { + case Zone2ElevatorState.GoToUndercity: + DebugLog.DebugWrite($"{Data.index} GO TO UNDERCITY"); + elevatorStatus.elevatorPair.elevator.topLight.FadeTo(1, 0.2f); + elevatorStatus.elevatorPair.elevator.GoToDestination(0); + break; + case Zone2ElevatorState.ReachedUndercity: + DebugLog.DebugWrite($"{Data.index} REACHED UNDERCITY"); + elevatorStatus.elevatorPair.elevator.topLight.FadeTo(0, 0.2f); + break; + case Zone2ElevatorState.ReturnToCity: + DebugLog.DebugWrite($"{Data.index} RETURN TO CITY"); + elevatorStatus.elevatorPair.elevator.GoToDestination(1); + break; + } + } +} diff --git a/QSB/EchoesOfTheEye/Ghosts/Patches/GhostControllerPatches.cs b/QSB/EchoesOfTheEye/Ghosts/Patches/GhostControllerPatches.cs index 5b01e6c3..7b5552f2 100644 --- a/QSB/EchoesOfTheEye/Ghosts/Patches/GhostControllerPatches.cs +++ b/QSB/EchoesOfTheEye/Ghosts/Patches/GhostControllerPatches.cs @@ -1,6 +1,8 @@ using GhostEnums; using HarmonyLib; +using QSB.EchoesOfTheEye.Ghosts.Messages; using QSB.EchoesOfTheEye.Ghosts.WorldObjects; +using QSB.Messaging; using QSB.Patches; using QSB.Utility; using QSB.WorldSync; @@ -69,4 +71,25 @@ internal class GhostControllerPatches : QSBPatch DebugLog.ToConsole($"Error - {MethodBase.GetCurrentMethod().Name} not supported!", OWML.Common.MessageType.Error); return false; } + + [HarmonyPrefix] + [HarmonyPatch(nameof(GhostController.SetNodeMap))] + public static bool SetNodeMap(GhostController __instance, GhostNodeMap nodeMap) + { + if (__instance._nodeMap == nodeMap) + { + return false; + } + + __instance.StopMoving(); + __instance.StopFacing(); + __instance._nodeMap = nodeMap; + __instance.transform.parent = nodeMap.transform; + __instance._nodeRoot = nodeMap.transform; + __instance.OnNodeMapChanged.Invoke(); + + __instance.GetWorldObject().SendMessage(new ChangeNodeMapMessage(nodeMap.GetWorldObject().ObjectId)); + + return false; + } } diff --git a/QSB/EchoesOfTheEye/Ghosts/Patches/GhostZone2DirectorPatches.cs b/QSB/EchoesOfTheEye/Ghosts/Patches/GhostZone2DirectorPatches.cs index b5b75708..6af92d24 100644 --- a/QSB/EchoesOfTheEye/Ghosts/Patches/GhostZone2DirectorPatches.cs +++ b/QSB/EchoesOfTheEye/Ghosts/Patches/GhostZone2DirectorPatches.cs @@ -1,7 +1,10 @@ using HarmonyLib; using QSB.EchoesOfTheEye.Ghosts.Actions; +using QSB.EchoesOfTheEye.Ghosts.Messages; using QSB.EchoesOfTheEye.Ghosts.WorldObjects; +using QSB.Messaging; using QSB.Patches; +using QSB.Player; using QSB.Utility; using QSB.WorldSync; using UnityEngine; @@ -77,11 +80,16 @@ internal class GhostZone2DirectorPatches : QSBPatch return true; } + if (!QSBCore.IsHost) + { + return false; + } + if (__instance._lightsProjectorExtinguished) { if (__instance._ghostsAreAwake && !__instance._ghostsAlerted && Time.time >= __instance._ghostAlertTime) { - __instance._ghostHowlAudioSource.PlayOneShot(global::AudioType.Ghost_SomeoneIsInHereHowl, 1f); + __instance._ghostHowlAudioSource.PlayOneShot(AudioType.Ghost_SomeoneIsInHereHowl, 1f); __instance._ghostsAlerted = true; } @@ -93,6 +101,7 @@ internal class GhostZone2DirectorPatches : QSBPatch QSBGhostZone2Director.ElevatorsStatus[i].elevatorPair.elevator.topLight.FadeTo(1f, 0.2f); QSBGhostZone2Director.ElevatorsStatus[i].elevatorPair.elevator.GoToDestination(0); QSBGhostZone2Director.ElevatorsStatus[i].activated = true; + new Zone2ElevatorStateMessage(i, Zone2ElevatorState.GoToUndercity).Send(); } if (!QSBGhostZone2Director.ElevatorsStatus[i].lightsDeactivated && QSBGhostZone2Director.ElevatorsStatus[i].activated && QSBGhostZone2Director.ElevatorsStatus[i].elevatorPair.elevator.isAtBottom) @@ -115,12 +124,14 @@ internal class GhostZone2DirectorPatches : QSBPatch QSBGhostZone2Director.ElevatorsStatus[i].elevatorAction.UseElevator(); QSBGhostZone2Director.ElevatorsStatus[i].timeSinceArrival = Time.time; + new Zone2ElevatorStateMessage(i, Zone2ElevatorState.ReachedUndercity).Send(); } if (QSBGhostZone2Director.ElevatorsStatus[i].lightsDeactivated && QSBGhostZone2Director.ElevatorsStatus[i].activated && !QSBGhostZone2Director.ElevatorsStatus[i].deactivated && Time.time >= QSBGhostZone2Director.ElevatorsStatus[i].timeSinceArrival + 2f) { QSBGhostZone2Director.ElevatorsStatus[i].elevatorPair.elevator.GoToDestination(1); QSBGhostZone2Director.ElevatorsStatus[i].deactivated = true; + new Zone2ElevatorStateMessage(i, Zone2ElevatorState.ReturnToCity).Send(); } } } @@ -128,6 +139,23 @@ internal class GhostZone2DirectorPatches : QSBPatch return false; } + [HarmonyPrefix] + [HarmonyPatch(typeof(GhostZone2Director), nameof(GhostZone2Director.OnStartGhostTutorial))] + public static bool OnStartGhostTutorial(GhostZone2Director __instance, GameObject hitObj) + { + if (__instance._lightsProjectorExtinguished && hitObj.CompareTag("PlayerDetector") && !__instance._ghostTutorialElevator.isAtTop) + { + __instance._ghostTutorialElevator.GoToDestination(1); + new Zone2ElevatorStateMessage(-1, Zone2ElevatorState.TutorialElevator).Send(); + for (var i = 0; i < __instance._cityGhosts.Length; i++) + { + __instance._cityGhosts[i].EscalateThreatAwareness(GhostData.ThreatAwareness.IntruderConfirmed); + } + } + + return false; + } + [HarmonyPrefix] [HarmonyPatch(typeof(GhostZone2Director), nameof(GhostZone2Director.OnLightsExtinguished))] public static bool OnLightsExtinguished(GhostZone2Director __instance) @@ -137,6 +165,11 @@ internal class GhostZone2DirectorPatches : QSBPatch return true; } + if (!QSBCore.IsHost) + { + return false; + } + DebugLog.DebugWrite($"LIGHTS EXTINGUISHED"); __instance._lightsProjectorExtinguished = true; __instance.WakeGhosts(); @@ -174,8 +207,25 @@ internal class GhostZone2DirectorPatches : QSBPatch QSBGhostZone2Director.ElevatorsStatus[j].ghostController = QSBGhostZone2Director.ElevatorsStatus[j].elevatorPair.ghost.GetComponent(); } + new Zone2ElevatorStateMessage(-1, Zone2ElevatorState.LightsExtinguished).Send(); + __instance._ghostAlertTime = Time.time + 2f; return false; } + + [HarmonyPrefix] + [HarmonyPatch(typeof(GhostZone2Director), nameof(GhostZone2Director.OnAlarmRinging))] + public static bool OnAlarmRinging(GhostZone2Director __instance) + { + foreach (var ghost in __instance._undergroundGhosts) + { + var qsbGhost = ghost.GetWorldObject(); + var totemPos = __instance._finalTotem.transform.position; + var closestPlayer = QSBPlayerManager.GetClosestPlayerToWorldPoint(totemPos, true); + qsbGhost.HintPlayerLocation(totemPos, 0, qsbGhost._data.players[closestPlayer]); + } + + return false; + } } diff --git a/QSB/EchoesOfTheEye/Ghosts/WorldObjects/QSBGhostBrain.cs b/QSB/EchoesOfTheEye/Ghosts/WorldObjects/QSBGhostBrain.cs index cb47cf35..93dd08e6 100644 --- a/QSB/EchoesOfTheEye/Ghosts/WorldObjects/QSBGhostBrain.cs +++ b/QSB/EchoesOfTheEye/Ghosts/WorldObjects/QSBGhostBrain.cs @@ -35,7 +35,9 @@ public class QSBGhostBrain : WorldObject, IGhostObject var label = $"Name:{AttachedObject.ghostName}" + $"\r\nAwareness:{AttachedObject.GetThreatAwareness()}" + $"\r\nCurrent action:{AttachedObject.GetCurrentActionName()}" + - $"\r\nIllumination meter:{_data.illuminatedByPlayerMeter}"; + $"\r\nMoveToTargetPosition:{AttachedObject._controller._moveToTargetPosition}" + + $"\r\nTargetSpeed:{AttachedObject._controller._targetSpeed}" + + $"\r\nFollowNodePath:{AttachedObject._controller._followNodePath}"; if (QSBCore.IsHost) { diff --git a/QSB/EchoesOfTheEye/Ghosts/Zone2ElevatorState.cs b/QSB/EchoesOfTheEye/Ghosts/Zone2ElevatorState.cs new file mode 100644 index 00000000..ada12a3b --- /dev/null +++ b/QSB/EchoesOfTheEye/Ghosts/Zone2ElevatorState.cs @@ -0,0 +1,10 @@ +namespace QSB.EchoesOfTheEye.Ghosts; + +public enum Zone2ElevatorState +{ + GoToUndercity, + ReachedUndercity, + ReturnToCity, + TutorialElevator, + LightsExtinguished +} diff --git a/QSB/Utility/DebugActions.cs b/QSB/Utility/DebugActions.cs index f26a9a23..fde2f7c5 100644 --- a/QSB/Utility/DebugActions.cs +++ b/QSB/Utility/DebugActions.cs @@ -73,7 +73,7 @@ public class DebugActions : MonoBehaviour, IAddComponentOnStart { var relativeLocation = new RelativeLocationData(Vector3.up * 2 + Vector3.forward * 2, Quaternion.identity, Vector3.zero); - var location = Keyboard.current[Key.LeftShift].isPressed ? DreamArrivalPoint.Location.Zone4 : DreamArrivalPoint.Location.Zone3; + var location = Keyboard.current[Key.LeftShift].isPressed ? DreamArrivalPoint.Location.Zone4 : DreamArrivalPoint.Location.Zone2; var arrivalPoint = Locator.GetDreamArrivalPoint(location); var dreamCampfire = Locator.GetDreamCampfire(location); if (Locator.GetToolModeSwapper().GetItemCarryTool().GetHeldItemType() != ItemType.DreamLantern)