-- LUALOCALS < --------------------------------------------------------- local math, minetest, nodecore, pairs, vector = math, minetest, nodecore, pairs, vector local math_abs, math_random = math.abs, math.random -- LUALOCALS > --------------------------------------------------------- local modname = minetest.get_current_modname() local myapi = _G[modname] local furmetakey = "catprill" nodecore.register_soaking_abm({ label = "cat furball", fieldname = "furball", nodenames = {"group:" .. modname .. "_cat"}, interval = 5, arealoaded = 3, soakrate = function(pos) local meta = minetest.get_meta(pos) if (meta:get_float(furmetakey) or 0) ~= 0 then return false end local found = #nodecore.find_nodes_around(pos, "group:" .. modname .. "_face", 3) return 2 ^ -math_abs(2 - found) end, soakcheck = function(data, pos) if data.total < 1000 then return end nodecore.log("action", "cat prill ready at " .. minetest.pos_to_string(pos)) minetest.get_meta(pos):set_float(furmetakey, 1) return false end }) local purrtimes = { 1.676, 1.617, 1.642, 1.655 } local hashpos = minetest.hash_node_position local purring = {} local purrgain = 0.15 local function playernear(pos) for _, player in pairs(minetest.get_connected_players()) do local ppos = player:get_pos() ppos.y = ppos.y + player:get_properties().eye_height local diff = vector.subtract(pos, ppos) local dsqr = vector.dot(diff, diff) if dsqr < 25 then return true end end end local function purr(pos) purring[hashpos(pos)] = nodecore.gametime local fade = math_random(1, 10) == 1 or not playernear(pos) local id = math_random(1, #purrtimes) local sh = nodecore.sound_play("nc_cats_purr_" .. id, { pos = pos, gain = purrgain, not_ephemeral = fade }) if fade then minetest.sound_fade(sh, -purrgain / purrtimes[id], 0) return minetest.after(purrtimes[id], function() purring[hashpos(pos)] = nil end) else nodecore.dnt_set(pos, modname .. ":purr", purrtimes[id]) end end nodecore.register_dnt({ name = modname .. ":purr", nodenames = {"group:" .. modname .. "_cat"}, action = purr }) local function furballcheck(pos, node, ejectpos) ejectpos = ejectpos or pos local meta = minetest.get_meta(pos) local ready = meta:get_float(furmetakey) or 0 if ready > 0 then nodecore.log("action", "cat ejects prill at " .. minetest.pos_to_string(pos)) nodecore.item_eject(ejectpos, modname .. ":prill", 5) nodecore.witness(pos, "cat eject prill") meta:set_float(furmetakey, 0) end node = node or minetest.get_node(pos) if minetest.get_item_group(node.name, modname .. "_longcat") < 1 then return end local fd = nodecore.facedirs[node.param2] local back = vector.add(pos, fd.k) local bnode = minetest.get_node(back) if myapi.longcatmatch(node, bnode) then return furballcheck(back, bnode, ejectpos) end end local function purrstart(pos) furballcheck(pos) return purr(pos) end function myapi.notpurring(pos) local purrtime = purring[hashpos(pos)] if purrtime and purrtime < nodecore.gametime - 2 then purrtime = nil purring[hashpos(pos)] = nil end return not purrtime and {} end local petgroups = minetest.registered_items[""].tool_capabilities.groupcaps.cuddly and {cuddly = 1} or {thumpy = 1} nodecore.register_craft({ label = "pet cat", action = "pummel", toolgroups = petgroups, indexkeys = {"group:" .. modname .. "_face"}, check = function(pos) return myapi.notpurring(pos) and playernear(pos) end, nodes = { {match = { groups = {[modname .. "_cat"] = true}, stacked = false }} }, after = purrstart })