Doors on all vehicles: no more part-logic FSMs in DoorSync, single sender for hinges
- DoorSync matched every FSM with door/hood/lid/trunk in its name, including the door parts' removal/assembly/bolt/paint FSMs and trigger_ objects, and forced their states at the other players: doors hung crooked, snapped back or came off. Those are excluded now (assembly runs via FsmSync). - HingeSync: on a parked vehicle everyone nearby sent the angle, so doors ping-ponged. Now only the player who clicked near the door (4 s) sends; on a driven vehicle the driver sends; received angles are held 3 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,12 @@
|
|||||||
- Konsole (F7): `model classic` zeigt wieder die MSCO-Figur, `model game` die MSC-Menschen; `rig` zeigt, wer welches
|
- Konsole (F7): `model classic` zeigt wieder die MSCO-Figur, `model game` die MSC-Menschen; `rig` zeigt, wer welches
|
||||||
Modell hat. Findet MSCO den Körper nicht, bleibt automatisch die MSCO-Figur
|
Modell hat. Findet MSCO den Körper nicht, bleibt automatisch die MSCO-Figur
|
||||||
|
|
||||||
|
**Türen an allen Fahrzeugen**
|
||||||
|
- Türen hingen schief, sprangen zurück oder lösten sich: der Tür-Sync erfasste auch die FSMs zum An-/Abbauen,
|
||||||
|
Festschrauben und Lackieren der Tür-Teile und erzwang deren Zustände beim Mitspieler. Jetzt nur noch Öffnen/Schließen
|
||||||
|
- Türen schaukelten hin und her: an einem stehenden Auto schickte jeder in der Nähe den Türwinkel zurück. Jetzt schickt
|
||||||
|
nur, wer an der Tür geklickt hat (bzw. beim fahrenden Auto der Fahrer); empfangene Winkel werden länger gehalten
|
||||||
|
|
||||||
**Mitfahren**
|
**Mitfahren**
|
||||||
- **Wer im Fahrzeug ist, fährt mit - genau an seiner Stelle**: Kopf in der Kabine, in der offenen Tür oder auf der
|
- **Wer im Fahrzeug ist, fährt mit - genau an seiner Stelle**: Kopf in der Kabine, in der offenen Tür oder auf der
|
||||||
Ladefläche -> die Position im Fahrzeug wird festgehalten, kein Umsetzen auf einen berechneten Sitz. Geht auch, wenn
|
Ladefläche -> die Position im Fahrzeug wird festgehalten, kein Umsetzen auf einen berechneten Sitz. Geht auch, wenn
|
||||||
|
|||||||
+16
@@ -16,6 +16,13 @@ namespace MSCO
|
|||||||
public class DoorSync
|
public class DoorSync
|
||||||
{
|
{
|
||||||
static readonly string[] Keywords = { "door", "gate", "hood", "bonnet", "trunk", "lid", "hatch" };
|
static readonly string[] Keywords = { "door", "gate", "hood", "bonnet", "trunk", "lid", "hatch" };
|
||||||
|
// Nicht die FSMs zum An-/Abbauen, Festschrauben, Lackieren, Speichern ... der Tür-TEILE: deren Zustände wurden
|
||||||
|
// beim Mitspieler erzwungen - Türen hingen schief, lösten sich oder sprangen zurück. Montage läuft über FsmSync.
|
||||||
|
static readonly string[] ExcludedFsms =
|
||||||
|
{
|
||||||
|
"removal", "assembly", "assemble", "boltcheck", "bolt", "screw", "paint", "data", "save", "load", "wiring",
|
||||||
|
"setup", "damage", "tightness", "detach", "attach", "install"
|
||||||
|
};
|
||||||
|
|
||||||
const float Cooldown = 1.5f; // Folge-Zustände der Animation nicht nochmal senden
|
const float Cooldown = 1.5f; // Folge-Zustände der Animation nicht nochmal senden
|
||||||
const float RescanInterval = 10f; // neue Objekte (z.B. angebaute Autotüren) aufnehmen
|
const float RescanInterval = 10f; // neue Objekte (z.B. angebaute Autotüren) aufnehmen
|
||||||
@@ -102,6 +109,7 @@ namespace MSCO
|
|||||||
string root = fsm.transform.root.name;
|
string root = fsm.transform.root.name;
|
||||||
if (root == "PLAYER" || root.StartsWith("MSCO_")) continue;
|
if (root == "PLAYER" || root.StartsWith("MSCO_")) continue;
|
||||||
if (!Matches(fsm.gameObject.name) && !Matches(fsm.FsmName) && !Matches(fsm.transform.parent != null ? fsm.transform.parent.name : "")) continue;
|
if (!Matches(fsm.gameObject.name) && !Matches(fsm.FsmName) && !Matches(fsm.transform.parent != null ? fsm.transform.parent.name : "")) continue;
|
||||||
|
if (IsPartLogic(fsm)) continue;
|
||||||
|
|
||||||
string key = FsmSync.PathOf(fsm.transform) + "|" + fsm.FsmName;
|
string key = FsmSync.PathOf(fsm.transform) + "|" + fsm.FsmName;
|
||||||
Tracked t;
|
Tracked t;
|
||||||
@@ -110,6 +118,14 @@ namespace MSCO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsPartLogic(PlayMakerFSM fsm)
|
||||||
|
{
|
||||||
|
string f = fsm.FsmName.ToLower(), o = fsm.gameObject.name.ToLower();
|
||||||
|
if (o.StartsWith("trigger_") || o.StartsWith("bolt")) return true;
|
||||||
|
foreach (string x in ExcludedFsms) if (f.Contains(x)) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool Matches(string name)
|
static bool Matches(string name)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(name)) return false;
|
if (string.IsNullOrEmpty(name)) return false;
|
||||||
|
|||||||
+32
-4
@@ -19,7 +19,12 @@ namespace MSCO
|
|||||||
const float SendInterval = 0.1f;
|
const float SendInterval = 0.1f;
|
||||||
const float MinAngle = 2f; // Grad - kleiner ist Zittern
|
const float MinAngle = 2f; // Grad - kleiner ist Zittern
|
||||||
const float NearRange = 4f; // so nah muss man an einer Tür stehen, um sie zu bewegen
|
const float NearRange = 4f; // so nah muss man an einer Tür stehen, um sie zu bewegen
|
||||||
const float ApplyHold = 1.5f; // so lange nach einer Nachricht die Feder halten und selbst nicht senden
|
const float ApplyHold = 3f; // so lange nach einer Nachricht die Feder halten und selbst nicht senden
|
||||||
|
// Steht das Fahrzeug, schickt nur, wer die Tür gerade selbst bewegt hat (Klick in der Nähe). Vorher schickte
|
||||||
|
// jeder in der Nähe: setzte sich die Tür beim anderen nach dem Übernehmen etwas anders, schickte er zurück -
|
||||||
|
// die Türen schaukelten hin und her.
|
||||||
|
const float InteractRange = 2.5f;
|
||||||
|
const float InteractAuthority = 4f; // so lange nach dem Klick (Tür schwingt aus)
|
||||||
const float SpringForce = 120f;
|
const float SpringForce = 120f;
|
||||||
const float SpringDamper = 12f;
|
const float SpringDamper = 12f;
|
||||||
|
|
||||||
@@ -34,6 +39,7 @@ namespace MSCO
|
|||||||
public float TargetAngle;
|
public float TargetAngle;
|
||||||
public float TargetTime = -100f;
|
public float TargetTime = -100f;
|
||||||
public bool Driving; // Feder gerade von uns gesetzt
|
public bool Driving; // Feder gerade von uns gesetzt
|
||||||
|
public float LocalAuthorityUntil = -100f;
|
||||||
public bool OrigUseSpring;
|
public bool OrigUseSpring;
|
||||||
public JointSpring OrigSpring;
|
public JointSpring OrigSpring;
|
||||||
}
|
}
|
||||||
@@ -69,10 +75,13 @@ namespace MSCO
|
|||||||
foreach (Hinge h in hinges.Values)
|
foreach (Hinge h in hinges.Values)
|
||||||
{
|
{
|
||||||
if (h.Joint == null || h.Rb == null || !h.Rb.gameObject.activeInHierarchy) continue;
|
if (h.Joint == null || h.Rb == null || !h.Rb.gameObject.activeInHierarchy) continue;
|
||||||
if (Time.time - h.TargetTime < ApplyHold) continue; // gerade von anderen gesetzt
|
bool mine = Time.time < h.LocalAuthorityUntil;
|
||||||
|
if (!mine && Time.time - h.TargetTime < ApplyHold) continue; // gerade von anderen gesetzt
|
||||||
int owner = objects.VehicleOwner(h.Root);
|
int owner = objects.VehicleOwner(h.Root);
|
||||||
if (owner != SyncedBody.NoOwner && owner != localId) continue; // der Fahrer schickt
|
// Fährt jemand: der Fahrer schickt (Türen schwingen während der Fahrt). Hat man selbst gerade an der Tür
|
||||||
if (owner == SyncedBody.NoOwner && (h.Rb.position - playerPos).sqrMagnitude > NearRange * NearRange) continue;
|
// geklickt, schickt man auch - sonst würde die Feder sie beim Fahrer gleich wieder zudrücken.
|
||||||
|
if (!mine && owner != SyncedBody.NoOwner && owner != localId) continue;
|
||||||
|
if (!mine && owner == SyncedBody.NoOwner) { h.SentAngle = SafeAngle(h, h.SentAngle); continue; } // stehendes Auto: nur wer klickt
|
||||||
|
|
||||||
float angle = h.Joint.angle;
|
float angle = h.Joint.angle;
|
||||||
if (float.IsNaN(angle) || float.IsInfinity(angle)) continue;
|
if (float.IsNaN(angle) || float.IsInfinity(angle)) continue;
|
||||||
@@ -90,6 +99,24 @@ namespace MSCO
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Jedes Frame: Klick (linke Maustaste / Benutzen) in der Nähe einer Tür = wir bewegen sie gerade.</summary>
|
||||||
|
public void NoteInteraction(Vector3 playerPos)
|
||||||
|
{
|
||||||
|
if (!Input.GetMouseButtonDown(0) && !Input.GetKeyDown(KeyCode.F)) return;
|
||||||
|
foreach (Hinge h in hinges.Values)
|
||||||
|
{
|
||||||
|
if (h.Rb == null || (h.Rb.worldCenterOfMass - playerPos).sqrMagnitude > InteractRange * InteractRange) continue;
|
||||||
|
h.LocalAuthorityUntil = Time.time + InteractAuthority;
|
||||||
|
h.TargetTime = -100f; // eigene Bewegung: keine Feder mehr auf den alten Winkel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static float SafeAngle(Hinge h, float fallback)
|
||||||
|
{
|
||||||
|
float a = h.Joint.angle;
|
||||||
|
return float.IsNaN(a) || float.IsInfinity(a) ? fallback : a;
|
||||||
|
}
|
||||||
|
|
||||||
public void Handle(BinaryReader r)
|
public void Handle(BinaryReader r)
|
||||||
{
|
{
|
||||||
int count = r.ReadInt32();
|
int count = r.ReadInt32();
|
||||||
@@ -100,6 +127,7 @@ namespace MSCO
|
|||||||
Hinge h;
|
Hinge h;
|
||||||
if (!hinges.TryGetValue(key, out h)) { nextScan = 0f; continue; }
|
if (!hinges.TryGetValue(key, out h)) { nextScan = 0f; continue; }
|
||||||
if (float.IsNaN(angle) || float.IsInfinity(angle) || Mathf.Abs(angle) > 180f) continue;
|
if (float.IsNaN(angle) || float.IsInfinity(angle) || Mathf.Abs(angle) > 180f) continue;
|
||||||
|
if (Time.time < h.LocalAuthorityUntil) continue; // wir bewegen sie gerade selbst
|
||||||
h.TargetAngle = angle;
|
h.TargetAngle = angle;
|
||||||
h.TargetTime = Time.time;
|
h.TargetTime = Time.time;
|
||||||
h.SentAngle = angle; // nicht als eigene Bewegung zurückschicken
|
h.SentAngle = angle; // nicht als eigene Bewegung zurückschicken
|
||||||
|
|||||||
@@ -1883,6 +1883,9 @@ namespace MSCO
|
|||||||
}
|
}
|
||||||
else if (IsPeerReady && MenuHelper.InGame && localPlayer != null && !overlays.AnyOpen)
|
else if (IsPeerReady && MenuHelper.InGame && localPlayer != null && !overlays.AnyOpen)
|
||||||
passengerResult = passenger.AutoUpdate(localPlayer, playerCamera, objects, players); // in die Beifahrertür treten
|
passengerResult = passenger.AutoUpdate(localPlayer, playerCamera, objects, players); // in die Beifahrertür treten
|
||||||
|
// Klick an einer Fahrzeugtür: wir bewegen sie (nur dann wird ihr Winkel geschickt, siehe HingeSync)
|
||||||
|
if (MenuHelper.InGame && localPlayer != null && !overlays.AnyOpen)
|
||||||
|
hinges.NoteInteraction(playerCamera != null ? playerCamera.transform.position : localPlayer.position);
|
||||||
if (passengerResult != null)
|
if (passengerResult != null)
|
||||||
{
|
{
|
||||||
SetStatus(passengerResult);
|
SetStatus(passengerResult);
|
||||||
|
|||||||
Reference in New Issue
Block a user