Merge branch 'dev' into update-changelog-popup

This commit is contained in:
Mister_Nebula 2022-05-04 10:28:59 +01:00
commit d425a0d712
59 changed files with 7804 additions and 88 deletions

View File

@ -17,5 +17,6 @@ internal class CharacterAnimManager : WorldObjectManager
QSBWorldSync.Init<QSBSolanumAnimController, SolanumAnimController>();
QSBWorldSync.Init<QSBHearthianRecorderEffects, HearthianRecorderEffects>();
QSBWorldSync.Init<QSBTravelerEyeController, TravelerEyeController>();
QSBWorldSync.Init<PrisonerDialogue, PrisonerDirector>();
}
}

View File

@ -0,0 +1,12 @@
namespace QSB.Animation.NPC.WorldObjects;
internal class PrisonerDialogue : NpcAnimController<PrisonerDirector>
{
public override void SendInitialState(uint to)
{
// todo : implement
}
public override CharacterDialogueTree GetDialogueTree()
=> AttachedObject._characterDialogueTree;
}

1171
QSB/Assets/cellevator.pdn Normal file

File diff suppressed because one or more lines are too long

1376
QSB/Assets/cellevator1.pdn Normal file

File diff suppressed because one or more lines are too long

BIN
QSB/Assets/cellevator1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 KiB

1376
QSB/Assets/cellevator2.pdn Normal file

File diff suppressed because one or more lines are too long

BIN
QSB/Assets/cellevator2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

1376
QSB/Assets/cellevator3.pdn Normal file

File diff suppressed because one or more lines are too long

BIN
QSB/Assets/cellevator3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 504 KiB

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,5 @@
using GhostEnums;
using QSB.Player;
using QSB.Utility;
using System;
using System.Collections.Generic;
@ -11,8 +12,8 @@ namespace QSB.EchoesOfTheEye.Ghosts.Actions;
internal class QSBGrabAction : QSBGhostAction
{
private bool _playerIsGrabbed;
private bool _grabAnimComplete;
private PlayerInfo _grabbedPlayer;
public override GhostAction.Name GetName()
{
@ -26,7 +27,7 @@ internal class QSBGrabAction : QSBGhostAction
return -100f;
}
if (PlayerState.IsAttached() || !_data.interestedPlayer.sensor.inContactWithPlayer)
if (_playerIsGrabbed || !_data.interestedPlayer.sensor.inContactWithPlayer)
{
return -100f;
}
@ -58,10 +59,16 @@ internal class QSBGrabAction : QSBGhostAction
_playerIsGrabbed = false;
_grabAnimComplete = false;
_effects.AttachedObject.OnGrabComplete -= OnGrabComplete;
_grabbedPlayer = null;
}
public override bool Update_Action()
{
if (_grabbedPlayer != null && !_grabbedPlayer.InDreamWorld)
{
return false;
}
if (_playerIsGrabbed)
{
return true;
@ -75,24 +82,20 @@ internal class QSBGrabAction : QSBGhostAction
_controller.FaceLocalPosition(_data.interestedPlayer.playerLocation.localPosition, TurnSpeed.FASTEST);
if (_sensors.CanGrabPlayer(_data.interestedPlayer))
{
DebugLog.DebugWrite($"Grab player {_data.interestedPlayer.player.PlayerId}!");
GrabPlayer();
}
else
{
DebugLog.DebugWrite($"can't grab player {_data.interestedPlayer.player.PlayerId}");
GrabPlayer(_data.interestedPlayer);
}
return !_grabAnimComplete;
}
private void GrabPlayer()
private void GrabPlayer(GhostPlayer player)
{
_grabbedPlayer = player.player;
_playerIsGrabbed = true;
_controller.StopMovingInstantly();
_controller.StopFacing();
_controller.SetLanternConcealed(true, false);
_controller.AttachedObject.GetGrabController().GrabPlayer(1f);
_controller.GetGrabController().GrabPlayer(1f, player);
}
private void OnGrabComplete()

View File

@ -27,11 +27,13 @@ internal class GhostManager : WorldObjectManager
QSBWorldSync.Init<QSBPrisonerEffects, GhostEffects>(QSBWorldSync.GetUnityObjects<PrisonerEffects>());
QSBWorldSync.Init<QSBGhostSensors, GhostSensors>();
QSBWorldSync.Init<QSBGhostNodeMap, GhostNodeMap>();
// to avoid disabled ghosts (TheCollector)
QSBWorldSync.Init<QSBGhostBrain, GhostBrain>(QSBWorldSync.GetUnityObjects<GhostBrain>().Where(x => x.gameObject.activeSelf).SortDeterministic());
QSBWorldSync.Init<QSBGhostGrabController, GhostGrabController>();
_hotelDirector = QSBWorldSync.GetUnityObjects<GhostHotelDirector>().First();
_partyPathDirector = QSBWorldSync.GetUnityObjects<GhostPartyPathDirector>().First();
_zone2Director = QSBWorldSync.GetUnityObjects<GhostZone2Director>().First();
_hotelDirector = QSBWorldSync.GetUnityObject<GhostHotelDirector>();
_partyPathDirector = QSBWorldSync.GetUnityObject<GhostPartyPathDirector>();
_zone2Director = QSBWorldSync.GetUnityObject<GhostZone2Director>();
for (int i = 0; i < _hotelDirector._hotelDepthsGhosts.Length; i++)
{

View File

@ -0,0 +1,20 @@
using QSB.EchoesOfTheEye.Ghosts.WorldObjects;
using QSB.Messaging;
using QSB.Player;
namespace QSB.EchoesOfTheEye.Ghosts.Messages;
internal class ContactTriggerMessage : QSBWorldObjectMessage<QSBGhostSensors, bool>
{
public ContactTriggerMessage(bool inContact) : base(inContact) { }
public override void OnReceiveRemote()
{
var player = QSBPlayerManager.GetPlayer(From);
if (WorldObject._data.players[player] != null && WorldObject._data.players[player].sensor != null)
{
WorldObject._data.players[player].sensor.inContactWithPlayer = Data;
}
}
}

View File

@ -0,0 +1,23 @@
using QSB.EchoesOfTheEye.Ghosts.WorldObjects;
using QSB.Messaging;
using QSB.Player;
using QSB.WorldSync;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace QSB.EchoesOfTheEye.Ghosts.Messages;
internal class GrabRemotePlayerMessage : QSBWorldObjectMessage<QSBGhostGrabController, (float speed, uint playerId)>
{
public GrabRemotePlayerMessage(float speed, uint playerId) : base((speed, playerId)) { }
public override void OnReceiveRemote()
{
var allGhosts = QSBWorldSync.GetWorldObjects<QSBGhostBrain>();
var owningGhost = allGhosts.First(x => x.AttachedObject._controller == WorldObject.AttachedObject._effects._controller);
WorldObject.GrabPlayer(Data.speed, owningGhost._data.players[QSBPlayerManager.GetPlayer(Data.playerId)], true);
}
}

View File

@ -66,7 +66,7 @@ internal class GhostSensorsPatches : QSBPatch
return true;
}
__instance.GetWorldObject<QSBGhostSensors>().OnEnterContactTrigger(hitObj);
DebugLog.ToConsole($"Error - {MethodBase.GetCurrentMethod().Name} not supported!", OWML.Common.MessageType.Error);
return false;
}
@ -79,7 +79,7 @@ internal class GhostSensorsPatches : QSBPatch
return true;
}
__instance.GetWorldObject<QSBGhostSensors>().OnExitContactTrigger(hitObj);
DebugLog.ToConsole($"Error - {MethodBase.GetCurrentMethod().Name} not supported!", OWML.Common.MessageType.Error);
return false;
}
}

