385 lines
10 KiB
Lua
385 lines
10 KiB
Lua
|
|
--[[
|
|
|
|
Copyright (C) 2015 - Auke Kok <sofar@foo-projects.org>
|
|
|
|
"crops" is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as
|
|
published by the Free Software Foundation; either version 2.1
|
|
of the license, or (at your option) any later version.
|
|
|
|
--]]
|
|
|
|
crops = {}
|
|
crops.plants = {}
|
|
crops.settings = {}
|
|
|
|
local settings = {}
|
|
settings.easy = {
|
|
chance = 4,
|
|
interval = 30,
|
|
light = 8,
|
|
watercan = 25,
|
|
watercan_max = 90,
|
|
watercan_uses = 20,
|
|
damage_chance = 8,
|
|
damage_interval = 30,
|
|
damage_tick_min = 0,
|
|
damage_tick_max = 1,
|
|
damage_max = 25,
|
|
hydration = false,
|
|
}
|
|
settings.normal = {
|
|
chance = 8,
|
|
interval = 30,
|
|
light = 10,
|
|
watercan = 25,
|
|
watercan_max = 90,
|
|
watercan_uses = 20,
|
|
damage_chance = 8,
|
|
damage_interval = 30,
|
|
damage_tick_min = 0,
|
|
damage_tick_max = 5,
|
|
damage_max = 50,
|
|
hydration = true,
|
|
}
|
|
settings.difficult = {
|
|
chance = 16,
|
|
interval = 30,
|
|
light = 13,
|
|
watercan = 25,
|
|
watercan_max = 100,
|
|
watercan_uses = 20,
|
|
damage_chance = 4,
|
|
damage_interval = 30,
|
|
damage_tick_min = 3,
|
|
damage_tick_max = 7,
|
|
damage_max = 100,
|
|
hydration = true,
|
|
}
|
|
|
|
|
|
local worldpath = minetest.get_worldpath()
|
|
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
|
|
|
-- Load support for intllib.
|
|
local S, _ = dofile(modpath .. "/intllib.lua")
|
|
crops.intllib = S
|
|
|
|
|
|
dofile(modpath .. "/crops_settings.txt")
|
|
|
|
if io.open(worldpath .. "/crops_settings.txt", "r") == nil then
|
|
io.input(modpath .. "/crops_settings.txt")
|
|
io.output(worldpath .. "/crops_settings.txt")
|
|
|
|
local size = 4096
|
|
while true do
|
|
local buf = io.read(size)
|
|
if not buf then
|
|
io.close()
|
|
break
|
|
end
|
|
io.write(buf)
|
|
end
|
|
else
|
|
dofile(worldpath .. "/crops_settings.txt")
|
|
end
|
|
|
|
if not crops.difficulty then
|
|
crops.difficulty = "normal"
|
|
minetest.log("error", "[crops] "..S("Defaulting to \"normal\" difficulty settings"))
|
|
end
|
|
crops.settings = settings[crops.difficulty]
|
|
if not crops.settings then
|
|
minetest.log("error", "[crops] "..S("Defaulting to \"normal\" difficulty settings"))
|
|
crops.settings = settings.normal
|
|
end
|
|
if crops.settings.hydration then
|
|
minetest.log("action", "[crops] "..S("Hydration and dehydration mechanics are enabled."))
|
|
end
|
|
|
|
local find_plant = function(node)
|
|
for i = 1,table.getn(crops.plants) do
|
|
if crops.plants[i].name == node.name then
|
|
return crops.plants[i]
|
|
end
|
|
end
|
|
minetest.log("error", "[crops] "..S("Unable to find plant \"@1\" in crops table", node.name))
|
|
return nil
|
|
end
|
|
|
|
crops.register = function(plantdef)
|
|
table.insert(crops.plants, plantdef)
|
|
end
|
|
|
|
crops.plant = function(pos, node)
|
|
minetest.set_node(pos, node)
|
|
local meta = minetest.get_meta(pos)
|
|
local plant = find_plant(node)
|
|
meta:set_int("crops_water", math.max(plant.properties.waterstart, 1))
|
|
meta:set_int("crops_damage", 0)
|
|
end
|
|
|
|
crops.can_grow = function(pos)
|
|
if minetest.get_node_light(pos) < crops.settings.light then
|
|
return false
|
|
end
|
|
local node = minetest.get_node(pos)
|
|
local plant = find_plant(node)
|
|
if not plant then
|
|
return false
|
|
end
|
|
local meta = minetest.get_meta(pos)
|
|
if crops.settings.hydration then
|
|
local water = meta:get_int("crops_water")
|
|
if water < plant.properties.wither or water > plant.properties.soak then
|
|
if math.random(0,1) == 0 then
|
|
return false
|
|
end
|
|
end
|
|
-- growing costs water!
|
|
meta:set_int("crops_water", math.max(1, water - 10))
|
|
end
|
|
|
|
-- damaged plants are less likely to grow
|
|
local damage = meta:get_int("crops_damage")
|
|
if not damage == 0 then
|
|
if math.random(math.min(50, damage), 100) > 75 then
|
|
return false
|
|
end
|
|
end
|
|
|
|
-- allow the plant to grow
|
|
return true
|
|
end
|
|
|
|
crops.particles = function(pos, flag)
|
|
if flag == 0 then
|
|
-- wither (0)
|
|
minetest.add_particlespawner({
|
|
amount = 1 * crops.settings.interval,
|
|
time = crops.settings.interval,
|
|
minpos = { x = pos.x - 0.4, y = pos.y - 0.4, z = pos.z - 0.4 },
|
|
maxpos = { x = pos.x + 0.4, y = pos.y + 0.4, z = pos.z + 0.4 },
|
|
minvel = { x = 0, y = 0.2, z = 0 },
|
|
maxvel = { x = 0, y = 0.4, z = 0 },
|
|
minacc = { x = 0, y = 0, z = 0 },
|
|
maxacc = { x = 0, y = 0.2, z = 0 },
|
|
minexptime = 3,
|
|
maxexptime = 5,
|
|
minsize = 1,
|
|
maxsize = 2,
|
|
collisiondetection = false,
|
|
texture = "crops_wither.png",
|
|
vertical = true,
|
|
})
|
|
elseif flag == 1 then
|
|
-- soak (1)
|
|
minetest.add_particlespawner({
|
|
amount = 8 * crops.settings.interval,
|
|
time = crops.settings.interval,
|
|
minpos = { x = pos.x - 0.4, y = pos.y - 0.4, z = pos.z - 0.4 },
|
|
maxpos = { x = pos.x + 0.4, y = pos.y - 0.4, z = pos.z + 0.4 },
|
|
minvel = { x = -0.04, y = 0, z = -0.04 },
|
|
maxvel = { x = 0.04, y = 0, z = 0.04 },
|
|
minacc = { x = 0, y = 0, z = 0 },
|
|
maxacc = { x = 0, y = 0, z = 0 },
|
|
minexptime = 3,
|
|
maxexptime = 5,
|
|
minsize = 1,
|
|
maxsize = 2,
|
|
collisiondetection = false,
|
|
texture = "crops_soak.png",
|
|
vertical = false,
|
|
})
|
|
elseif flag == 2 then
|
|
-- watering (2)
|
|
minetest.add_particlespawner({
|
|
amount = 30,
|
|
time = 3,
|
|
minpos = { x = pos.x - 0.4, y = pos.y - 0.4, z = pos.z - 0.4 },
|
|
maxpos = { x = pos.x + 0.4, y = pos.y + 0.4, z = pos.z + 0.4 },
|
|
minvel = { x = 0, y = 0.0, z = 0 },
|
|
maxvel = { x = 0, y = 0.0, z = 0 },
|
|
minacc = { x = 0, y = -9.81, z = 0 },
|
|
maxacc = { x = 0, y = -9.81, z = 0 },
|
|
minexptime = 2,
|
|
maxexptime = 2,
|
|
minsize = 1,
|
|
maxsize = 3,
|
|
collisiondetection = false,
|
|
texture = "crops_watering.png",
|
|
vertical = true,
|
|
})
|
|
else
|
|
-- withered/rotting (3)
|
|
minetest.add_particlespawner({
|
|
amount = 20,
|
|
time = 30,
|
|
minpos = { x = pos.x + 0.3, y = pos.y - 0.5, z = pos.z - 0.5 },
|
|
maxpos = { x = pos.x + 0.5, y = pos.y + 0.5, z = pos.z + 0.5 },
|
|
minvel = { x = -0.6, y = -0.1, z = -0.2 },
|
|
maxvel = { x = -0.4, y = 0.1, z = 0.2 },
|
|
minacc = { x = 0.4, y = 0, z = -0.1 },
|
|
maxacc = { x = 0.5, y = 0, z = 0.1 },
|
|
minexptime = 2,
|
|
maxexptime = 4,
|
|
minsize = 1,
|
|
maxsize = 1,
|
|
collisiondetection = false,
|
|
texture = "crops_flies.png",
|
|
vertical = true,
|
|
})
|
|
minetest.add_particlespawner({
|
|
amount = 20,
|
|
time = 30,
|
|
minpos = { x = pos.x - 0.3, y = pos.y - 0.5, z = pos.z - 0.5 },
|
|
maxpos = { x = pos.x - 0.5, y = pos.y + 0.5, z = pos.z + 0.5 },
|
|
minvel = { x = 0.6, y = -0.1, z = -0.2 },
|
|
maxvel = { x = 0.4, y = 0.1, z = 0.2 },
|
|
minacc = { x = -0.4, y = 0, z = -0.1 },
|
|
maxacc = { x = -0.5, y = 0, z = 0.1 },
|
|
minexptime = 2,
|
|
maxexptime = 4,
|
|
minsize = 1,
|
|
maxsize = 1,
|
|
collisiondetection = false,
|
|
texture = "crops_flies.png",
|
|
vertical = true,
|
|
})
|
|
minetest.add_particlespawner({
|
|
amount = 20,
|
|
time = 30,
|
|
minpos = { x = pos.x - 0.5, y = pos.y - 0.5, z = pos.z + 0.3 },
|
|
maxpos = { x = pos.x + 0.5, y = pos.y + 0.5, z = pos.z + 0.5 },
|
|
minvel = { z = -0.6, y = -0.1, x = -0.2 },
|
|
maxvel = { z = -0.4, y = 0.1, x = 0.2 },
|
|
minacc = { z = 0.4, y = 0, x = -0.1 },
|
|
maxacc = { z = 0.5, y = 0, x = 0.1 },
|
|
minexptime = 2,
|
|
maxexptime = 4,
|
|
minsize = 1,
|
|
maxsize = 1,
|
|
collisiondetection = false,
|
|
texture = "crops_flies.png",
|
|
vertical = true,
|
|
})
|
|
minetest.add_particlespawner({
|
|
amount = 20,
|
|
time = 30,
|
|
minpos = { x = pos.x - 0.5, y = pos.y - 0.5, z = pos.z - 0.3 },
|
|
maxpos = { x = pos.x + 0.5, y = pos.y + 0.5, z = pos.z - 0.5 },
|
|
minvel = { z = 0.6, y = -0.1, x = -0.2 },
|
|
maxvel = { z = 0.4, y = 0.1, x = 0.2 },
|
|
minacc = { z = -0.4, y = 0, x = -0.1 },
|
|
maxacc = { z = -0.5, y = 0, x = 0.1 },
|
|
minexptime = 2,
|
|
maxexptime = 4,
|
|
minsize = 1,
|
|
maxsize = 1,
|
|
collisiondetection = false,
|
|
texture = "crops_flies.png",
|
|
vertical = true,
|
|
})
|
|
end
|
|
end
|
|
|
|
crops.die = function(pos)
|
|
crops.particles(pos, 3)
|
|
local node = minetest.get_node(pos)
|
|
local plant = find_plant(node)
|
|
plant.properties.die(pos)
|
|
minetest.sound_play("crops_flies", {pos=pos, gain=0.8})
|
|
end
|
|
|
|
if crops.settings.hydration then
|
|
dofile(modpath .. "/tools.lua")
|
|
end
|
|
|
|
-- crop nodes, crafts, craftitems
|
|
dofile(modpath .. "/melon.lua")
|
|
dofile(modpath .. "/pumpkin.lua")
|
|
dofile(modpath .. "/corn.lua")
|
|
dofile(modpath .. "/tomato.lua")
|
|
dofile(modpath .. "/potato.lua")
|
|
dofile(modpath .. "/polebean.lua")
|
|
|
|
local nodenames = {}
|
|
for i = 1,table.getn(crops.plants) do
|
|
table.insert(nodenames, crops.plants[i].name)
|
|
end
|
|
|
|
-- water handling code
|
|
if crops.settings.hydration then
|
|
minetest.register_abm({
|
|
nodenames = nodenames,
|
|
interval = crops.settings.damage_interval,
|
|
chance = crops.settings.damage_chance,
|
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
|
local meta = minetest.get_meta(pos)
|
|
local water = meta:get_int("crops_water")
|
|
local damage = meta:get_int("crops_damage")
|
|
|
|
-- get plant specific data
|
|
local plant = find_plant(node)
|
|
if plant == nil then
|
|
return
|
|
end
|
|
|
|
-- increase water for nearby water sources
|
|
local f = minetest.find_node_near(pos, 1, {"default:water_source", "default:water_flowing"})
|
|
if not f == nil then
|
|
water = math.min(100, water + 2)
|
|
else
|
|
f = minetest.find_node_near(pos, 2, {"default:water_source", "default:water_flowing"})
|
|
if not f == nil then
|
|
water = math.min(100, water + 1)
|
|
end
|
|
end
|
|
|
|
if minetest.get_node_light(pos, nil) < plant.properties.night then
|
|
-- compensate for light: at night give some water back to the plant
|
|
water = math.min(100, water + 1)
|
|
else
|
|
-- dry out the plant
|
|
water = math.max(1, water - plant.properties.wateruse)
|
|
end
|
|
|
|
meta:set_int("crops_water", water)
|
|
|
|
-- for convenience, copy water attribute to top half
|
|
if not plant.properties.doublesize == nil and plant.properties.doublesize then
|
|
local above = { x = pos.x, y = pos.y + 1, z = pos.z}
|
|
local abovemeta = minetest.get_meta(above)
|
|
abovemeta:set_int("crops_water", water)
|
|
end
|
|
|
|
if water <= plant.properties.wither_damage then
|
|
crops.particles(pos, 0)
|
|
damage = damage + math.random(crops.settings.damage_tick_min, crops.settings.damage_tick_max)
|
|
elseif water <= plant.properties.wither then
|
|
crops.particles(pos, 0)
|
|
return
|
|
elseif water >= plant.properties.soak_damage then
|
|
crops.particles(pos, 1)
|
|
damage = damage + math.random(crops.settings.damage_tick_min, crops.settings.damage_tick_max)
|
|
elseif water >= plant.properties.soak then
|
|
crops.particles(pos, 1)
|
|
return
|
|
end
|
|
meta:set_int("crops_damage", math.min(crops.settings.damage_max, damage))
|
|
|
|
-- is it dead?
|
|
if damage >= 100 then
|
|
crops.die(pos)
|
|
end
|
|
end
|
|
})
|
|
end
|
|
|
|
-- cooking recipes that mix craftitems
|
|
dofile(modpath .. "/cooking.lua")
|
|
dofile(modpath .. "/mapgen.lua")
|
|
|
|
minetest.log("action", "[crops] "..S("Loaded!"))
|