feat: add indexArg and hereHandler to commands
This commit is contained in:
1 parent
63b15fb146
commit
1d5768acd1
1 file changed
+163
@@ -159,3 +159,166 @@ Handlers.attack = function(game, args)
|
|||||||
return false, "there is nothing to attack there"
|
return false, "there is nothing to attack there"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Handlers.wait = function() return true, "you wait" end
|
||||||
|
Handlers.z = Handlers.wait
|
||||||
|
Handlers["."] = Handlers.wait
|
||||||
|
|
||||||
|
Handlers.pickup = function(game)
|
||||||
|
game:pickupHere()
|
||||||
|
return true, nil
|
||||||
|
end
|
||||||
|
Handlers.g = Handlers.pickup
|
||||||
|
|
||||||
|
-- Game:autoExplore already returns the exact (consumesTurn, message) shape
|
||||||
|
-- every handler here does - it just may have spent several turns getting
|
||||||
|
-- there instead of one, stopping itself the moment a hostile comes into
|
||||||
|
-- sight or the player takes damage rather than walking on regardless.
|
||||||
|
Handlers.explore = function(game)
|
||||||
|
return game:autoExplore()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Game:restUntilHealed shares the same shape and the same "may spend several
|
||||||
|
-- turns before returning" behaviour as Game:autoExplore just above.
|
||||||
|
Handlers.rest = function(game)
|
||||||
|
return game:restUntilHealed()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Game:travelTo shares that same "may spend several turns" shape too. "down"/
|
||||||
|
-- "up" are the level's own stairs (self.level.downX/Y, upX/Y) - always a
|
||||||
|
-- valid, already-walkable destination regardless of what the player has
|
||||||
|
-- explored yet, exactly like choosePlayerAction's own goal-seeking already
|
||||||
|
-- assumes; a raw x/y command is deliberately not offered since nothing in
|
||||||
|
-- this interface ever shows the player a raw coordinate to aim one at.
|
||||||
|
Handlers.travel = function(game, args)
|
||||||
|
if args[1] == "down" then return game:travelTo(game.level.downX, game.level.downY) end
|
||||||
|
if args[1] == "up" then return game:travelTo(game.level.upX, game.level.upY) end
|
||||||
|
return false, "travel where? down or up"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Every handler below that takes an inventory index shares the same shape:
|
||||||
|
-- a missing or non-numeric first arg fails without spending a turn, exactly
|
||||||
|
-- like an unknown verb, rather than crashing into the underlying Game
|
||||||
|
-- method with a nil index.
|
||||||
|
local function indexArg(args)
|
||||||
|
return tonumber(args[1])
|
||||||
|
end
|
||||||
|
|
||||||
|
Handlers.use = function(game, args)
|
||||||
|
local index = indexArg(args)
|
||||||
|
if not index then return false, "use what? give an inventory number" end
|
||||||
|
if game:useItem(index) then return true, nil end
|
||||||
|
return false, "you cannot use that"
|
||||||
|
end
|
||||||
|
Handlers.u = Handlers.use
|
||||||
|
|
||||||
|
Handlers.drop = function(game, args)
|
||||||
|
local index = indexArg(args)
|
||||||
|
if not index then return false, "drop what? give an inventory number" end
|
||||||
|
if game:dropItem(index) then return true, nil end
|
||||||
|
return false, "you have nothing there to drop"
|
||||||
|
end
|
||||||
|
|
||||||
|
Handlers.sell = function(game, args)
|
||||||
|
local index = indexArg(args)
|
||||||
|
if not index then return false, "sell what? give an inventory number" end
|
||||||
|
if game:sellItem(index) then return true, nil end
|
||||||
|
return false, "that cannot be sold here"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Trailing target number is always the argument slot right after whatever
|
||||||
|
-- an individual handler needed for itself (an inventory index, a spell/skill
|
||||||
|
-- key) - see resolveTarget above for exactly what "explicit" changes.
|
||||||
|
Handlers.throw = function(game, args)
|
||||||
|
local index = indexArg(args)
|
||||||
|
if not index then return false, "throw what? give an inventory number" end
|
||||||
|
local target, explicit = resolveTarget(game, args[2])
|
||||||
|
if not target then
|
||||||
|
if explicit then return false, "no monster in sight at that number" end
|
||||||
|
return false, "there is nothing in sight to throw at"
|
||||||
|
end
|
||||||
|
if game:throwAt(index, target) then return true, nil end
|
||||||
|
return false, "you cannot throw that"
|
||||||
|
end
|
||||||
|
|
||||||
|
Handlers.capture = function(game, args)
|
||||||
|
local index = indexArg(args)
|
||||||
|
if not index then return false, "capture with what? give an inventory number" end
|
||||||
|
local target, explicit = resolveTarget(game, args[2])
|
||||||
|
if not target then
|
||||||
|
if explicit then return false, "no monster in sight at that number" end
|
||||||
|
return false, "there is nothing in sight to capture"
|
||||||
|
end
|
||||||
|
if game:captureAt(index, target) then return true, nil end
|
||||||
|
return false, "the capture attempt fails"
|
||||||
|
end
|
||||||
|
|
||||||
|
Handlers.fire = function(game, args)
|
||||||
|
local target, explicit = resolveTarget(game, args[1])
|
||||||
|
if not target then
|
||||||
|
if explicit then return false, "no monster in sight at that number" end
|
||||||
|
return false, "there is nothing in sight to fire at"
|
||||||
|
end
|
||||||
|
if game:fireAt(target) then return true, nil end
|
||||||
|
return false, "you cannot fire right now"
|
||||||
|
end
|
||||||
|
|
||||||
|
Handlers.cast = function(game, args)
|
||||||
|
local key = args[1]
|
||||||
|
if not key then return false, "cast what spell?" end
|
||||||
|
local def = Spells.catalog[key]
|
||||||
|
if not def then return false, "you know no spell by that name" end
|
||||||
|
local target = nil
|
||||||
|
if def.targeted then
|
||||||
|
local explicit
|
||||||
|
target, explicit = resolveTarget(game, args[2])
|
||||||
|
if not target then
|
||||||
|
if explicit then return false, "no monster in sight at that number" end
|
||||||
|
return false, "there is nothing in sight to cast that at"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if game:castSpell(key, target) then return true, nil end
|
||||||
|
return false, "the spell fails"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- multishot's two targets are named together or not at all: giving only one
|
||||||
|
-- explicit number is ambiguous about which of the (up to) two shots it picks
|
||||||
|
-- out, so that case falls back to the same auto-pick-both-nearest behaviour
|
||||||
|
-- as giving none, rather than guessing which slot the player meant.
|
||||||
|
Handlers.useskill = function(game, args)
|
||||||
|
local key = resolveSkillKey(args[1])
|
||||||
|
if not key then return false, "use which skill?" end
|
||||||
|
local success
|
||||||
|
if key == "cleave" then
|
||||||
|
local target, explicit = resolveTarget(game, args[2])
|
||||||
|
if not target and explicit then return false, "no monster in sight at that number" end
|
||||||
|
success = game:useSkill(key, target)
|
||||||
|
elseif key == "multishot" then
|
||||||
|
if args[2] and args[3] then
|
||||||
|
local list = visibleHostilesInOrder(game)
|
||||||
|
local t1, t2 = list[tonumber(args[2]) or -1], list[tonumber(args[3]) or -1]
|
||||||
|
if not t1 or not t2 then return false, "no monster in sight at that number" end
|
||||||
|
success = game:useSkill(key, t1, t2)
|
||||||
|
else
|
||||||
|
local targets = nearestHostiles(game, 2)
|
||||||
|
success = game:useSkill(key, targets[1], targets[2])
|
||||||
|
end
|
||||||
|
else
|
||||||
|
success = game:useSkill(key)
|
||||||
|
end
|
||||||
|
if success then return true, nil end
|
||||||
|
return false, "that skill fails"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Zero-argument actions that always resolve against whatever stands on the
|
||||||
|
-- player's own tile (a chest, a corpse, a captive, a node, a stairwell...),
|
||||||
|
-- the same way every one of these Game methods already looks itself up by
|
||||||
|
-- self.player.x/y rather than taking a target. `nothingMessage` only ever
|
||||||
|
-- surfaces when the underlying method itself failed silently (no log line
|
||||||
|
-- of its own) - most branches already explain themselves through game.log.
|
||||||
|
local function hereHandler(methodName, nothingMessage)
|
||||||
|
return function(game)
|
||||||
|
if game[methodName](game) then return true, nil end
|
||||||
|
return false, nothingMessage
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Reference in new issue
Block a user