add light sensor sync

This commit is contained in:
Mister_Nebula 2021-11-08 20:55:53 +00:00
parent d66db3baf9
commit bc1aa66de9
9 changed files with 241 additions and 24 deletions

View File

@ -0,0 +1,13 @@
using QSB.EchoesOfTheEye.AirlockSync.WorldObjects;
using QSB.WorldSync;
namespace QSB.EchoesOfTheEye.AirlockSync
{
class AirlockManager : WorldObjectManager
{
protected override void RebuildWorldObjects(OWScene scene)
{
QSBWorldSync.Init<QSBGhostAirlock, GhostAirlock>();
}
}
}

View File

@ -0,0 +1,17 @@
using QSB.WorldSync;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace QSB.EchoesOfTheEye.AirlockSync.WorldObjects
{
class QSBGhostAirlock : WorldObject<GhostAirlock>
{
public override void Init(GhostAirlock airlock, int id)
{
ObjectId = id;
AttachedObject = airlock;
}
}
}

View File

@ -0,0 +1,13 @@
using QSB.EchoesOfTheEye.LightSensorSync.WorldObjects;
using QSB.WorldSync;
namespace QSB.EchoesOfTheEye.LightSensorSync
{
class LightSensorManager : WorldObjectManager
{
protected override void RebuildWorldObjects(OWScene scene)
{
QSBWorldSync.Init<QSBSingleLightSensor, SingleLightSensor>();
}
}
}

View File

@ -0,0 +1,150 @@
using HarmonyLib;
using QSB.Patches;
using QSB.Player;
using QSB.Tools;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace QSB.EchoesOfTheEye.LightSensorSync.Patches
{
[HarmonyPatch]
class LightSensorPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(typeof(SingleLightSensor), nameof(SingleLightSensor.UpdateIllumination))]
public static bool UpdateIlluminationReplacement(SingleLightSensor __instance)
{
__instance._illuminated = false;
if (__instance._illuminatingDreamLanternList != null)
{
__instance._illuminatingDreamLanternList.Clear();
}
var vector = __instance.transform.TransformPoint(__instance._localSensorOffset);
var sensorWorldDir = Vector3.zero;
if (__instance._directionalSensor)
{
sensorWorldDir = __instance.transform.TransformDirection(__instance._localDirection).normalized;
}
if (__instance._lightSources == null)
{
return false;
}
for (var i = 0; i < __instance._lightSources.Count; i++)
{
var source = __instance._lightSources[i];
if ((__instance._lightSourceMask & source.GetLightSourceType()) == source.GetLightSourceType()
&& source.CheckIlluminationAtPoint(vector, __instance._sensorRadius, __instance._maxDistance))
{
var lightSourceType = source.GetLightSourceType();
switch (lightSourceType)
{
case LightSourceType.UNDEFINED:
{
var owlight = source as OWLight2;
var occludableLight = owlight.GetLight().shadows != LightShadows.None
&& owlight.GetLight().shadowStrength > 0.5f;
if (owlight.CheckIlluminationAtPoint(vector, __instance._sensorRadius, __instance._maxDistance)
&& !__instance.CheckOcclusion(owlight.transform.position, vector, sensorWorldDir, occludableLight))
{
__instance._illuminated = true;
}
break;
}
case LightSourceType.FLASHLIGHT:
{
if (source is Flashlight && (source as Flashlight) == Locator.GetFlashlight())
{
var position = Locator.GetPlayerCamera().transform.position;
var to = __instance.transform.position - position;
if (Vector3.Angle(Locator.GetPlayerCamera().transform.forward, to) <= __instance._maxSpotHalfAngle
&& !__instance.CheckOcclusion(position, vector, sensorWorldDir, true))
{
__instance._illuminated = true;
}
}
else
{
var player = QSBPlayerManager.PlayerList.First(x => x.FlashLight == (QSBFlashlight)source);
var position = player.Camera.transform.position;
var to = __instance.transform.position - position;
if (Vector3.Angle(player.Camera.transform.forward, to) <= __instance._maxSpotHalfAngle
&& !__instance.CheckOcclusion(position, vector, sensorWorldDir, true))
{
__instance._illuminated = true;
}
}
break;
}
case LightSourceType.PROBE:
{
var probe = Locator.GetProbe();
if (probe != null
&& probe.IsLaunched()
&& !probe.IsRetrieving()
&& probe.CheckIlluminationAtPoint(vector, __instance._sensorRadius, __instance._maxDistance)
&& !__instance.CheckOcclusion(probe.GetLightSourcePosition(), vector, sensorWorldDir, true))
{
__instance._illuminated = true;
}
break;
}
case LightSourceType.FLASHLIGHT | LightSourceType.PROBE:
case LightSourceType.FLASHLIGHT | LightSourceType.DREAM_LANTERN:
case LightSourceType.PROBE | LightSourceType.DREAM_LANTERN:
case LightSourceType.FLASHLIGHT | LightSourceType.PROBE | LightSourceType.DREAM_LANTERN:
break;
case LightSourceType.DREAM_LANTERN:
{
var dreamLanternController = __instance._lightSources[i] as DreamLanternController;
if (dreamLanternController.IsLit()
&& dreamLanternController.IsFocused(__instance._lanternFocusThreshold)
&& dreamLanternController.CheckIlluminationAtPoint(vector, __instance._sensorRadius, __instance._maxDistance)
&& !__instance.CheckOcclusion(dreamLanternController.GetLightPosition(), vector, sensorWorldDir, true))
{
__instance._illuminatingDreamLanternList.Add(dreamLanternController);
__instance._illuminated = true;
}
break;
}
case LightSourceType.SIMPLE_LANTERN:
foreach (var owlight in __instance._lightSources[i].GetLights())
{
var occludableLight = owlight.GetLight().shadows != LightShadows.None
&& owlight.GetLight().shadowStrength > 0.5f;
var maxDistance = Mathf.Min(__instance._maxSimpleLanternDistance, __instance._maxDistance);
if (owlight.CheckIlluminationAtPoint(vector, __instance._sensorRadius, maxDistance) && !__instance.CheckOcclusion(owlight.transform.position, vector, sensorWorldDir, occludableLight))
{
__instance._illuminated = true;
break;
}
}
break;
default:
if (lightSourceType == LightSourceType.VOLUME_ONLY)
{
__instance._illuminated = true;
}
break;
}
}
}
return false;
}
}
}

