Don't sync parts that are attached to a vehicle (they were flung away / car fell apart); softer plaid, calmer colors
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+46
-6
@@ -27,6 +27,10 @@ namespace MSCO
|
||||
public float NextPartScan;
|
||||
public float StillTime;
|
||||
public float NoMotionClaimUntil; // kurz nach einer Übergabe nicht wegen Nachfedern/Nachrollen übernehmen
|
||||
// Am Auto angebautes Teil (Gelenk zum Fahrzeug oder unter einem anderen Rigidbody): bewegt sich mit dem Auto,
|
||||
// wird dann NICHT als loses Objekt synchronisiert - sonst reißt das Gelenk und das Teil fliegt weg
|
||||
public bool Attached;
|
||||
public float NextAttachCheck;
|
||||
|
||||
public Vector3 TargetPos;
|
||||
public Quaternion TargetRot;
|
||||
@@ -107,6 +111,7 @@ namespace MSCO
|
||||
SyncedBody b;
|
||||
if (!byId.TryGetValue(id, out b) || b.Rb == null || b.OwnerId != SyncedBody.NoOwner) return false;
|
||||
if (!IsValidPose(pos, rot)) return false;
|
||||
if (IsAttached(b)) return false; // inzwischen angebaut: Position kommt vom Auto
|
||||
if (b.IsVehicle) pos = AboveGround(pos, b.Rb.transform); // gespeicherte Position evtl. knapp im Boden
|
||||
b.Rb.transform.position = pos;
|
||||
b.Rb.transform.rotation = rot;
|
||||
@@ -247,6 +252,7 @@ namespace MSCO
|
||||
{
|
||||
if (b.Rb == null) { removeList.Add(b); continue; } // z.B. Teil wurde montiert
|
||||
if (!b.Rb.gameObject.activeInHierarchy) continue;
|
||||
if (UpdateAttached(b)) continue; // angebaut: bewegt sich mit dem Auto
|
||||
|
||||
bool active = b == held || b == driven;
|
||||
if (!IsRemoteOwned(b)) StopRunaway(b);
|
||||
@@ -292,7 +298,7 @@ namespace MSCO
|
||||
{
|
||||
foreach (SyncedBody b in byId.Values)
|
||||
{
|
||||
if (!IsRemoteOwned(b) || b.Rb == null) continue;
|
||||
if (!IsRemoteOwned(b) || b.Rb == null || b.Attached) continue;
|
||||
if (b.IsVehicle && Time.time >= b.NextPartScan) FreezeParts(b);
|
||||
if (Time.time - b.AvatarHoldTime < 0.2f) continue; // sitzt gerade in der Hand eines Mitspielers
|
||||
if ((b.Rb.position - b.TargetPos).sqrMagnitude > SnapDistance * SnapDistance)
|
||||
@@ -315,7 +321,7 @@ namespace MSCO
|
||||
public void ApplyAvatarHold(int playerId, int bodyId, Vector3 pos, Quaternion rot)
|
||||
{
|
||||
SyncedBody b;
|
||||
if (!byId.TryGetValue(bodyId, out b) || b.Rb == null || b.IsVehicle) return; // ältere Mods melden evtl. ein Auto als "gehalten"
|
||||
if (!byId.TryGetValue(bodyId, out b) || b.Rb == null || b.IsVehicle || b.Attached) return; // ältere Mods melden evtl. ein Auto als "gehalten"
|
||||
if (b.OwnerId != playerId)
|
||||
{
|
||||
if (!Wins(playerId, true, b.OwnerId, b.OwnerActive)) return;
|
||||
@@ -428,7 +434,7 @@ namespace MSCO
|
||||
float now = Time.time;
|
||||
foreach (SyncedBody b in byId.Values)
|
||||
{
|
||||
if (!IsLocal(b) || b.Rb == null) continue;
|
||||
if (!IsLocal(b) || b.Rb == null || b.Attached) continue;
|
||||
bool changed = (b.Rb.position - b.LastSentPos).sqrMagnitude > 0.0001f
|
||||
|| Quaternion.Angle(b.Rb.rotation, b.LastSentRot) > 0.5f;
|
||||
if (!changed && now - b.LastSentTime < KeepAliveInterval) continue;
|
||||
@@ -457,7 +463,7 @@ namespace MSCO
|
||||
int id = r.ReadInt32();
|
||||
bool active = r.ReadBoolean();
|
||||
SyncedBody b;
|
||||
if (!byId.TryGetValue(id, out b) || b.Rb == null) return;
|
||||
if (!byId.TryGetValue(id, out b) || b.Rb == null || IsAttached(b)) return;
|
||||
if (!Wins(from, active, b.OwnerId, b.OwnerActive))
|
||||
{
|
||||
// Wir besitzen es und gewinnen: nochmal melden, damit alle es wissen
|
||||
@@ -476,7 +482,7 @@ namespace MSCO
|
||||
int id; Vector3 pos; Quaternion rot; Vector3 vel;
|
||||
ReadState(r, out id, out pos, out rot, out vel);
|
||||
SyncedBody b;
|
||||
if (!byId.TryGetValue(id, out b) || b.Rb == null || !IsValidPose(pos, rot)) continue;
|
||||
if (!byId.TryGetValue(id, out b) || b.Rb == null || !IsValidPose(pos, rot) || IsAttached(b)) continue;
|
||||
// Nur dem aktuellen Besitzer folgen (oder freie Objekte übernehmen)
|
||||
if (b.OwnerId != from && b.OwnerId != SyncedBody.NoOwner) continue;
|
||||
SetRemote(b, from, b.OwnerId == from && b.OwnerActive);
|
||||
@@ -492,7 +498,7 @@ namespace MSCO
|
||||
ReadState(r, out id, out pos, out rot, out vel);
|
||||
SyncedBody b;
|
||||
if (!byId.TryGetValue(id, out b) || b.Rb == null || b.OwnerId != from) return;
|
||||
if (!IsValidPose(pos, rot)) { SetFree(b); return; }
|
||||
if (!IsValidPose(pos, rot) || IsAttached(b)) { SetFree(b); return; }
|
||||
b.Rb.transform.position = pos;
|
||||
b.Rb.transform.rotation = rot;
|
||||
RestoreKinematic(b);
|
||||
@@ -514,6 +520,7 @@ namespace MSCO
|
||||
/// </summary>
|
||||
void StopRunaway(SyncedBody b)
|
||||
{
|
||||
if (b.Attached) return;
|
||||
Rigidbody rb = b.Rb;
|
||||
if (rb.isKinematic || rb.velocity.sqrMagnitude < RunawaySpeed * RunawaySpeed) return;
|
||||
rb.velocity = Vector3.zero;
|
||||
@@ -527,6 +534,39 @@ namespace MSCO
|
||||
ModConsole.Warning("[MSCO] Stopped " + b.RootName + " - it was flung away by the physics");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ist das Objekt gerade an ein Fahrzeug angebaut? Dann Besitz aufgeben und nicht mehr als loses Objekt behandeln.
|
||||
/// Wird es wieder abgebaut, läuft der Sync ganz normal weiter. Gibt true zurück, solange es angebaut ist.
|
||||
/// </summary>
|
||||
bool UpdateAttached(SyncedBody b)
|
||||
{
|
||||
if (Time.time < b.NextAttachCheck) return b.Attached;
|
||||
b.NextAttachCheck = Time.time + 0.5f;
|
||||
bool attached = IsAttached(b);
|
||||
if (attached == b.Attached) return attached;
|
||||
b.Attached = attached;
|
||||
if (attached)
|
||||
{
|
||||
if (IsRemoteOwned(b)) RestoreKinematic(b);
|
||||
b.OwnerId = SyncedBody.NoOwner; // jeder Spieler erkennt das Anbauen selbst (Montage kommt über FsmSync)
|
||||
b.OwnerActive = false;
|
||||
}
|
||||
else b.NoMotionClaimUntil = Time.time + HandoverCooldown; // gerade abgebaut: kurz zur Ruhe kommen lassen
|
||||
return attached;
|
||||
}
|
||||
|
||||
static bool IsAttached(SyncedBody b)
|
||||
{
|
||||
if (b.IsVehicle || b.Rb == null) return false;
|
||||
// Unter einem anderen Rigidbody (z.B. am Auto eingehängt)
|
||||
for (Transform p = b.Rb.transform.parent; p != null; p = p.parent)
|
||||
if (p.GetComponent<Rigidbody>() != null) return true;
|
||||
// Per Gelenk mit etwas verbunden, das nicht der Spieler ist (die Hand hält Items nicht über Gelenke fest)
|
||||
foreach (Joint j in b.Rb.GetComponents<Joint>())
|
||||
if (j != null && j.connectedBody != null && j.connectedBody.transform.root.name != "PLAYER") return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>Position innerhalb der Karte, Drehung gültig (gleiche Regel wie auf dem Server).</summary>
|
||||
static bool IsValidPose(Vector3 p, Quaternion q)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user