View File

@ -157,12 +157,19 @@ public class QSBGhostBrain : WorldObject<GhostBrain>, IGhostObject
return false;
}
if (fearAudioAlreadyPlaying)
if (_data.interestedPlayer == null)
{
return _currentAction.GetName() is GhostAction.Name.Chase or GhostAction.Name.Grab;
return false;
}
return _currentAction.GetName() == GhostAction.Name.Chase;
if (_data.interestedPlayer.player != QSBPlayerManager.LocalPlayer)
{
return false;
}
return fearAudioAlreadyPlaying
? _currentAction.GetName() is GhostAction.Name.Chase or GhostAction.Name.Grab
: _currentAction.GetName() == GhostAction.Name.Chase;
}
public void Awake()
@ -181,7 +188,7 @@ public class QSBGhostBrain : WorldObject<GhostBrain>, IGhostObject
AttachedObject.enabled = false;
AttachedObject._controller.GetDreamLanternController().enabled = false;
AttachedObject._controller.GetWorldObject<QSBGhostController>().Initialize(AttachedObject._nodeLayer, AttachedObject._effects.GetWorldObject<QSBGhostEffects>());
AttachedObject._sensors.GetWorldObject<QSBGhostSensors>().Initialize(_data, AttachedObject._guardVolume);
AttachedObject._sensors.GetWorldObject<QSBGhostSensors>().Initialize(_data);
AttachedObject._effects.GetWorldObject<QSBGhostEffects>().Initialize(AttachedObject._controller.GetNodeRoot(), AttachedObject._controller.GetWorldObject<QSBGhostController>(), _data);
AttachedObject._effects.OnCallForHelp += AttachedObject.OnCallForHelp;
_data.reducedFrights_allowChase = AttachedObject._reducedFrights_allowChase;
@ -190,11 +197,8 @@ public class QSBGhostBrain : WorldObject<GhostBrain>, IGhostObject
AttachedObject._intruderConfirmPending = false;
AttachedObject._intruderConfirmTime = 0f;
DebugLog.DebugWrite($"{AttachedObject._name} setting up actions :");
for (var i = 0; i < AttachedObject._actions.Length; i++)
{
DebugLog.DebugWrite($"- {AttachedObject._actions[i]}");
var ghostAction = QSBGhostAction.CreateAction(AttachedObject._actions[i]);
ghostAction.Initialize(this);
_actionLibrary.Add(ghostAction);
@ -269,10 +273,7 @@ public class QSBGhostBrain : WorldObject<GhostBrain>, IGhostObject
}
public void WakeUp()
{
DebugLog.DebugWrite($"Wake up!");
_data.hasWokenUp = true;
}
=> _data.hasWokenUp = true;
public bool HearGhostCall(Vector3 playerLocalPosition, float reactDelay, bool playResponseAudio = false)
{
@ -300,8 +301,6 @@ public class QSBGhostBrain : WorldObject<GhostBrain>, IGhostObject
return false;
}
DebugLog.DebugWrite($"{AttachedObject._name} Hear call for help!");
if (_data.threatAwareness < GhostData.ThreatAwareness.IntruderConfirmed)
{
_data.threatAwareness = GhostData.ThreatAwareness.IntruderConfirmed;
@ -408,7 +407,6 @@ public class QSBGhostBrain : WorldObject<GhostBrain>, IGhostObject
&& (_data.threatAwareness > GhostData.ThreatAwareness.EverythingIsNormal || _data.players.Values.Any(x => x.playerLocation.distance < 20f) || _data.players.Values.Any(x => x.sensor.isPlayerIlluminatedByUs))
&& (_data.players.Values.Any(x => x.sensor.isPlayerVisible) || _data.players.Values.Any(x => x.sensor.inContactWithPlayer)))
{
DebugLog.DebugWrite($"INTRUDER CONFIRMED BY SELF");
AttachedObject._intruderConfirmedBySelf = true;
AttachedObject._intruderConfirmPending = true;
var closestPlayer = _data.players.Values.MinBy(x => x.playerLocation.distance);
@ -558,8 +556,6 @@ public class QSBGhostBrain : WorldObject<GhostBrain>, IGhostObject
public void OnCallForHelp()
{
DebugLog.DebugWrite($"{AttachedObject._name} - iterating through helper list for callforhelp");
if (AttachedObject._helperGhosts != null)
{
for (var i = 0; i < AttachedObject._helperGhosts.Length; i++)

View File

@ -39,6 +39,9 @@ public class QSBGhostController : WorldObject<GhostController>, IGhostObject
AttachedObject._playerCollider = Locator.GetPlayerBody().GetComponent<CapsuleCollider>();
}
public QSBGhostGrabController GetGrabController()
=> AttachedObject.GetGrabController().GetWorldObject<QSBGhostGrabController>();
public void SetLanternConcealed(bool concealed, bool playAudio = true)
{
if (playAudio && AttachedObject._lantern.IsConcealed() != concealed)

View File

@ -0,0 +1,67 @@
using QSB.EchoesOfTheEye.Ghosts.Messages;
using QSB.Messaging;
using QSB.Player;
using QSB.Utility;
using QSB.WorldSync;
using UnityEngine;
namespace QSB.EchoesOfTheEye.Ghosts.WorldObjects;
public class QSBGhostGrabController : WorldObject<GhostGrabController>
{
public override void SendInitialState(uint to)
{
}
public void GrabPlayer(float speed, GhostPlayer player, bool remote = false)
{
if (!remote)
{
this.SendMessage(new GrabRemotePlayerMessage(speed, player.player.PlayerId));
}
var isLocalPlayer = player.player.IsLocalPlayer;
if (isLocalPlayer)
{
AttachedObject.enabled = true;
AttachedObject._snappingNeck = !player.player.AssignedSimulationLantern.AttachedObject.GetLanternController().IsHeldByPlayer();
AttachedObject._holdingInPlace = true;
AttachedObject._grabMoveComplete = false;
AttachedObject._extinguishStarted = false;
AttachedObject._attachPoint.transform.parent = AttachedObject._origParent;
AttachedObject._attachPoint.transform.position = Locator.GetPlayerTransform().position;
AttachedObject._attachPoint.transform.rotation = Locator.GetPlayerTransform().rotation;
AttachedObject._startLocalPos = AttachedObject._attachPoint.transform.localPosition;
AttachedObject._startLocalRot = AttachedObject._attachPoint.transform.localRotation;
AttachedObject._playerAttached = true;
AttachedObject._attachPoint.AttachPlayer();
GlobalMessenger.FireEvent("PlayerGrabbedByGhost");
OWInput.ChangeInputMode(InputMode.None);
ReticleController.Hide();
Locator.GetDreamWorldController().SetActiveGhostGrabController(AttachedObject);
AttachedObject._grabStartTime = Time.time;
AttachedObject._grabMoveDuration = Mathf.Min(Vector3.Distance(AttachedObject._startLocalPos, AttachedObject._holdPoint.localPosition) / speed, 2f);
RumbleManager.PlayGhostGrab();
Achievement_Ghost.GotCaughtByGhost();
}
var effects = AttachedObject._effects.GetWorldObject<QSBGhostEffects>();
if (QSBCore.IsHost)
{
if (AttachedObject._snappingNeck)
{
effects.PlaySnapNeckAnimation();
}
else
{
// todo : make this track grab counts, so we can use the fast animation
effects.PlayBlowOutLanternAnimation();
}
}
effects.AttachedObject.PlayGrabAudio(AudioType.Ghost_Grab_Contact);
}
}

View File

@ -22,11 +22,14 @@ public class QSBGhostSensors : WorldObject<GhostSensors>, IGhostObject
public QSBGhostData _data;
public void Initialize(QSBGhostData data, OWTriggerVolume guardVolume = null)
public void Initialize(QSBGhostData data)
{
_data = data;
AttachedObject._contactTrigger.OnEntry -= AttachedObject.OnEnterContactTrigger;
AttachedObject._contactTrigger.OnEntry += OnEnterContactTrigger;
AttachedObject._contactTrigger.OnExit -= AttachedObject.OnExitContactTrigger;
AttachedObject._contactTrigger.OnExit += OnExitContactTrigger;
AttachedObject._origEdgeCatcherSize = AttachedObject._contactEdgeCatcherShape.size;
AttachedObject._guardVolume = guardVolume;
}
public bool CanGrabPlayer(GhostPlayer player)
@ -107,7 +110,6 @@ public class QSBGhostSensors : WorldObject<GhostSensors>, IGhostObject
if (_data.interestedPlayer != closest)
{
DebugLog.DebugWrite($"CHANGE INTERESTED PLAYER!");
_data.interestedPlayer = closest;
this.SendMessage(new ChangeInterestedPlayerMessage(closest.player.PlayerId));
}
@ -118,6 +120,11 @@ public class QSBGhostSensors : WorldObject<GhostSensors>, IGhostObject
if (hitObj.CompareTag("PlayerDetector") && _data.localPlayer != null && _data.localPlayer.sensor != null)
{
_data.localPlayer.sensor.inContactWithPlayer = true;
if (!QSBCore.IsHost)
{
this.SendMessage(new ContactTriggerMessage(true));
}
}
}
@ -126,6 +133,11 @@ public class QSBGhostSensors : WorldObject<GhostSensors>, IGhostObject
if (hitObj.CompareTag("PlayerDetector") && _data.localPlayer != null && _data.localPlayer.sensor != null)
{
_data.localPlayer.sensor.inContactWithPlayer = false;
if (!QSBCore.IsHost)
{
this.SendMessage(new ContactTriggerMessage(false));
}
}
}
}