View File

@ -0,0 +1,13 @@
using QSB.WorldSync;
namespace QSB.EchoesOfTheEye.LightSensorSync.WorldObjects
{
class QSBSingleLightSensor : WorldObject<SingleLightSensor>
{
public override void Init(SingleLightSensor sensor, int id)
{
ObjectId = id;
AttachedObject = sensor;
}
}
}

View File

@ -10,6 +10,7 @@ using QSB.FrequencySync.Patches;
using QSB.GeyserSync.Patches;
using QSB.Inputs.Patches;
using QSB.ItemSync.Patches;
using QSB.EchoesOfTheEye.LightSensorSync.Patches;
using QSB.LogSync.Patches;
using QSB.OrbSync.Patches;
using QSB.Player.Patches;
@ -69,7 +70,8 @@ namespace QSB.Patches
new RespawnPatches(),
new LauncherPatches(),
new SolanumPatches(),
new SatelliteProjectorPatches()
new SatelliteProjectorPatches(),
new LightSensorPatches()
};
TypeToInstance = new Dictionary<QSBPatchTypes, Harmony>

View File

@ -87,6 +87,8 @@
<Compile Include="DeathSync\Patches\DeathPatches.cs" />
<Compile Include="DeathSync\Patches\RespawnPatches.cs" />
<Compile Include="DeathSync\RespawnManager.cs" />
<Compile Include="EchoesOfTheEye\AirlockSync\AirlockManager.cs" />
<Compile Include="EchoesOfTheEye\AirlockSync\WorldObjects\QSBGhostAirlock.cs" />
<Compile Include="ElevatorSync\WorldObjects\QSBElevator.cs" />
<Compile Include="ElevatorSync\Events\ElevatorEvent.cs" />
<Compile Include="ElevatorSync\ElevatorManager.cs" />
@ -110,6 +112,9 @@
<Compile Include="ItemSync\WorldObjects\Sockets\QSBOWItemDoubleSocket.cs" />
<Compile Include="ItemSync\WorldObjects\Sockets\QSBSlideProjectorSocket.cs" />
<Compile Include="ItemSync\WorldObjects\Sockets\QSBSlideReelSocket.cs" />
<Compile Include="EchoesOfTheEye\LightSensorSync\LightSensorManager.cs" />
<Compile Include="EchoesOfTheEye\LightSensorSync\Patches\LightSensorPatches.cs" />
<Compile Include="EchoesOfTheEye\LightSensorSync\WorldObjects\QSBSingleLightSensor.cs" />
<Compile Include="Menus\IMenuAPI.cs" />
<Compile Include="Menus\MenuManager.cs" />
<Compile Include="Messaging\BoolMessage.cs" />

View File

