summaryrefslogtreecommitdiff
path: root/functions.lua
diff options
context:
space:
mode:
Diffstat (limited to 'functions.lua')
-rw-r--r--functions.lua236
1 files changed, 236 insertions, 0 deletions
diff --git a/functions.lua b/functions.lua
new file mode 100644
index 0000000..d3c8af3
--- /dev/null
+++ b/functions.lua
@@ -0,0 +1,236 @@
+-- read/write
+function hunger.read(player)
+ local inv = player:get_inventory()
+ if not inv then
+ return nil
+ end
+ local hgp = inv:get_stack("hunger", 1):get_count()
+ if hgp == 0 then
+ hgp = 21
+ inv:set_stack("hunger", 1, ItemStack({name = ":", count = hgp}))
+ else
+ hgp = hgp
+ end
+ if tonumber(hgp) > HUNGER_MAX + 1 then
+ hgp = HUNGER_MAX + 1
+ end
+ return hgp - 1
+end
+
+function hunger.save(player)
+ local inv = player:get_inventory()
+ local name = player:get_player_name()
+ local value = hunger[name].lvl
+ if not inv or not value then
+ return nil
+ end
+ if value > HUNGER_MAX then
+ value = HUNGER_MAX
+ end
+ if value < 0 then
+ value = 0
+ end
+ inv:set_stack("hunger", 1, ItemStack({name = ":", count = value + 1}))
+ return true
+end
+
+function hunger.update_hunger(player, new_lvl)
+ local name = player:get_player_name() or nil
+ if not name then
+ return false
+ end
+ if minetest.setting_getbool("enable_damage") == false then
+ hunger[name] = 20
+ return
+ end
+ local lvl = hunger[name].lvl
+ if new_lvl then
+ lvl = new_lvl
+ end
+ if lvl > HUNGER_MAX then
+ lvl = HUNGER_MAX
+ end
+ hunger[name].lvl = lvl
+ if lvl > 20 then
+ lvl = 20
+ end
+ hud.change_item(player, "hunger", {number = lvl})
+ hunger.save(player)
+end
+local update_hunger = hunger.update_hunger
+
+-- player-action based hunger changes
+function hunger.handle_node_actions(pos, oldnode, player, ext)
+ if not player or not player:is_player() then
+ return
+ end
+ local name = player:get_player_name()
+ local exhaus = hunger[name].exhaus
+ if not exhaus then
+ hunger[name].exhaus = 0
+ --return
+ end
+
+ local new = HUNGER_EXHAUST_PLACE
+
+ -- placenode event
+ if not ext then
+ new = HUNGER_EXHAUST_DIG
+ end
+
+ -- assume its send by action_timer(globalstep)
+ if not pos and not oldnode then
+ new = HUNGER_EXHAUST_MOVE
+ end
+
+ exhaus = exhaus + new
+
+ if exhaus > HUNGER_EXHAUST_LVL then
+ exhaus = 0
+ local h = tonumber(hunger[name].lvl)
+ if h > 0 then
+ update_hunger(player, h - 1)
+ end
+ end
+
+ hunger[name].exhaus = exhaus
+end
+
+-- Time based hunger functions
+if minetest.setting_getbool("enable_damage") then
+ local hunger_timer = 0
+ local health_timer = 0
+ local action_timer = 0
+ minetest.register_globalstep(function(dtime)
+ hunger_timer = hunger_timer + dtime
+ health_timer = health_timer + dtime
+ action_timer = action_timer + dtime
+
+ if action_timer > HUNGER_MOVE_TICK then
+ for _,player in ipairs(minetest.get_connected_players()) do
+ local controls = player:get_player_control()
+ -- Determine if the player is walking
+ if controls.up or controls.down or controls.left or controls.right then
+ hunger.handle_node_actions(nil, nil, player)
+ end
+ end
+ action_timer = 0
+ end
+
+ -- lower saturation by 1 point after <HUNGER_TICK> second(s)
+ if hunger_timer > HUNGER_TICK then
+ for _,player in ipairs(minetest.get_connected_players()) do
+ local name = player:get_player_name()
+ local tab = hunger[name]
+ if tab then
+ local hunger = tab.lvl
+ if hunger > 0 then
+ update_hunger(player, hunger - 1)
+ end
+ end
+ end
+ hunger_timer = 0
+ end
+
+ -- heal or damage player, depending on saturation
+ if health_timer > HUNGER_HEALTH_TICK then
+ for _,player in ipairs(minetest.get_connected_players()) do
+ local name = player:get_player_name()
+ local tab = hunger[name]
+ if tab then
+ local air = player:get_breath() or 0
+ local hp = player:get_hp()
+
+ -- heal player by 1 hp if not dead and saturation is > 15 (of 30)
+ if tonumber(tab.lvl) > HUNGER_HEAL_LVL and air > 0 then
+ player:set_hp(hp + HUNGER_HEAL)
+ end
+
+ -- or damage player by 1 hp if saturation is < 2 (of 30)
+ if tonumber(tab.lvl) < HUNGER_STARVE_LVL then
+ player:set_hp(hp - HUNGER_STARVE)
+ end
+ end
+ end
+
+ health_timer = 0
+ end
+ end)
+end
+
+
+-- food functions
+local food = hunger.food
+
+function hunger.register_food(name, hunger_change, replace_with_item, poisen, heal, sound)
+ food[name] = {}
+ food[name].saturation = hunger_change -- hunger points added
+ food[name].replace = replace_with_item -- what item is given back after eating
+ food[name].poisen = poisen -- time its poisening
+ food[name].healing = heal -- amount of HP
+ food[name].sound = sound -- special sound that is played when eating
+end
+
+-- Poison player
+local function poisenp(tick, time, time_left, player)
+ time_left = time_left + tick
+ if time_left < time then
+ minetest.after(tick, poisenp, tick, time, time_left, player)
+ else
+ hud.change_item(player, "hunger", {text = "hud_hunger_fg.png"})
+ end
+ local hp = player:get_hp() -1 or 0
+ if hp > 0 then
+ player:set_hp(hp)
+ end
+end
+
+function hunger.eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
+ local item = itemstack:get_name()
+ local def = food[item]
+ if not def then
+ def = {}
+ def.saturation = hp_change * 1.3
+ def.replace = replace_with_item
+ end
+ local func = hunger.item_eat(def.saturation, def.replace, def.poisen, def.healing, def.sound)
+ return func(itemstack, user, pointed_thing)
+end
+
+function hunger.item_eat(hunger_change, replace_with_item, poisen, heal, sound)
+ return function(itemstack, user, pointed_thing)
+ if itemstack:take_item() ~= nil and user ~= nil then
+ local name = user:get_player_name()
+ local sat = tonumber(hunger[name].lvl)
+ local hp = user:get_hp()
+ -- Saturation
+ if sat < HUNGER_MAX and hunger_change then
+ sat = sat + hunger_change
+ hunger.update_hunger(user, sat)
+ end
+ -- Healing
+ if hp < 20 and heal then
+ hp = hp + heal
+ if hp > 20 then
+ hp = 20
+ end
+ user:set_hp(hp)
+ end
+ -- Poison
+ if poisen then
+ hud.change_item(user, "hunger", {text = "hunger_statbar_poisen.png"})
+ poisenp(1.0, poisen, 0, user)
+ end
+
+ -- eating sound
+ if not sound then
+ sound = "hunger_eat"
+ end
+ minetest.sound_play(sound, {to_player = name, gain = 0.7})
+
+ itemstack:add_item(replace_with_item)
+ end
+
+ return itemstack
+ end
+end