Mapping & Hammer

Aufzüge und Züge in Hammer bauen: func_door bis func_tracktrain

Aufzüge und Züge in Source- und GMod-Maps: welches Entity wofür, Aufbau mit Keyvalues, Rufknöpfe, path_track-Strecken, Ursachen von Quetschen und Ruckeln.

Einen Aufzug mit zwei Haltestellen baust du aus einem func_door oder func_movelinear, mehrere Stockwerke und Züge aus einem func_tracktrain, das einer Kette von path_track folgt. Zerquetscht werden Spieler, wenn ein Block-Damage-Wert gesetzt ist und das Entity bei einer Blockade weiterschiebt. Das Ruckeln beim Mitfahren beschreibt das Valve-Wiki als allgemeine Eigenschaft vertikal bewegter Plattformen in Multiplayer-Spielen der Source Engine. Eine Abhilfe nennt es nicht, teste den Lift deshalb früh. Stecken bleibt ein Aufzug meist, weil etwas im Weg steht oder die Strecke falsch verkettet ist.

Welches Entity wofür

EntityBewegungPasst fürGrenzen
func_doorzwischen zwei Positionen, Strecke = Brush-Größe minus Lipeinfacher Lift mit zwei Haltenkann nicht zwischendrin halten
func_movelinearentlang einer Richtung über Move Distance, jede Zwischenposition per SetPositionLift mit zwei Halten, Plattformen, Torelaut Valve-Wiki fehlerhaft, wenn es an ein anderes func_movelinear geparentet wird
func_tracktrainentlang einer Kette von path_trackmehrere Stockwerke, Züge, Kurvenmehr Aufwand, hält bei höherem Tempo etwas vor dem Ziel

func_tanktrain ist ein Zug, der auf den Spieler schießt und zerstört werden kann, und passt hier nicht. func_train und func_plat stehen nicht in der FGD von GMod.

Aufzug mit zwei Haltestellen

Am wenigsten Arbeit macht ein func_movelinear:

  1. Baue den Kabinenboden als Brush, drücke Strg+T und wähle func_movelinear. Name: lift.
  2. Stelle Move Direction (Pitch Yaw Roll) auf Up. Im Feld steht dann -90 0 0.
  3. Trage bei Move Distance den Abstand zwischen den beiden Fußböden in Units ein und bei Speed das Tempo.
  4. Baue Wände und Decke der Kabine als func_brush und trage bei Parent den Namen lift ein.
  5. Setze auf jedem Stockwerk einen func_button als Rufknopf und verbinde ihn mit dem Lift.
Entity        My Output       Target Entity   Target Input
button_up     OnPressed       lift            Open
button_down   OnPressed       lift            Close
lift          OnFullyOpen     door_top        Open
lift          OnFullyClosed   door_bottom     Open

Open fährt zur Endposition, Close zurück zur Startposition. OnFullyOpen und OnFullyClosed melden die Ankunft, damit öffnest du die Etagentüren. Wie Outputs, Verzögerungen und Namen genau funktionieren, erklärt der Artikel über Inputs und Outputs in Hammer.

Mit einem func_door rechnest du anders: Die Tür fährt immer um ihre eigene Brush-Größe, abzüglich Lip. Ein 16 Units dicker Boden, der 256 Units steigen soll, braucht also einen Lip von -240. Dazu kommen Delay Before Reset (-1 stay) auf -1, das Flag Toggle und ein entferntes Häkchen bei Touch Opens.

Türen und Knöpfe an der Kabine

Alles, was mitfahren soll, bekommt im Feld Parent den Namen des bewegten Entity. Ein Kind behält seinen Abstand zum Parent und macht jede Bewegung mit.

  • Kabinentüren: zwei func_door mit Parent = lift. Nimm dafür kein zweites func_movelinear, wegen des Parenting-Fehlers aus der Tabelle.
  • Knöpfe in der Kabine: func_button mit Parent = lift. Mit dem Flag Don't move fährt der Knopf beim Drücken nicht in die Wand.
  • Knöpfe sperren: Schicke bei OnPressed den Input Lock an alle Knöpfe (lift_button*) und bei OnFullyOpen und OnFullyClosed wieder Unlock.
  • Sandbox-Werkzeuge: Die FGD von GMod kennt für diese Entities Allow Physics Gun und Sandbox Tool Whitelist. Stelle Ersteres auf No, damit in Sandbox niemand den Lift mit der Physics Gun greift.

Züge und mehrere Stockwerke mit func_tracktrain

  1. Setze den ersten path_track und gib ihm einen Namen, etwa track_1. Klonst du ihn mit gedrückter Umschalttaste, zählt Hammer den Namen hoch und trägt Next Stop Target selbst ein.
  2. Baue den Zug so, dass seine Front entlang der X-Achse zeigt, in der Draufsicht nach rechts. Beim Spawnen dreht er sich in Richtung des nächsten path_track.
  3. Mache ihn zum func_tracktrain und trage bei First Stop Target den ersten path_track ein. Dort spawnt der Zug.
  4. Max Speed (units / second) begrenzt jedes Tempo. Initial Speed (units / second) 0 bedeutet, dass der Zug zunächst steht.
  5. Setze das Flag No User Control. Für einen Aufzug kommt Fixed Orientation dazu, damit sich die Kabine nicht dreht.
  6. Starte mit dem Input StartForward. An einer Haltestelle schickt der path_track über OnPass ein Stop an den Zug.

