luv

Workshop wiki

riding.lisp

luvcraft/riding.lisp

system luvcraft/core · 16 definitions · on GitHub

Riding an animal. #W2E5HR is the design.

Mounting is the same session transition as reading a world terminal (#8JCMA5) and it deliberately feels like one: TAB enters the interaction with whatever the crosshair is on, shift-TAB leaves it, ordinary player input stands down for the duration, and the camera eases from wherever it was into the pose the interaction asks for -- the same easing, at the same rate, into the same narrowed field of view.

Two things make a mount different from a wall. Its pose moves -- the pose is a seat on the animal's own back, so it is asked again every frame and the view rides the animal's gait and its slow turns; and it carries the player, so the scalar controller stands down completely and the player's body is set on the animal instead of left standing where it mounted. That is what keeps chunk residency, checkpoints, and the return camera all following the ride rather than the place it started.

in-package#:luvcraft

Where the rider sits is art direction rather than physics, and it is settled by looking: these are parameters so that a live image can move the seat between two screenshots.

defparameter*critter-ride-seat-lift*0.34d0

How far above the animal's own back the rider's eyes sit, in cells.

Measured from the top of the animal rather than from the ground, so a rider sits on whatever they have mounted instead of at a height which only suits a turtle.

defparameter*critter-ride-seat-offset*-0.42d0

How far back along the animal the rider sits, in cells: on it, not on its head.

defparameter*critter-ride-seat-pitch*-0.33d0

How far a seated rider looks down, in radians.

Enough to keep the shell they are sitting on in the bottom of the frame and the ground the animal is walking over in the middle of it.

defclasscritter-ride
critter:initarg:critter:readercritter-ride-critter
:documentation

A player mounted on an animal, going where it goes.

The rider steers with the session's own movement intent. Going forward is going forward whether the player's legs or an animal's are doing it, so a mount reads the same urges the player controller would have read rather than keeping a second copy of them.

defmethodactivate-luvcraft-critter

A turtle can be ridden. It is not fast, but it is willing.

declare
ignoresession
make-instance'critter-ride:crittercritter
defmethodluvcraft-focus-carries-player-p
declare
ignorefocus
t
defuncarry-luvcraft-player
sessioncritter

Set the player on critter's back, at rest and standing on nothing else.

let
player
luvcraft-session-playersession
whenplayer
player
defparameter*dismount-offsets*'
0d00d0
0.9d00d0
-0.9d00d0
0d00.9d0
0d0-0.9d0
0.9d00.9d0
-0.9d00.9d0
0.9d0-0.9d0
-0.9d0-0.9d0
"Where to try putting a rider down, nearest the animal first."
defundismount-luvcraft-player
sessioncritter

Stand the player beside critter somewhere their own box actually fits.

An animal can walk under a ledge its rider could not stand under, so getting off is a search for room rather than simply letting go. When nothing fits, the player is left where the animal is and the ordinary controller resolves it on the next step.

let
player
luvcraft-session-playersession
world
luvcraft-session-worldsession
whenplayer
loopfor
offset-xoffset-z
in*dismount-offsets*forx=forz=fory=when
body-position-clear-pplayerworldxyz
do
setf
player-xplayer
x
player-yplayer
y
player-zplayer
z
returnplayer
finally
returnplayer
defmethodluvcraft-focus-left
session

Let the animal have its own mind back, and put the rider down safely.

urge-critter
critter-ride-critterride
0d00d00d0
dismount-luvcraft-playersession
critter-ride-critterride
nil
defmethodhandle-luvcraft-focus-event
declare
ignoreridesessioncanvasevent

A rider is not editing blocks, and the mount owns the view: everything else that arrives while mounted is simply not for anyone.

t
defmethodluvcraft-focus-camera-pose
session

Sit the rider on the animal's back, looking out over its shell.

The seat is a place on the animal rather than a distance behind it, so the pose is asked again every frame and the camera stays locked to a body that is walking: what the ride feels like is the animal's own gait and its own slow turns, not a camera trailing after it. The mount's sway rides along, and the easing which brings the view here on mounting is what smooths it.

declare
ignoresession
defmethodadvance-luvcraft-focus
sessionseconds

Rein the animal, ride along with it, and get off if it is no longer there.

let
critter
critter-ride-critterride
cond
not
findcritter
critter-population-critters
luvcraft-session-critterssession
:test#'eq

The animal is gone -- it wandered out of the world, or the population forgot it. Leaving the focus puts the rider back on their own feet and hands the camera back.

t
let
intent
luvcraft-session-movement-intentsession
urge-crittercritter
movement-intent-axisintent:forward:backward
movement-intent-axisintent:right:left
seconds
ride

The seat's knobs, read every frame the rider is carried.

define-knobride-seat-lift
:label"seat lift":group:riding:quantity
:quantity:seat-offset:unit:cell
:typedouble-float:minimum-0.5:maximum2.0:step0.02
*critter-ride-seat-lift*
define-knobride-seat-offset
:label"seat setback":group:riding:quantity
:quantity:seat-offset:unit:cell
:typedouble-float:minimum-2.0:maximum1.0:step0.02
*critter-ride-seat-offset*
define-knobride-seat-pitch
:label"seat pitch":group:riding:quantity
:quantity:seat-pitch:unit:radian
:typedouble-float:minimum-1.2:maximum0.6:step0.01
*critter-ride-seat-pitch*