nc_cats-cd2025/node.lua
Aaron Suen 71885b5d47 Fix cat spawning probability effects
Cats should have a pretty significant impact on
the probability distribution of the color of cats
hatching nearby.
2022-10-07 14:59:07 -04:00

216 lines
6.0 KiB
Lua

-- LUALOCALS < ---------------------------------------------------------
local ipairs, math, minetest, nodecore, type, vector
= ipairs, math, minetest, nodecore, type, vector
local math_random
= math.random
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local myapi = _G[modname]
local function faceallow(pos, param2)
local face = nodecore.facedirs[param2]
local fp = vector.add(pos, face.f)
return nodecore.sunlight_propagates(fp)
end
local function checkfacedir(pos)
local node = minetest.get_node(pos)
if faceallow(pos, node.param2) then return end
local t = {}
for i = 0, 23 do
if faceallow(pos, i) then t[#t + 1] = i end
end
if #t < 1 then return end
node.param2 = t[math_random(1, #t)]
minetest.swap_node(pos, node)
return node
end
local function getcatid(node)
local catid = minetest.get_item_group(node.name, modname .. '_cat')
return catid > 0 and catid
end
local function longcatmatch(nodea, nodeb)
return getcatid(nodea) == getcatid(nodeb)
and vector.equals(
nodecore.facedirs[nodea.param2].f,
nodecore.facedirs[nodeb.param2].f)
end
myapi.longcatmatch = longcatmatch
local function findtail(pos, node, ishead)
local fd = nodecore.facedirs[node.param2]
local back = vector.add(pos, fd.k)
local bnode = minetest.get_node(back)
local istail = not longcatmatch(node, bnode)
local catname = not istail and findtail(back, bnode, false)
local part = ishead and istail and ":cat_"
or ishead and ":longcat_front_"
or istail and ":longcat_back_"
or ":longcat_mid_"
node.name = modname .. part .. getcatid(node)
if not istail then node.param2 = bnode.param2 end
local saved = minetest.get_meta(pos):to_table()
saved.fields.realname = saved.fields.realname or saved.fields.description
saved.fields.description = istail and saved.fields.realname or catname
nodecore.set_node_check(pos, node)
minetest.get_meta(pos):from_table(saved)
return saved.fields.description
end
local function findhead(pos, node)
local fd = nodecore.facedirs[node.param2]
local fore = vector.add(pos, fd.f)
local fnode = minetest.get_node(fore)
if longcatmatch(node, fnode) then
return findhead(fore, fnode)
end
findtail(pos, node, true)
end
local function checksnake(pos, node)
node = node or minetest.get_node(pos)
if not getcatid(node) then return end
return findhead(pos, node)
end
local function reg(id, base, spot)
myapi.maxcatid = ((not myapi.maxcatid) or (id > myapi.maxcatid)) and id or myapi.maxcatid
local txr = "nc_cats_base.png^[multiply:" .. base .. ":255"
if base ~= spot then
txr = txr .. "^(nc_cats_spots.png^[multiply:" .. spot .. ":255)"
end
local basedef = {
description = "Cat",
tiles = {
txr .. "^nc_cats_ears.png",
txr .. "^nc_cats_paws_front.png^nc_cats_paws_back.png",
txr,
txr,
txr .. "^nc_cats_tail.png",
txr .. "^nc_cats_face.png",
},
groups = {
snappy = 1,
falling_node = 1,
[modname .. "_cat"] = id
},
stack_max = 1,
paramtype2 = "facedir",
on_place = function(stack, placer, pointed, inf, orient, ...)
orient = orient or {}
orient.invert_wall = pointed.above.y == pointed.under.y
return minetest.rotate_and_place(stack, placer, pointed, inf, orient, ...)
end,
sounds = nodecore.sounds(modname .. "_mew"),
drop = modname .. ":cat_" .. id,
preserve_metadata = function(_, _, oldmeta, drops)
if oldmeta.realname then
oldmeta.description = oldmeta.realname
oldmeta.realname = nil
end
drops[1]:get_meta():from_table({fields = oldmeta})
end,
after_place_node = function(pos, _, itemstack)
local node = checkfacedir(pos)
local meta = minetest.get_meta(pos)
meta:from_table(itemstack:get_meta():to_table())
myapi.setname(meta)
checksnake(pos, node)
end,
after_destruct = function(pos)
for _, dir in ipairs(nodecore.dirs()) do
local p = vector.add(pos, dir)
checksnake(p)
end
end
}
minetest.register_node(modname .. ":cat_" .. id, nodecore.underride({
groups = {
[modname .. "_face"] = 1
}
}, basedef))
minetest.register_node(modname .. ":longcat_front_" .. id,
nodecore.underride({
description = "LongCat",
tiles = {
txr .. "^nc_cats_ears.png",
txr .. "^nc_cats_paws_front.png",
txr,
txr,
txr,
txr .. "^nc_cats_face.png",
},
groups = {
falling_node = 0,
[modname .. "_face"] = 1,
[modname .. "_longcat"] = 1
},
drop = modname .. ":cat_" .. id
}, basedef))
minetest.register_node(modname .. ":longcat_mid_" .. id,
nodecore.underride({
description = "LongCat",
tiles = {
txr,
txr .. "^nc_cats_paws_mid.png",
txr,
txr,
txr,
txr,
},
groups = {
falling_node = 0,
[modname .. "_longcat"] = 1
},
drop = modname .. ":cat_" .. id
}, basedef))
minetest.register_node(modname .. ":longcat_back_" .. id,
nodecore.underride({
description = "LongCat",
tiles = {
txr,
txr .. "^nc_cats_paws_back.png",
txr,
txr,
txr .. "^nc_cats_tail.png",
txr,
},
groups = {
falling_node = 0,
[modname .. "_longcat"] = 1
},
drop = modname .. ":cat_" .. id
}, basedef))
end
reg(1, "#c0c0c0", "#404040") -- light gray
reg(2, "#404040", "#202020") -- mid gray
reg(3, "#202020", "#101010") -- dark gray
reg(4, "#ff8000", "#804000") -- dark orange
reg(5, "#e0c040", "#ff8000") -- light orange
reg(6, "#804000", "#402000") -- dark brown
reg(7, "#c0a080", "#806020") -- light brown
function myapi.makecat(pos, param2)
local probs = {}
for i = 1, myapi.maxcatid do
probs[i] = 1
end
for _, np in ipairs(nodecore.find_nodes_around(pos,
{"group:" .. modname .. "_cat"}, 2)) do
local id = getcatid(minetest.get_node(np))
if id and probs[id] then
probs[id] = probs[id] * 1.2
end
end
local _, newid = nodecore.pickrand(probs,
function(v) return v end)
nodecore.set_loud(pos, {
name = modname .. ":cat_" .. newid,
param2 = type(param2) == "number" and param2
or math_random(0, 3)
})
myapi.setname(minetest.get_meta(pos))
end