Merge branch 'dev' into picture-frame-doors

This commit is contained in:
Mister_Nebula 2022-03-11 09:07:11 +00:00
commit c8ce4bdfb4
15 changed files with 181 additions and 433 deletions

View File

@ -1,5 +1,4 @@
using Mirror;
using QSB.ItemSync.WorldObjects.Items;
using QSB.ItemSync.WorldObjects.Items;
using QSB.Messaging;
using QSB.Player;
using QSB.SectorSync.WorldObjects;
@ -8,39 +7,21 @@ using UnityEngine;
namespace QSB.ItemSync.Messages;
internal class DropItemMessage : QSBWorldObjectMessage<IQSBItem>
internal class DropItemMessage : QSBWorldObjectMessage<IQSBItem,
(Vector3 LocalPos, Vector3 LocalNorm, int SectorId)>
{
private Vector3 Position;
private Vector3 Normal;
private int SectorId;
public DropItemMessage(Vector3 position, Vector3 normal, Sector sector)
{
Position = position;
Normal = normal;
SectorId = sector.GetWorldObject<QSBSector>().ObjectId;
}
public override void Serialize(NetworkWriter writer)
{
base.Serialize(writer);
writer.Write(Position);
writer.Write(Normal);
writer.Write(SectorId);
}
public override void Deserialize(NetworkReader reader)
{
base.Deserialize(reader);
Position = reader.ReadVector3();
Normal = reader.ReadVector3();
SectorId = reader.Read<int>();
}
public DropItemMessage(Vector3 position, Vector3 normal, Sector sector) : base((
sector.transform.InverseTransformPoint(position),
sector.transform.InverseTransformDirection(normal),
sector.GetWorldObject<QSBSector>().ObjectId
)) { }
public override void OnReceiveRemote()
{
var sector = SectorId.GetWorldObject<QSBSector>().AttachedObject;
WorldObject.DropItem(sector.transform.TransformPoint(Position), Normal, sector);
var sector = Data.SectorId.GetWorldObject<QSBSector>().AttachedObject;
var position = sector.transform.TransformPoint(Data.LocalPos);
var normal = sector.transform.TransformDirection(Data.LocalNorm);
WorldObject.DropItem(position, normal, sector);
var player = QSBPlayerManager.GetPlayer(From);
player.HeldItem = WorldObject;

View File

@ -90,7 +90,7 @@ internal class ItemPatches : QSBPatch
var parent = (customDropTarget == null)
? targetRigidbody.transform
: customDropTarget.GetItemDropTargetTransform(hit.collider.gameObject);
var IQSBItem = __instance._heldItem.GetWorldObject<IQSBItem>();
var qsbItem = __instance._heldItem.GetWorldObject<IQSBItem>();
__instance._heldItem.DropItem(hit.point, hit.normal, parent, sector, customDropTarget);
__instance._heldItem = null;
QSBPlayerManager.LocalPlayer.HeldItem = null;
@ -98,12 +98,13 @@ internal class ItemPatches : QSBPatch
var parentSector = parent.GetComponentInChildren<Sector>();
if (parentSector != null)
{
var localPos = parentSector.transform.InverseTransformPoint(hit.point);
IQSBItem.SendMessage(new DropItemMessage(localPos, hit.normal, parentSector));
return false;
qsbItem.SendMessage(new DropItemMessage(hit.point, hit.normal, parentSector));
}
else
{
DebugLog.ToConsole($"Error - No sector found for rigidbody {targetRigidbody.name}!.", MessageType.Error);
}
DebugLog.ToConsole($"Error - No sector found for rigidbody {targetRigidbody.name}!.", MessageType.Error);
return false;
}
}

View File

@ -1,11 +0,0 @@
using QSB.Messaging;
using QSB.MeteorSync.WorldObjects;
namespace QSB.MeteorSync.Messages;
public class FragmentDamageMessage : QSBWorldObjectMessage<QSBFragment, float>
{
public FragmentDamageMessage(float damage) : base(damage) { }
public override void OnReceiveRemote() => WorldObject.AddDamage(Data);
}

View File

