quantum-space-buddies/QSB/ShipSync/Patches/ShipPatches.cs
2022-03-02 19:46:33 -08:00

255 lines
7.1 KiB
C#

using HarmonyLib;
using QSB.Messaging;
using QSB.Patches;
using QSB.ShipSync.Messages;
using QSB.ShipSync.Messages.Component;
using QSB.ShipSync.Messages.Hull;
using QSB.ShipSync.TransformSync;
using QSB.ShipSync.WorldObjects;
using QSB.Utility;
using QSB.WorldSync;
using UnityEngine;
namespace QSB.ShipSync.Patches;
[HarmonyPatch]
internal class ShipPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPrefix]
[HarmonyPatch(typeof(HatchController), nameof(HatchController.OnPressInteract))]
public static bool HatchController_OnPressInteract()
{
if (!PlayerState.IsInsideShip())
{
ShipManager.Instance.ShipTractorBeam.ActivateTractorBeam();
new FunnelEnableMessage().Send();
}
new HatchMessage(true).Send();
return true;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(HatchController), nameof(HatchController.OnEntry))]
public static bool HatchController_OnEntry(GameObject hitObj)
{
if (hitObj.CompareTag("PlayerDetector"))
{
new HatchMessage(false).Send();
}
return true;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipTractorBeamSwitch), nameof(ShipTractorBeamSwitch.OnTriggerExit))]
public static bool ShipTractorBeamSwitch_OnTriggerExit(ShipTractorBeamSwitch __instance, Collider hitCollider)
{
if (!__instance._isPlayerInShip && __instance._functional && hitCollider.CompareTag("PlayerDetector") && !ShipManager.Instance.HatchController._hatchObject.activeSelf)
{
ShipManager.Instance.HatchController.CloseHatch();
ShipManager.Instance.ShipTractorBeam.DeactivateTractorBeam();
new HatchMessage(false).Send();
}
return false;
}
[HarmonyReversePatch]
[HarmonyPatch(typeof(SingleInteractionVolume), nameof(SingleInteractionVolume.UpdateInteractVolume))]
public static void SingleInteractionVolume_UpdateInteractVolume_Stub(object instance) { }
[HarmonyPrefix]
[HarmonyPatch(typeof(InteractZone), nameof(InteractZone.UpdateInteractVolume))]
public static bool InteractZone_UpdateInteractVolume(InteractZone __instance)
{
/* Angle for interaction with the ship hatch
*
* \ 80° / - If in ship
* \ /
* \ /
* [=====] - Hatch
* / \
* / \
* / 280° \ - If not in ship
*
*/
if (!QSBWorldSync.AllObjectsReady || __instance != ShipManager.Instance.HatchInteractZone)
{
return true;
}
var angle = 2f * Vector3.Angle(__instance._playerCam.transform.forward, __instance.transform.forward);
__instance._focused = PlayerState.IsInsideShip()
? angle <= 80
: angle >= 280;
SingleInteractionVolume_UpdateInteractVolume_Stub(__instance);
return false;
}
[HarmonyReversePatch]
[HarmonyPatch(typeof(ShipComponent), nameof(ShipComponent.OnEnterShip))]
public static void ShipComponent_OnEnterShip_Stub(object instance) { }
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipElectricalComponent), nameof(ShipElectricalComponent.OnEnterShip))]
public static bool ShipElectricalComponent_OnEnterShip(ShipElectricalComponent __instance)
{
ShipComponent_OnEnterShip_Stub(__instance);
return false;
}
[HarmonyReversePatch]
[HarmonyPatch(typeof(ShipComponent), nameof(ShipComponent.OnExitShip))]
public static void ShipComponent_OnExitShip_Stub(object instance) { }
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipElectricalComponent), nameof(ShipElectricalComponent.OnExitShip))]
public static bool ShipElectricalComponent_OnExitShip(ShipElectricalComponent __instance)
{
ShipComponent_OnExitShip_Stub(__instance);
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipComponent), nameof(ShipComponent.SetDamaged))]
public static bool ShipComponent_SetDamaged(ShipComponent __instance, bool damaged)
{
if (__instance._damaged == damaged)
{
return false;
}
var qsbShipComponent = __instance.GetWorldObject<QSBShipComponent>();
if (damaged)
{
__instance._damaged = true;
__instance._repairFraction = 0f;
__instance.OnComponentDamaged();
__instance.RaiseEvent(nameof(__instance.OnDamaged), __instance);
qsbShipComponent
.SendMessage(new ComponentDamagedMessage());
}
else
{
__instance._damaged = false;
__instance._repairFraction = 1f;
__instance.OnComponentRepaired();
__instance.RaiseEvent(nameof(__instance.OnRepaired), __instance);
qsbShipComponent
.SendMessage(new ComponentRepairedMessage());
}
__instance.UpdateColliderState();
if (__instance._damageEffect)
{
__instance._damageEffect.SetEffectBlend(1f - __instance._repairFraction);
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipHull), nameof(ShipHull.FixedUpdate))]
public static bool ShipHull_FixedUpdate(ShipHull __instance)
{
if (__instance._dominantImpact != null)
{
var damage = Mathf.InverseLerp(30f, 200f, __instance._dominantImpact.speed);
if (damage > 0f)
{
var num2 = 0.15f;
if (damage < num2 && __instance._integrity > 1f - num2)
{
damage = num2;
}
__instance._integrity = Mathf.Max(__instance._integrity - damage, 0f);
var qsbShipHull = __instance.GetWorldObject<QSBShipHull>();
if (!__instance._damaged)
{
__instance._damaged = true;
__instance.RaiseEvent(nameof(__instance.OnDamaged), __instance);
qsbShipHull
.SendMessage(new HullDamagedMessage());
}
if (__instance._damageEffect != null)
{
__instance._damageEffect.SetEffectBlend(1f - __instance._integrity);
}
qsbShipHull
.SendMessage(new HullChangeIntegrityMessage(__instance._integrity));
}
foreach (var component in __instance._components)
{
if (!(component == null) && !component.isDamaged)
{
if (component.ApplyImpact(__instance._dominantImpact))
{
break;
}
}
}
__instance.RaiseEvent(nameof(__instance.OnImpact), __instance._dominantImpact, damage);
__instance._dominantImpact = null;
}
__instance.enabled = false;
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipDamageController), nameof(ShipDamageController.OnImpact))]
public static bool ShipDamageController_OnImpact()
=> ShipTransformSync.LocalInstance == null || ShipTransformSync.LocalInstance.hasAuthority;
[HarmonyPostfix]
[HarmonyPatch(typeof(ShipComponent), nameof(ShipComponent.RepairTick))]
public static void ShipComponent_RepairTick(ShipComponent __instance) =>
__instance.GetWorldObject<QSBShipComponent>()
.SendMessage(new ComponentRepairTickMessage(__instance._repairFraction));
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipHull), nameof(ShipHull.RepairTick))]
public static bool ShipHull_RepairTick(ShipHull __instance)
{
if (!__instance._damaged)
{
return false;
}
__instance._integrity = Mathf.Min(__instance._integrity + (Time.deltaTime / __instance._repairTime), 1f);
var qsbShipHull = __instance.GetWorldObject<QSBShipHull>();
qsbShipHull
.SendMessage(new HullChangeIntegrityMessage(__instance._integrity));
if (__instance._integrity >= 1f)
{
__instance._damaged = false;
__instance.RaiseEvent(nameof(__instance.OnRepaired), __instance);
qsbShipHull
.SendMessage(new HullRepairedMessage());
}
if (__instance._damageEffect != null)
{
__instance._damageEffect.SetEffectBlend(1f - __instance._integrity);
}
return false;
}
}