I wasn’t sure which of Eric’s examples you meant, so I adapted the code for PushTravel actions to accomplish what felt like the desired behavior: riding a bicycle somewhere should result in both the player and the bicycle ending up in the destination, much like pushing an object there would.
DefineTAction(Ride);
DefineTAction(RideDir);
DefineIAction(RideVague);
VerbRule(Ride)
('ride' | 'mount') singleDobj
: RideAction
verbPhrase = 'ride/riding (what)'
;
VerbRule(RideDir)
'ride' singleDobj ('to' ('the'|) |) singleDir
| 'ride' singleDir ('on' ('the'|) |) singleDobj
: RideDirAction
verbPhrase = ('ride/riding (what) ' + dirMatch.dir.name)
;
VerbRule(RideVague)
'ride' singleDir
: RideVagueAction
verbPhrase = ('ride/riding ' + dirMatch.dir.name)
;
/*
RideTravel is not matched by any grammar rules.
RideDir and RideVague remap here to carry out travel.
*/
DefineAction(RideTravel, PushTravelAction)
performTravel()
{
local conn;
conn = gActor.location.getTravelConnector(getDirection(), gActor);
nestedAction(TravelVia, conn);
}
setDirection(dir) { _dir = dir; }
getDirection() { return _dir; }
_dir = nil
;
modify RideDirAction
execAction()
{
// store direction for later use
RideTravelAction.setDirection(gAction.dirMatch.dir);
inherited();
}
;
modify RideVagueAction
execAction()
{
// store direction for later use
RideTravelAction.setDirection(gAction.dirMatch.dir);
// player did not specify what to ride; pick something
local _ride = new Vector(5);
forEachInstance(Rideable, {obj: gActor.getOutermostRoom() == obj.getOutermostRoom()
? _ride.append(obj)
: nil});
_ride = _ride.sort(true, {a, b: a.rideScore - b.rideScore});
if (!_ride.length())
reportFailure(¬hingToRideMsg);
else
replaceAction(RideTravel, _ride[1]);
}
;
modify Thing
dobjFor(Ride)
{
preCond = [touchObj]
action() { reportFailure(&cannotRideMsg); }
}
dobjFor(RideDir)
{
preCond = [touchObj]
action() { reportFailure(&cannotRideMsg); }
}
;
class Rideable: TravelPushable
cannotTakeMsg = &cannotTakeRideableMsg
cannotMoveMsg = &cannotMoveRideableMsg
cannotPutMsg = &cannotPutRideableMsg
// show object in the room contents
isListed = true
// preference score used when player does not specify what to ride
rideScore = 100
dobjFor(Ride)
{
action()
{
mainReport(&okayRideLocalMsg, self);
}
}
dobjFor(RideDir)
{
action()
{
replaceAction(RideTravel, gDobj);
}
}
describeMovePushable(traveler, connector)
{
if (gActor.isPlayerChar)
mainReport(&okayRideTravelMsg, self);
}
pushTravelerClass = RideTraveler
;
class RideTraveler: PushTraveler
travelerTravelWithin(actor, dest)
{
reportFailure(&cannotRideObjectNestedMsg, obj_);
exit;
}
;
class RideTravelBarrier: PushTravelBarrier
explainTravelBarrier(traveler)
{
reportFailure(&cannotRideObjectThatWayMsg, traveler.obj_);
}
;
modify playerActionMessages
okayRideLocalMsg(obj)
{
return '<.p>{You/he} ride around the area on ' + obj.theNameObj + '. ';
}
okayRideTravelMsg(obj)
{
return '<.p>{You/he} ride ' + obj.theNameObj + ' into the area. ';
}
nothingToRideMsg = 'There is nothing here to ride. '
cannotRideMsg = '{That dobj/he} {is} not something you can ride. '
cannotTakeRideableMsg = '{You/he} {can\'t} take {that/him dobj}, but
{it actor/he} might {be|have been} able to ride it somewhere. '
cannotMoveRideableMsg = 'It wouldn’t {|have} accomplish{|ed}
anything to move {the dobj/him} around aimlessly, but {it actor/he}
might {be|have been} able to ride {it dobj/him} in a specific
direction. '
cannotPutRideableMsg = '{You/he} {can\'t} put {that/him dobj} anywhere,
but {it actor/he} might {be|have been} able to ride it somewhere. '
cannotRideObjectThatWayMsg(obj)
{
gMessageParams(obj);
return '{You/he} {can\'t} go that way riding {the obj/him}. ';
}
cannotRideObjectNestedMsg(obj)
{
gMessageParams(obj);
return '{You/he} {can\'t} ride {the obj/him} there. ';
}
;
tricycle: Rideable 'tricycle' 'TRICYCLE' @storage
"You had {a dobj/him} just like it as a kid. "
;
This is slightly non-responsive since your specific question isn’t addressed - how to stop the player from traveling in a direction unless they are on the bicycle. To do that you can set a global variable in the performTravel() method of the RideTravel action defined above, then test for that in canActorTravel() method of the room connector in question.