mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
148 lines
7.5 KiB
C#
148 lines
7.5 KiB
C#
using NewHorizons.Builder.Orbital;
|
|
using NewHorizons.External;
|
|
using NewHorizons.OrbitalPhysics;
|
|
using OWML.Utils;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using UnityEngine;
|
|
using NewHorizons.Utility;
|
|
using Logger = NewHorizons.Utility.Logger;
|
|
|
|
namespace NewHorizons.Builder.General
|
|
{
|
|
static class DetectorBuilder
|
|
{
|
|
public static void Make(GameObject body, OWRigidbody OWRB, AstroObject primaryBody, AstroObject astroObject)
|
|
{
|
|
GameObject detectorGO = new GameObject("FieldDetector");
|
|
detectorGO.SetActive(false);
|
|
detectorGO.transform.parent = body.transform;
|
|
detectorGO.transform.localPosition = Vector3.zero;
|
|
detectorGO.layer = 20;
|
|
|
|
ConstantForceDetector forceDetector = detectorGO.AddComponent<ConstantForceDetector>();
|
|
forceDetector.SetValue("_inheritElement0", true);
|
|
OWRB.RegisterAttachedForceDetector(forceDetector);
|
|
|
|
GravityVolume parentGravityVolume = primaryBody.GetAttachedOWRigidbody().GetAttachedGravityVolume();
|
|
if (parentGravityVolume != null)
|
|
{
|
|
forceDetector.SetValue("_detectableFields", new ForceVolume[] { parentGravityVolume });
|
|
}
|
|
else
|
|
{
|
|
// It's probably a focal point (or its just broken)
|
|
var binaryFocalPoint = primaryBody.gameObject.GetComponent<BinaryFocalPoint>();
|
|
if(binaryFocalPoint != null)
|
|
{
|
|
if(astroObject.GetCustomName().Equals(binaryFocalPoint.PrimaryName)) {
|
|
binaryFocalPoint.Primary = astroObject;
|
|
if (binaryFocalPoint.Secondary != null)
|
|
{
|
|
var secondaryRB = binaryFocalPoint.Secondary.GetAttachedOWRigidbody();
|
|
SetBinaryForceDetectableFields(binaryFocalPoint, forceDetector, secondaryRB.GetAttachedForceDetector(), OWRB, secondaryRB);
|
|
}
|
|
}
|
|
else if (astroObject.GetCustomName().Equals(binaryFocalPoint.SecondaryName))
|
|
{
|
|
binaryFocalPoint.Secondary = astroObject;
|
|
if (binaryFocalPoint.Primary != null)
|
|
{
|
|
var primaryRB = binaryFocalPoint.Primary.GetAttachedOWRigidbody();
|
|
SetBinaryForceDetectableFields(binaryFocalPoint, primaryRB.GetAttachedForceDetector(), forceDetector, primaryRB, OWRB);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// It's a planet
|
|
binaryFocalPoint.Planets.Add(astroObject);
|
|
if(binaryFocalPoint.Primary != null && binaryFocalPoint.Secondary != null)
|
|
{
|
|
var primaryGravityVolume = binaryFocalPoint.Primary.GetGravityVolume();
|
|
var secondaryGravityVolume = binaryFocalPoint.Secondary.GetGravityVolume();
|
|
forceDetector.SetValue("_detectableFields", new ForceVolume[] { primaryGravityVolume, secondaryGravityVolume });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
detectorGO.SetActive(true);
|
|
}
|
|
|
|
private static void SetBinaryForceDetectableFields(BinaryFocalPoint point, ForceDetector primaryCFD, ForceDetector secondaryCFD, OWRigidbody primaryRB, OWRigidbody secondaryRB)
|
|
{
|
|
Logger.Log($"Setting up binary focal point for {point.name}");
|
|
|
|
var primary = point.Primary;
|
|
var secondary = point.Secondary;
|
|
var planets = point.Planets;
|
|
|
|
|
|
// Binaries have to use inverse square gravity so overwrite it now
|
|
var primaryGV = primary.GetGravityVolume();
|
|
//primaryGV.SetValue("_falloffType", primaryGV.GetType().GetNestedType("FalloffType", BindingFlags.NonPublic).GetField("inverseSquared").GetValue(primaryGV));
|
|
//primaryGV.SetValue("_falloffExponent", 2);
|
|
|
|
var secondaryGV = secondary.GetGravityVolume();
|
|
//secondaryGV.SetValue("_falloffType", secondaryGV.GetType().GetNestedType("FalloffType", BindingFlags.NonPublic).GetField("inverseSquared").GetValue(secondaryGV));
|
|
//secondaryGV.SetValue("_falloffExponent", 2);
|
|
|
|
|
|
// Very specific distance between them
|
|
Vector3 separation = primary.transform.position - secondary.transform.position;
|
|
var Gm1 = primaryGV.GetStandardGravitationalParameter();
|
|
var Gm2 = secondaryGV.GetStandardGravitationalParameter();
|
|
float r1 = separation.magnitude * Gm2 / (Gm1 + Gm2);
|
|
float r2 = separation.magnitude * Gm1 / (Gm1 + Gm2);
|
|
|
|
primary.transform.position = point.transform.position + r1 * separation.normalized;
|
|
secondary.transform.position = point.transform.position - r2 * separation.normalized;
|
|
|
|
// Set detectable fields
|
|
primaryCFD.SetValue("_detectableFields", new ForceVolume[] { secondaryGV });
|
|
primaryCFD.SetValue("_inheritDetector", point.GetAttachedOWRigidbody().GetAttachedForceDetector());
|
|
primaryCFD.SetValue("_activeInheritedDetector", point.GetAttachedOWRigidbody().GetAttachedForceDetector());
|
|
primaryCFD.SetValue("_inheritElement0", false);
|
|
|
|
secondaryCFD.SetValue("_detectableFields", new ForceVolume[] { primaryGV });
|
|
secondaryCFD.SetValue("_inheritDetector", point.GetAttachedOWRigidbody().GetAttachedForceDetector());
|
|
secondaryCFD.SetValue("_activeInheritedDetector", point.GetAttachedOWRigidbody().GetAttachedForceDetector());
|
|
secondaryCFD.SetValue("_inheritElement0", false);
|
|
|
|
// Update speeds
|
|
var direction = Vector3.Cross(separation, Vector3.up).normalized;
|
|
var m1 = primaryRB.GetMass();
|
|
var m2 = secondaryRB.GetMass();
|
|
var reducedMass = m1 * m2 / (m1 + m2);
|
|
var r = separation.magnitude;
|
|
float v1 = OrbitalHelper.GetOrbitalVelocity(r, new Gravity(secondaryGV.GetFalloffExponent(), reducedMass), KeplerElements.FromTrueAnomaly(0.5f, r, 0, 0, 0, 0));
|
|
float v2 = OrbitalHelper.GetOrbitalVelocity(r, new Gravity(primaryGV.GetFalloffExponent(), reducedMass), KeplerElements.FromTrueAnomaly(0.5f, r, 0, 0, 0, 180));
|
|
|
|
Logger.Log($"Speed: {v1} {v2}");
|
|
|
|
primaryRB.UpdateCenterOfMass();
|
|
primaryRB.AddVelocityChange(direction * v1);
|
|
secondaryRB.UpdateCenterOfMass();
|
|
secondaryRB.AddVelocityChange(direction * -v2);
|
|
|
|
|
|
|
|
/*
|
|
//Hacky but whatever
|
|
var primaryInitialMotion = primary.gameObject.GetComponent<InitialMotion>();
|
|
if(primaryInitialMotion.GetValue<bool>("_isInitVelocityDirty"))
|
|
primaryInitialMotion.SetValue("_cachedInitVelocity", OWPhysics.CalculateOrbitVelocity(secondaryRB, primaryRB, 0f));
|
|
else
|
|
primaryInitialMotion.SetPrimaryBody(secondaryRB);
|
|
|
|
var secondaryInitialMotion = primary.gameObject.GetComponent<InitialMotion>();
|
|
if (secondaryInitialMotion.GetValue<bool>("_isInitVelocityDirty"))
|
|
secondaryInitialMotion.SetValue("_cachedInitVelocity", OWPhysics.CalculateOrbitVelocity(primaryRB, secondaryRB, 0f));
|
|
else
|
|
secondaryInitialMotion.SetPrimaryBody(primaryRB);
|
|
*/
|
|
}
|
|
}
|
|
}
|