View File

@ -0,0 +1,187 @@
using QSB.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace QSB.EchoesOfTheEye.Prisoner;
internal class CustomAutoSlideProjector : MonoBehaviour
{
public float _defaultSlideDuration;
public float _endPauseDuration;
[SerializeField]
public CustomSlideCollectionContainer _slideCollectionItem;
public OWLight2 _light;
[SerializeField]
[Space]
private OWAudioSource _oneShotAudio;
private float _lastSlidePlayTime;
private float _startPausingEndTime;
private bool _isPlaying;
private bool _isPausingEnd;
protected void Awake()
{
if (this._slideCollectionItem != null)
{
this._slideCollectionItem.onSlideTextureUpdated += this.OnSlideTextureUpdated;
this._slideCollectionItem.Initialize();
this._slideCollectionItem.enabled = false;
}
else
{
DebugLog.DebugWrite($"COLLECTION ITEM NULL IN AWAKE", OWML.Common.MessageType.Error);
}
base.enabled = false;
}
protected void OnDestroy()
{
if (this._slideCollectionItem != null)
{
this._slideCollectionItem.onSlideTextureUpdated -= this.OnSlideTextureUpdated;
}
}
public bool IsPlaying()
{
return this._isPlaying;
}
public void Play(bool reset)
{
if (this._isPlaying)
{
return;
}
this._light.SetActivation(true);
if (reset)
{
this._slideCollectionItem.ResetSlideIndex();
}
this.UpdateSlideTexture();
this._lastSlidePlayTime = Time.time;
this._isPlaying = true;
base.enabled = true;
}
public void Stop()
{
if (!this._isPlaying)
{
return;
}
this._isPlaying = false;
base.enabled = false;
this._slideCollectionItem.enabled = false;
}
public void TurnOff()
{
this.Stop();
this._oneShotAudio.PlayOneShot(global::AudioType.Lantern_Remove, 1f);
this._light.SetActivation(false);
}
public void SetSlideCollection(CustomSlideCollectionContainer collection)
{
if (this._slideCollectionItem != null)
{
if (this._isPlaying)
{
this._slideCollectionItem.enabled = false;
}
this._slideCollectionItem.onSlideTextureUpdated -= this.OnSlideTextureUpdated;
}
this._slideCollectionItem = collection;
this._slideCollectionItem.onSlideTextureUpdated += this.OnSlideTextureUpdated;
this._slideCollectionItem.Initialize();
if (this._isPlaying)
{
this.UpdateSlideTexture();
}
}
protected virtual void Update()
{
if (this._isPlaying)
{
if (this._isPausingEnd)
{
if (Time.time >= this._endPauseDuration + this._startPausingEndTime)
{
this._isPausingEnd = false;
this.FirstSlide();
}
return;
}
if (Time.time >= this.GetCurrentSlidePlayDuration() + this._lastSlidePlayTime)
{
if (!this._slideCollectionItem.isEndOfSlide)
{
this.NextSlide();
return;
}
if (this._endPauseDuration > 0f)
{
this._isPausingEnd = true;
this._startPausingEndTime = Time.time;
return;
}
this.FirstSlide();
}
}
}
private void OnSlideTextureUpdated()
{
this.UpdateSlideTexture();
}
private void UpdateSlideTexture()
{
if (_light == null)
{
DebugLog.DebugWrite($"- Light is null!");
}
if (_slideCollectionItem == null)
{
DebugLog.DebugWrite($"- slide collection item is null!");
}
this._light.GetLight().cookie = this._slideCollectionItem.GetCurrentSlideTexture();
}
private void FirstSlide()
{
this._slideCollectionItem.ResetSlideIndex();
this._lastSlidePlayTime = Time.time;
if (this._oneShotAudio != null)
{
this._oneShotAudio.PlayOneShot(global::AudioType.Projector_Next, 1f);
}
}
private void NextSlide()
{
this._slideCollectionItem.IncreaseSlideIndex();
this._lastSlidePlayTime = Time.time;
if (this._oneShotAudio != null)
{
this._oneShotAudio.PlayOneShot(global::AudioType.Projector_Next, 1f);
}
}
private float GetCurrentSlidePlayDuration()
{
return this._defaultSlideDuration;
}
}

View File

@ -0,0 +1,105 @@
using QSB.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace QSB.EchoesOfTheEye.Prisoner;
[Serializable]
public class CustomSlide
{
public Texture2D _image;
private Texture2D _textureOverride;
private CustomSlideCollectionContainer _owningItem;
public bool expanded;
public Texture2D textureOverride
{
get
{
return this._textureOverride;
}
set
{
if (this._textureOverride == value)
{
return;
}
this._textureOverride = value;
this.InvokeTextureUpdate();
}
}
public CustomSlide()
{
this._image = null;
this.expanded = false;
}
public CustomSlide(CustomSlide other)
{
this._image = other._image;
this.expanded = false;
}
public Texture GetTexture()
{
if (this._textureOverride != null)
{
return this._textureOverride;
}
if (_image == null)
{
DebugLog.DebugWrite($"IMAGE IS NULL!", OWML.Common.MessageType.Error);
}
return this._image;
}
public void Display(CustomSlideCollectionContainer owner, bool forward)
{
if (owner == null)
{
DebugLog.DebugWrite($"OWNER IS NULL IN DISPLAY", OWML.Common.MessageType.Error);
}
this._owningItem = owner;
this.InvokeTextureUpdate();
}
public void InvokeTextureUpdate()
{
if (this._owningItem != null)
{
this._owningItem.onSlideTextureUpdated.Invoke();
}
else
{
DebugLog.DebugWrite($"OWNING ITEM IS NULL!", OWML.Common.MessageType.Error);
}
}
public void SetChangeSlidesAllowed(bool allowed)
{
this._owningItem.SetChangeSlidesAllowed(allowed);
}
public void SetOwner(CustomSlideCollectionContainer owner)
{
this._owningItem = owner;
}
public static CustomSlide CreateSlide(Texture2D texture)
{
CustomSlide slide = new CustomSlide
{
_image = texture
};
return slide;
}
}

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace QSB.EchoesOfTheEye.Prisoner;
public class CustomSlideCollection
{
[SerializeField]
public CustomSlide[] slides;
public CustomSlideCollection(int startArrSize)
{
this.slides = new CustomSlide[startArrSize];
}
public CustomSlide this[int i]
{
get
{
return this.slides[i];
}
}
}

