forked from MTSR/techage_modpack
361 lines
10 KiB
Lua
361 lines
10 KiB
Lua
--[[
|
|
|
|
Signs Bot
|
|
=========
|
|
|
|
Copyright (C) 2019-2024 Joachim Stolberg
|
|
|
|
GPL v3
|
|
See LICENSE.txt for more information
|
|
|
|
Bot move commands
|
|
|
|
]]--
|
|
|
|
-- Load support for I18n.
|
|
local S = signs_bot.S
|
|
|
|
local lib = signs_bot.lib
|
|
local get_node_lvm = tubelib2.get_node_lvm
|
|
|
|
|
|
local function node_and_pos(pos)
|
|
return get_node_lvm(pos), pos
|
|
end
|
|
|
|
-- Positions to check:
|
|
-- 5 6
|
|
-- [R]1
|
|
-- 3 2
|
|
-- 4
|
|
function signs_bot.move_robot(mem)
|
|
local param2 = mem.robot_param2
|
|
local pos = mem.robot_pos
|
|
local node1, pos1 = node_and_pos(lib.next_pos(pos, param2))
|
|
local node2, pos2 = node_and_pos({x=pos1.x, y=pos1.y-1, z=pos1.z})
|
|
local node3, pos3 = node_and_pos({x=pos.x, y=pos.y-1, z=pos.z})
|
|
|
|
--
|
|
-- One step forward (pos1)
|
|
--
|
|
if lib.check_pos(pos1, node1, node2, param2) or
|
|
lib.check_pos(pos1, node1, node3, param2) then
|
|
if node3.name == "signs_bot:robot_foot" then
|
|
minetest.swap_node(pos3, mem.stored_node or {name = "air"})
|
|
minetest.remove_node(pos)
|
|
elseif node3.name == "signs_bot:robot_leg" then
|
|
local node4, pos4 = node_and_pos({x=pos.x, y=pos.y-2, z=pos.z})
|
|
if node4.name == "signs_bot:robot_foot" then
|
|
minetest.swap_node(pos4, mem.stored_node or {name = "air"})
|
|
end
|
|
minetest.swap_node(pos3, {name = "air"})
|
|
minetest.remove_node(pos)
|
|
else
|
|
minetest.swap_node(pos, mem.stored_node or {name = "air"})
|
|
end
|
|
mem.stored_node = node1
|
|
minetest.set_node(pos1, {name="signs_bot:robot", param2=param2})
|
|
minetest.sound_play('signs_bot_step', {pos = pos1})
|
|
return pos1
|
|
end
|
|
|
|
--
|
|
-- One step up (pos5)
|
|
--
|
|
local node6, pos6 = node_and_pos({x=pos1.x, y=pos1.y+1, z=pos1.z})
|
|
if lib.check_pos(pos6, node6, node1, param2) then
|
|
local node5, pos5 = node_and_pos({x=pos.x, y=pos.y+1, z=pos.z})
|
|
if node5.name == "air" then
|
|
if node3.name == "signs_bot:robot_leg" then
|
|
return nil
|
|
elseif node3.name == "signs_bot:robot_foot" then
|
|
minetest.swap_node(pos3, {name="signs_bot:robot_leg"})
|
|
else
|
|
minetest.swap_node(pos, {name="signs_bot:robot_foot"})
|
|
end
|
|
minetest.set_node(pos5, {name="signs_bot:robot", param2=param2})
|
|
minetest.sound_play('signs_bot_step', {pos = pos5})
|
|
return pos5
|
|
end
|
|
end
|
|
|
|
--
|
|
-- One step down I (pos3)
|
|
--
|
|
local node4, pos4 = node_and_pos({x=pos.x, y=pos.y-2, z=pos.z})
|
|
if lib.check_pos(pos3, node3, node4, param2) then --
|
|
minetest.remove_node(pos)
|
|
minetest.set_node(pos3, {name="signs_bot:robot", param2=param2})
|
|
minetest.sound_play('signs_bot_step', {pos = pos3})
|
|
mem.stored_node = node3
|
|
return pos3
|
|
end
|
|
--
|
|
-- One step down II (pos3)
|
|
--
|
|
if node3.name == "signs_bot:robot_foot" or node3.name == "signs_bot:robot_leg" then
|
|
minetest.remove_node(pos)
|
|
minetest.set_node(pos3, {name="signs_bot:robot", param2=param2})
|
|
minetest.sound_play('signs_bot_step', {pos = pos3})
|
|
return pos3
|
|
end
|
|
end
|
|
|
|
|
|
local function backward_robot(mem)
|
|
local param2 = mem.robot_param2
|
|
local pos = mem.robot_pos
|
|
local node1, pos1 = node_and_pos(lib.next_pos(pos, (param2 + 2) % 4))
|
|
local node2, pos2 = node_and_pos({x=pos1.x, y=pos1.y-1, z=pos1.z})
|
|
local node3, pos3 = node_and_pos({x=pos.x, y=pos.y-1, z=pos.z})
|
|
local node4, pos4 = node_and_pos({x=pos.x, y=pos.y-2, z=pos.z})
|
|
local new_pos = nil
|
|
|
|
if lib.check_pos(pos1, node1, node2, param2) then
|
|
if node3.name == "signs_bot:robot_foot" or node3.name == "signs_bot:robot_leg" then
|
|
minetest.remove_node(pos3)
|
|
if node4.name == "signs_bot:robot_foot" then
|
|
minetest.remove_node(pos4)
|
|
end
|
|
end
|
|
minetest.swap_node(pos, mem.stored_node or {name = "air"})
|
|
minetest.set_node(pos1, {name="signs_bot:robot", param2=param2})
|
|
minetest.sound_play('signs_bot_step', {pos = pos1})
|
|
mem.stored_node = node1
|
|
return pos1
|
|
end
|
|
end
|
|
|
|
signs_bot.register_botcommand("backward", {
|
|
mod = "move",
|
|
params = "",
|
|
num_param = 0,
|
|
description = S("Move the robot one step back"),
|
|
cmnd = function(base_pos, mem)
|
|
local new_pos = backward_robot(mem)
|
|
if new_pos then -- not blocked?
|
|
mem.robot_pos = new_pos
|
|
end
|
|
return signs_bot.DONE
|
|
end,
|
|
})
|
|
|
|
local function turn_robot(pos, param2, dir)
|
|
if dir == "R" then
|
|
param2 = (param2 + 1) % 4
|
|
else
|
|
param2 = (param2 + 3) % 4
|
|
end
|
|
minetest.swap_node(pos, {name="signs_bot:robot", param2=param2})
|
|
minetest.sound_play('signs_bot_step', {pos = pos, gain = 0.6})
|
|
return param2
|
|
end
|
|
|
|
signs_bot.register_botcommand("turn_left", {
|
|
mod = "move",
|
|
params = "",
|
|
num_param = 0,
|
|
description = S("Turn the robot to the left"),
|
|
cmnd = function(base_pos, mem)
|
|
mem.robot_param2 = turn_robot(mem.robot_pos, mem.robot_param2, "L")
|
|
return signs_bot.DONE
|
|
end,
|
|
})
|
|
|
|
signs_bot.register_botcommand("turn_right", {
|
|
mod = "move",
|
|
params = "",
|
|
num_param = 0,
|
|
description = S("Turn the robot to the right"),
|
|
cmnd = function(base_pos, mem)
|
|
mem.robot_param2 = turn_robot(mem.robot_pos, mem.robot_param2, "R")
|
|
return signs_bot.DONE
|
|
end,
|
|
})
|
|
|
|
signs_bot.register_botcommand("turn_around", {
|
|
mod = "move",
|
|
params = "",
|
|
num_param = 0,
|
|
description = S("Turn the robot around"),
|
|
cmnd = function(base_pos, mem)
|
|
mem.robot_param2 = turn_robot(mem.robot_pos, mem.robot_param2, "R")
|
|
mem.robot_param2 = turn_robot(mem.robot_pos, mem.robot_param2, "R")
|
|
return signs_bot.DONE
|
|
end,
|
|
})
|
|
|
|
|
|
-- Positions to check:
|
|
-- 1
|
|
-- [R]
|
|
-- 2
|
|
local function robot_up(pos, param2)
|
|
local node1, pos1 = node_and_pos({x=pos.x, y=pos.y+1, z=pos.z})
|
|
local node2, pos2 = node_and_pos({x=pos.x, y=pos.y-1, z=pos.z})
|
|
if lib.check_pos(pos1, node1, node2, param2) then
|
|
if node2.name == "signs_bot:robot_leg" then
|
|
return nil
|
|
elseif node2.name == "signs_bot:robot_foot" then
|
|
minetest.swap_node(pos, {name="signs_bot:robot_leg"})
|
|
else
|
|
minetest.swap_node(pos, {name="signs_bot:robot_foot"})
|
|
end
|
|
minetest.set_node(pos1, {name="signs_bot:robot", param2=param2})
|
|
minetest.sound_play('signs_bot_step', {pos = pos1})
|
|
return pos1
|
|
end
|
|
return nil
|
|
end
|
|
|
|
signs_bot.register_botcommand("move_up", {
|
|
mod = "move",
|
|
params = "",
|
|
num_param = 0,
|
|
description = S("Move the robot upwards"),
|
|
cmnd = function(base_pos, mem)
|
|
local new_pos = robot_up(mem.robot_pos, mem.robot_param2)
|
|
if new_pos then -- not blocked?
|
|
mem.robot_pos = new_pos
|
|
end
|
|
return signs_bot.DONE
|
|
end,
|
|
})
|
|
|
|
-- Positions to check:
|
|
-- [R]
|
|
-- 1
|
|
-- 2
|
|
-- 3
|
|
local function robot_down(pos, param2)
|
|
local node1, pos1 = node_and_pos({x=pos.x, y=pos.y-1, z=pos.z})
|
|
local node2, pos2 = node_and_pos({x=pos.x, y=pos.y-2, z=pos.z})
|
|
local node3, pos3 = node_and_pos({x=pos.x, y=pos.y-3, z=pos.z})
|
|
if lib.check_pos(pos1, node1, node2, param2)
|
|
or (node1.name == "air" and lib.check_pos(pos2, node2, node3, param2))
|
|
or (node1.name == "signs_bot:robot_leg" or node1.name == "signs_bot:robot_foot") then
|
|
minetest.remove_node(pos)
|
|
minetest.set_node(pos1, {name="signs_bot:robot", param2=param2})
|
|
minetest.sound_play('signs_bot_step', {pos = pos1})
|
|
return pos1
|
|
end
|
|
return nil
|
|
end
|
|
|
|
signs_bot.register_botcommand("move_down", {
|
|
mod = "move",
|
|
params = "",
|
|
num_param = 0,
|
|
description = S("Move the robot down"),
|
|
cmnd = function(base_pos, mem)
|
|
local new_pos = robot_down(mem.robot_pos, mem.robot_param2)
|
|
if new_pos then -- not blocked?
|
|
mem.robot_pos = new_pos
|
|
end
|
|
return signs_bot.DONE
|
|
end,
|
|
})
|
|
|
|
signs_bot.register_botcommand("fall_down", {
|
|
mod = "move",
|
|
params = "",
|
|
num_param = 0,
|
|
description = S("Fall into a hole/chasm (up to 10 blocks)"),
|
|
cmnd = function(base_pos, mem)
|
|
if not mem.bot_falling then
|
|
--Run a while loop that checks the 10 nodes below bot for a node with the walkable property, breaking the loop once it finds a walkable node.
|
|
local fallcounter = 0
|
|
local fallnode = {walkable = false}
|
|
while fallcounter <= 9 and fallnode.walkable == false do
|
|
fallcounter = fallcounter + 1
|
|
--Pulls the node name from the next position, then assigns the node definintion to the fallnode variable.
|
|
fallnode = minetest.get_node_or_nil({x=mem.robot_pos.x, y=mem.robot_pos.y-fallcounter, z=mem.robot_pos.z})
|
|
fallnode = minetest.registered_nodes[fallnode.name]
|
|
end
|
|
--If the first nine nodes below the bot are not walkable, then it should assign the definintion to the 10th node. If it too is not walkable, then a "Too Deep" error is returned.
|
|
if fallnode.walkable == false then
|
|
return signs_bot.ERROR, "Too deep"
|
|
end
|
|
--Designates the node above the walkable node as the new location for the bot.
|
|
local pos3 = {x=mem.robot_pos.x, y=mem.robot_pos.y-fallcounter+1, z=mem.robot_pos.z}
|
|
--Turns the bot into a falling node.
|
|
local sts, _ = minetest.spawn_falling_node(mem.robot_pos)
|
|
--Stores the data for the node the bot will land in and replaces it with air. This way if the node the bot lands in is occupied by an unwalkable node, such as a rail or sign,
|
|
--it will be repalced when the bot moves.
|
|
mem.stored_node = get_node_lvm(pos3)
|
|
minetest.swap_node(pos3, {name="air"})
|
|
if sts then
|
|
mem.bot_falling = 2
|
|
mem.robot_pos = {x=pos3.x, y=pos3.y, z=pos3.z}
|
|
return signs_bot.BUSY
|
|
end
|
|
else
|
|
mem.bot_falling = mem.bot_falling - 1
|
|
if mem.bot_falling <= 0 then
|
|
mem.bot_falling = nil
|
|
return signs_bot.DONE
|
|
end
|
|
return signs_bot.BUSY
|
|
end
|
|
end,
|
|
})
|
|
|
|
signs_bot.register_botcommand("pause", {
|
|
mod = "move",
|
|
params = "<sec>",
|
|
num_param = 1,
|
|
description = S("Stop the robot for <sec> seconds\n(1..9999)"),
|
|
check = function(sec)
|
|
sec = tonumber(sec) or 1
|
|
return sec and sec > 0 and sec < 10000
|
|
end,
|
|
cmnd = function(base_pos, mem, sec)
|
|
if not mem.steps then
|
|
mem.steps = tonumber(sec) or 1
|
|
end
|
|
mem.steps = mem.steps - 1
|
|
if mem.steps == 0 then
|
|
mem.steps = nil
|
|
return signs_bot.DONE
|
|
end
|
|
if mem.capa then
|
|
mem.capa = mem.capa + 1
|
|
end
|
|
return signs_bot.BUSY
|
|
end,
|
|
})
|
|
|
|
signs_bot.register_botcommand("stop", {
|
|
mod = "move",
|
|
params = "",
|
|
num_param = 0,
|
|
description = S("Stop the robot."),
|
|
cmnd = function(base_pos, mem, slot)
|
|
local param2 = mem.robot_param2
|
|
local pos = mem.robot_pos
|
|
local node1, pos1 = node_and_pos(lib.next_pos(pos, param2))
|
|
if mem.capa then
|
|
mem.capa = mem.capa + 2
|
|
end
|
|
if node1 and node1.name ~= "signs_bot:sign_stop" then
|
|
return signs_bot.DONE
|
|
end
|
|
return signs_bot.BUSY
|
|
end,
|
|
})
|
|
|
|
signs_bot.register_botcommand("turn_off", {
|
|
mod = "move",
|
|
params = "",
|
|
num_param = 0,
|
|
description = S("Turn the robot off\n"..
|
|
"and put it back in the box."),
|
|
cmnd = function(base_pos, mem)
|
|
signs_bot.stop_robot(base_pos, mem)
|
|
return signs_bot.TURN_OFF
|
|
end,
|
|
})
|
|
|
|
|
|
|