Ascensores y trenes en Hammer: de func_door a func_tracktrain
Ascensores y trenes en mapas Source y GMod: qué entity encaja, montaje con keyvalues, botones de llamada, rutas path_track, causas de aplastamiento y tirones.
Un ascensor de dos paradas lo construyes con un func_door o un func_movelinear, y varias plantas o trenes con un func_tracktrain que sigue una cadena de entities path_track. Los jugadores acaban aplastados cuando hay un valor de daño por bloqueo configurado y la entity sigue empujando mientras está bloqueada. Los tirones durante el trayecto los describe la wiki de Valve como un rasgo general de las plataformas que se mueven en vertical en los juegos Source multijugador. No menciona ninguna solución, así que prueba el ascensor pronto. Un ascensor suele quedarse atascado porque hay algo en medio o porque la ruta está mal encadenada.
Qué entity para cada tarea
| Entity | Movimiento | Sirve para | Límites |
|---|---|---|---|
func_door | entre dos posiciones, distancia = tamaño del brush menos Lip | ascensor sencillo de dos paradas | no puede parar a medio camino |
func_movelinear | a lo largo de una dirección durante Move Distance, cualquier posición intermedia mediante SetPosition | ascensor de dos paradas, plataformas, portones | con fallos, según la wiki de Valve, cuando se emparenta a otro func_movelinear |
func_tracktrain | a lo largo de una cadena de path_track | varias plantas, trenes, curvas | más trabajo, se detiene un poco antes de su destino a mayor velocidad |
func_tanktrain es un tren que dispara al jugador y al que se puede matar, así que aquí no encaja. func_train y func_plat no están en el FGD de GMod.
Un ascensor de dos paradas
Un func_movelinear es lo que menos trabajo da:
- Construye el suelo de la cabina como brush, pulsa
Ctrl+Ty eligefunc_movelinear. Nombre:lift. - Pon
Move Direction (Pitch Yaw Roll)enUp. El campo muestra entonces-90 0 0. - Introduce en
Move Distancela distancia entre los dos suelos, en unidades, y enSpeedla velocidad. - Construye las paredes y el techo de la cabina como un
func_brushe introduce el nombreliftenParent. - Coloca un
func_buttonen cada planta como botón de llamada y conéctalo al ascensor.
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 lo lleva a la posición final, Close de vuelta a la posición inicial. OnFullyOpen y OnFullyClosed avisan de la llegada, y con eso abres las puertas de planta. Cómo funcionan en detalle los outputs, los retardos y los nombres lo explica el artículo sobre inputs y outputs en Hammer.
Con un func_door las cuentas son otras: una puerta siempre se desplaza el tamaño de su propio brush, menos Lip. Un suelo de 16 unidades de grosor que deba subir 256 unidades necesita, por tanto, un Lip de -240. Añade Delay Before Reset (-1 stay) en -1, el flag Toggle y Touch Opens desmarcado.
Puertas y botones en la cabina
Todo lo que deba viajar con ella lleva el nombre de la entity móvil en su campo Parent. Una entity hija mantiene su separación respecto al parent y sigue cada movimiento.
- Puertas de la cabina: dos entities
func_doorconParent=lift. No uses aquí un segundofunc_movelinear, por el fallo de parenting de la tabla. - Botones en la cabina:
func_buttonconParent=lift. Con el flagDon't move, el botón no se mete en la pared al pulsarlo. - Bloquear los botones: En
OnPressed, envía el inputLocka todos los botones (lift_button*), y otra vezUnlockenOnFullyOpenyOnFullyClosed. - Herramientas de Sandbox: El FGD de GMod ofrece
Allow Physics GunySandbox Tool Whitelistpara estas entities. Pon el primero enNopara que nadie en Sandbox agarre el ascensor con la Physics Gun.
Trenes y varias plantas con func_tracktrain
- Coloca el primer
path_tracky dale un nombre comotrack_1. Si lo clonas manteniendo pulsado Shift, Hammer va incrementando el nombre y rellenaNext Stop Targetpor su cuenta. - Construye el tren de modo que su frente apunte a lo largo del eje X, hacia la derecha en la vista superior. Al hacer spawn, gira hacia el siguiente
path_track. - Conviértelo en un
func_tracktraine introduce el primerpath_trackenFirst Stop Target. El tren hace spawn ahí. Max Speed (units / second)limita cualquier velocidad.Initial Speed (units / second)0 significa que el tren está parado al principio.- Activa el flag
No User Control. Para un ascensor, añadeFixed Orientationpara que la cabina no gire. - Ponlo en marcha con el input
StartForward. En una parada, elpath_trackle envíaStopal tren medianteOnPass.
Para un circuito cerrado, introduce el primer path_track como Next Stop Target del último. New Train Speed en un path_track cambia la velocidad a partir de ahí, pero solo surte efecto con No User Control.
En GMod, func_tracktrain tiene además el input MoveToPathNode. Viaja hasta el path_track indicado de la misma ruta y se detiene ahí. Eso hace sencillo un ascensor de muchas plantas:
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
La wiki de Valve recoge dos peculiaridades más: un func_tracktrain solo actualiza su dirección diez veces por segundo, así que los trenes rápidos se salen del trazado en las curvas cerradas. Y Reverse o StartBackward pueden fallar si New Train Speed es 0 en las entities path_track implicadas.
Por qué los ascensores aplastan, dan tirones o se atascan
Aplastamiento. Cada una de las tres entities tiene su propio valor de daño: Blocking Damage en func_door, Block Damage en func_movelinear, Damage on Crush en func_tracktrain. El valor por defecto es 0 en todas. Para la puerta y func_movelinear, el FGD indica el valor por frame, así que los números pequeños matan rápido. Cómo se comporta la entity al quedar bloqueada se ve en el código público del Source SDK: un func_door invierte el sentido, salvo que Delay Before Reset sea negativo o Force Closed esté activado. Un func_movelinear nunca invierte el sentido y sigue empujando. Con 0 el ascensor no causa daño por bloqueo, pero un jugador en el hueco puede retenerlo. Así que o mantienes 0 y cierras el hueco con puertas de planta que solo se abren cuando el ascensor ha llegado, o pones un valor de daño y dejas que gane el ascensor. En un func_door puedes reaccionar tú mismo con OnBlockedClosing y OnBlockedOpening.
Tirones. La wiki de Valve afirma que cualquier plataforma que se mueve en vertical les parece brusca a quienes van en ella en los juegos multijugador, y da como motivo la física de red de los jugadores. Un consejo de la página de discusión del tutorial de ascensores de la wiki de Valve, no documentado y que no todos los mapas confirman: no dejes que los jugadores estén directamente sobre el func_tracktrain, sino sobre un func_brush emparentado a él. Para func_brush, el FGD describe el keyvalue Solid BSP justo para este caso, un brush en la jerarquía de un objeto móvil sobre el que están los jugadores. Comprueba el resultado en un servidor real con ping, como se describe en probar un mapa de GMod con jugadores.
Props a bordo. Un prop_physics lo simula la física y, según la wiki de Valve, se comporta de forma extraña cuando lo emparentas. Por eso la decoración de la cabina va en el ascensor como un prop_dynamic emparentado. Los props de física sueltos sobre una plataforma en movimiento pueden deslizarse y quedar encajados. Es experiencia de la práctica, no un comportamiento documentado. Los tipos de prop se comparan en prop_static, prop_dynamic y prop_physics.
Atascos. ¿Hay algo en medio? ¿Tiene algún path_track activado el flag Disabled o Disable train, o un Next Stop Target vacío? ¿Se bloquearon botones que nunca se desbloquearon, porque el ascensor quedó bloqueado y OnFullyOpen no llegó nunca? En un func_tracktrain, el flag Is unblockable by player ayuda contra los jugadores que lo bloquean.
Preguntas frecuentes
¿Por qué mi func_tracktrain no se detiene exactamente en el path_track?
El tren se detiene justo antes de su destino, y se nota más a mayor velocidad. Reduce la velocidad antes de la parada, o desplaza el path_track la distancia que falta hasta que la cabina quede enrasada.
¿Por qué la cabina está mal iluminada durante el trayecto?
Las brush entities llevan lightmaps precalculados desde su posición inicial, que dejan de encajar en cuanto la cabina entra en una zona con otra iluminación. El remedio: construye la cabina visible como un prop_dynamic y emparéntala a un brush invisible. Más sobre esto en la guía de iluminación del Source Engine.
¿Pueden los jugadores conducir un tren ellos mismos?
Sí, siempre que el flag No User Control del tren esté desactivado. Según la wiki de Valve, un jugador que está sobre un func_tracktrain puede entonces controlarlo. Un func_traincontrols cuyos Train Name y Parent apuntan ambos al tren lo limita a su brush: el jugador tiene que estar dentro de él y sobre el tren.