View File

@ -0,0 +1,143 @@
using QSB.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace QSB.EchoesOfTheEye.Prisoner;
public class CustomSlideCollectionContainer : MonoBehaviour
{
[SerializeField]
public CustomSlideCollection _slideCollection = new CustomSlideCollection(0);
private bool _changeSlidesAllowed;
private int _currentSlideIndex;
private bool _initialized;
public int slideCount
{
get
{
if (this._slideCollection.slides == null)
{
return 0;
}
return this._slideCollection.slides.Length;
}
}
public bool isEndOfSlide
{
get
{
return this._currentSlideIndex >= this.slideCount - 1;
}
}
public int slideIndex
{
get
{
return this._currentSlideIndex;
}
set
{
if (!this._changeSlidesAllowed)
{
return;
}
if (this._currentSlideIndex == value)
{
return;
}
bool forward = this._currentSlideIndex < value;
this._currentSlideIndex = value;
if (this._currentSlideIndex > this._slideCollection.slides.Length - 1)
{
this._currentSlideIndex = 0;
}
if (this._currentSlideIndex < 0)
{
this._currentSlideIndex = this._slideCollection.slides.Length - 1;
}
this.GetCurrentSlide().Display(this, forward);
}
}
public OWEvent onSlideTextureUpdated = new OWEvent(1);
public OWEvent onEndOfSlides = new OWEvent(1);
public void Initialize()
{
if (this._initialized)
{
return;
}
this._changeSlidesAllowed = true;
this._initialized = true;
}
public CustomSlide GetCurrentSlide()
{
if (this._slideCollection.slides.Length == 0)
{
return null;
}
return this._slideCollection.slides[this._currentSlideIndex];
}
public Texture GetCurrentSlideTexture()
{
if (this._slideCollection.slides.Length == 0)
{
DebugLog.DebugWrite($"NO SLIDES!", OWML.Common.MessageType.Error);
return null;
}
return this.GetCurrentSlide().GetTexture();
}
public void ResetSlideIndex()
{
this.slideIndex = 0;
this.GetCurrentSlide().SetOwner(this);
}
public bool IncreaseSlideIndex()
{
if (!this._changeSlidesAllowed)
{
return false;
}
int slideIndex = this.slideIndex;
this.slideIndex = slideIndex + 1;
if (this.slideIndex == 0)
{
this.onEndOfSlides.Invoke();
}
return true;
}
public bool DecreaseSlideIndex()
{
if (!this._changeSlidesAllowed)
{
return false;
}
int slideIndex = this.slideIndex;
this.slideIndex = slideIndex - 1;
return true;
}
public void SetChangeSlidesAllowed(bool allowed)
{
this._changeSlidesAllowed = allowed;
}
}

View File

@ -0,0 +1,14 @@
using QSB.EchoesOfTheEye.Prisoner.WorldObjects;
using QSB.Messaging;
namespace QSB.EchoesOfTheEye.Prisoner.Messages;
internal class CellevatorCallMessage : QSBWorldObjectMessage<QSBPrisonCellElevator, int>
{
public CellevatorCallMessage(int index) : base(index) { }
public override void OnReceiveRemote()
{
WorldObject.CallToFloorIndex(Data, true);
}
}

View File

@ -0,0 +1,19 @@
using QSB.Messaging;
using QSB.WorldSync;
using System.Linq;
namespace QSB.EchoesOfTheEye.Prisoner.Messages;
internal class EmergeTriggerMessage : QSBMessage
{
public override void OnReceiveRemote()
{
// hewwo
var director = QSBWorldSync.GetUnityObject<PrisonerDirector>();
director._darknessAwoken = true;
director._cellevator.OnPrisonerReveal();
director._musicSource.SetLocalVolume(Locator.GetAudioManager().GetAudioEntry(director._musicSource.audioLibraryClip).volume);
director._musicSource.Play();
director._prisonerBrain.BeginBehavior(PrisonerBehavior.Emerge);
}
}

View File

@ -0,0 +1,17 @@
using QSB.Messaging;
using QSB.WorldSync;
using System.Linq;
namespace QSB.EchoesOfTheEye.Prisoner.Messages;
internal class EnterLightsOutMessage : QSBMessage
{
public override void OnReceiveRemote()
{
var director = QSBWorldSync.GetUnityObject<PrisonerDirector>();
director._lightsOutTrigger.OnEntry -= director.OnEnterLightsOutTrigger;
director._prisonLighting.FadeTo(0, 1);
director._hangingLampSource.PlayOneShot(AudioType.Candle_Extinguish, 1f);
director._lightsOnAudioVolume.SetVolumeActivation(false);
}
}

View File

@ -0,0 +1,14 @@
using QSB.Messaging;
using QSB.WorldSync;
using System.Linq;
namespace QSB.EchoesOfTheEye.Prisoner.Messages;
internal class MindProjectionCompleteMessage : QSBMessage
{
public override void OnReceiveRemote()
{
var director = QSBWorldSync.GetUnityObject<PrisonerDirector>();
director.OnMindProjectionComplete();
}
}

View File

@ -0,0 +1,14 @@
using QSB.Messaging;
using QSB.WorldSync;
using System.Linq;
namespace QSB.EchoesOfTheEye.Prisoner.Messages;
internal class ProjectMessage : QSBMessage
{
public override void OnReceiveRemote()
{
var director = QSBWorldSync.GetUnityObject<PrisonerDirector>();
director._prisonerBrain.BeginBehavior(PrisonerBehavior.ExperienceVision, 0f);
}
}

View File

@ -0,0 +1,28 @@
using QSB.Messaging;
using QSB.WorldSync;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace QSB.EchoesOfTheEye.Prisoner.Messages;
internal class StopProjectMessage : QSBMessage<bool>
{
public StopProjectMessage(bool done) : base(done) { }
public override void OnReceiveRemote()
{
var director = QSBWorldSync.GetUnityObject<PrisonerDirector>();
if (!Data)
{
director._prisonerBrain.BeginBehavior(PrisonerBehavior.WaitForProjection, 0.5f);
return;
}
director._prisonerDetector.SetActivation(false);
director._prisonerBrain.BeginBehavior(PrisonerBehavior.ExperienceEmotionalCatharsis, 0.5f);
}
}

View File

@ -0,0 +1,28 @@
using HarmonyLib;
using QSB.EchoesOfTheEye.Prisoner.WorldObjects;
using QSB.Patches;
using QSB.WorldSync;
namespace QSB.EchoesOfTheEye.Prisoner.Patches;
[HarmonyPatch(typeof(PrisonCellElevator))]
public class CellevatorPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(nameof(PrisonCellElevator.CallToTopFloor))]
public static bool CallToTopFloor(PrisonCellElevator __instance)
{
__instance.GetWorldObject<QSBPrisonCellElevator>().CallToFloorIndex(1);
return false;
}
[HarmonyPrefix]
[HarmonyPatch(nameof(PrisonCellElevator.CallToBottomFloor))]
public static bool CallToBottomFloor(PrisonCellElevator __instance)
{
__instance.GetWorldObject<QSBPrisonCellElevator>().CallToFloorIndex(0);
return false;
}
}

