Add Wuzzy to mailmap
[minetest_hbhunger.git] / hunger.lua
blob2e0f49e6f7507ebd64155c80f8e84c5391d4cf7c
1 -- Keep these for backwards compatibility
2 function hbhunger.save_hunger(player)
3 hbhunger.set_hunger_raw(player)
4 end
5 function hbhunger.load_hunger(player)
6 hbhunger.get_hunger_raw(player)
7 end
9 -- wrapper for minetest.item_eat (this way we make sure other mods can't break this one)
10 local org_eat = minetest.do_item_eat
11 minetest.do_item_eat = function(hp_change, replace_with_item, itemstack, user, pointed_thing)
12 local old_itemstack = itemstack
13 itemstack = hbhunger.eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
14 for _, callback in pairs(minetest.registered_on_item_eats) do
15 local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing, old_itemstack)
16 if result then
17 return result
18 end
19 end
20 return itemstack
21 end
23 -- food functions
24 local food = hbhunger.food
26 function hbhunger.register_food(name, hunger_change, replace_with_item, poisen, heal, sound)
27 food[name] = {}
28 food[name].saturation = hunger_change -- hunger points added
29 food[name].replace = replace_with_item -- what item is given back after eating
30 food[name].poisen = poisen -- time its poisening
31 food[name].healing = heal -- amount of HP
32 food[name].sound = sound -- special sound that is played when eating
33 end
35 function hbhunger.eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
36 local item = itemstack:get_name()
37 local def = food[item]
38 if not def then
39 def = {}
40 if type(hp_change) ~= "number" then
41 hp_change = 1
42 minetest.log("error", "Wrong on_use() definition for item '" .. item .. "'")
43 end
44 def.saturation = hp_change * 1.3
45 def.replace = replace_with_item
46 end
47 local func = hbhunger.item_eat(def.saturation, def.replace, def.poisen, def.healing, def.sound)
48 return func(itemstack, user, pointed_thing)
49 end
51 -- Poison player
52 local function poisenp(tick, time, time_left, player)
53 -- First check if player is still there
54 if not player:is_player() then
55 return
56 end
57 time_left = time_left + tick
58 if time_left < time then
59 minetest.after(tick, poisenp, tick, time, time_left, player)
60 else
61 hbhunger.poisonings[player:get_player_name()] = hbhunger.poisonings[player:get_player_name()] - 1
62 if hbhunger.poisonings[player:get_player_name()] <= 0 then
63 -- Reset HUD bar color
64 hb.change_hudbar(player, "health", nil, nil, "hudbars_icon_health.png", nil, "hudbars_bar_health.png")
65 end
66 end
67 if player:get_hp()-1 > 0 then
68 player:set_hp(player:get_hp()-1)
69 end
71 end
73 function hbhunger.item_eat(hunger_change, replace_with_item, poisen, heal, sound)
74 return function(itemstack, user, pointed_thing)
75 if itemstack:take_item() ~= nil and user ~= nil then
76 local name = user:get_player_name()
77 local h = tonumber(hbhunger.hunger[name])
78 local hp = user:get_hp()
79 if h == nil or hp == nil then
80 return
81 end
82 if user:is_player() then
83 local object, object_pos
84 -- Check if user is a "fake player" (unofficial imitation of a the player data structure)
85 if type(user) == "userdata" then
86 object = user
87 else
88 object_pos = user:get_pos()
89 end
90 minetest.sound_play(
91 {name = sound or "hbhunger_eat_generic",
92 gain = 1},
93 {object=object,
94 pos=object_pos,
95 max_hear_distance = 16,
96 pitch = 1 + math.random(-10, 10)*0.005,},
97 true
99 end
101 -- Saturation
102 if h < hbhunger.SAT_MAX and hunger_change then
103 h = h + hunger_change
104 if h > hbhunger.SAT_MAX then h = hbhunger.SAT_MAX end
105 hbhunger.hunger[name] = h
106 hbhunger.set_hunger_raw(user)
108 -- Healing
109 if hp < 20 and heal then
110 hp = hp + heal
111 if hp > 20 then hp = 20 end
112 user:set_hp(hp)
114 -- Poison
115 if poisen then
116 -- Set poison bar
117 hb.change_hudbar(user, "health", nil, nil, "hbhunger_icon_health_poison.png", nil, "hbhunger_bar_health_poison.png")
118 hbhunger.poisonings[name] = hbhunger.poisonings[name] + 1
119 poisenp(1, poisen, 0, user)
122 if itemstack:get_count() == 0 then
123 itemstack:add_item(replace_with_item)
124 else
125 local inv = user:get_inventory()
126 if inv:room_for_item("main", replace_with_item) then
127 inv:add_item("main", replace_with_item)
128 else
129 minetest.add_item(user:get_pos(), replace_with_item)
133 return itemstack
137 -- player-action based hunger changes
138 function hbhunger.handle_node_actions(pos, oldnode, player, ext)
139 -- is_fake_player comes from the pipeworks, we are not interested in those
140 if not player or not player:is_player() or player.is_fake_player == true then
141 return
143 local name = player:get_player_name()
144 local exhaus = hbhunger.exhaustion[name]
145 if exhaus == nil then return end
146 local new = hbhunger.EXHAUST_PLACE
147 -- placenode event
148 if not ext then
149 new = hbhunger.EXHAUST_DIG
151 -- assume its send by main timer when movement detected
152 if not pos and not oldnode then
153 new = hbhunger.EXHAUST_MOVE
155 exhaus = exhaus + new
156 if exhaus > hbhunger.EXHAUST_LVL then
157 exhaus = 0
158 local h = tonumber(hbhunger.hunger[name])
159 h = h - 1
160 if h < 0 then h = 0 end
161 hbhunger.hunger[name] = h
162 hbhunger.set_hunger_raw(player)
164 hbhunger.exhaustion[name] = exhaus
167 minetest.register_on_placenode(hbhunger.handle_node_actions)
168 minetest.register_on_dignode(hbhunger.handle_node_actions)