This repository has been archived by the owner on Dec 14, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathfunctions.lua
278 lines (248 loc) · 7.01 KB
/
functions.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
-- 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.players[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.players[name] = 20
return
end
local lvl = hunger.players[name].lvl
if new_lvl then
lvl = new_lvl
end
if lvl > HUNGER_MAX then
lvl = HUNGER_MAX
end
hunger.players[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()
if not name or not hunger.players[name] then
return
end
local exhaus = hunger.players[name].exhaus
if not exhaus then
hunger.players[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.players[name].lvl)
if h > 0 then
update_hunger(player, h - 1)
end
end
hunger.players[name].exhaus = exhaus
end
-- Time based hunger functions
local hunger_timer = 0
local health_timer = 0
local action_timer = 0
local function hunger_globaltimer(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.players[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.players[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) player is not drowning
if tonumber(tab.lvl) > HUNGER_HEAL_LVL and hp > 0 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
if minetest.setting_getbool("enable_damage") then
minetest.register_globalstep(hunger_globaltimer)
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
-- wrapper for minetest.item_eat (this way we make sure other mods can't break this one)
local org_eat = core.do_item_eat
core.do_item_eat = function(hp_change, replace_with_item, itemstack, user, pointed_thing)
local old_itemstack = itemstack
itemstack = hunger.eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
for _, callback in pairs(core.registered_on_item_eats) do
local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing, old_itemstack)
if result then
return result
end
end
return itemstack
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 = {}
if type(hp_change) ~= "number" then
hp_change = 1
core.log("error", "Wrong on_use() definition for item '" .. item .. "'")
end
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()
if not hunger.players[name] then
return itemstack
end
local sat = tonumber(hunger.players[name].lvl or 0)
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})
if replace_with_item then
if itemstack:is_empty() then
itemstack:add_item(replace_with_item)
else
local inv = user:get_inventory()
if inv:room_for_item("main", {name=replace_with_item}) then
inv:add_item("main", replace_with_item)
else
local pos = user:getpos()
pos.y = math.floor(pos.y + 0.5)
core.add_item(pos, replace_with_item)
end
end
end
end
return itemstack
end
end