@ -1,147 +1,27 @@
using Mirror;
using OWML.Common;
using OWML.Common;
using QSB.Messaging;
using QSB.MeteorSync.WorldObjects;
using QSB.Utility;
using UnityEngine;
namespace QSB.MeteorSync.Messages;
/// called when we request a resync on client join
/// pain
public class FragmentInitialStateMessage : QSBWorldObjectMessage<QSBFragment>
/// <summary>
/// original integrity, leash length
/// </summary>
public class FragmentInitialStateMessage : QSBWorldObjectMessage<QSBFragment, (float OrigIntegrity, float LeashLength)>
{
private float Integrity;
private float OrigIntegrity;
private float LeashLength;
private bool IsDetached;
private bool IsThruWhiteHole;
private Vector3 RelPos;
private Quaternion RelRot;
private Vector3 RelVel;
private Vector3 RelAngVel;
public FragmentInitialStateMessage(QSBFragment qsbFragment)
{
Integrity = qsbFragment.AttachedObject._integrity;
OrigIntegrity = qsbFragment.AttachedObject._origIntegrity;
LeashLength = qsbFragment.LeashLength;
IsDetached = qsbFragment.IsDetached;
if (IsDetached)
{
IsThruWhiteHole = qsbFragment.IsThruWhiteHole;
var body = qsbFragment.Body;
var refBody = qsbFragment.RefBody;
var pos = body.GetPosition();
RelPos = refBody.transform.ToRelPos(pos);
RelRot = refBody.transform.ToRelRot(body.GetRotation());
RelVel = refBody.ToRelVel(body.GetVelocity(), pos);
RelAngVel = refBody.ToRelAngVel(body.GetAngularVelocity());
}
}
public override void Serialize(NetworkWriter writer)
{
base.Serialize(writer);
writer.Write(Integrity);
writer.Write(OrigIntegrity);
writer.Write(LeashLength);
writer.Write(IsDetached);
if (IsDetached)
{
writer.Write(IsThruWhiteHole);
writer.Write(RelPos);
writer.Write(RelRot);
writer.Write(RelVel);
writer.Write(RelAngVel);
}
}
public override void Deserialize(NetworkReader reader)
{
base.Deserialize(reader);
Integrity = reader.Read<float>();
OrigIntegrity = reader.Read<float>();
LeashLength = reader.Read<float>();
IsDetached = reader.Read<bool>();
if (IsDetached)
{
IsThruWhiteHole = reader.Read<bool>();
RelPos = reader.ReadVector3();
RelRot = reader.ReadQuaternion();
RelVel = reader.ReadVector3();
RelAngVel = reader.ReadVector3();
}
}
public FragmentInitialStateMessage(float origIntegrity, float leashLength) : base((origIntegrity, leashLength)) { }
public override void OnReceiveRemote()
{
WorldObject.AttachedObject._origIntegrity = OrigIntegrity;
WorldObject.LeashLength = LeashLength;
if (!OWMath.ApproxEquals(WorldObject.AttachedObject._integrity, Integrity))
WorldObject.AttachedObject._origIntegrity = Data.OrigIntegrity;
if (WorldObject.LeashLength == null)
{
WorldObject.AttachedObject._integrity = Integrity;
WorldObject.AttachedObject.CallOnTakeDamage();
WorldObject.LeashLength = Data.LeashLength;
}
if (IsDetached && !WorldObject.IsDetached)
else
{
// the detach is delayed, so wait until that happens
Delay.RunWhen(() => WorldObject.IsDetached, () =>
{
var body = WorldObject.Body;
if (IsThruWhiteHole && !WorldObject.IsThruWhiteHole)
{
var whiteHoleVolume = MeteorManager.WhiteHoleVolume;
var attachedFluidDetector = body.GetAttachedFluidDetector();
var attachedForceDetector = body.GetAttachedForceDetector();
if (attachedFluidDetector is ConstantFluidDetector constantFluidDetector)
{
constantFluidDetector.SetDetectableFluid(whiteHoleVolume._fluidVolume);
}
if (attachedForceDetector is ConstantForceDetector constantForceDetector)
{
constantForceDetector.ClearAllFields();
}
WorldObject.DetachableFragment.ChangeFragmentSector(whiteHoleVolume._whiteHoleSector,
whiteHoleVolume._whiteHoleProxyShadowSuperGroup);
WorldObject.DetachableFragment.EndWarpScaling();
body.gameObject.AddComponent<DebrisLeash>().Init(whiteHoleVolume._whiteHoleBody, WorldObject.LeashLength);
whiteHoleVolume._ejectedBodyList.Add(body);
}
else if (!IsThruWhiteHole && WorldObject.IsThruWhiteHole)
{
// should only happen if client is way too far ahead and they try to connect. we fail here.
DebugLog.ToConsole($"{WorldObject} is thru white hole, but msg is not. fuck", MessageType.Error);
return;
}
if (WorldObject.IsThruWhiteHole)
{
var debrisLeash = body.GetComponent<DebrisLeash>();
debrisLeash._deccelerating = false;
debrisLeash.enabled = true;
}
var refBody = WorldObject.RefBody;
var pos = refBody.transform.FromRelPos(RelPos);
body.SetPosition(pos);
body.SetRotation(refBody.transform.FromRelRot(RelRot));
body.SetVelocity(refBody.FromRelVel(RelVel, pos));
body.SetAngularVelocity(refBody.FromRelAngVel(RelAngVel));
});
}
else if (!IsDetached && WorldObject.IsDetached)
{
// should only happen if client is way too far ahead and they try to connect. we fail here.
DebugLog.ToConsole($"{WorldObject} is detached, but msg is not. fuck", MessageType.Error);
DebugLog.ToConsole($"leash length for {WorldObject} already set", MessageType.Warning);
}
}
}
}

