mirror of
https://github.com/misternebula/quantum-space-buddies.git
synced 2025-01-27 03:35:20 +00:00
Merge branch 'dev' into picture-frame-doors
This commit is contained in:
commit
c8ce4bdfb4
@ -1,5 +1,4 @@
|
|||||||
using Mirror;
|
using QSB.ItemSync.WorldObjects.Items;
|
||||||
using QSB.ItemSync.WorldObjects.Items;
|
|
||||||
using QSB.Messaging;
|
using QSB.Messaging;
|
||||||
using QSB.Player;
|
using QSB.Player;
|
||||||
using QSB.SectorSync.WorldObjects;
|
using QSB.SectorSync.WorldObjects;
|
||||||
@ -8,39 +7,21 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace QSB.ItemSync.Messages;
|
namespace QSB.ItemSync.Messages;
|
||||||
|
|
||||||
internal class DropItemMessage : QSBWorldObjectMessage<IQSBItem>
|
internal class DropItemMessage : QSBWorldObjectMessage<IQSBItem,
|
||||||
|
(Vector3 LocalPos, Vector3 LocalNorm, int SectorId)>
|
||||||
{
|
{
|
||||||
private Vector3 Position;
|
public DropItemMessage(Vector3 position, Vector3 normal, Sector sector) : base((
|
||||||
private Vector3 Normal;
|
sector.transform.InverseTransformPoint(position),
|
||||||
private int SectorId;
|
sector.transform.InverseTransformDirection(normal),
|
||||||
|
sector.GetWorldObject<QSBSector>().ObjectId
|
||||||
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 override void OnReceiveRemote()
|
public override void OnReceiveRemote()
|
||||||
{
|
{
|
||||||
var sector = SectorId.GetWorldObject<QSBSector>().AttachedObject;
|
var sector = Data.SectorId.GetWorldObject<QSBSector>().AttachedObject;
|
||||||
WorldObject.DropItem(sector.transform.TransformPoint(Position), Normal, sector);
|
var position = sector.transform.TransformPoint(Data.LocalPos);
|
||||||
|
var normal = sector.transform.TransformDirection(Data.LocalNorm);
|
||||||
|
WorldObject.DropItem(position, normal, sector);
|
||||||
|
|
||||||
var player = QSBPlayerManager.GetPlayer(From);
|
var player = QSBPlayerManager.GetPlayer(From);
|
||||||
player.HeldItem = WorldObject;
|
player.HeldItem = WorldObject;
|
||||||
|
@ -90,7 +90,7 @@ internal class ItemPatches : QSBPatch
|
|||||||
var parent = (customDropTarget == null)
|
var parent = (customDropTarget == null)
|
||||||
? targetRigidbody.transform
|
? targetRigidbody.transform
|
||||||
: customDropTarget.GetItemDropTargetTransform(hit.collider.gameObject);
|
: 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.DropItem(hit.point, hit.normal, parent, sector, customDropTarget);
|
||||||
__instance._heldItem = null;
|
__instance._heldItem = null;
|
||||||
QSBPlayerManager.LocalPlayer.HeldItem = null;
|
QSBPlayerManager.LocalPlayer.HeldItem = null;
|
||||||
@ -98,12 +98,13 @@ internal class ItemPatches : QSBPatch
|
|||||||
var parentSector = parent.GetComponentInChildren<Sector>();
|
var parentSector = parent.GetComponentInChildren<Sector>();
|
||||||
if (parentSector != null)
|
if (parentSector != null)
|
||||||
{
|
{
|
||||||
var localPos = parentSector.transform.InverseTransformPoint(hit.point);
|
qsbItem.SendMessage(new DropItemMessage(hit.point, hit.normal, parentSector));
|
||||||
IQSBItem.SendMessage(new DropItemMessage(localPos, hit.normal, parentSector));
|
}
|
||||||
return false;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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);
|
|
||||||
}
|
|
@ -1,147 +1,27 @@
|
|||||||
using Mirror;
|
using OWML.Common;
|
||||||
using OWML.Common;
|
|
||||||
using QSB.Messaging;
|
using QSB.Messaging;
|
||||||
using QSB.MeteorSync.WorldObjects;
|
using QSB.MeteorSync.WorldObjects;
|
||||||
using QSB.Utility;
|
using QSB.Utility;
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace QSB.MeteorSync.Messages;
|
namespace QSB.MeteorSync.Messages;
|
||||||
|
|
||||||
/// called when we request a resync on client join
|
/// <summary>
|
||||||
/// pain
|
/// original integrity, leash length
|
||||||
public class FragmentInitialStateMessage : QSBWorldObjectMessage<QSBFragment>
|
/// </summary>
|
||||||
|
public class FragmentInitialStateMessage : QSBWorldObjectMessage<QSBFragment, (float OrigIntegrity, float LeashLength)>
|
||||||
{
|
{
|
||||||
private float Integrity;
|
public FragmentInitialStateMessage(float origIntegrity, float leashLength) : base((origIntegrity, leashLength)) { }
|
||||||
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 override void OnReceiveRemote()
|
public override void OnReceiveRemote()
|
||||||
{
|
{
|
||||||
WorldObject.AttachedObject._origIntegrity = OrigIntegrity;
|
WorldObject.AttachedObject._origIntegrity = Data.OrigIntegrity;
|
||||||
WorldObject.LeashLength = LeashLength;
|
if (WorldObject.LeashLength == null)
|
||||||
if (!OWMath.ApproxEquals(WorldObject.AttachedObject._integrity, Integrity))
|
|
||||||
{
|
{
|
||||||
WorldObject.AttachedObject._integrity = Integrity;
|
WorldObject.LeashLength = Data.LeashLength;
|
||||||
WorldObject.AttachedObject.CallOnTakeDamage();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (IsDetached && !WorldObject.IsDetached)
|
|
||||||
{
|
{
|
||||||
// the detach is delayed, so wait until that happens
|
DebugLog.ToConsole($"leash length for {WorldObject} already set", MessageType.Warning);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
QSB/MeteorSync/Messages/FragmentIntegrityMessage.cs
Normal file
10
QSB/MeteorSync/Messages/FragmentIntegrityMessage.cs
Normal 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);
|
||||||
|
}
|
@ -1,33 +1,18 @@
|
|||||||
using Mirror;
|
using QSB.Messaging;
|
||||||
using QSB.Messaging;
|
|
||||||
using QSB.MeteorSync.WorldObjects;
|
using QSB.MeteorSync.WorldObjects;
|
||||||
|
using QSB.WorldSync;
|
||||||
|
|
||||||
namespace QSB.MeteorSync.Messages;
|
namespace QSB.MeteorSync.Messages;
|
||||||
|
|
||||||
public class MeteorLaunchMessage : QSBWorldObjectMessage<QSBMeteorLauncher>
|
public class MeteorLaunchMessage : QSBWorldObjectMessage<QSBMeteorLauncher, (int MeteorId, float LaunchSpeed)>
|
||||||
{
|
{
|
||||||
private int MeteorId;
|
public MeteorLaunchMessage(MeteorController meteor, float launchSpeed) : base((
|
||||||
private float LaunchSpeed;
|
meteor.GetWorldObject<QSBMeteor>().ObjectId,
|
||||||
|
launchSpeed
|
||||||
|
)) { }
|
||||||
|
|
||||||
public MeteorLaunchMessage(QSBMeteorLauncher qsbMeteorLauncher)
|
public override void OnReceiveRemote() => WorldObject.LaunchMeteor(
|
||||||
{
|
Data.MeteorId.GetWorldObject<QSBMeteor>().AttachedObject,
|
||||||
MeteorId = qsbMeteorLauncher.MeteorId;
|
Data.LaunchSpeed
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
@ -3,6 +3,9 @@ using QSB.MeteorSync.WorldObjects;
|
|||||||
|
|
||||||
namespace QSB.MeteorSync.Messages;
|
namespace QSB.MeteorSync.Messages;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// for syncing impact with a remote player/probe
|
||||||
|
/// </summary>
|
||||||
public class MeteorSpecialImpactMessage : QSBWorldObjectMessage<QSBMeteor>
|
public class MeteorSpecialImpactMessage : QSBWorldObjectMessage<QSBMeteor>
|
||||||
{
|
{
|
||||||
public override void OnReceiveRemote() => WorldObject.SpecialImpact();
|
public override void OnReceiveRemote() => WorldObject.SpecialImpact();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
using QSB.MeteorSync.WorldObjects;
|
using QSB.MeteorSync.WorldObjects;
|
||||||
|
using QSB.Utility;
|
||||||
using QSB.WorldSync;
|
using QSB.WorldSync;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -18,8 +19,14 @@ public class MeteorManager : WorldObjectManager
|
|||||||
await UniTask.WaitUntil(() => LateInitializerManager.isDoneInitializing, cancellationToken: ct);
|
await UniTask.WaitUntil(() => LateInitializerManager.isDoneInitializing, cancellationToken: ct);
|
||||||
|
|
||||||
WhiteHoleVolume = QSBWorldSync.GetUnityObjects<WhiteHoleVolume>().First();
|
WhiteHoleVolume = QSBWorldSync.GetUnityObjects<WhiteHoleVolume>().First();
|
||||||
QSBWorldSync.Init<QSBMeteorLauncher, MeteorLauncher>();
|
|
||||||
QSBWorldSync.Init<QSBMeteor, MeteorController>();
|
|
||||||
QSBWorldSync.Init<QSBFragment, FragmentIntegrity>();
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,13 +19,8 @@ public class MeteorServerPatches : QSBPatch
|
|||||||
|
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(MeteorLauncher), nameof(MeteorLauncher.FixedUpdate))]
|
[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)
|
if (__instance._launchedMeteors != null)
|
||||||
{
|
{
|
||||||
for (var i = __instance._launchedMeteors.Count - 1; i >= 0; i--)
|
for (var i = __instance._launchedMeteors.Count - 1; i >= 0; i--)
|
||||||
@ -63,13 +58,13 @@ public class MeteorServerPatches : QSBPatch
|
|||||||
if (!__instance._areParticlesPlaying)
|
if (!__instance._areParticlesPlaying)
|
||||||
{
|
{
|
||||||
__instance._areParticlesPlaying = true;
|
__instance._areParticlesPlaying = true;
|
||||||
foreach (var particleSystem in __instance._launchParticles)
|
foreach (var launchParticle in __instance._launchParticles)
|
||||||
{
|
{
|
||||||
particleSystem.Play();
|
launchParticle.Play();
|
||||||
}
|
}
|
||||||
|
|
||||||
var qsbMeteorLauncher = __instance.GetWorldObject<QSBMeteorLauncher>();
|
__instance.GetWorldObject<QSBMeteorLauncher>()
|
||||||
qsbMeteorLauncher.SendMessage(new MeteorPreLaunchMessage());
|
.SendMessage(new MeteorPreLaunchMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Time.time > __instance._lastLaunchTime + __instance._launchDelay + 2.3f)
|
if (Time.time > __instance._lastLaunchTime + __instance._launchDelay + 2.3f)
|
||||||
@ -78,9 +73,9 @@ public class MeteorServerPatches : QSBPatch
|
|||||||
__instance._lastLaunchTime = Time.time;
|
__instance._lastLaunchTime = Time.time;
|
||||||
__instance._launchDelay = Random.Range(__instance._minInterval, __instance._maxInterval);
|
__instance._launchDelay = Random.Range(__instance._minInterval, __instance._maxInterval);
|
||||||
__instance._areParticlesPlaying = false;
|
__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]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(MeteorLauncher), nameof(MeteorLauncher.LaunchMeteor))]
|
[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);
|
var flag = __instance._dynamicMeteorPool != null && (__instance._meteorPool == null || Random.value < __instance._dynamicProbability);
|
||||||
MeteorController meteorController = null;
|
MeteorController meteorController = null;
|
||||||
@ -125,13 +120,9 @@ public class MeteorServerPatches : QSBPatch
|
|||||||
|
|
||||||
if (meteorController != null)
|
if (meteorController != null)
|
||||||
{
|
{
|
||||||
var qsbMeteorLauncher = __instance.GetWorldObject<QSBMeteorLauncher>();
|
var launchSpeed = Random.Range(__instance._minLaunchSpeed, __instance._maxLaunchSpeed);
|
||||||
var qsbMeteor = meteorController.GetWorldObject<QSBMeteor>();
|
|
||||||
|
|
||||||
qsbMeteorLauncher.MeteorId = qsbMeteor.ObjectId;
|
var linearVelocity = __instance._parentBody.GetPointVelocity(__instance.transform.position) + __instance.transform.TransformDirection(__instance._launchDirection) * launchSpeed;
|
||||||
qsbMeteorLauncher.LaunchSpeed = Random.Range(__instance._minLaunchSpeed, __instance._maxLaunchSpeed);
|
|
||||||
|
|
||||||
var linearVelocity = __instance._parentBody.GetPointVelocity(__instance.transform.position) + (__instance.transform.TransformDirection(__instance._launchDirection) * qsbMeteorLauncher.LaunchSpeed);
|
|
||||||
var angularVelocity = __instance.transform.forward * 2f;
|
var angularVelocity = __instance.transform.forward * 2f;
|
||||||
meteorController.Launch(null, __instance.transform.position, __instance.transform.rotation, linearVelocity, angularVelocity);
|
meteorController.Launch(null, __instance.transform.position, __instance.transform.rotation, linearVelocity, angularVelocity);
|
||||||
if (__instance._audioSector.ContainsOccupant(DynamicOccupant.Player))
|
if (__instance._audioSector.ContainsOccupant(DynamicOccupant.Player))
|
||||||
@ -140,32 +131,18 @@ public class MeteorServerPatches : QSBPatch
|
|||||||
__instance._launchSource.PlayOneShot(AudioType.BH_MeteorLaunch);
|
__instance._launchSource.PlayOneShot(AudioType.BH_MeteorLaunch);
|
||||||
}
|
}
|
||||||
|
|
||||||
qsbMeteorLauncher.SendMessage(new MeteorLaunchMessage(qsbMeteorLauncher));
|
__instance.GetWorldObject<QSBMeteorLauncher>()
|
||||||
|
.SendMessage(new MeteorLaunchMessage(meteorController, launchSpeed));
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(FragmentIntegrity), nameof(FragmentIntegrity.AddDamage))]
|
[HarmonyPatch(typeof(FragmentIntegrity), nameof(FragmentIntegrity.AddDamage))]
|
||||||
public static void AddDamage(FragmentIntegrity __instance,
|
public static void FragmentIntegrity_AddDamage(FragmentIntegrity __instance) =>
|
||||||
float damage)
|
__instance.GetWorldObject<QSBFragment>()
|
||||||
{
|
.SendMessage(new FragmentIntegrityMessage(__instance._integrity));
|
||||||
var qsbFragment = __instance.GetWorldObject<QSBFragment>();
|
|
||||||
qsbFragment.SendMessage(new FragmentDamageMessage(damage));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -177,97 +154,13 @@ public class MeteorClientPatches : QSBPatch
|
|||||||
|
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(MeteorLauncher), nameof(MeteorLauncher.FixedUpdate))]
|
[HarmonyPatch(typeof(MeteorLauncher), nameof(MeteorLauncher.FixedUpdate))]
|
||||||
public static bool FixedUpdate(MeteorLauncher __instance)
|
public static bool MeteorLauncher_FixedUpdate()
|
||||||
=> false;
|
=> false;
|
||||||
|
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(MeteorLauncher), nameof(MeteorLauncher.LaunchMeteor))]
|
[HarmonyPatch(typeof(FragmentIntegrity), nameof(FragmentIntegrity.AddDamage))]
|
||||||
public static bool LaunchMeteor(MeteorLauncher __instance)
|
public static bool FragmentIntegrity_AddDamage()
|
||||||
{
|
=> false;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -277,86 +170,46 @@ public class MeteorPatches : QSBPatch
|
|||||||
{
|
{
|
||||||
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
|
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]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(DetachableFragment), nameof(DetachableFragment.Detach))]
|
[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
|
// this gets set to null in Detach, so store it here and and then restore it in postfix
|
||||||
__state = __instance._fragmentIntegrity;
|
__state = __instance._fragmentIntegrity;
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(DetachableFragment), nameof(DetachableFragment.Detach))]
|
[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;
|
__instance._fragmentIntegrity = __state;
|
||||||
|
|
||||||
[HarmonyPrefix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(DebrisLeash), nameof(DebrisLeash.MoveByDistance))]
|
[HarmonyPatch(typeof(DebrisLeash), nameof(DebrisLeash.Init))]
|
||||||
public static bool MoveByDistance(DebrisLeash __instance,
|
public static void DebrisLeash_Init(DebrisLeash __instance)
|
||||||
float distance)
|
|
||||||
{
|
{
|
||||||
if (__instance._detachableFragment == null || __instance._detachableFragment._fragmentIntegrity == null)
|
if (__instance._detachableFragment == null || __instance._detachableFragment._fragmentIntegrity == null)
|
||||||
{
|
{
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var qsbFragment = __instance._detachableFragment._fragmentIntegrity.GetWorldObject<QSBFragment>();
|
var qsbFragment = __instance._detachableFragment._fragmentIntegrity.GetWorldObject<QSBFragment>();
|
||||||
|
if (qsbFragment.LeashLength != null)
|
||||||
if (__instance.enabled)
|
|
||||||
{
|
{
|
||||||
var vector = __instance._attachedBody.GetPosition() - __instance._anchorBody.GetPosition();
|
__instance._leashLength = (float)qsbFragment.LeashLength;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var vector2 = __instance._attachedBody.GetVelocity() - __instance._anchorBody.GetVelocity();
|
DebugLog.ToConsole($"DebrisLeash.Init called for {qsbFragment} before LeashLength was set", MessageType.Warning);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,27 +11,34 @@ public class QSBFragment : WorldObject<FragmentIntegrity>
|
|||||||
{
|
{
|
||||||
public override async UniTask Init(CancellationToken ct)
|
public override async UniTask Init(CancellationToken ct)
|
||||||
{
|
{
|
||||||
DetachableFragment = AttachedObject.GetComponent<DetachableFragment>();
|
|
||||||
|
|
||||||
if (QSBCore.IsHost)
|
if (QSBCore.IsHost)
|
||||||
{
|
{
|
||||||
LeashLength = Random.Range(MeteorManager.WhiteHoleVolume._debrisDistMin, MeteorManager.WhiteHoleVolume._debrisDistMax);
|
LeashLength = Random.Range(MeteorManager.WhiteHoleVolume._debrisDistMin, MeteorManager.WhiteHoleVolume._debrisDistMax);
|
||||||
|
// SetIntegrity(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SendInitialState(uint to) =>
|
public override void SendInitialState(uint to)
|
||||||
this.SendMessage(new FragmentInitialStateMessage(this) { To = to });
|
{
|
||||||
|
this.SendMessage(new FragmentInitialStateMessage(AttachedObject._origIntegrity, (float)LeashLength) { To = to });
|
||||||
|
this.SendMessage(new FragmentIntegrityMessage(AttachedObject._integrity));
|
||||||
|
}
|
||||||
|
|
||||||
public DetachableFragment DetachableFragment;
|
public void SetIntegrity(float integrity)
|
||||||
public bool IsDetached => DetachableFragment != null && DetachableFragment._isDetached;
|
{
|
||||||
public bool IsThruWhiteHole => IsDetached && DetachableFragment._sector != null &&
|
if (OWMath.ApproxEquals(AttachedObject._integrity, integrity))
|
||||||
DetachableFragment._sector._parentSector == MeteorManager.WhiteHoleVolume._whiteHoleSector;
|
{
|
||||||
public OWRigidbody RefBody => IsThruWhiteHole ? MeteorManager.WhiteHoleVolume._whiteHoleBody : Locator._brittleHollow._owRigidbody;
|
return;
|
||||||
public OWRigidbody Body => IsDetached ? AttachedObject.transform.parent.parent.GetAttachedOWRigidbody() : null;
|
}
|
||||||
|
|
||||||
/// what the leash length will be when we eventually detach and fall thru white hole
|
AttachedObject._integrity = integrity;
|
||||||
public float LeashLength;
|
AttachedObject.CallOnTakeDamage();
|
||||||
|
}
|
||||||
|
|
||||||
public void AddDamage(float damage)
|
/// <summary>
|
||||||
=> AttachedObject.AddDamage(damage);
|
/// 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;
|
||||||
|
}
|
||||||
|
@ -1,26 +1,38 @@
|
|||||||
using QSB.WorldSync;
|
using Cysharp.Threading.Tasks;
|
||||||
|
using QSB.WorldSync;
|
||||||
|
using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace QSB.MeteorSync.WorldObjects;
|
namespace QSB.MeteorSync.WorldObjects;
|
||||||
|
|
||||||
public class QSBMeteor : WorldObject<MeteorController>
|
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)
|
public override void SendInitialState(uint to)
|
||||||
{
|
{
|
||||||
// todo SendInitialState
|
// todo SendInitialState
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsSpecialImpact(GameObject go) =>
|
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()
|
public void SpecialImpact()
|
||||||
{
|
{
|
||||||
AttachedObject._intactRenderer.enabled = false;
|
AttachedObject._intactRenderer.enabled = false;
|
||||||
AttachedObject._impactLight.enabled = true;
|
AttachedObject._impactLight.enabled = true;
|
||||||
AttachedObject._impactLight.intensity = AttachedObject._impactLightCurve.Evaluate(0f);
|
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);
|
AttachedObject._impactSource.PlayOneShot(AudioType.BH_MeteorImpact);
|
||||||
@ -36,4 +48,4 @@ public class QSBMeteor : WorldObject<MeteorController>
|
|||||||
AttachedObject._hasImpacted = true;
|
AttachedObject._hasImpacted = true;
|
||||||
AttachedObject._impactTime = Time.time;
|
AttachedObject._impactTime = Time.time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
namespace QSB.MeteorSync.WorldObjects;
|
||||||
|
|
||||||
public class QSBMeteorLauncher : WorldObject<MeteorLauncher>
|
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)
|
public override void SendInitialState(uint to)
|
||||||
{
|
{
|
||||||
// todo SendInitialState
|
// todo SendInitialState
|
||||||
}
|
}
|
||||||
|
|
||||||
public int MeteorId;
|
|
||||||
public float LaunchSpeed;
|
|
||||||
|
|
||||||
public void PreLaunchMeteor()
|
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;
|
meteor.Initialize(AttachedObject.transform, AttachedObject._detectableField, AttachedObject._detectableFluid);
|
||||||
LaunchSpeed = launchSpeed;
|
|
||||||
|
|
||||||
AttachedObject.LaunchMeteor();
|
var linearVelocity = AttachedObject._parentBody.GetPointVelocity(AttachedObject.transform.position) + AttachedObject.transform.TransformDirection(AttachedObject._launchDirection) * launchSpeed;
|
||||||
foreach (var particleSystem in AttachedObject._launchParticles)
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,10 @@ using QSB.OrbSync.Messages;
|
|||||||
using QSB.OrbSync.TransformSync;
|
using QSB.OrbSync.TransformSync;
|
||||||
using QSB.Utility;
|
using QSB.Utility;
|
||||||
using QSB.WorldSync;
|
using QSB.WorldSync;
|
||||||
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace QSB.OrbSync.WorldObjects;
|
namespace QSB.OrbSync.WorldObjects;
|
||||||
|
|
||||||
@ -37,7 +39,7 @@ public class QSBOrb : WorldObject<NomaiInterfaceOrb>
|
|||||||
public override void SendInitialState(uint to)
|
public override void SendInitialState(uint to)
|
||||||
{
|
{
|
||||||
this.SendMessage(new OrbDragMessage(AttachedObject._isBeingDragged) { To = 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 });
|
this.SendMessage(new OrbSlotMessage(slotIndex, false) { To = to });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ public class PlayerJoinMessage : QSBMessage
|
|||||||
|
|
||||||
var player = QSBPlayerManager.GetPlayer(From);
|
var player = QSBPlayerManager.GetPlayer(From);
|
||||||
player.Name = PlayerName;
|
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);
|
DebugLog.DebugWrite($"{player} joined. qsbVersion:{QSBVersion}, gameVersion:{GameVersion}, dlcInstalled:{DlcInstalled}", MessageType.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ public static class Extensions
|
|||||||
return y;
|
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;
|
public static bool IsInRange<T>(this IList<T> list, int index) => index >= 0 && index < list.Count;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user