waterican/init.lua

274 lines
8.6 KiB
Lua

local MODNAME = "waterican"
--
-- Waterican (by gravgun)
-- v1.2
-- A mod that add watering cans that make crops grow faster.
--
-- LICENSE: GPLv3+
-- ('cuz every time you use proprietary software, a kitten dies)
--
-- Why that name?
-- Because somehow when I wrote "watering can" fast I actually wrote "waterican".
--
local function rn() return math.random()-.5 end
local function rr(min, max) return min + math.random() * (max-min) end
local function waternode(user, pos)
local node = minetest.get_node(pos)
local nodedef = minetest.registered_nodes[node.name]
if nodedef == nil then
return -- dafuq?
end
-- General soil wetting
local soil = nodedef.soil
if soil and node.name == soil.dry then
minetest.set_node(pos, {name=soil.wet})
return
end
-- Farming soil wetting (compatibility with Farming Redo)
if node.name == "farming:soil" then
minetest.set_node(pos, {name="farming:soil_wet"})
return
end
-- Seed growth
if minetest.get_item_group(node.name, "seed") > 0 and nodedef.fertility then
local grow = false
local node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z})
if node_under == nil then
return
end
-- Can this seed grow on the node that's beneath it?
for _, v in pairs(nodedef.fertility) do
if minetest.get_item_group(node_under.name, v) > 0 then
grow = true
end
end
if grow then
minetest.set_node(pos, {name=node.name:gsub("seed_", "") .. "_1"})
end
return
end
-- Plant growth
local plant_nbr_s, plant_nbr_e = string.find(node.name, "_[0-9]+$")
if minetest.get_item_group(node.name, "plant") > 0 and plant_nbr_s then
local plant_nbr = tonumber(string.sub(node.name, plant_nbr_s+1, plant_nbr_e))
local orig_name = string.sub(node.name, 0, plant_nbr_s)
local next = orig_name .. (plant_nbr+1)
if minetest.registered_nodes[next] then
minetest.set_node(pos, {name=next})
end
return
end
-- Cactus growth
if node.name == "default:cactus" then
default.grow_cactus(pos, minetest.get_node(pos))
return
end
-- Papyrus growth
if node.name == "default:papyrus" then
default.grow_papyrus(pos, minetest.get_node(pos))
return
end
-- Grow grass on dirt
-- Convery dry grass to grass
if (node.name == "default:dirt" and minetest.find_node_near(pos, 1, {"default:dirt_with_grass"}))
or (node.name == "default:dirt_with_dry_grass")
and math.random() > 0.4 then
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
local name = minetest.get_node(above).name
local above_nodedef = minetest.registered_nodes[name]
if name ~= "ignore" and above_nodedef and
((above_nodedef.sunlight_propagates or above_nodedef.paramtype == "light") and above_nodedef.liquidtype == "none") then
minetest.set_node(pos, {name="default:dirt_with_grass"})
end
return
end
-- Put out fire
if node.name == "fire:basic_flame" then
minetest.set_node(pos, {name="air"})
minetest.sound_play("default_cool_lava",
{pos = pos, max_hear_distance = 16, gain = 0.25})
return
end
-- Tree growth
if math.random() > 0.9 then
-- The code in this `if` statement is copied from the `default` mod, therefore is LGPLv2.1+.
-- If Minetest coredevs had the lil' idea to plan ahead, they would have **named** ABMs
-- so we can reuse them OR added a way to force ABMs to trigger on certain nodes.
-- But no, they seem way too dumb for that simple shit.
local node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z})
if not node_under then
return
end
local name_under = node_under.name
local is_soil = minetest.get_item_group(name_under, "soil")
if is_soil == 0 then
return
end
local mapgen = minetest.get_mapgen_params().mgname
if node.name == "default:sapling" then
minetest.log("action", "A sapling grows into a tree at "..
minetest.pos_to_string(pos))
if mapgen == "v6" then
default.grow_tree(pos, random(1, 4) == 1)
else
default.grow_new_apple_tree(pos)
end
elseif node.name == "default:junglesapling" then
minetest.log("action", "A jungle sapling grows into a tree at "..
minetest.pos_to_string(pos))
if mapgen == "v6" then
default.grow_jungle_tree(pos)
else
default.grow_new_jungle_tree(pos)
end
elseif node.name == "default:pine_sapling" then
minetest.log("action", "A pine sapling grows into a tree at "..
minetest.pos_to_string(pos))
if mapgen == "v6" then
default.grow_pine_tree(pos)
else
default.grow_new_pine_tree(pos)
end
elseif node.name == "default:acacia_sapling" then
minetest.log("action", "An acacia sapling grows into a tree at "..
minetest.pos_to_string(pos))
default.grow_new_acacia_tree(pos)
end
end
end
local function water(user, minp, maxp, chance)
for x=minp.x,maxp.x do
for y=minp.y,maxp.y do
for z=minp.z,maxp.z do
if math.random() < chance then
waternode(user, {x=x, y=y, z=z})
end
end
end
end
local particle_count = math.random(1, 4) * (maxp.x-minp.x+1) * (maxp.z-minp.z+1)
for _=0,particle_count do
minetest.add_particle({
pos = {x = rr(minp.x, maxp.x), y = maxp.y + 0.7, z = rr(minp.z, maxp.z) },
vel = {x=rn()*.6, y=0, z=rn()*.6},
acc = {x=0, y=-10, z=0},
expirationtime = math.random()*2+1,
size = 1,
collisiondetection = true,
vertical = false,
texture = "waterican_droplet.png",
playername = user:get_player_name()
})
end
end
local function reg_waterican(def)
local img = "waterican_waterican.png"
if def.color then
img = img .. "^[colorize:" .. def.color .. "^waterican_waterican_alphaoverlay.png"
end
local matname = ""
if def.materialname then
matname = " (" .. def.materialname .. ")"
end
local toolname = MODNAME .. ":waterican_" .. def.material
minetest.register_tool(toolname, {
description = "Waterican" .. matname,
liquids_pointable = true,
inventory_image = img,
wield_image = img .. "^[transformFX",
wield_scale = {x = 1, y = 1, z = 6},
on_use = function(itemstack, user, pointed_thing)
local wear = itemstack:get_wear()
-- Refill if pointing at water and not already full
if pointed_thing.type == "node" then
local node = minetest.get_node(pointed_thing.under)
-- Don't check for default, since Watericans that
-- wear out are only available if default is.
if node.name == "default:water_source" then
if wear > 0 then
itemstack:set_wear(0)
minetest.set_node(pointed_thing.under, {name="air"})
return itemstack
end
return
end
end
-- Worn out = no more water.
if wear == 65534 then
return
end
if pointed_thing.type == "node" then
p = pointed_thing.under
if user:get_player_control().sneak then
water(user, {x=p.x,y=p.y-1,z=p.z}, p, def.chance)
else
water(user, {x=p.x-1,y=p.y-1,z=p.z-1}, {x=p.x+1,y=p.y,z=p.z+1}, def.chance)
end
end
if def.uses then
local wearadd = 0
if user:get_player_control().sneak then
wearadd = 65534/(def.uses*9)+1
else
wearadd = 65534/def.uses+1
end
wearadd = math.min(wearadd, 65534-wear)
itemstack:add_wear(wearadd)
return itemstack
end
end
})
return toolname
end
reg_waterican({material = "op", chance = 1})
if default then
local reg_craft = function(...) end
if bucket then
reg_craft = function (out, item)
minetest.register_craft({
output = out,
recipe = {
{"", "", item},
{item, "bucket:bucket_water", item},
{"", item, ""}
},
replacements = {
{"bucket:bucket_water", "bucket:bucket_empty", ""}
}
})
end
end
reg_craft(reg_waterican({material = "diamond", materialname = "Diamond", color = "#00FFFF", uses = 60, chance = 0.8}),
"default:diamond")
reg_craft(reg_waterican({material = "mese", materialname = "Mese", color = "#FFFF00", uses = 50, chance = 0.7}),
"default:mese_crystal")
reg_craft(reg_waterican({material = "gold", materialname = "Gold", color = "#E6C717", uses = 40, chance = 0.6}),
"default:gold_ingot")
reg_craft(reg_waterican({material = "steel", materialname = "Steel", color = "#CCCCCC", uses = 30, chance = 0.5}),
"default:steel_ingot")
reg_craft(reg_waterican({material = "bronze", materialname = "Bronze", color = "#FF873D", uses = 20, chance = 0.4}),
"default:bronze_ingot")
reg_craft(reg_waterican({material = "stone", materialname = "Stone", color = "#7F7F7F", uses = 15, chance = 0.3}),
"default:cobble")
reg_craft(reg_waterican({material = "wood", materialname = "Wood", color = "#6C4913", uses = 10, chance = 0.2}),
"group:wood")
end