View File

@ -0,0 +1,10 @@
using QSB.Messaging;
using QSB.MeteorSync.WorldObjects;
namespace QSB.MeteorSync.Messages;
public class FragmentIntegrityMessage : QSBWorldObjectMessage<QSBFragment, float>
{
public FragmentIntegrityMessage(float integrity) : base(integrity) { }
public override void OnReceiveRemote() => WorldObject.SetIntegrity(Data);
}

View File

@ -1,33 +1,18 @@
using Mirror;
using QSB.Messaging;
using QSB.Messaging;
using QSB.MeteorSync.WorldObjects;
using QSB.WorldSync;
namespace QSB.MeteorSync.Messages;
public class MeteorLaunchMessage : QSBWorldObjectMessage<QSBMeteorLauncher>
public class MeteorLaunchMessage : QSBWorldObjectMessage<QSBMeteorLauncher, (int MeteorId, float LaunchSpeed)>
{
private int MeteorId;
private float LaunchSpeed;
public MeteorLaunchMessage(MeteorController meteor, float launchSpeed) : base((
meteor.GetWorldObject<QSBMeteor>().ObjectId,
launchSpeed
)) { }
public MeteorLaunchMessage(QSBMeteorLauncher qsbMeteorLauncher)
{
MeteorId = qsbMeteorLauncher.MeteorId;
LaunchSpeed = qsbMeteorLauncher.LaunchSpeed;
}
public override void Serialize(NetworkWriter writer)
{
base.Serialize(writer);
writer.Write(MeteorId);
writer.Write(LaunchSpeed);
}
public override void Deserialize(NetworkReader reader)
{
base.Deserialize(reader);
MeteorId = reader.Read<int>();
LaunchSpeed = reader.Read<float>();
}
public override void OnReceiveRemote() => WorldObject.LaunchMeteor(MeteorId, LaunchSpeed);
}
public override void OnReceiveRemote() => WorldObject.LaunchMeteor(
Data.MeteorId.GetWorldObject<QSBMeteor>().AttachedObject,
Data.LaunchSpeed
);
}

View File

@ -3,6 +3,9 @@ using QSB.MeteorSync.WorldObjects;
namespace QSB.MeteorSync.Messages;
/// <summary>
/// for syncing impact with a remote player/probe
/// </summary>
public class MeteorSpecialImpactMessage : QSBWorldObjectMessage<QSBMeteor>
{
public override void OnReceiveRemote() => WorldObject.SpecialImpact();

View File

@ -1,5 +1,6 @@
using Cysharp.Threading.Tasks;
using QSB.MeteorSync.WorldObjects;
using QSB.Utility;
using QSB.WorldSync;
using System.Linq;
using System.Threading;
@ -18,8 +19,14 @@ public class MeteorManager : WorldObjectManager
await UniTask.WaitUntil(() => LateInitializerManager.isDoneInitializing, cancellationToken: ct);
WhiteHoleVolume = QSBWorldSync.GetUnityObjects<WhiteHoleVolume>().First();
QSBWorldSync.Init<QSBMeteorLauncher, MeteorLauncher>();
QSBWorldSync.Init<QSBMeteor, MeteorController>();
QSBWorldSync.Init<QSBFragment, FragmentIntegrity>();
var meteorLaunchers = QSBWorldSync.GetUnityObjects<MeteorLauncher>().SortDeterministic().ToList();
QSBWorldSync.Init<QSBMeteorLauncher, MeteorLauncher>(meteorLaunchers);
// order by pool instead of using SortDeterministic
var meteors = meteorLaunchers.SelectMany(x =>
x._meteorPool.EmptyIfNull().Concat(x._dynamicMeteorPool.EmptyIfNull()));
QSBWorldSync.Init<QSBMeteor, MeteorController>(meteors);
}
}
}

