From 855e0ea12a794857696d6fe1dad1c5c2ec98ac2b Mon Sep 17 00:00:00 2001 From: minjaesong Date: Mon, 9 Feb 2026 02:34:49 +0900 Subject: [PATCH] moving platforms can 'steal' actors --- .../terrarum/gameactors/PhysContraption.kt | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/net/torvald/terrarum/gameactors/PhysContraption.kt b/src/net/torvald/terrarum/gameactors/PhysContraption.kt index bd7b9453e..d09c40ff4 100644 --- a/src/net/torvald/terrarum/gameactors/PhysContraption.kt +++ b/src/net/torvald/terrarum/gameactors/PhysContraption.kt @@ -133,18 +133,29 @@ abstract class PhysContraption() : ActorWithBody() { INGAME.actorNowPlaying?.let { candidates.add(it) } for (actor in candidates) { - if (!actorsRiding.contains(actor.referenceID) && actor.platformsRiding.isEmpty() && isActorOnTop(actor)) { - mount(actor) - snapRiderToSurface(actor) - // Landing on the contraption kills all vertical velocity. - // controllerV.y must also be zeroed: during a jump-then-fall, - // controllerV.y stays negative (jump impulse) while externalV.y - // goes positive (gravity). Zeroing only externalV.y would leave - // a net upward velocity that immediately triggers dismount. - actor.externalV.y = 0.0 - actor.controllerV?.let { it.y = 0.0 } - actor.walledBottom = true + if (actorsRiding.contains(actor.referenceID)) continue + if (!isActorOnTop(actor)) continue + + // If already riding another contraption, only steal if this + // surface is strictly above (smaller Y) to prevent oscillation. + if (actor.platformsRiding.isNotEmpty()) { + val currentPlatform = INGAME.getActorByID(actor.platformsRiding[0]) as? PhysContraption + if (currentPlatform != null && hitbox.startY >= currentPlatform.hitbox.startY) continue + // Transfer: remove from old contraption without velocity impulse + currentPlatform?.actorsRiding?.remove(actor.referenceID) + actor.platformsRiding.clear() } + + mount(actor) + snapRiderToSurface(actor) + // Landing on the contraption kills all vertical velocity. + // controllerV.y must also be zeroed: during a jump-then-fall, + // controllerV.y stays negative (jump impulse) while externalV.y + // goes positive (gravity). Zeroing only externalV.y would leave + // a net upward velocity that immediately triggers dismount. + actor.externalV.y = 0.0 + actor.controllerV?.let { it.y = 0.0 } + actor.walledBottom = true } }