Freeze attached parts of remote-driven vehicles (joints broke, car fell apart); don't sync bolt tightness
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+52
-7
@@ -22,6 +22,9 @@ namespace MSCO
|
||||
public int OwnerId = NoOwner;
|
||||
public bool OwnerActive; // Besitzer hält/fährt es gerade aktiv
|
||||
public bool WasKinematic; // Zustand bevor ein anderer Spieler es übernommen hat
|
||||
// Angebaute Teile eines Fahrzeugs (eigene Rigidbodies mit Gelenken), solange ein anderer fährt: kinematisch
|
||||
public Dictionary<Rigidbody, bool> FrozenParts;
|
||||
public float NextPartScan;
|
||||
public float StillTime;
|
||||
public float NoMotionClaimUntil; // kurz nach einer Übergabe nicht wegen Nachfedern/Nachrollen übernehmen
|
||||
|
||||
@@ -177,7 +180,7 @@ namespace MSCO
|
||||
public void Reset()
|
||||
{
|
||||
foreach (SyncedBody b in byId.Values)
|
||||
if (IsRemoteOwned(b) && b.Rb != null) b.Rb.isKinematic = b.WasKinematic;
|
||||
if (IsRemoteOwned(b) && b.Rb != null) RestoreKinematic(b);
|
||||
byId.Clear();
|
||||
byRb.Clear();
|
||||
rejected.Clear();
|
||||
@@ -194,7 +197,7 @@ namespace MSCO
|
||||
foreach (SyncedBody b in byId.Values)
|
||||
{
|
||||
if (b.OwnerId != playerId || b.Rb == null) continue;
|
||||
b.Rb.isKinematic = b.WasKinematic;
|
||||
RestoreKinematic(b);
|
||||
b.OwnerId = SyncedBody.NoOwner;
|
||||
b.NoMotionClaimUntil = Time.time + HandoverCooldown;
|
||||
}
|
||||
@@ -290,6 +293,7 @@ namespace MSCO
|
||||
foreach (SyncedBody b in byId.Values)
|
||||
{
|
||||
if (!IsRemoteOwned(b) || b.Rb == null) 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)
|
||||
{
|
||||
@@ -333,7 +337,7 @@ namespace MSCO
|
||||
|
||||
void Claim(SyncedBody b, bool active)
|
||||
{
|
||||
if (IsRemoteOwned(b)) b.Rb.isKinematic = b.WasKinematic;
|
||||
if (IsRemoteOwned(b)) RestoreKinematic(b);
|
||||
b.OwnerId = LocalId;
|
||||
b.OwnerActive = active;
|
||||
b.StillTime = 0f;
|
||||
@@ -362,8 +366,7 @@ namespace MSCO
|
||||
if (b.OwnerId == ownerId) return;
|
||||
if (!IsRemoteOwned(b))
|
||||
{
|
||||
b.WasKinematic = b.Rb.isKinematic;
|
||||
b.Rb.isKinematic = true;
|
||||
FreezeForRemote(b);
|
||||
b.TargetPos = b.Rb.position;
|
||||
b.TargetRot = b.Rb.rotation;
|
||||
}
|
||||
@@ -372,11 +375,53 @@ namespace MSCO
|
||||
|
||||
void SetFree(SyncedBody b)
|
||||
{
|
||||
if (IsRemoteOwned(b)) b.Rb.isKinematic = b.WasKinematic;
|
||||
if (IsRemoteOwned(b)) RestoreKinematic(b);
|
||||
b.OwnerId = SyncedBody.NoOwner;
|
||||
b.NoMotionClaimUntil = Time.time + HandoverCooldown;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ein anderer Spieler bewegt das Objekt: bei uns nur noch folgen (kinematisch). Bei Fahrzeugen auch alle
|
||||
/// angebauten Teile - die hängen in MSC mit Gelenken (mit Bruchkraft) am Auto. Würde nur das Auto ruckartig
|
||||
/// versetzt, rissen die Gelenke und das Auto fiele auseinander.
|
||||
/// </summary>
|
||||
void FreezeForRemote(SyncedBody b)
|
||||
{
|
||||
b.WasKinematic = b.Rb.isKinematic;
|
||||
b.Rb.isKinematic = true;
|
||||
if (b.IsVehicle) FreezeParts(b);
|
||||
}
|
||||
|
||||
void FreezeParts(SyncedBody b)
|
||||
{
|
||||
b.NextPartScan = Time.time + 1f;
|
||||
if (b.FrozenParts == null) b.FrozenParts = new Dictionary<Rigidbody, bool>();
|
||||
foreach (Rigidbody part in b.Rb.GetComponentsInChildren<Rigidbody>())
|
||||
{
|
||||
if (part == b.Rb || b.FrozenParts.ContainsKey(part)) continue;
|
||||
b.FrozenParts[part] = part.isKinematic;
|
||||
part.isKinematic = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Wieder selbst simulieren: Auto und angebaute Teile zurück auf ihren vorherigen Zustand.</summary>
|
||||
void RestoreKinematic(SyncedBody b)
|
||||
{
|
||||
if (b.Rb != null) b.Rb.isKinematic = b.WasKinematic;
|
||||
if (b.FrozenParts == null) return;
|
||||
foreach (KeyValuePair<Rigidbody, bool> kv in b.FrozenParts)
|
||||
{
|
||||
if (kv.Key == null) continue;
|
||||
kv.Key.isKinematic = kv.Value;
|
||||
if (!kv.Value)
|
||||
{
|
||||
kv.Key.velocity = Vector3.zero; // keinen Schwung aus dem Folgen mitnehmen
|
||||
kv.Key.angularVelocity = Vector3.zero;
|
||||
}
|
||||
}
|
||||
b.FrozenParts = null;
|
||||
}
|
||||
|
||||
void SendOwnedStates()
|
||||
{
|
||||
sendList.Clear();
|
||||
@@ -450,7 +495,7 @@ namespace MSCO
|
||||
if (!IsValidPose(pos, rot)) { SetFree(b); return; }
|
||||
b.Rb.transform.position = pos;
|
||||
b.Rb.transform.rotation = rot;
|
||||
b.Rb.isKinematic = b.WasKinematic;
|
||||
RestoreKinematic(b);
|
||||
if (!b.Rb.isKinematic)
|
||||
{
|
||||
b.Rb.velocity = vel;
|
||||
|
||||
+3
-2
@@ -21,13 +21,14 @@ namespace MSCO
|
||||
static readonly string[] Keywords =
|
||||
{
|
||||
"fuel", "oil", "coolant", "water", "fluid", "brake", "clutchfluid", "battery", "charge",
|
||||
"bolt", "tight", "damage", "wear", "condition", "odo", "km", "dirt", "paint", "color", "colour",
|
||||
"damage", "wear", "condition", "odo", "km", "dirt", "paint", "color", "colour",
|
||||
"tune", "tuning", "ratio", "broken", "fixed", "flat", "pressure", "level", "mixture", "timing",
|
||||
"idle", "air", "jet", "spark", "gap", "rust", "health", "burn", "cool", "temp"
|
||||
};
|
||||
|
||||
// Montiert-Flags nicht direkt setzen: das echte Anbauen läuft über FsmSync (Events)
|
||||
static readonly string[] Excluded = { "install", "rpm", "speed", "steer", "throttle", "gear", "raycast", "distance" };
|
||||
// Schrauben/Festigkeit laufen über FsmSync (Events) - ein falscher Wert hier würde Teile lockern und abfallen lassen
|
||||
static readonly string[] Excluded = { "install", "bolt", "tight", "detach", "attach", "rpm", "speed", "steer", "throttle", "gear", "raycast", "distance" };
|
||||
|
||||
const float ScanInterval = 10f;
|
||||
const float CheckInterval = 0.5f;
|
||||
|
||||
Reference in New Issue
Block a user