View File

@ -19,13 +19,8 @@ public class MeteorServerPatches : QSBPatch
[HarmonyPrefix]
[HarmonyPatch(typeof(MeteorLauncher), nameof(MeteorLauncher.FixedUpdate))]
public static bool FixedUpdate(MeteorLauncher __instance)
public static bool MeteorLauncher_FixedUpdate(MeteorLauncher __instance)
{
if (!QSBWorldSync.AllObjectsReady)
{
return true;
}
if (__instance._launchedMeteors != null)
{
for (var i = __instance._launchedMeteors.Count - 1; i >= 0; i--)
@ -63,13 +58,13 @@ public class MeteorServerPatches : QSBPatch
if (!__instance._areParticlesPlaying)
{
__instance._areParticlesPlaying = true;
foreach (var particleSystem in __instance._launchParticles)
foreach (var launchParticle in __instance._launchParticles)
{
particleSystem.Play();
launchParticle.Play();
}
var qsbMeteorLauncher = __instance.GetWorldObject<QSBMeteorLauncher>();
qsbMeteorLauncher.SendMessage(new MeteorPreLaunchMessage());
__instance.GetWorldObject<QSBMeteorLauncher>()
.SendMessage(new MeteorPreLaunchMessage());
}
if (Time.time > __instance._lastLaunchTime + __instance._launchDelay + 2.3f)
@ -78,9 +73,9 @@ public class MeteorServerPatches : QSBPatch
__instance._lastLaunchTime = Time.time;
__instance._launchDelay = Random.Range(__instance._minInterval, __instance._maxInterval);
__instance._areParticlesPlaying = false;
foreach (var particleSystem in __instance._launchParticles)
foreach (var launchParticle in __instance._launchParticles)
{
particleSystem.Stop();
launchParticle.Stop();
}
}
}
@ -90,7 +85,7 @@ public class MeteorServerPatches : QSBPatch
[HarmonyPrefix]
[HarmonyPatch(typeof(MeteorLauncher), nameof(MeteorLauncher.LaunchMeteor))]
public static bool LaunchMeteor(MeteorLauncher __instance)
public static bool MeteorLauncher_LaunchMeteor(MeteorLauncher __instance)
{
var flag = __instance._dynamicMeteorPool != null && (__instance._meteorPool == null || Random.value < __instance._dynamicProbability);
MeteorController meteorController = null;
@ -125,13 +120,9 @@ public class MeteorServerPatches : QSBPatch
if (meteorController != null)
{
var qsbMeteorLauncher = __instance.GetWorldObject<QSBMeteorLauncher>();
var qsbMeteor = meteorController.GetWorldObject<QSBMeteor>();
var launchSpeed = Random.Range(__instance._minLaunchSpeed, __instance._maxLaunchSpeed);
qsbMeteorLauncher.MeteorId = qsbMeteor.ObjectId;
qsbMeteorLauncher.LaunchSpeed = Random.Range(__instance._minLaunchSpeed, __instance._maxLaunchSpeed);
var linearVelocity = __instance._parentBody.GetPointVelocity(__instance.transform.position) + (__instance.transform.TransformDirection(__instance._launchDirection) * qsbMeteorLauncher.LaunchSpeed);
var linearVelocity = __instance._parentBody.GetPointVelocity(__instance.transform.position) + __instance.transform.TransformDirection(__instance._launchDirection) * launchSpeed;
var angularVelocity = __instance.transform.forward * 2f;
meteorController.Launch(null, __instance.transform.position, __instance.transform.rotation, linearVelocity, angularVelocity);
if (__instance._audioSector.ContainsOccupant(DynamicOccupant.Player))
@ -140,32 +131,18 @@ public class MeteorServerPatches : QSBPatch
__instance._launchSource.PlayOneShot(AudioType.BH_MeteorLaunch);
}
qsbMeteorLauncher.SendMessage(new MeteorLaunchMessage(qsbMeteorLauncher));
__instance.GetWorldObject<QSBMeteorLauncher>()
.SendMessage(new MeteorLaunchMessage(meteorController, launchSpeed));
}
return false;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(MeteorController), nameof(MeteorController.Impact))]
public static void Impact(MeteorController __instance,
GameObject hitObject, Vector3 impactPoint, Vector3 impactVel)
{
var qsbMeteor = __instance.GetWorldObject<QSBMeteor>();
if (QSBMeteor.IsSpecialImpact(hitObject))
{
qsbMeteor.SendMessage(new MeteorSpecialImpactMessage());
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(FragmentIntegrity), nameof(FragmentIntegrity.AddDamage))]
public static void AddDamage(FragmentIntegrity __instance,
float damage)
{
var qsbFragment = __instance.GetWorldObject<QSBFragment>();
qsbFragment.SendMessage(new FragmentDamageMessage(damage));
}
public static void FragmentIntegrity_AddDamage(FragmentIntegrity __instance) =>
__instance.GetWorldObject<QSBFragment>()
.SendMessage(new FragmentIntegrityMessage(__instance._integrity));
}
/// <summary>
@ -177,97 +154,13 @@ public class MeteorClientPatches : QSBPatch
[HarmonyPrefix]
[HarmonyPatch(typeof(MeteorLauncher), nameof(MeteorLauncher.FixedUpdate))]
public static bool FixedUpdate(MeteorLauncher __instance)
public static bool MeteorLauncher_FixedUpdate()
=> false;
[HarmonyPrefix]
[HarmonyPatch(typeof(MeteorLauncher), nameof(MeteorLauncher.LaunchMeteor))]
public static bool LaunchMeteor(MeteorLauncher __instance)
{
var qsbMeteorLauncher = __instance.GetWorldObject<QSBMeteorLauncher>();
MeteorController meteorController = null;
QSBMeteor qsbMeteor;
bool MeteorMatches(MeteorController x)
{
qsbMeteor = x.GetWorldObject<QSBMeteor>();
return qsbMeteor.ObjectId == qsbMeteorLauncher.MeteorId;
}
if (__instance._meteorPool != null)
{
meteorController = __instance._meteorPool.Find(MeteorMatches);
if (meteorController != null)
{
meteorController.Initialize(__instance.transform, __instance._detectableField, __instance._detectableFluid);
}
}
else if (__instance._dynamicMeteorPool != null)
{
meteorController = __instance._dynamicMeteorPool.Find(MeteorMatches);
if (meteorController != null)
{
meteorController.Initialize(__instance.transform, null, null);
}
}
if (meteorController != null)
{
var linearVelocity = __instance._parentBody.GetPointVelocity(__instance.transform.position) + (__instance.transform.TransformDirection(__instance._launchDirection) * qsbMeteorLauncher.LaunchSpeed);
var angularVelocity = __instance.transform.forward * 2f;
meteorController.Launch(null, __instance.transform.position, __instance.transform.rotation, linearVelocity, angularVelocity);
if (__instance._audioSector.ContainsOccupant(DynamicOccupant.Player))
{
__instance._launchSource.pitch = Random.Range(0.4f, 0.6f);
__instance._launchSource.PlayOneShot(AudioType.BH_MeteorLaunch);
}
}
else
{
DebugLog.ToConsole($"{qsbMeteorLauncher} - could not find meteor {qsbMeteorLauncher.MeteorId} in pool", MessageType.Warning);
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(MeteorController), nameof(MeteorController.Impact))]
public static bool Impact(MeteorController __instance,
GameObject hitObject, Vector3 impactPoint, Vector3 impactVel)
{
__instance._intactRenderer.enabled = false;
__instance._impactLight.enabled = true;
__instance._impactLight.intensity = __instance._impactLightCurve.Evaluate(0f);
var rotation = Quaternion.LookRotation(impactVel);
foreach (var particleSystem in __instance._impactParticles)
{
particleSystem.transform.rotation = rotation;
particleSystem.Play();
}
__instance._impactSource.PlayOneShot(AudioType.BH_MeteorImpact);
foreach (var owCollider in __instance._owColliders)
{
owCollider.SetActivation(false);
}
__instance._owRigidbody.MakeKinematic();
__instance.transform.SetParent(hitObject.GetAttachedOWRigidbody().transform);
FragmentSurfaceProxy.UntrackMeteor(__instance);
FragmentCollisionProxy.UntrackMeteor(__instance);
__instance._ignoringCollisions = false;
__instance._hasImpacted = true;
__instance._impactTime = Time.time;
var qsbMeteor = __instance.GetWorldObject<QSBMeteor>();
if (QSBMeteor.IsSpecialImpact(hitObject))
{
qsbMeteor.SendMessage(new MeteorSpecialImpactMessage());
}
return false;
}
[HarmonyPatch(typeof(FragmentIntegrity), nameof(FragmentIntegrity.AddDamage))]
public static bool FragmentIntegrity_AddDamage()
=> false;
}
/// <summary>
@ -277,86 +170,46 @@ public class MeteorPatches : QSBPatch
{
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
[HarmonyPostfix]
[HarmonyPatch(typeof(MeteorController), nameof(MeteorController.Impact))]
public static void MeteorController_Impact(MeteorController __instance,
GameObject hitObject, Vector3 impactPoint, Vector3 impactVel)
{
if (QSBMeteor.IsSpecialImpact(hitObject))
{
__instance.GetWorldObject<QSBMeteor>()
.SendMessage(new MeteorSpecialImpactMessage());
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(DetachableFragment), nameof(DetachableFragment.Detach))]
public static void Detach_Prefix(DetachableFragment __instance, out FragmentIntegrity __state) =>
public static void DetachableFragment_Detach_Prefix(DetachableFragment __instance, out FragmentIntegrity __state) =>
// this gets set to null in Detach, so store it here and and then restore it in postfix
__state = __instance._fragmentIntegrity;
[HarmonyPostfix]
[HarmonyPatch(typeof(DetachableFragment), nameof(DetachableFragment.Detach))]
public static void Detach_Postfix(DetachableFragment __instance, FragmentIntegrity __state) =>
public static void DetachableFragment_Detach_Postfix(DetachableFragment __instance, FragmentIntegrity __state) =>
__instance._fragmentIntegrity = __state;
[HarmonyPrefix]
[HarmonyPatch(typeof(DebrisLeash), nameof(DebrisLeash.MoveByDistance))]
public static bool MoveByDistance(DebrisLeash __instance,
float distance)
[HarmonyPostfix]
[HarmonyPatch(typeof(DebrisLeash), nameof(DebrisLeash.Init))]
public static void DebrisLeash_Init(DebrisLeash __instance)
{
if (__instance._detachableFragment == null || __instance._detachableFragment._fragmentIntegrity == null)
{
return true;
return;
}
var qsbFragment = __instance._detachableFragment._fragmentIntegrity.GetWorldObject<QSBFragment>();
if (__instance.enabled)
if (qsbFragment.LeashLength != null)
{
var vector = __instance._attachedBody.GetPosition() - __instance._anchorBody.GetPosition();
var d = Mathf.Min(distance, qsbFragment.LeashLength - vector.magnitude);
__instance._attachedBody.SetPosition(__instance._anchorBody.GetPosition() + (vector.normalized * d));
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(DebrisLeash), nameof(DebrisLeash.FixedUpdate))]
public static bool FixedUpdate(DebrisLeash __instance)
{
if (__instance._detachableFragment == null || __instance._detachableFragment._fragmentIntegrity == null)
{
return true;
}
if (!QSBWorldSync.AllObjectsReady)
{
return true;
}
var qsbFragment = __instance._detachableFragment._fragmentIntegrity.GetWorldObject<QSBFragment>();
if (!__instance._deccelerating)
{
var num = Vector3.Distance(__instance._attachedBody.GetPosition(), __instance._anchorBody.GetPosition());
var num2 = Mathf.Pow(__instance._attachedBody.GetVelocity().magnitude, 2f) / (2f * __instance._deccel);
var vector = __instance._attachedBody.GetVelocity() - __instance._anchorBody.GetVelocity();
if (num >= qsbFragment.LeashLength - num2 && vector.magnitude > 0.1f)
{
__instance._deccelerating = true;
return false;
}
__instance._leashLength = (float)qsbFragment.LeashLength;
}
else
{
var vector2 = __instance._attachedBody.GetVelocity() - __instance._anchorBody.GetVelocity();
var velocityChange = -vector2.normalized * Mathf.Min(__instance._deccel * Time.deltaTime, vector2.magnitude);
if (velocityChange.magnitude < 0.01f)
{
__instance._attachedBody.SetVelocity(__instance._anchorBody.GetVelocity());
__instance._deccelerating = false;
if (__instance._detachableFragment != null)
{
__instance._detachableFragment.ComeToRest(__instance._anchorBody);
}
__instance.enabled = false;
return false;
}
__instance._attachedBody.AddVelocityChange(velocityChange);
DebugLog.ToConsole($"DebrisLeash.Init called for {qsbFragment} before LeashLength was set", MessageType.Warning);
}
return false;
}
}
}

