feat: add groundIndexHere and Commands.apply to commands
This commit is contained in:
1 parent
4e4d22cf2e
commit
6f9d811c81
1 file changed
+146
@@ -477,3 +477,149 @@ Handlers.enchant = function(game, args)
|
||||
return false, "that cannot be enchanted"
|
||||
end
|
||||
|
||||
Handlers.disenchant = function(game, args)
|
||||
local target = targetArg(args[1])
|
||||
if not target then return false, "disenchant what? weapon, armor or an item number" end
|
||||
if game:disenchantItem(target) then return true, nil end
|
||||
return false, "that cannot be disenchanted"
|
||||
end
|
||||
|
||||
Handlers.repair = function(game, args)
|
||||
local slot = args[1]
|
||||
if slot ~= "weapon" and slot ~= "armor" and slot ~= "bow" then
|
||||
return false, "repair what? weapon, armor or bow"
|
||||
end
|
||||
if game:repairEquipped(slot) then return true, nil end
|
||||
return false, nil
|
||||
end
|
||||
|
||||
-- Steals whichever warded ware sits underfoot, the same tile Game:pickupHere
|
||||
-- already resolves against - unlike Game:stealFromShop's own raw floorItems
|
||||
-- index, a typed command can only ever mean "the ware I am standing on".
|
||||
local function groundIndexHere(game)
|
||||
for i, ground in ipairs(game.level.floorItems) do
|
||||
if ground.x == game.player.x and ground.y == game.player.y then return i, ground end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
Handlers.steal = function(game)
|
||||
local index = groundIndexHere(game)
|
||||
if index and game:stealFromShop(index) then return true, nil end
|
||||
return false, "there is nothing here worth stealing"
|
||||
end
|
||||
|
||||
Handlers.dismiss = function(game)
|
||||
if game:dismissHireling() then return true, nil end
|
||||
return false, nil
|
||||
end
|
||||
|
||||
Handlers.learn = function(game, args)
|
||||
local key = resolveSkillKey(args[1])
|
||||
if not key then return false, "learn which skill?" end
|
||||
game:learnSkill(key)
|
||||
return false, nil
|
||||
end
|
||||
|
||||
-- Duplicates Game:brewAt's own precondition checks (cauldron underfoot, two
|
||||
-- distinct herb items) before ever calling it, the same shape as disarm
|
||||
-- above and for the same reason: past those preconditions, brewing always
|
||||
-- spends both herbs, whether the pairing brews a potion or curdles into gas
|
||||
-- (see Alchemy.brew), so this handler must not read a curdle's own `false`
|
||||
-- as "nothing happened" and hand the player a free turn back.
|
||||
Handlers.brew = function(game, args)
|
||||
local a, b = tonumber(args[1]), tonumber(args[2])
|
||||
if not a or not b then return false, "brew which two herbs? give two inventory numbers" end
|
||||
if not game.level:cauldronAt(game.player.x, game.player.y) then
|
||||
return false, "there is no cauldron here"
|
||||
end
|
||||
if a == b then return false, "brew two different herbs, not the same one twice" end
|
||||
local herbA, herbB = game.player.inventory[a], game.player.inventory[b]
|
||||
if not herbA or not herbB or herbA.kind ~= "herb" or herbB.kind ~= "herb" then
|
||||
return false, "you need two herbs to brew"
|
||||
end
|
||||
game:brewAt(a, b)
|
||||
return true, nil
|
||||
end
|
||||
|
||||
-- Purely informational commands. Every one of these returns false (spends no
|
||||
-- turn) and carries its whole answer in the message, which is the one place
|
||||
-- a caller should print something the game log itself would never contain.
|
||||
Handlers.inventory = function(game)
|
||||
if #game.player.inventory == 0 then return false, "you are carrying nothing" end
|
||||
local lines = {}
|
||||
for i, item in ipairs(game.player.inventory) do
|
||||
lines[#lines + 1] = string.format(" %d) %s", i, Identify.label(game.identify, item))
|
||||
end
|
||||
return false, table.concat(lines, "\n")
|
||||
end
|
||||
Handlers.i = Handlers.inventory
|
||||
|
||||
Handlers.status = function(game)
|
||||
local p = game.player
|
||||
return false, string.format(
|
||||
"hp %d/%d mana %d/%d gold %d essence %d level %d xp %d/%d depth %d turn %d",
|
||||
p.hp, p.maxHp, p.mana or 0, p.maxMana or 0, p.gold, p.essence,
|
||||
p.level, p.xp, p.xpNext, game.depth, game.turn)
|
||||
end
|
||||
|
||||
Handlers.look = function(game)
|
||||
local targets = visibleHostilesInOrder(game)
|
||||
if #targets == 0 then return false, "you see no threats nearby" end
|
||||
local names = {}
|
||||
for i, entity in ipairs(targets) do
|
||||
names[#names + 1] = string.format("%d) %s", i, entity.name)
|
||||
end
|
||||
return false, "in sight: " .. table.concat(names, ", ")
|
||||
end
|
||||
Handlers.l = Handlers.look
|
||||
|
||||
-- Detail views (examine.lua): `examine <n>` inspects inventory item n, the
|
||||
-- same index use/drop/sell already key off; `examine monster <n>` inspects
|
||||
-- the nth entry of the very list Handlers.look just numbered. Both branches
|
||||
-- are free, like every other informational command here.
|
||||
Handlers.examine = function(game, args)
|
||||
if args[1] == "monster" then
|
||||
local index = tonumber(args[2])
|
||||
if not index then return false, "examine which monster? give the number look showed you" end
|
||||
local target = visibleHostilesInOrder(game)[index]
|
||||
if not target then return false, "no monster in sight at that number" end
|
||||
return false, Examine.monster(game.player, target)
|
||||
end
|
||||
local index = indexArg(args)
|
||||
if not index then return false, "examine what? give an inventory number, or 'monster <n>'" end
|
||||
local item = game.player.inventory[index]
|
||||
if not item then return false, "you are not carrying anything at that number" end
|
||||
return false, Examine.item(game.identify, item)
|
||||
end
|
||||
Handlers.x = Handlers.examine
|
||||
|
||||
Handlers.help = function()
|
||||
return false, "commands: north/south/east/west/ne/nw/se/sw (or n/s/e/w/...), attack <dir>, " ..
|
||||
"wait, pickup, explore, rest, travel down/up, inventory, use <n>, drop <n>, sell <n>, throw <n> [target], " ..
|
||||
"fire [target], capture <n> [target], cast <spell> [target], useskill <skill> [target], " ..
|
||||
"open, pray, quest, appease <faction>, butcher, raise, " ..
|
||||
"scavenge, harvest, ransom, sellcaptive, interrogate, dig <dir>, disarm <dir>, " ..
|
||||
"descend, ascend, enterrift, exitrift, horde, " ..
|
||||
"steal, dismiss, learn <skill>, forge <element>, merge <a> <b>, brew <a> <b>, " ..
|
||||
"socket <target> <gem>, socketrune <target> <rune>, temper <target>, " ..
|
||||
"enchant <target> <affix>, disenchant <target>, repair <slot>, " ..
|
||||
"examine <n>, examine monster <n>, look, status, help " ..
|
||||
"([target] is the number look/examine gives a monster; omit it to auto-target the nearest one)"
|
||||
end
|
||||
|
||||
-- Parses `text` and dispatches it against `game`. Returns (consumesTurn,
|
||||
-- message): Game:manualStep spends the player's turn iff the first value is
|
||||
-- true, and either surfaces `message` itself (a failure reason, or an
|
||||
-- informational answer) or leaves the game log to speak for a successful
|
||||
-- action, exactly the way every Game:<action> method already logs its own
|
||||
-- outcome.
|
||||
function Commands.apply(game, text)
|
||||
local parsed = Commands.parse(text)
|
||||
if not parsed then return false, "say something" end
|
||||
local handler = Handlers[parsed.verb]
|
||||
if not handler then return false, "unknown command: " .. parsed.verb end
|
||||
return handler(game, parsed.args)
|
||||
end
|
||||
|
||||
return Commands
|
||||
Reference in new issue
Block a user