View File

@ -3,13 +3,9 @@ using QSB.EchoesOfTheEye.Prisoner.Messages;
using QSB.EchoesOfTheEye.Prisoner.WorldObjects;
using QSB.Messaging;
using QSB.Patches;
using QSB.Player;
using QSB.Utility;
using QSB.WorldSync;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace QSB.EchoesOfTheEye.Prisoner.Patches;
@ -87,4 +83,17 @@ internal class PrisonerBrainPatches : QSBPatch
__instance.GetWorldObject<QSBPrisonerBrain>().FixedUpdate();
return false;
}
[HarmonyPrefix]
[HarmonyPatch(nameof(PrisonerBrain.OnFinishEmergeAnimation))]
public static bool OnFinishEmergeAnimation(PrisonerBrain __instance)
{
if (__instance._currentBehavior is PrisonerBehavior.Emerge or PrisonerBehavior.WaitForConversation)
{
__instance._effects.OnRevealAnimationComplete -= __instance.OnFinishEmergeAnimation;
__instance.OnFinishEmergeBehavior.Invoke();
}
return false;
}
}

View File

@ -0,0 +1,78 @@
using HarmonyLib;
using QSB.EchoesOfTheEye.Prisoner.Messages;
using QSB.Messaging;
using QSB.Patches;
using UnityEngine;
namespace QSB.EchoesOfTheEye.Prisoner.Patches;
[HarmonyPatch(typeof(PrisonerDirector))]
public class PrisonerDirectorPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(nameof(PrisonerDirector.OnEnterEmergeTrigger))]
public static bool OnEnterEmergeTrigger(PrisonerDirector __instance, GameObject hitObj)
{
if (__instance._darknessAwoken)
{
return false;
}
if (hitObj.CompareTag("PlayerDetector"))
{
__instance._darknessAwoken = true;
__instance._prisonerBrain.BeginBehavior(PrisonerBehavior.Emerge, 0f);
__instance._cellevator.OnPrisonerReveal();
__instance._musicSource.SetLocalVolume(Locator.GetAudioManager().GetAudioEntry(__instance._musicSource.audioLibraryClip).volume);
__instance._musicSource.Play();
new EmergeTriggerMessage().Send();
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(nameof(PrisonerDirector.OnMindProjectionComplete))]
public static bool OnMindProjectionComplete(PrisonerDirector __instance)
{
if (__instance._projectingVision)
{
__instance._visionTorchItem.mindProjectorTrigger.SetProjectorActive(false);
__instance._projectingVision = false;
__instance._prisonerBrain.BeginBehavior(PrisonerBehavior.OfferTorch, 3f);
new MindProjectionCompleteMessage().Send();
}
return false;
}
[HarmonyPostfix]
[HarmonyPatch(nameof(PrisonerDirector.OnStartProjectingOnPrisoner))]
public static void OnStartProjectingOnPrisoner()
=> new ProjectMessage().Send();
[HarmonyPostfix]
[HarmonyPatch(nameof(PrisonerDirector.OnStopProjectingOnPrisoner))]
public static void OnStopProjectingOnPrisoner(PrisonerDirector __instance)
=> new StopProjectMessage(__instance._visionTorchItem.mindSlideProjector.mindSlideCollection.slideCollectionContainer.isEndOfSlide).Send();
[HarmonyPrefix]
[HarmonyPatch(nameof(PrisonerDirector.OnEnterLightsOutTrigger))]
public static bool OnEnterLightsOutTrigger(PrisonerDirector __instance, GameObject hitObj)
{
if (hitObj.CompareTag("PlayerDetector"))
{
__instance._lightsOutTrigger.OnEntry -= __instance.OnEnterLightsOutTrigger;
__instance._prisonLighting.FadeTo(0f, 1f);
__instance._hangingLampSource.PlayOneShot(AudioType.Candle_Extinguish, 1f);
__instance._lightsOnAudioVolume.SetVolumeActivation(false);
new EnterLightsOutMessage().Send();
}
return false;
}
}

View File

@ -18,7 +18,7 @@ internal class PrisonerManager : WorldObjectManager
public override async UniTask BuildWorldObjects(OWScene scene, CancellationToken ct)
{
var director = QSBWorldSync.GetUnityObjects<PrisonerDirector>().First();
var director = QSBWorldSync.GetUnityObject<PrisonerDirector>();
var markers = new List<Transform>()
{
@ -37,5 +37,6 @@ internal class PrisonerManager : WorldObjectManager
QSBWorldSync.Init<QSBPrisonerMarker, PrisonerBehaviourCueMarker>();
QSBWorldSync.Init<QSBPrisonerBrain, PrisonerBrain>();
QSBWorldSync.Init<QSBPrisonCellElevator, PrisonCellElevator>();
}
}

View File

@ -0,0 +1,93 @@
using Cysharp.Threading.Tasks;
using QSB.Audio;
using QSB.EchoesOfTheEye.Ghosts.WorldObjects;
using QSB.EchoesOfTheEye.Prisoner.Messages;
using QSB.ItemSync.WorldObjects;
using QSB.Messaging;
using QSB.Player;
using QSB.Utility;
using QSB.WorldSync;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
namespace QSB.EchoesOfTheEye.Prisoner.WorldObjects;
internal class QSBPrisonCellElevator : WorldObject<PrisonCellElevator>, IQSBDropTarget, IGhostObject
{
public override void SendInitialState(uint to)
{
// todo : implement this
}
IItemDropTarget IQSBDropTarget.AttachedObject => AttachedObject;
/*public override async UniTask Init(CancellationToken ct)
{
DebugLog.DebugWrite($"INIT {AttachedObject.name}");
var Interactibles_PrisonCell = AttachedObject.GetAttachedOWRigidbody().GetOrigParent().parent;
DebugLog.DebugWrite(Interactibles_PrisonCell.name);
var AUTO_SLIDE_PROJECTOR = new GameObject("AUTO SLIDE PROJECTOR");
AUTO_SLIDE_PROJECTOR.transform.parent = Interactibles_PrisonCell;
AUTO_SLIDE_PROJECTOR.transform.localPosition = new Vector3(-1.8f, 6.4f, 11.33f);
AUTO_SLIDE_PROJECTOR.transform.localRotation = Quaternion.identity;
AUTO_SLIDE_PROJECTOR.transform.localScale = Vector3.one;
AUTO_SLIDE_PROJECTOR.SetActive(false);
var Light = new GameObject("Light");
Light.transform.parent = AUTO_SLIDE_PROJECTOR.transform;
Light.transform.localPosition = Vector3.zero;
Light.transform.localRotation = Quaternion.Euler(32f, 90f, 0f);
var lightComponent = Light.AddComponent<Light>();
lightComponent.type = LightType.Spot;
lightComponent.range = 10;
lightComponent.intensity = 2;
lightComponent.spotAngle = 50;
lightComponent.shadows = LightShadows.Soft;
lightComponent.shadowStrength = 1f;
lightComponent.shadowResolution = UnityEngine.Rendering.LightShadowResolution.Low;
lightComponent.shadowBias = 0.05f;
lightComponent.shadowNormalBias = 0.4f;
lightComponent.shadowNearPlane = 0.2f;
Light.AddComponent<OWLight2>();
var projectorComponent = AUTO_SLIDE_PROJECTOR.AddComponent<CustomAutoSlideProjector>();
projectorComponent._light = Light.GetComponent<OWLight2>();
var cellevator1 = TextureHelper.LoadTexture("Assets/cellevator1.png", TextureWrapMode.Clamp, true);
var cellevator2 = TextureHelper.LoadTexture("Assets/cellevator2.png", TextureWrapMode.Clamp, true);
var cellevator3 = TextureHelper.LoadTexture("Assets/cellevator3.png", TextureWrapMode.Clamp, true);
var slideCollection = new CustomSlideCollection(3);
slideCollection.slides[0] = new CustomSlide() { _image = cellevator1 };
slideCollection.slides[1] = new CustomSlide() { _image = cellevator2 };
slideCollection.slides[2] = new CustomSlide() { _image = cellevator3 };
var slideContainer = AUTO_SLIDE_PROJECTOR.AddComponent<CustomSlideCollectionContainer>();
slideContainer._slideCollection = slideCollection;
projectorComponent.SetSlideCollection(slideContainer);
projectorComponent._defaultSlideDuration = 1f;
AUTO_SLIDE_PROJECTOR.SetActive(true);
projectorComponent.Play(false);
}*/
public void CallToFloorIndex(int index, bool remote = false)
{
if (!remote)
{
this.SendMessage(new CellevatorCallMessage(index));
}
AttachedObject.CallElevatorToFloor(index);
}
}