View File

@ -11,27 +11,34 @@ public class QSBFragment : WorldObject<FragmentIntegrity>
{
public override async UniTask Init(CancellationToken ct)
{
DetachableFragment = AttachedObject.GetComponent<DetachableFragment>();
if (QSBCore.IsHost)
{
LeashLength = Random.Range(MeteorManager.WhiteHoleVolume._debrisDistMin, MeteorManager.WhiteHoleVolume._debrisDistMax);
// SetIntegrity(0);
}
}
public override void SendInitialState(uint to) =>
this.SendMessage(new FragmentInitialStateMessage(this) { To = to });
public override void SendInitialState(uint to)
{
this.SendMessage(new FragmentInitialStateMessage(AttachedObject._origIntegrity, (float)LeashLength) { To = to });
this.SendMessage(new FragmentIntegrityMessage(AttachedObject._integrity));
}
public DetachableFragment DetachableFragment;
public bool IsDetached => DetachableFragment != null && DetachableFragment._isDetached;
public bool IsThruWhiteHole => IsDetached && DetachableFragment._sector != null &&
DetachableFragment._sector._parentSector == MeteorManager.WhiteHoleVolume._whiteHoleSector;
public OWRigidbody RefBody => IsThruWhiteHole ? MeteorManager.WhiteHoleVolume._whiteHoleBody : Locator._brittleHollow._owRigidbody;
public OWRigidbody Body => IsDetached ? AttachedObject.transform.parent.parent.GetAttachedOWRigidbody() : null;
public void SetIntegrity(float integrity)
{
if (OWMath.ApproxEquals(AttachedObject._integrity, integrity))
{
return;
}
/// what the leash length will be when we eventually detach and fall thru white hole
public float LeashLength;
AttachedObject._integrity = integrity;
AttachedObject.CallOnTakeDamage();
}
public void AddDamage(float damage)
=> AttachedObject.AddDamage(damage);
}
/// <summary>
/// what the leash length will be when we eventually detach and fall thru white hole.
/// <para/>
/// generated by the server and sent to clients in the initial state message.
/// </summary>
public float? LeashLength;
}

