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>(); var buoyancyTriggerVolume = buoyancyObject.AddComponent<OWTriggerVolume>();
buoyancyTriggerVolume._owCollider = owCollider; buoyancyTriggerVolume._owCollider = owCollider;
var fluidVolume = buoyancyObject.AddComponent<RadialFluidVolume>(); var fluidVolume = buoyancyObject.AddComponent<NHFluidVolume>();
fluidVolume._fluidType = FluidVolume.Type.WATER; fluidVolume._fluidType = FluidVolume.Type.WATER;
fluidVolume._attachedBody = rb; fluidVolume._attachedBody = rb;
fluidVolume._triggerVolume = buoyancyTriggerVolume; 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 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) if (config.Props.Scatter != null)
{ {
@ -40,7 +40,10 @@ namespace NewHorizons.Builder.Props
} }
if(config.Props.Rafts != null) if(config.Props.Rafts != null)
{ {
// TODO foreach(var raftInfo in config.Props.Rafts)
{
RaftBuilder.Make(go, sector, raftInfo, planetBody);
}
} }
if(config.Props.Tornados != null) if(config.Props.Tornados != null)
{ {

View File

@ -1,4 +1,8 @@
using NewHorizons.Builder.General; using NewHorizons.Builder.General;
using NewHorizons.Components;
using NewHorizons.External;
using NewHorizons.Handlers;
using NewHorizons.Utility;
using OWML.Utils; using OWML.Utils;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -12,86 +16,56 @@ namespace NewHorizons.Builder.Props
{ {
public static class RaftBuilder 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"); if(_prefab == null)
{
GameObject raftObject = new GameObject($"{body.name}Raft"); _prefab = GameObject.FindObjectOfType<RaftController>().gameObject.InstantiateInactive();
raftObject.SetActive(false); _prefab.name = "Raft_Body_Prefab";
}
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);
GameObject raftObject = _prefab.InstantiateInactive();
raftObject.name = "Raft_Body";
raftObject.transform.parent = sector.transform; raftObject.transform.parent = sector.transform;
raftObject.transform.localPosition = position; raftObject.transform.localPosition = info.position;
raftObject.transform.rotation = Quaternion.FromToRotation(raftObject.transform.TransformDirection(Vector3.up), position.normalized); 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; lightSensor._sector.OnSectorOccupantsUpdated -= lightSensor.OnSectorOccupantsUpdated;
l._sector = sector; lightSensor._sector = sector;
l._sector.OnSectorOccupantsUpdated += l.OnSectorOccupantsUpdated; sector.OnSectorOccupantsUpdated += lightSensor.OnSectorOccupantsUpdated;
l._lightSourceMask = LightSourceType.FLASHLIGHT;
l.SetDetectorActive(true);
l.gameObject.SetActive(true);
} }
var rigidBody = raftObject.AddComponent<Rigidbody>(); /*
rigidBody.isKinematic = true; // Debug
rigidBody.interpolation = originalRaft.GetComponent<Rigidbody>().interpolation; foreach (var point in fluidDetector._localAlignmentCheckPoints)
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>())
{ {
c.ClearParentBody(); var sphere = AddDebugShape.AddSphere(fluidDetector.gameObject, 0.5f, Color.green);
c._parentBody = owRigidBody; sphere.transform.localPosition = point;
c.ListenForParentBodySuspension();
} }
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); 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) 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) if (body.Config.Signal != null)
SignalBuilder.Make(go, sector, body.Config.Signal, body.Mod); 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 PacificEngine.OW_CommonResources.Geometry.Orbits;
using NewHorizons.Utility.CommonResources; using NewHorizons.Utility.CommonResources;
using UnityEngine.Events; using UnityEngine.Events;
using HarmonyLib;
using System.Reflection;
namespace NewHorizons namespace NewHorizons
{ {
@ -111,6 +113,9 @@ namespace NewHorizons
BodyDict["EyeOfTheUniverse"] = new List<NewHorizonsBody>(); // Keep this empty tho fr BodyDict["EyeOfTheUniverse"] = new List<NewHorizonsBody>(); // Keep this empty tho fr
SystemDict["SolarSystem"] = new NewHorizonsSystem("SolarSystem", new StarSystemConfig(null), this); SystemDict["SolarSystem"] = new NewHorizonsSystem("SolarSystem", new StarSystemConfig(null), this);
// Patches
Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly());
Tools.Patches.Apply(); Tools.Patches.Apply();
Tools.WarpDrivePatches.Apply(); Tools.WarpDrivePatches.Apply();
Tools.OWCameraFix.Apply(); Tools.OWCameraFix.Apply();

View File

@ -16,6 +16,7 @@
<DebugType>none</DebugType> <DebugType>none</DebugType>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="HarmonyX" Version="2.10.0" />
<PackageReference Include="OWML" Version="2.1.0" /> <PackageReference Include="OWML" Version="2.1.0" />
<PackageReference Include="OuterWildsGameLibs" Version="1.1.11.73" /> <PackageReference Include="OuterWildsGameLibs" Version="1.1.11.73" />
</ItemGroup> </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.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml.Linq; using System.Xml.Linq;
using Harmony; using HarmonyLib;
using NewHorizons.Utility; using NewHorizons.Utility;
using OWML.Utils; using OWML.Utils;
using UnityEngine; using UnityEngine;