large_slugs/behavior.lua
Jude Melton-Houghton 3828c22946 Initial commit
2021-09-24 10:30:37 -04:00

126 lines
4.0 KiB
Lua

local MOVE_INTERVAL =
tonumber(minetest.settings:get("large_slugs_move_interval")) or 5
local MOVE_CHANCE =
tonumber(minetest.settings:get("large_slugs_move_chance")) or 5
local BIRTH_INTERVAL =
tonumber(minetest.settings:get("large_slugs_birth_interval")) or 10
local BIRTH_CHANCE =
tonumber(minetest.settings:get("large_slugs_birth_chance")) or 10
local BIRTH_SPACE =
tonumber(minetest.settings:get("large_slugs_birth_space")) or 11
local WALLMOUNT_TO_PERP_WALLMOUNTS = {}
WALLMOUNT_TO_PERP_WALLMOUNTS[0] = {4, 2, 5, 3}
WALLMOUNT_TO_PERP_WALLMOUNTS[2] = {4, 0, 5, 1}
WALLMOUNT_TO_PERP_WALLMOUNTS[4] = {2, 0, 3, 1}
WALLMOUNT_TO_PERP_WALLMOUNTS[1] = WALLMOUNT_TO_PERP_WALLMOUNTS[0]
WALLMOUNT_TO_PERP_WALLMOUNTS[3] = WALLMOUNT_TO_PERP_WALLMOUNTS[2]
WALLMOUNT_TO_PERP_WALLMOUNTS[5] = WALLMOUNT_TO_PERP_WALLMOUNTS[4]
local WALLMOUNT_TO_OPP_WALLMOUNT = {
[0] = 1, [1] = 0, [2] = 3, [3] = 2, [4] = 5, [5] = 4,
}
local function get_move_options(pos, node, include_here)
local ground_nodes = large_slugs.registered_slugs[node.name].ground
local wallmount = node.param2 % 6
local dir = minetest.wallmounted_to_dir(wallmount)
local rotate_opts = include_here and {}
local shift_opts = {}
local rotate_shift_opts = {}
local perp_wallmounts = WALLMOUNT_TO_PERP_WALLMOUNTS[wallmount]
for _, perp_wallmount in ipairs(perp_wallmounts) do
local perp_dir = minetest.wallmounted_to_dir(perp_wallmount)
local check_pos = vector.add(pos, perp_dir)
local check_node = minetest.get_node(check_pos)
if include_here and ground_nodes[check_node.name] then
rotate_opts[#rotate_opts + 1] = perp_wallmount
elseif check_node.name == "air" then
local shift_pos = check_pos
check_pos = vector.add(check_pos, dir)
check_node = minetest.get_node(check_pos)
if ground_nodes[check_node.name] then
shift_opts[#shift_opts + 1] = shift_pos
elseif check_node.name == "air" then
rotate_shift_opts[#rotate_shift_opts + 1] = {
WALLMOUNT_TO_OPP_WALLMOUNT[
perp_wallmount],
check_pos,
}
end
end
end
return rotate_opts, shift_opts, rotate_shift_opts
end
local function move_slug(pos, node)
local rotate_opts, shift_opts, rotate_shift_opts =
get_move_options(pos, node, true)
local n_rotate_opts = #rotate_opts
local n_shift_opts = #shift_opts
local n_rotate_shift_opts = #rotate_shift_opts
local n_opts = n_rotate_opts + n_shift_opts + n_rotate_shift_opts
if n_opts < 1 then return end
local choice = math.random(n_opts)
if choice <= n_rotate_opts then
local chosen_wallmount = rotate_opts[choice]
node.param2 = node.param2 - node.param2 % 8 + chosen_wallmount
minetest.swap_node(pos, node)
elseif choice <= n_rotate_opts + n_shift_opts then
local chosen_pos = shift_opts[choice - n_rotate_opts]
minetest.remove_node(pos)
minetest.set_node(chosen_pos, node)
else
local chosen =
rotate_shift_opts[choice - n_rotate_opts - n_shift_opts]
minetest.remove_node(pos)
node.param2 = node.param2 - node.param2 % 8 + chosen[1]
minetest.set_node(chosen[2], node)
end
end
local function birth_slug(pos, node)
if minetest.find_node_near(pos, BIRTH_SPACE, node.name) then return end
local _rotate_opts, shift_opts, rotate_shift_opts =
get_move_options(pos, node, false)
local n_shift_opts = #shift_opts
local n_rotate_shift_opts = #rotate_shift_opts
local n_opts = n_shift_opts + n_rotate_shift_opts
if n_opts < 1 then return end
local choice = math.random(n_opts)
if choice <= n_shift_opts then
local chosen_pos = shift_opts[choice]
minetest.set_node(chosen_pos, node)
else
local chosen = rotate_shift_opts[choice - n_shift_opts]
node.param2 = node.param2 - node.param2 % 8 + chosen[1]
minetest.set_node(chosen[2], node)
end
end
minetest.register_abm({
label = "Slugs moving",
nodenames = "group:large_slug",
interval = MOVE_INTERVAL,
chance = MOVE_CHANCE,
catch_up = false,
action = move_slug,
})
minetest.register_abm({
label = "Slugs birthing",
nodenames = "group:large_slug",
interval = BIRTH_INTERVAL,
chance = BIRTH_CHANCE,
catch_up = false,
action = birth_slug,
})