View File

@ -1,26 +1,38 @@
using QSB.WorldSync;
using Cysharp.Threading.Tasks;
using QSB.WorldSync;
using System.Threading;
using UnityEngine;
namespace QSB.MeteorSync.WorldObjects;
public class QSBMeteor : WorldObject<MeteorController>
{
private QSBMeteorLauncher _qsbMeteorLauncher;
public override async UniTask Init(CancellationToken ct)
{
var meteorLauncher = AttachedObject._suspendRoot.GetComponent<MeteorLauncher>();
await UniTask.WaitUntil(() => QSBWorldSync.AllObjectsAdded, cancellationToken: ct);
_qsbMeteorLauncher = meteorLauncher.GetWorldObject<QSBMeteorLauncher>();
}
public override void SendInitialState(uint to)
{
// todo SendInitialState
}
public static bool IsSpecialImpact(GameObject go) =>
go == Locator.GetPlayerCollider().gameObject || (Locator.GetProbe() != null && go == Locator.GetProbe()._anchor._collider.gameObject);
go == Locator.GetPlayerCollider().gameObject ||
Locator.GetProbe() != null && go == Locator.GetProbe()._anchor._collider.gameObject;
public void SpecialImpact()
{
AttachedObject._intactRenderer.enabled = false;
AttachedObject._impactLight.enabled = true;
AttachedObject._impactLight.intensity = AttachedObject._impactLightCurve.Evaluate(0f);
foreach (var particleSystem in AttachedObject._impactParticles)
foreach (var impactParticle in AttachedObject._impactParticles)
{
particleSystem.Play();
impactParticle.Play();
}
AttachedObject._impactSource.PlayOneShot(AudioType.BH_MeteorImpact);
@ -36,4 +48,4 @@ public class QSBMeteor : WorldObject<MeteorController>
AttachedObject._hasImpacted = true;
AttachedObject._impactTime = Time.time;
}
}
}

