Rafts + patching with HarmonyLib

This commit is contained in:
Nick 2022-05-05 18:43:04 -04:00
parent 176d9e3011
commit 74a683def0
11 changed files with 235 additions and 200 deletions

View File

@ -70,7 +70,7 @@ namespace NewHorizons.Builder.Body
var buoyancyTriggerVolume = buoyancyObject.AddComponent<OWTriggerVolume>();
buoyancyTriggerVolume._owCollider = owCollider;
var fluidVolume = buoyancyObject.AddComponent<RadialFluidVolume>();
var fluidVolume = buoyancyObject.AddComponent<NHFluidVolume>();
fluidVolume._fluidType = FluidVolume.Type.WATER;
fluidVolume._attachedBody = rb;
fluidVolume._triggerVolume = buoyancyTriggerVolume;

View File

@ -1,124 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.Props
{
public class PlanetaryRaftController : MonoBehaviour
{
private LightSensor[] _lightSensors;
private float _acceleration = 5f;
private Vector3 _localAcceleration = Vector3.zero;
private OWRigidbody _raftBody;
private Sector _sector;
private GameObject parentBody;
//private GravityVolume gravityVolume;
public float BuoyancyModifier = 5f;
private Vector3 initialPosition;
private float targetRadius;
private void Awake()
{
this._raftBody = base.GetComponent<OWRigidbody>();
_lightSensors = GetComponentsInChildren<LightSensor>();
//gravity = (GetComponentInChildren<ConstantForceDetector>()._activeVolumes[0] as GravityVolume);
//gravityVolume = _sector.transform.parent.GetComponentInChildren<GravityVolume>();
initialPosition = transform.position - _sector.transform.position;
targetRadius = initialPosition.magnitude;
parentBody = _sector.transform.parent.gameObject;
Logger.Log($"{targetRadius}");
}
public void OnDestroy()
{
if(_sector != null)
{
_sector.OnOccupantEnterSector += OnOccupantEnterSector;
_sector.OnOccupantExitSector += OnOccupantExitSector;
}
}
private void FixedUpdate()
{
if (this._lightSensors[0].IsIlluminated())
{
this._localAcceleration += Vector3.forward * this._acceleration;
}
if (this._lightSensors[1].IsIlluminated())
{
this._localAcceleration += Vector3.right * this._acceleration;
}
if (this._lightSensors[2].IsIlluminated())
{
this._localAcceleration -= Vector3.forward * this._acceleration;
}
if (this._lightSensors[3].IsIlluminated())
{
this._localAcceleration -= Vector3.right * this._acceleration;
}
/*
var currentRadius = GetRelativePosition().magnitude;
if(currentRadius != targetRadius)
{
float g = 1f;
var r = (currentRadius / targetRadius);
//if (gravityVolume != null) g = gravityVolume.CalculateGravityMagnitude(currentRadius);
_raftBody.AddAcceleration((1f - Mathf.Sqrt(r)) * GetRelativePosition().normalized * g * BuoyancyModifier);
}
*/
/*
Vector3 vector2 = _raftBody.GetVelocity();
var normalVector = GetRelativePosition().normalized;
float normalComponent2 = Vector3.Dot(vector2, normalVector);
vector2 -= normalComponent2 * normalVector;
_raftBody.SetVelocity(vector2);
_raftBody.SetPosition(_sector.transform.position + normalVector * targetRadius);
*/
if (this._localAcceleration.sqrMagnitude > 0.001f)
{
this._raftBody.AddLocalAcceleration(this._localAcceleration);
}
this._localAcceleration = Vector3.zero;
}
private Vector3 GetRelativePosition()
{
return transform.position - parentBody.transform.position;
}
public void SetSector(Sector sector)
{
_sector = sector;
_sector.OnOccupantEnterSector += OnOccupantEnterSector;
_sector.OnOccupantExitSector += OnOccupantExitSector;
}
private void OnOccupantEnterSector(SectorDetector sectorDetector)
{
if (sectorDetector.GetOccupantType() == DynamicOccupant.Player)
{
_raftBody.Unsuspend();
}
}
private void OnOccupantExitSector(SectorDetector sectorDetector)
{
if (sectorDetector.GetOccupantType() == DynamicOccupant.Player)
{
_raftBody.Suspend();
}
}
}
}