Für eine Rundstrecke trägst du beim letzten path_track wieder den ersten als Next Stop Target ein. New Train Speed am path_track ändert das Tempo ab dieser Stelle, wirkt aber nur mit No User Control.

In GMod kennt func_tracktrain außerdem den Input MoveToPathNode. Er fährt zum genannten path_track derselben Strecke und hält dort. Damit wird ein Aufzug mit vielen Stockwerken einfach:

Entity          My Output                    Target Entity   Target Input     Parameter   Delay
button_floor3   OnPressed                    lift_door       Close                        0.00
button_floor3   OnPressed                    lift            MoveToPathNode   floor_3     1.00
lift            OnArrivedAtDestinationNode   lift_door       Open                         0.00

Zwei weitere Eigenheiten nennt das Valve-Wiki: Ein func_tracktrain aktualisiert seine Richtung nur zehnmal pro Sekunde, schnelle Züge schießen in engen Kurven deshalb über die Strecke hinaus. Und Reverse oder StartBackward können versagen, wenn bei den beteiligten path_track New Train Speed auf 0 steht.

Warum Aufzüge quetschen, ruckeln oder hängen bleiben

Quetschen. Jedes der drei Entities hat einen eigenen Schadenswert: Blocking Damage beim func_door, Block Damage beim func_movelinear, Damage on Crush beim func_tracktrain. Der Standard ist überall 0. Bei Tür und func_movelinear gilt der Wert laut FGD pro Frame, kleine Zahlen töten also schnell. Wie sich das Entity bei einer Blockade verhält, zeigt der öffentliche Source-SDK-Code: Ein func_door kehrt um, außer Delay Before Reset ist negativ oder Force Closed gesetzt. Ein func_movelinear kehrt nie um und drückt weiter. Mit 0 teilt der Lift keinen Block-Schaden aus, lässt sich aber von einem Spieler im Schacht aufhalten. Also entweder 0 und ein geschlossener Schacht mit Etagentüren, die erst öffnen, wenn der Lift da ist, oder ein Schadenswert, mit dem sich der Lift durchsetzt. Beim func_door kannst du mit OnBlockedClosing und OnBlockedOpening selbst reagieren.

Ruckeln. Das Valve-Wiki hält fest, dass jede vertikal bewegte Plattform in Multiplayer-Spielen für Mitfahrende ruckelig wirkt, und nennt als Grund die Netzwerk-Physik der Spieler. Ein Tipp von der Diskussionsseite des Aufzug-Tutorials im Valve-Wiki, nicht dokumentiert und nicht in jeder Map bestätigt: Spieler nicht direkt auf dem func_tracktrain stehen lassen, sondern auf einem daran geparenteten func_brush. Die FGD beschreibt beim func_brush den Keyvalue Solid BSP für genau diesen Fall, ein Brush in der Hierarchie eines bewegten Objekts, auf dem Spieler stehen. Prüfe das Ergebnis auf einem echten Server mit Ping, wie in GMod-Map mit Spielern testen beschrieben.

Props an Bord. Ein prop_physics wird von der Physik simuliert und verhält sich laut Valve-Wiki seltsam, wenn du es parentest. Dekoration in der Kabine gehört deshalb als prop_dynamic an den Lift geparentet. Lose Physik-Props auf einer fahrenden Plattform können rutschen und sich verkeilen. Das ist Erfahrung aus der Praxis, kein dokumentiertes Verhalten. Die Prop-Typen vergleicht prop_static, prop_dynamic und prop_physics.

Hängen bleiben. Steht etwas im Weg? Ist bei einem path_track das Flag Disabled oder Disable train gesetzt oder Next Stop Target leer? Wurden Knöpfe gesperrt, aber nie wieder entsperrt, weil der Lift blockiert wurde und OnFullyOpen nie kam? Beim func_tracktrain hilft gegen blockierende Spieler das Flag Is unblockable by player.

Häufige Fragen

Warum hält mein func_tracktrain nicht genau am path_track?

Der Zug stoppt kurz vor dem Ziel, bei höherem Tempo deutlicher. Senke das Tempo vor der Haltestelle oder verschiebe den path_track um die fehlende Strecke, bis die Kabine bündig steht.

Warum ist die Kabine während der Fahrt falsch beleuchtet?

Brush-Entities tragen vorberechnete Lightmaps von ihrer Startposition, die nicht mehr passen, sobald die Kabine in einen anders beleuchteten Bereich fährt. Abhilfe: Baue die sichtbare Kabine als prop_dynamic und parente sie an einen unsichtbaren Brush. Mehr dazu in Source Engine Beleuchtung.

Können Spieler einen Zug selbst steuern?

Ja, solange das Flag No User Control am Zug aus ist. Laut Valve-Wiki kann ein Spieler, der auf einem func_tracktrain steht, ihn dann steuern. Ein func_traincontrols, dessen Train Name und Parent beide auf den Zug zeigen, begrenzt das auf seinen Brush: Der Spieler muss darin und auf dem Zug stehen.