View File

@ -1,34 +1,52 @@
using QSB.WorldSync;
using Cysharp.Threading.Tasks;
using QSB.Utility;
using QSB.WorldSync;
using System.Linq;
using System.Threading;
using UnityEngine;
namespace QSB.MeteorSync.WorldObjects;
public class QSBMeteorLauncher : WorldObject<MeteorLauncher>
{
private QSBMeteor[] _qsbMeteors;
public override async UniTask Init(CancellationToken ct)
{
var meteors = AttachedObject._meteorPool.EmptyIfNull().Concat(AttachedObject._dynamicMeteorPool.EmptyIfNull());
await UniTask.WaitUntil(() => QSBWorldSync.AllObjectsAdded, cancellationToken: ct);
_qsbMeteors = meteors.Select(x => x.GetWorldObject<QSBMeteor>()).ToArray();
}
public override void SendInitialState(uint to)
{
// todo SendInitialState
}
public int MeteorId;
public float LaunchSpeed;
public void PreLaunchMeteor()
{
foreach (var particleSystem in AttachedObject._launchParticles)
foreach (var launchParticle in AttachedObject._launchParticles)
{
particleSystem.Play();
launchParticle.Play();
}
}
public void LaunchMeteor(int meteorId, float launchSpeed)
public void LaunchMeteor(MeteorController meteor, float launchSpeed)
{
MeteorId = meteorId;
LaunchSpeed = launchSpeed;
meteor.Initialize(AttachedObject.transform, AttachedObject._detectableField, AttachedObject._detectableFluid);
AttachedObject.LaunchMeteor();
foreach (var particleSystem in AttachedObject._launchParticles)
var linearVelocity = AttachedObject._parentBody.GetPointVelocity(AttachedObject.transform.position) + AttachedObject.transform.TransformDirection(AttachedObject._launchDirection) * launchSpeed;
var angularVelocity = AttachedObject.transform.forward * 2f;
meteor.Launch(null, AttachedObject.transform.position, AttachedObject.transform.rotation, linearVelocity, angularVelocity);
if (AttachedObject._audioSector.ContainsOccupant(DynamicOccupant.Player))
{
particleSystem.Stop();
AttachedObject._launchSource.pitch = Random.Range(0.4f, 0.6f);
AttachedObject._launchSource.PlayOneShot(AudioType.BH_MeteorLaunch);
}
foreach (var launchParticle in AttachedObject._launchParticles)
{
launchParticle.Stop();
}
}
}
}