View File

@ -18,7 +18,7 @@ namespace NewHorizons.Builder.Props
{
public static class PropBuildManager
{
public static void Make(GameObject go, Sector sector, IPlanetConfig config, IModBehaviour mod, string uniqueModName)
public static void Make(GameObject go, Sector sector, OWRigidbody planetBody, IPlanetConfig config, IModBehaviour mod, string uniqueModName)
{
if (config.Props.Scatter != null)
{
@ -40,7 +40,10 @@ namespace NewHorizons.Builder.Props
}
if(config.Props.Rafts != null)
{
// TODO
foreach(var raftInfo in config.Props.Rafts)
{
RaftBuilder.Make(go, sector, raftInfo, planetBody);
}
}
if(config.Props.Tornados != null)
{

View File

@ -1,4 +1,8 @@
using NewHorizons.Builder.General;
using NewHorizons.Components;
using NewHorizons.External;
using NewHorizons.Handlers;
using NewHorizons.Utility;
using OWML.Utils;
using System;
using System.Collections.Generic;
@ -12,86 +16,56 @@ namespace NewHorizons.Builder.Props
{
public static class RaftBuilder
{
public static void Make(GameObject body, Vector3 position, Sector sector, OWRigidbody OWRB, AstroObject ao)
private static GameObject _prefab;
public static void Make(GameObject planetGO, Sector sector, PropModule.RaftInfo info, OWRigidbody planetBody)
{
var originalRaft = GameObject.Find("RingWorld_Body/Sector_RingInterior/Interactibles_RingInterior/Rafts/Raft_Body");
GameObject raftObject = new GameObject($"{body.name}Raft");
raftObject.SetActive(false);
GameObject lightSensors = GameObject.Instantiate(GameObject.Find("RingWorld_Body/Sector_RingInterior/Sector_Zone2/Structures_Zone2/RaftHouse_Eye_Zone2/Interactables_RaftHouse_Eye_Zone2/Prefab_IP_RaftDock/RaftSocket/Raft_Body (7)/LightSensorRoot"), raftObject.transform);
GameObject geometry = GameObject.Instantiate(GameObject.Find("RingWorld_Body/Sector_RingInterior/Sector_Zone2/Structures_Zone2/RaftHouse_Eye_Zone2/Interactables_RaftHouse_Eye_Zone2/Prefab_IP_RaftDock/RaftSocket/Raft_Body (7)/Structure_IP_Raft"), raftObject.transform);
GameObject collidersObject = GameObject.Instantiate(GameObject.Find("RingWorld_Body/Sector_RingInterior/Sector_Zone2/Structures_Zone2/RaftHouse_Eye_Zone2/Interactables_RaftHouse_Eye_Zone2/Prefab_IP_RaftDock/RaftSocket/Raft_Body (7)/Colliders/"), raftObject.transform);
if(_prefab == null)
{
_prefab = GameObject.FindObjectOfType<RaftController>().gameObject.InstantiateInactive();
_prefab.name = "Raft_Body_Prefab";
}
GameObject raftObject = _prefab.InstantiateInactive();
raftObject.name = "Raft_Body";
raftObject.transform.parent = sector.transform;
raftObject.transform.localPosition = position;
raftObject.transform.rotation = Quaternion.FromToRotation(raftObject.transform.TransformDirection(Vector3.up), position.normalized);
raftObject.transform.localPosition = info.position;
raftObject.transform.localRotation = Quaternion.identity;
foreach (var l in lightSensors.GetComponentsInChildren<SingleLightSensor>())
sector.OnOccupantEnterSector += (sd) => OWAssetHandler.OnOccupantEnterSector(raftObject, sd, sector);
OWAssetHandler.LoadObject(raftObject);
var raftController = raftObject.GetComponent<RaftController>();
// Since awake already ran we have to unhook these events
raftController._sector.OnOccupantEnterSector -= raftController.OnOccupantEnterSector;
raftController._sector.OnOccupantExitSector -= raftController.OnOccupantExitSector;
raftController._riverFluid = null;
raftController._sector = sector;
sector.OnOccupantEnterSector += raftController.OnOccupantEnterSector;
sector.OnOccupantExitSector += raftController.OnOccupantExitSector;
// Detectors
var fluidDetector = raftObject.transform.Find("Detector_Raft").GetComponent<RaftFluidDetector>();
var waterVolume = planetGO.GetComponentInChildren<NHFluidVolume>();
fluidDetector._alignmentFluid = waterVolume;
// Light sensors
foreach(var lightSensor in raftObject.GetComponentsInChildren<SingleLightSensor>())
{
if (l._sector != null) l._sector.OnSectorOccupantsUpdated -= l.OnSectorOccupantsUpdated;
l._sector = sector;
l._sector.OnSectorOccupantsUpdated += l.OnSectorOccupantsUpdated;
l._lightSourceMask = LightSourceType.FLASHLIGHT;
l.SetDetectorActive(true);
l.gameObject.SetActive(true);
lightSensor._sector.OnSectorOccupantsUpdated -= lightSensor.OnSectorOccupantsUpdated;
lightSensor._sector = sector;
sector.OnSectorOccupantsUpdated += lightSensor.OnSectorOccupantsUpdated;
}
var rigidBody = raftObject.AddComponent<Rigidbody>();
rigidBody.isKinematic = true;
rigidBody.interpolation = originalRaft.GetComponent<Rigidbody>().interpolation;
rigidBody.collisionDetectionMode = originalRaft.GetComponent<Rigidbody>().collisionDetectionMode;
rigidBody.mass = originalRaft.GetComponent<Rigidbody>().mass;
rigidBody.drag = originalRaft.GetComponent<Rigidbody>().drag;
rigidBody.angularDrag = originalRaft.GetComponent<Rigidbody>().angularDrag;
var kinematicRigidBody = raftObject.AddComponent<KinematicRigidbody>();
kinematicRigidBody.centerOfMass = Vector3.zero;
var owRigidBody = raftObject.AddComponent<OWRigidbody>();
owRigidBody._kinematicSimulation = true;
owRigidBody._rigidbody = rigidBody;
owRigidBody._kinematicRigidbody = kinematicRigidBody;
kinematicRigidBody._rigidbody = rigidBody;
kinematicRigidBody._owRigidbody = owRigidBody;
//var motion = raftObject.AddComponent<MatchInitialMotion>();
//motion.SetBodyToMatch(OWRB);
foreach (var c in collidersObject.GetComponentsInChildren<OWCollider>())
/*
// Debug
foreach (var point in fluidDetector._localAlignmentCheckPoints)
{
c.ClearParentBody();
c._parentBody = owRigidBody;
c.ListenForParentBodySuspension();
var sphere = AddDebugShape.AddSphere(fluidDetector.gameObject, 0.5f, Color.green);
sphere.transform.localPosition = point;
}
var meshColliders = collidersObject.GetComponentsInChildren<MeshCollider>();
foreach (var c in meshColliders)
{
var child = c.gameObject;
var newCollider = child.AddComponent<MeshCollider>();
newCollider.sharedMesh = c.sharedMesh;
newCollider.material = c.material;
newCollider.sharedMaterial = c.sharedMaterial;
GameObject.Destroy(c);
}
foreach (var child in raftObject.GetComponentsInChildren<StreamingRenderMeshHandle>())
{
StreamingManager.LoadStreamingAssets(child.assetBundle);
}
//var detectorGO = DetectorBuilder.Make(raftObject, owRigidBody, ao, null, false, false);
//var fluidDetector = detectorGO.AddComponent<DynamicFluidDetector>();
//Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => fluidDetector._activeVolumes = new EffectVolume[] { body.GetComponentInChildren<RadialFluidVolume>() }.ToList());
var targetBodyAlignment = raftObject.AddComponent<AlignWithTargetBody>();
targetBodyAlignment._owRigidbody = owRigidBody;
targetBodyAlignment.SetTargetBody(OWRB);
targetBodyAlignment.SetUsePhysicsToRotate(true);
var controller = raftObject.AddComponent<PlanetaryRaftController>();
controller.SetSector(sector);
*/
raftObject.SetActive(true);
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Components
{
public class NHFluidVolume : RadialFluidVolume
{
public override float GetDepthAtPosition(Vector3 worldPosition)
{
Vector3 vector = transform.InverseTransformPoint(worldPosition);
float dist = Mathf.Sqrt(vector.x * vector.x + vector.z * vector.z + vector.y * vector.y);
return dist - _radius;
}
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Components
{
public class NHPlanetaryRaftFix : MonoBehaviour
{
private RaftController _raftController;
private RaftFluidDetector _fluidDetector;
private FluidVolume _fluidVolume;
private RaftEffectsController _effectsController;
public void Awake()
{
_raftController = gameObject.GetComponent<RaftController>();
_fluidDetector = _raftController._fluidDetector;
_fluidVolume = _fluidDetector._alignmentFluid;
_effectsController = _raftController._effectsController;
}
public void FixedUpdate()
{
if (_raftController._raftBody.IsSuspended()) return;
if (!_raftController._playerInEffectsRange) return;
// Normally this part won't get called because in RaftController it checks how submerged we are in the Ringworld river
// Just copy pasted it here using the actual fluid volume instead of making an ugly patch
float num = _fluidDetector.InFluidType(FluidVolume.Type.WATER) ? _fluidVolume.GetFractionSubmerged(_fluidDetector) : 0f;
bool allowMovement = num > 0.25f && num < 1f;
Logger.Log($"AllowMovement? [{allowMovement}]");
allowMovement = true;
_effectsController.UpdateMovementAudio(allowMovement, _raftController._lightSensors);
_effectsController.UpdateGroundedAudio(_fluidDetector);
}
}
}

View File

@ -340,7 +340,7 @@ namespace NewHorizons.Handlers
}
if (body.Config.Props != null)
PropBuildManager.Make(go, sector, body.Config, body.Mod, body.Mod.ModHelper.Manifest.UniqueName);
PropBuildManager.Make(go, sector, rb, body.Config, body.Mod, body.Mod.ModHelper.Manifest.UniqueName);
if (body.Config.Signal != null)
SignalBuilder.Make(go, sector, body.Config.Signal, body.Mod);

View File

@ -28,6 +28,8 @@ using NewHorizons.Builder.Atmosphere;
using PacificEngine.OW_CommonResources.Geometry.Orbits;
using NewHorizons.Utility.CommonResources;
using UnityEngine.Events;
using HarmonyLib;
using System.Reflection;
namespace NewHorizons
{
@ -111,6 +113,9 @@ namespace NewHorizons
BodyDict["EyeOfTheUniverse"] = new List<NewHorizonsBody>(); // Keep this empty tho fr
SystemDict["SolarSystem"] = new NewHorizonsSystem("SolarSystem", new StarSystemConfig(null), this);
// Patches
Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly());
Tools.Patches.Apply();
Tools.WarpDrivePatches.Apply();
Tools.OWCameraFix.Apply();

View File

@ -16,6 +16,7 @@
<DebugType>none</DebugType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="HarmonyX" Version="2.10.0" />
<PackageReference Include="OWML" Version="2.1.0" />
<PackageReference Include="OuterWildsGameLibs" Version="1.1.11.73" />
</ItemGroup>

View File

@ -0,0 +1,116 @@
using HarmonyLib;
using NewHorizons.Components;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Patches
{
[HarmonyPatch]
public class RaftPatches : HarmonyPatch
{
[HarmonyPrefix]
[HarmonyPatch(typeof(RaftController), nameof(RaftController.FixedUpdate))]
public static bool RaftController_FixedUpdate(RaftController __instance)
{
// If it has a river fluid its a normal one and we don't do anything
if (__instance._riverFluid != null) return true;
// Copy paste the original method
if (__instance._raftBody.IsSuspended())
{
return false;
}
bool playerInEffectsRange = __instance._playerInEffectsRange;
__instance._playerInEffectsRange = ((Locator.GetPlayerBody().GetPosition() - __instance._raftBody.GetPosition()).sqrMagnitude < 2500f);
if (playerInEffectsRange && !__instance._playerInEffectsRange)
{
__instance._effectsController.StopAllEffects();
}
if (__instance._dock != null || __instance._movingToTarget)
{
__instance._localAcceleration = Vector3.zero;
if (__instance._playerInEffectsRange)
{
__instance._effectsController.UpdateMovementAudio(false, __instance._lightSensors);
}
if (__instance._movingToTarget)
{
__instance.UpdateMoveToTarget();
}
return false;
}
if (__instance._fluidDetector.InFluidType(FluidVolume.Type.WATER))
{
if (__instance._lightSensors[0].IsIlluminated())
{
__instance._localAcceleration += Vector3.forward * __instance._acceleration;
}
if (__instance._lightSensors[1].IsIlluminated())
{
__instance._localAcceleration += Vector3.right * __instance._acceleration;
}
if (__instance._lightSensors[2].IsIlluminated())
{
__instance._localAcceleration -= Vector3.forward * __instance._acceleration;
}
if (__instance._lightSensors[3].IsIlluminated())
{
__instance._localAcceleration -= Vector3.right * __instance._acceleration;
}
}
if (__instance._localAcceleration.sqrMagnitude > 0.001f)
{
__instance._raftBody.AddLocalAcceleration(__instance._localAcceleration);
}
if (__instance._playerInEffectsRange)
{
// All this to change what fluidVolume we use on this line
float num = __instance._fluidDetector.InFluidType(FluidVolume.Type.WATER) ? __instance._fluidDetector._alignmentFluid.GetFractionSubmerged(__instance._fluidDetector) : 0f;
bool allowMovement = num > 0.25f && num < 1f;
__instance._effectsController.UpdateMovementAudio(allowMovement, __instance._lightSensors);
__instance._effectsController.UpdateGroundedAudio(__instance._fluidDetector);
}
__instance._localAcceleration = Vector3.zero;
return false;
}
[HarmonyReversePatch]
[HarmonyPatch(typeof(AsymmetricFluidDetector), "ManagedFixedUpdate")]
public static void AsymmetricFluidDetector_ManagedFixedUpdate(AsymmetricFluidDetector __instance)
{
// This is like doing base.FixedUpdate
}
[HarmonyPrefix]
[HarmonyPatch(typeof(AlignToSurfaceFluidDetector), "ManagedFixedUpdate")]
public static bool AlignToSurfaceFluidDetector_ManagedFixedUpdate(AlignToSurfaceFluidDetector __instance)
{
if (!__instance._alignmentFluid is NHFluidVolume) return true;
// Mostly copy pasting from the AlignWithDirection class
AsymmetricFluidDetector_ManagedFixedUpdate(__instance);
if (__instance._inAlignmentFluid)
{
// Both in world space
var currentDirection = __instance._owRigidbody.transform.up;
var alignmentDirection = (__instance.transform.position - __instance._alignmentFluid.transform.position).normalized;
var degreesToTarget = Vector3.Angle(currentDirection, alignmentDirection);
var adjustedSlerpRate = Mathf.Clamp01(100f / degreesToTarget * Time.fixedDeltaTime);
Vector3 a = OWPhysics.FromToAngularVelocity(currentDirection, alignmentDirection);
__instance._owRigidbody.SetAngularVelocity(Vector3.zero);
__instance._owRigidbody.AddAngularVelocityChange(a * adjustedSlerpRate);
}
return false;
}
}
}

View File

@ -10,7 +10,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Harmony;
using HarmonyLib;
using NewHorizons.Utility;
using OWML.Utils;
using UnityEngine;