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
|
||||
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**
|
||||
- **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
|
||||
|
||||
+16
@@ -16,6 +16,13 @@ namespace MSCO
|
||||
public class DoorSync
|
||||
{
|
||||
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 RescanInterval = 10f; // neue Objekte (z.B. angebaute Autotüren) aufnehmen
|
||||
@@ -102,6 +109,7 @@ namespace MSCO
|
||||
string root = fsm.transform.root.name;
|
||||
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 (IsPartLogic(fsm)) continue;
|
||||
|
||||
string key = FsmSync.PathOf(fsm.transform) + "|" + fsm.FsmName;
|
||||
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)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) return false;
|
||||
|
||||
+32
-4
@@ -19,7 +19,12 @@ namespace MSCO
|
||||
const float SendInterval = 0.1f;
|
||||
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 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 SpringDamper = 12f;
|
||||
|
||||
@@ -34,6 +39,7 @@ namespace MSCO
|
||||
public float TargetAngle;
|
||||
public float TargetTime = -100f;
|
||||
public bool Driving; // Feder gerade von uns gesetzt
|
||||
public float LocalAuthorityUntil = -100f;
|
||||
public bool OrigUseSpring;
|
||||
public JointSpring OrigSpring;
|
||||
}
|
||||
@@ -69,10 +75,13 @@ namespace MSCO
|
||||
foreach (Hinge h in hinges.Values)
|
||||
{
|
||||
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);
|
||||
if (owner != SyncedBody.NoOwner && owner != localId) continue; // der Fahrer schickt
|
||||
if (owner == SyncedBody.NoOwner && (h.Rb.position - playerPos).sqrMagnitude > NearRange * NearRange) continue;
|
||||
// Fährt jemand: der Fahrer schickt (Türen schwingen während der Fahrt). Hat man selbst gerade an der Tür
|
||||
// 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;
|
||||
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)
|
||||
{
|
||||
int count = r.ReadInt32();
|
||||
@@ -100,6 +127,7 @@ namespace MSCO
|
||||
Hinge h;
|
||||
if (!hinges.TryGetValue(key, out h)) { nextScan = 0f; 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.TargetTime = Time.time;
|
||||
h.SentAngle = angle; // nicht als eigene Bewegung zurückschicken
|
||||
|
||||
@@ -1883,6 +1883,9 @@ namespace MSCO
|
||||
}
|
||||
else if (IsPeerReady && MenuHelper.InGame && localPlayer != null && !overlays.AnyOpen)
|
||||
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)
|
||||
{
|
||||
SetStatus(passengerResult);
|
||||
|
||||
Reference in New Issue
Block a user