View File

@ -5,8 +5,10 @@ using QSB.OrbSync.Messages;
using QSB.OrbSync.TransformSync;
using QSB.Utility;
using QSB.WorldSync;
using System;
using System.Threading;
using UnityEngine;
using Object = UnityEngine.Object;
namespace QSB.OrbSync.WorldObjects;
@ -37,7 +39,7 @@ public class QSBOrb : WorldObject<NomaiInterfaceOrb>
public override void SendInitialState(uint to)
{
this.SendMessage(new OrbDragMessage(AttachedObject._isBeingDragged) { To = to });
var slotIndex = AttachedObject._slots.IndexOf(AttachedObject._occupiedSlot);
var slotIndex = Array.IndexOf(AttachedObject._slots, AttachedObject._occupiedSlot);
this.SendMessage(new OrbSlotMessage(slotIndex, false) { To = to });
}

View File

@ -74,7 +74,7 @@ public class PlayerJoinMessage : QSBMessage
var player = QSBPlayerManager.GetPlayer(From);
player.Name = PlayerName;
DebugLog.ToAll($"{player} joined!", MessageType.Info);
DebugLog.ToAll($"{player.Name} joined!", MessageType.Info);
DebugLog.DebugWrite($"{player} joined. qsbVersion:{QSBVersion}, gameVersion:{GameVersion}, dlcInstalled:{DlcInstalled}", MessageType.Info);
}

View File

@ -156,7 +156,7 @@ public static class Extensions
return y;
}
public static int IndexOf<T>(this T[] array, T value) => Array.IndexOf(array, value);
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source) => source ?? Enumerable.Empty<T>();
public static bool IsInRange<T>(this IList<T> list, int index) => index >= 0 && index < list.Count;