@ -5,10 +5,12 @@ using QSB.Animation.NPC;
using QSB.CampfireSync;
using QSB.ConversationSync;
using QSB.DeathSync;
using QSB.EchoesOfTheEye.AirlockSync;
using QSB.ElevatorSync;
using QSB.GeyserSync;
using QSB.Inputs;
using QSB.ItemSync;
using QSB.EchoesOfTheEye.LightSensorSync;
using QSB.Menus;
using QSB.OrbSync;
using QSB.Patches;
@ -119,6 +121,8 @@ namespace QSB
gameObject.AddComponent<CharacterAnimManager>();
gameObject.AddComponent<ShipManager>();
gameObject.AddComponent<ProbeLauncherManager>();
gameObject.AddComponent<LightSensorManager>();
gameObject.AddComponent<AirlockManager>();
DebugBoxManager.Init();

View File

@ -3,29 +3,35 @@ using UnityEngine;
namespace QSB.Tools
{
public class QSBFlashlight : MonoBehaviour
public class QSBFlashlight : MonoBehaviour, ILightSource
{
private OWLight2[] _lights;
internal OWLight2 _illuminationCheckLight;
private Transform _root;
private Transform _basePivot;
private Transform _wobblePivot;
private Vector3 _baseForward;
private Quaternion _baseRotation;
private LightSourceVolume _lightSourceVolume;
public bool FlashlightOn;
public void Start()
{
_lightSourceVolume = this.GetRequiredComponentInChildren<LightSourceVolume>();
_lightSourceVolume.LinkLightSource(this);
_lightSourceVolume.SetVolumeActivation(FlashlightOn);
_baseForward = _basePivot.forward;
_baseRotation = _basePivot.rotation;
}
public void Init(Flashlight oldComponent)
{
_lights = oldComponent.GetValue<OWLight2[]>("_lights");
_root = oldComponent.GetValue<Transform>("_root");
_basePivot = oldComponent.GetValue<Transform>("_basePivot");
_wobblePivot = oldComponent.GetValue<Transform>("_wobblePivot");
_lights = oldComponent._lights;
_illuminationCheckLight = oldComponent._illuminationCheckLight;
_root = oldComponent._root;
_basePivot = oldComponent._basePivot;
_wobblePivot = oldComponent._wobblePivot;
Destroy(oldComponent.GetComponent<LightLOD>());
foreach (var light in _lights)
@ -37,6 +43,12 @@ namespace QSB.Tools
FlashlightOn = false;
}
public LightSourceType GetLightSourceType()
=> LightSourceType.FLASHLIGHT;
public OWLight2[] GetLights()
=> _lights;
public void UpdateState(bool value)
{
if (value)
@ -58,7 +70,7 @@ namespace QSB.Tools
foreach (var light in _lights)
{
light.GetLight().enabled = true;
light.SetActivation(true);
}
FlashlightOn = true;
@ -66,6 +78,7 @@ namespace QSB.Tools
_basePivot.rotation = rotation;
_baseRotation = rotation;
_baseForward = _basePivot.forward;
_lightSourceVolume.SetVolumeActivation(FlashlightOn);
}
private void TurnOff()
@ -77,15 +90,16 @@ namespace QSB.Tools
foreach (var light in _lights)
{
light.GetLight().enabled = false;
light.SetActivation(false);
}
FlashlightOn = false;
_lightSourceVolume.SetVolumeActivation(FlashlightOn);
}
public bool CheckIlluminationAtPoint(Vector3 point, float buffer = 0f, float maxDistance = float.PositiveInfinity)
public bool CheckIlluminationAtPoint(Vector3 worldPoint, float buffer = 0f, float maxDistance = float.PositiveInfinity)
=> FlashlightOn
&& _lights[1].CheckIlluminationAtPoint(point, buffer, maxDistance);
&& _illuminationCheckLight.CheckIlluminationAtPoint(worldPoint, buffer, maxDistance);
public void FixedUpdate()
{
@ -97,19 +111,5 @@ namespace QSB.Tools
_baseForward = _basePivot.forward;
_wobblePivot.localRotation = OWUtilities.GetWobbleRotation(0.3f, 0.15f) * Quaternion.identity;
}
private void OnRenderObject()
{
if (!QSBCore.WorldObjectsReady || !QSBCore.DebugMode || !QSBCore.ShowLinesInDebug)
{
return;
}
var light = _lights[1].GetLight();
if (light.enabled)
{
Popcron.Gizmos.Cone(light.transform.position, light.transform.rotation, light.range, light.spotAngle, Color.yellow);
}
}
}
}