View File

@ -10,7 +10,7 @@ using UnityEngine;
namespace QSB.EchoesOfTheEye.Prisoner.WorldObjects;
internal class QSBPrisonerBrain : WorldObject<PrisonerBrain>
internal class QSBPrisonerBrain : WorldObject<PrisonerBrain>, IGhostObject
{
public override void SendInitialState(uint to)
{
@ -27,13 +27,57 @@ internal class QSBPrisonerBrain : WorldObject<PrisonerBrain>
public QSBGhostSensors Sensors => AttachedObject._sensors.GetWorldObject<QSBGhostSensors>();
public QSBGhostData Data;
public override void DisplayLines()
{
ControllerLines(Controller);
DataLines(Data, Controller);
}
private void ControllerLines(QSBGhostController controller)
{
Popcron.Gizmos.Sphere(controller.AttachedObject.transform.position, 2f, Color.white);
if (controller.AttachedObject._followNodePath)
{
for (var i = controller.AttachedObject._nodePath.Count - 1; i >= 0; i--)
{
Popcron.Gizmos.Sphere(controller.AttachedObject.LocalToWorldPosition(controller.AttachedObject._nodePath[i].localPosition), 0.25f, Color.cyan, 3);
var hasVisited = controller.AttachedObject._pathIndex < i;
var color = hasVisited ? Color.white : Color.cyan;
if (i != 0)
{
Popcron.Gizmos.Line(controller.AttachedObject.LocalToWorldPosition(controller.AttachedObject._nodePath[i].localPosition), controller.AttachedObject.LocalToWorldPosition(controller.AttachedObject._nodePath[i - 1].localPosition), color);
}
}
if (controller.AttachedObject._hasFinalPathPosition)
{
Popcron.Gizmos.Sphere(controller.AttachedObject.LocalToWorldPosition(controller.AttachedObject._finalPathPosition), 0.3f, Color.red, 8);
}
}
}
private void DataLines(QSBGhostData data, QSBGhostController controller)
{
foreach (var player in data.players.Values)
{
if (player.timeSincePlayerLocationKnown != float.PositiveInfinity)
{
Popcron.Gizmos.Line(controller.AttachedObject.transform.position, controller.AttachedObject.LocalToWorldPosition(player.lastKnownPlayerLocation.localPosition), Color.magenta);
Popcron.Gizmos.Sphere(controller.AttachedObject.LocalToWorldPosition(player.lastKnownPlayerLocation.localPosition), 1f, Color.magenta);
}
}
}
public void Start()
{
AttachedObject.enabled = false;
AttachedObject._controller.GetDreamLanternController().enabled = false;
Controller.Initialize(AttachedObject._nodeLayer, Effects);
Data = new QSBGhostData();
Sensors.Initialize(Data, null);
Sensors.Initialize(Data);
Effects.Initialize(AttachedObject._controller.GetNodeRoot(), Controller, Data);
}

View File

@ -12,7 +12,7 @@ internal class EyeCloneSeenMessage : QSBMessage
public override void OnReceiveRemote()
{
var controller = QSBWorldSync.GetUnityObjects<PlayerCloneController>().First();
var controller = QSBWorldSync.GetUnityObject<PlayerCloneController>();
controller._warpFlickerActivated = true;
controller._warpTime = Time.time + 0.5f;

View File

@ -29,7 +29,7 @@ internal class KillGalaxiesMessage : QSBMessage
public override void OnReceiveRemote()
{
var galaxyController = QSBWorldSync.GetUnityObjects<MiniGalaxyController>().First();
var galaxyController = QSBWorldSync.GetUnityObject<MiniGalaxyController>();
galaxyController._killTrigger.OnEntry -= galaxyController.OnEnterKillTrigger;

View File

@ -24,7 +24,7 @@ internal class GalaxyMapManager : MonoBehaviour, IAddComponentOnStart
return;
}
var mapController = QSBWorldSync.GetUnityObjects<GalaxyMapController>().First();
var mapController = QSBWorldSync.GetUnityObject<GalaxyMapController>();
var map = mapController._interactVolume.gameObject;
map.SetActive(false);

View File

@ -10,7 +10,7 @@ internal class ZoomOutMessage : QSBMessage
public override void OnReceiveRemote()
{
var controller = QSBWorldSync.GetUnityObjects<GalaxyMapController>().First();
var controller = QSBWorldSync.GetUnityObject<GalaxyMapController>();
controller.enabled = true;
Locator.GetPlayerController().SetColliderActivation(false);
controller._endlessObservatoryVolume.SetActivation(false);

View File

@ -13,10 +13,10 @@ internal class QSBQuantumInstrument : WorldObject<QuantumInstrument>
public void Gather()
{
var maskZoneController = QSBWorldSync.GetUnityObjects<MaskZoneController>().First();
var maskZoneController = QSBWorldSync.GetUnityObject<MaskZoneController>();
if (maskZoneController._maskInstrument == AttachedObject)
{
var shuttleController = QSBWorldSync.GetUnityObjects<EyeShuttleController>().First();
var shuttleController = QSBWorldSync.GetUnityObject<EyeShuttleController>();
foreach (var player in MaskManager.WentOnSolanumsWildRide)
{

View File

@ -39,8 +39,7 @@ internal class MaskManager : MonoBehaviour, IAddComponentOnStart
{
if (_flickering && Time.time > _flickerOutTime)
{
// TODO : Optimize this out.
var controller = QSBWorldSync.GetUnityObjects<EyeShuttleController>().First();
var controller = QSBWorldSync.GetUnityObject<EyeShuttleController>();
controller._shuttleObject.SetActive(false);
_flickering = false;
_flickerOutTime = 0f;

View File

@ -35,7 +35,7 @@ internal class ItemManager : WorldObjectManager
// other drop targets that don't already have world objects
var listToInitFrom = QSBWorldSync.GetUnityObjects<MonoBehaviour>()
.Where(x => x is IItemDropTarget and not (RaftDock or RaftController))
.Where(x => x is IItemDropTarget and not (RaftDock or RaftController or PrisonCellElevator))
.SortDeterministic();
QSBWorldSync.Init<QSBOtherDropTarget, MonoBehaviour>(listToInitFrom);
}

View File

@ -17,7 +17,7 @@ public class MeteorManager : WorldObjectManager
// wait for all late initializers (which includes meteor launchers) to finish
await UniTask.WaitUntil(() => LateInitializerManager.isDoneInitializing, cancellationToken: ct);
WhiteHoleVolume = QSBWorldSync.GetUnityObjects<WhiteHoleVolume>().First();
WhiteHoleVolume = QSBWorldSync.GetUnityObject<WhiteHoleVolume>();
QSBWorldSync.Init<QSBFragment, FragmentIntegrity>();
QSBWorldSync.Init<QSBMeteorLauncher, MeteorLauncher>();
QSBWorldSync.Init<QSBMeteor, MeteorController>();

View File

@ -40,7 +40,7 @@ public static class LocalPlayerCreation
PlayerToolsManager.InitLocal();
// stick
var pivot = QSBWorldSync.GetUnityObjects<RoastingStickController>().First().transform.Find("Stick_Root/Stick_Pivot");
var pivot = QSBWorldSync.GetUnityObject<RoastingStickController>().transform.Find("Stick_Root/Stick_Pivot");
player.RoastingStick = pivot.parent.gameObject;
visibleRoastingSystem = pivot.parent.parent;
visibleStickPivot = pivot;

View File

@ -73,6 +73,10 @@
<None Include="storage.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Assets\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Remove="Assets\*.pdn" />
<None Include="AssetBundles\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@ -89,7 +93,7 @@
<ProjectReference Include="..\EpicOnlineTransport\EpicOnlineTransport.csproj" />
<ProjectReference Include="..\EpicRerouter\EpicRerouter.csproj" />
<ProjectReference Include="..\MirrorWeaver\MirrorWeaver.csproj" ReferenceOutputAssembly="false" />
<PackageReference Include="HarmonyX" Version="2.9.0" IncludeAssets="compile" />
<PackageReference Include="OWML" Version="2.3.2" IncludeAssets="compile" />
<PackageReference Include="HarmonyX" Version="2.10.0" IncludeAssets="compile" />
<PackageReference Include="OWML" Version="2.3.3" IncludeAssets="compile" />
</ItemGroup>
</Project>

View File

@ -217,4 +217,6 @@ public class QSBCore : ModBehaviour
* Daft Punk
* Natalie Holt
* WMD
* Woody Jackson
* Brian David Gilbert
*/

View File

@ -34,7 +34,7 @@ internal class QuantumManager : WorldObjectManager
QSBWorldSync.Init<QSBQuantumSkeletonTower, QuantumSkeletonTower>();
if (scene == OWScene.SolarSystem)
{
Shrine = QSBWorldSync.GetUnityObjects<QuantumShrine>().First();
Shrine = QSBWorldSync.GetUnityObject<QuantumShrine>();
}
UpdateFromDebugSetting();

View File

@ -51,7 +51,7 @@ internal class MarshmallowEventMessage : QSBMessage<MarshmallowMessageType>
var stick = player.RoastingStick;
var stickTip = stick.transform.GetChild(0);
var mallowPrefab = QSBWorldSync.GetUnityObjects<RoastingStickController>().First()._mallowBodyPrefab;
var mallowPrefab = QSBWorldSync.GetUnityObject<RoastingStickController>()._mallowBodyPrefab;
var tossedMallow = Object.Instantiate(mallowPrefab, stickTip.position, stickTip.rotation);
var rigidbody = tossedMallow.GetComponent<OWRigidbody>();

View File

@ -52,7 +52,7 @@ internal class SatelliteProjectorManager : MonoBehaviour, IAddComponentOnStart
{
if (newScene == OWScene.SolarSystem)
{
Projector = QSBWorldSync.GetUnityObjects<SatelliteSnapshotController>().First();
Projector = QSBWorldSync.GetUnityObject<SatelliteSnapshotController>();
Projector._loopingSource.spatialBlend = 1f;
Projector._oneShotSource.spatialBlend = 1f;

View File

@ -18,6 +18,7 @@ internal class GameStateMessage : QSBMessage
private int LoopCount;
private bool[] KnownFrequencies;
private Dictionary<int, bool> KnownSignals;
private bool ReducedFrights;
public GameStateMessage(uint toId)
{
@ -29,6 +30,7 @@ internal class GameStateMessage : QSBMessage
LoopCount = gameSave.loopCount;
KnownFrequencies = gameSave.knownFrequencies;
KnownSignals = gameSave.knownSignals;
ReducedFrights = PlayerData.GetReducedFrights();
}
@ -48,6 +50,8 @@ internal class GameStateMessage : QSBMessage
writer.Write(name);
writer.Write(discovered);
}
writer.Write(ReducedFrights);
}
public override void Deserialize(NetworkReader reader)
@ -68,6 +72,8 @@ internal class GameStateMessage : QSBMessage
var value = reader.Read<bool>();
KnownSignals.Add(key, value);
}
ReducedFrights = reader.Read<bool>();
}
public override void OnReceiveRemote()
@ -88,6 +94,7 @@ internal class GameStateMessage : QSBMessage
gameSave.secondsRemainingOnWarp = SecondsRemainingOnWarp;
PlayerData.SetPersistentCondition("LAUNCH_CODES_GIVEN", LaunchCodesGiven);
PlayerData._settingsSave.reducedFrights = ReducedFrights;
PlayerData.SaveCurrentGame();

View File

@ -62,8 +62,7 @@ public class QSBSector : WorldObject<Sector>
}
else if (QSBSceneManager.CurrentScene == OWScene.EyeOfTheUniverse)
{
// TODO : Optimize this out.
var shuttleController = QSBWorldSync.GetUnityObjects<EyeShuttleController>().First();
var shuttleController = QSBWorldSync.GetUnityObject<EyeShuttleController>();
if (shuttleController == null)
{
DebugLog.ToConsole($"Warning - Expected to find a EyeShuttleController for {AttachedObject.name}!", MessageType.Warning);

View File

@ -63,9 +63,9 @@ internal class ShipManager : WorldObjectManager
}
HatchInteractZone = HatchController.GetComponent<InteractZone>();
ShipTractorBeam = QSBWorldSync.GetUnityObjects<ShipTractorBeamSwitch>().First();
CockpitController = QSBWorldSync.GetUnityObjects<ShipCockpitController>().First();
ShipElectricalComponent = QSBWorldSync.GetUnityObjects<ShipElectricalComponent>().First();
ShipTractorBeam = QSBWorldSync.GetUnityObject<ShipTractorBeamSwitch>();
CockpitController = QSBWorldSync.GetUnityObject<ShipCockpitController>();
ShipElectricalComponent = QSBWorldSync.GetUnityObject<ShipElectricalComponent>();
var sphereShape = HatchController.GetComponent<SphereShape>();
sphereShape.radius = 2.5f;

View File

@ -31,7 +31,7 @@ internal class TimeSyncUI : MonoBehaviour, IAddComponentOnStart
private void OnUniverseSceneLoad(OWScene oldScene, OWScene newScene)
{
_isSetUp = true;
var obj = QSBWorldSync.GetUnityObjects<SleepTimerUI>().First();
var obj = QSBWorldSync.GetUnityObject<SleepTimerUI>();
_canvas = obj._canvas;
_text = obj._text;
_canvas.enabled = false;

View File

@ -99,7 +99,15 @@ public class DebugActions : MonoBehaviour, IAddComponentOnStart
if (Keyboard.current[Key.Numpad3].wasPressedThisFrame)
{
Destroy(Locator.GetProbe().gameObject);
var sarcoController = QSBWorldSync.GetUnityObject<SarcophagusController>();
sarcoController.firstSealProjector.SetLit(false);
sarcoController.secondSealProjector.SetLit(false);
sarcoController.thirdSealProjector.SetLit(false);
sarcoController._attemptOpenAfterDelay = true;
sarcoController._openAttemptTime = Time.time + 0.5f;
sarcoController.enabled = true;
}
if (Keyboard.current[Key.Numpad4].wasPressedThisFrame)

View File

@ -234,7 +234,7 @@ internal class DebugGUI : MonoBehaviour, IAddComponentOnStart
if (QSBWorldSync.AllObjectsReady)
{
var ghost = QSBWorldSync.GetWorldObjects<QSBGhostBrain>().First(x => x.AttachedObject._name == "Kamaji");
var ghost = QSBWorldSync.GetWorldObjects<QSBGhostBrain>().First(x => x.AttachedObject._name == "Yubaba");
WriteLine(4, ghost.AttachedObject._name);
WriteLine(4, $"Action:{ghost.GetCurrentActionName()}");
WriteLine(4, $"Threat Awareness:{ghost.GetThreatAwareness()}");
@ -255,15 +255,24 @@ internal class DebugGUI : MonoBehaviour, IAddComponentOnStart
WriteLine(4, $"- IsHeldByPlayer:{lantern.AttachedObject.GetLanternController().IsHeldByPlayer()}");
WriteLine(4, $"- Concealed:{lantern.AttachedObject.GetLanternController().IsConcealed()}");
}
else
{
WriteLine(4, $"- LANTERN NULL", Color.red);
}
var position = player.player.Camera.transform.position;
var playerCamera = player.player.Camera;
if (playerCamera != null)
{
var position = playerCamera.transform.position;
WriteLine(4, $"- Camera in vision cone:{ghost.AttachedObject._sensors.CheckPointInVisionCone(position)}");
WriteLine(4, $"- CheckLineOccluded:{ghost.AttachedObject._sensors.CheckLineOccluded(ghost.AttachedObject._sensors._sightOrigin.position, position)}");
}
WriteLine(4, $"First check:{!ghost.AttachedObject._intruderConfirmPending}");
WriteLine(4, $"Second check:{ghost._data.threatAwareness > GhostData.ThreatAwareness.EverythingIsNormal || ghost._data.players.Values.Any(x => x.playerLocation.distance < 20f) || ghost._data.players.Values.Any(x => x.sensor.isPlayerIlluminatedByUs)}");
WriteLine(4, $"Third check:{ghost._data.players.Values.Any(x => x.sensor.isPlayerVisible) || ghost._data.players.Values.Any(x => x.sensor.inContactWithPlayer)}");
else
{
WriteLine(4, $"- CAMERA NULL", Color.red);
}
}
}
/*

View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace QSB.Utility;
public static class TextureHelper
{
public static Texture2D LoadTexture(string relativePath, TextureWrapMode wrapMode, bool forceMaxResolution)
{
var path = QSBCore.Helper.Manifest.ModFolderPath + relativePath;
if (!File.Exists(path))
{
return null;
}
var data = File.ReadAllBytes(path);
var tex = forceMaxResolution
? new Texture2D(1, 1, TextureFormat.RGB24, false)
: new Texture2D(1, 1);
tex.LoadImage(data);
tex.wrapMode = wrapMode;
return tex;
}
}

View File

@ -178,6 +178,7 @@ public static class QSBWorldSync
private static readonly List<IWorldObject> WorldObjects = new();
private static readonly Dictionary<MonoBehaviour, IWorldObject> UnityObjectsToWorldObjects = new();
private static readonly Dictionary<Type, MonoBehaviour> CachedUnityObjects = new();
static QSBWorldSync() =>
RequestInitialStatesMessage.SendInitialState += to =>
@ -216,6 +217,7 @@ public static class QSBWorldSync
DialogueConditions.Clear();
PersistentConditions.Clear();
ShipLogFacts.Clear();
CachedUnityObjects.Clear();
}
public static IEnumerable<IWorldObject> GetWorldObjects() => WorldObjects;
@ -260,6 +262,30 @@ public static class QSBWorldSync
return (TWorldObject)worldObject;
}
/// <summary>
/// not deterministic across platforms
/// </summary>
public static TUnityObject GetUnityObject<TUnityObject>()
where TUnityObject : MonoBehaviour
{
if (CachedUnityObjects.ContainsKey(typeof(TUnityObject)))
{
return CachedUnityObjects[typeof(TUnityObject)] as TUnityObject;
}
var unityObjects = GetUnityObjects<TUnityObject>();
if (unityObjects.Count() != 1)
{
DebugLog.ToConsole($"Warning - Tried to cache a unity object that there are multiple of. ({typeof(TUnityObject).Name})" +
$"\r\nCaching the first one - this probably is going to end badly!", MessageType.Warning);
}
var unityObject = unityObjects.First();
CachedUnityObjects.Add(typeof(TUnityObject), unityObject);
return unityObject;
}
/// <summary>
/// not deterministic across platforms
/// </summary>

View File

@ -7,8 +7,8 @@
"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.18.0",
"owmlVersion": "2.3.2",
"version": "0.19.0",
"owmlVersion": "2.3.3",
"dependencies": [ "_nebula.MenuFramework" ],
"pathsToPreserve": [ "debugsettings.json" ]
}

View File

@ -75,10 +75,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
### How complete is this mod? How far through the game can I play?
| Area of the game | Working |
|-------------------|--------------------|
| Base game | :heavy_check_mark: |
| Echoes of the Eye | :x: |
The base game is around 95% done, whereas EotE is around 80% done.
### Compatibility with other mods
TL;DR - Don't use any mods with QSB that aren't marked as QSB compatible.
@ -87,9 +84,7 @@ QSB relies on object hierarchy to sync objects, so any mod that changes that ris
### Will you make this compatible with NomaiVR?
Short answer : No.
Long answer : Pay me enough money, and maybe I'll consider it.
Maybe.
### Why do I keep getting thrown around the ship?
@ -136,11 +131,11 @@ Some debugging options exist to make things easier. These come in the form of ac
Hold Q and press :
- Numpad 1 - Teleport to nearest player.
- Numpad 2 - Warp to the Dreamworld.
- Numpad 3 - Destroy the probe.
- Numpad 2 - If holding LeftShift, warp to the dreamworld Vault fire. If not, warp to the Endless Canyon.
- Numpad 3 - Unlock the Sealed Vault.
- Numpad 4 - Damage the ship's electrical system.
- Numpad 5 - Trigger the supernova.
- Numpad 6 - Set the flags for meeting Solanum and the Prisoner.
- Numpad 6 - Set the flags for having met Solanum and the Prisoner.
- Numpad 7 - Warp to the Vessel.
- Numpad 8 - Insert the Advanced Warp Core into the Vessel.
- Numpad 9 - If holding LeftShift, load the SolarSystem scene. If not, load the EyeOfTheUniverse scene.
@ -164,7 +159,8 @@ The template for this file is this :
"drawLabels": false,
"drawQuantumVisibilityObjects": false,
"skipTitleScreen": false,
"greySkybox": false
"greySkybox": false,
"drawGhostAI": false
}
```
@ -180,6 +176,7 @@ The template for this file is this :
- drawQuantumVisibilityObjects - Indicates visibility objects with an orange shape.
- skipTitleScreen - Auto-skips the splash screen.
- greySkybox - Turns the skybox grey. Useful in the Eye, where it's pretty dark.
- drawGhostAI - Draws debug lines and labels just for the ghosts.
**Warning : Mod development can lead to unexpected errors in your computer system.**
- **When editing the networking code, mistakes can lead to QSB overwhelming your network connection with excess packets**.