Page 1 of 2

[Mod] Hunger [hunger]

PostPosted: Tue Sep 18, 2012 09:38
by Casimir
I wrote a new hunger mod from ground up. It works very different from the old one. You can just install it like every other mod.
* you regularly get hungry
* when you feel hunger it hurts
* the less health you have the faster you get hungry
* no hunger bar
* when doing nothing (afk) nothing happens, you won't die

Download in the attachment.
License: GPLv3 or later

==Old Version==
This adds hunger to minetest.
There is no bar that shows you how hungry you are. Instead the program counts and after a day without eating your stomach is rebelling (you will get hurt, hear a sound and get a message). Half the time later it happens again. Half of half the time again. It gets faster and faster until you starve to death.
When eating something the counter is not set to zero, but to its half.
You can get a "Hunger-meter" by using "/giveme hunger:hunger_meter"

Installing:
Now, just like any other mod.

Download (old!):
http://ompldr.org/vZ3Zsag/hunger%2020121229.zip <--- latest
Older versions (for installation see posts below):
http://ompldr.org/vZ3R2cw/hunger%2020121226.zip
http://ompldr.org/vZmttZA/hunger%2020120921.zip

License: CC BY-SA
No dependencies on non-default mods.

==original post==
I want to make a mod that adds hunger to the game. Mainly based on drowning. I'm happy for everyone who wants to work on this project.
The goal is a bugfree mod that can be added to the default game. So you can make a survival-gamemode.

At the moment I'm searching for a method to check if a player eats something. The only thing I found so far is in the item-definition.
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.item_eat(hp_change, replace_with_item)

You would have to overwrite all eatable items. But there are a lot mods out there that add eatable stuff, so it would be better to have something independently working.

Best thing would be
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.register_on_eat (func(player, item))

Is there a possibility to ad a minetest.register* in Lua or is it only possible in C++?

PostPosted: Tue Sep 18, 2012 09:42
by cornernote
Health can only go up when you eat (i think) . You could check on_step to see the last time the health went up.

PostPosted: Tue Sep 18, 2012 09:53
by Calinou
Casimir wrote:The goal is a bugfree mod that can be added to the default game. So you can make a survival-gamemode.

Heh, I don't think celeron55 would want hunger in the default game. Very unlikely.

PostPosted: Tue Sep 18, 2012 10:24
by Casimir
I never thought to get it working that fast. Thanks cornernote, for this genius idea.
This is what I have at the moment.
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
hunger = {}    -- Exported functions

local players_hungry = {}
local hunger_seconds = {}
local health = {}
local health_previous = {}

local START_HUNGER_SECONDS = 40
local FACTOR_HUNGER_SECONDS = 2
local MIN_HUNGER_SECONDS = 2
local HUNGER_DAMAGE = 1

local timer = 0
if minetest.setting_getbool("enable_damage") == true then
minetest.register_globalstep(function(dtime)
    timer = timer + dtime
    if timer >= .5 then
        timer = timer - .5
    else
        return
    end
    for _,player in ipairs(minetest.get_connected_players()) do
            local player_name = player:get_player_name()
            if players_hungry[player_name] == nil then
                players_hungry[player_name] = {count=0}
            end
            if hunger_seconds[player_name] == nil then
                hunger_seconds[player_name] = START_HUNGER_SECONDS
            end
            players_hungry[player_name].count = players_hungry[player_name].count + .5
            if players_hungry[player_name].count >= hunger_seconds[player_name] then
                if player:get_hp() > 0 then
                    player:set_hp(player:get_hp() - HUNGER_DAMAGE)
                    pos = player:getpos()
                    pos.y=pos.y+1
                    -- minetest.sound_play({name="drowning_gurp"}, {pos = pos, gain = 1.0, max_hear_distance = 16})
                    players_hungry[player_name].count = players_hungry[player_name].count - hunger_seconds[player_name]
                    hunger_seconds[player_name] = math.floor(hunger_seconds[player_name]/FACTOR_HUNGER_SECONDS)
                    if hunger_seconds[player_name] < MIN_HUNGER_SECONDS then
                        hunger_seconds[player_name] = MIN_HUNGER_SECONDS
                    end
                else
                    players_hungry[player_name] = {count=0}
                    hunger_seconds[player_name] = START_HUNGER_SECONDS
                end
            end
    end
end)
end

minetest.register_on_respawnplayer(reset_on_respawn)

reset_on_respawn = function(player)
    for _,player in ipairs(minetest.get_connected_players()) do
            local player_name = player:get_player_name()
            players_hungry[player_name] = {count=0}
            hunger_seconds[player_name] = START_HUNGER_SECONDS
    end
end

if minetest.setting_getbool("enable_damage") == true then
minetest.register_globalstep(function(dtime)
    for _,player in ipairs(minetest.get_connected_players()) do
        local player_name = player:get_player_name()
        if health[player_name] == nil then
            health[player_name] = player:get_hp()
        end
        if health_previous[player_name] == nil then
            health_previous[player_name] = player:get_hp()
        end
        if health[player_name] > health_previous[player_name] then
            players_hungry[player_name] = {count=0}
            hunger_seconds[player_name] = START_HUNGER_SECONDS
        end
        health_previous[player_name] = health[player_name]
        health[player_name] = player:get_hp()
    end
end)
end


@ Calinou
Minetest is opensource isn't it? Second, when creating a new world, you can choose between the games [minetest] and [minimal], you could just add a third one [survival] - no conflicts.

PostPosted: Tue Sep 18, 2012 16:17
by Feorth
Really liked the idea, but how will this work? Will there be a server message telling me when i'm hungry or maybe a gui interface?

PostPosted: Tue Sep 18, 2012 17:45
by Casimir
What I have in mind is the simplest version, everything else can be added if needed. The idea is that you have to eat regularly e.g. one time every day (24 minuets gameplay equals day and night - I think). When the day is over and you haven't eaten anything you'll get a half heart damage. Then the time to the next damage is half a day, then 1/4th and so on until you eat something. So you will recognise soon enough that you are hungry and won't die to fast.

PostPosted: Tue Sep 18, 2012 23:01
by Feorth
Uhm, i see. Yes that could work really well. ^^

PostPosted: Tue Sep 18, 2012 23:06
by babe223
launches this mod soon XD
I look forward to having hunger for the game =D

PostPosted: Tue Sep 18, 2012 23:07
by babe223
WTF?FEORTH E BRASILEIRO XD

PostPosted: Tue Sep 18, 2012 23:11
by leo_rockway
With inventory_plus a formspec with stats could be added for the RPG lovers. Strength, armor bonuses, oxygen... and hunger.

PostPosted: Wed Sep 19, 2012 08:57
by cornernote
hey, wokste just responded with a better idea:
http://minetest.net/forum/viewtopic.php?pid=43501#p43501

Its a little hacky, but it is probably the best way until core supports registering a function for on_eat.

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest_item_eat = minetest.item_eat
minetest.item_eat = function(hp_change, replace_with_item)
    minetest_item_eat(hp_change, replace_with_item)
    -- do your stuff here
end

PostPosted: Wed Sep 19, 2012 12:00
by rubenwardy
This would be good, it would add real meaning to my food mod.

PostPosted: Wed Sep 19, 2012 13:19
by Casimir
It works as long as you don't die ;). [edit]Fixed.[/edit]

in item.lua (bulitin) search for the following funktion and ad the marked lines.
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
eating = {} -- this is for the hungermod

function minetest.item_eat(hp_change, replace_with_item)
    return function(itemstack, user, pointed_thing)  -- closure
        if itemstack:take_item() ~= nil then
            user:set_hp(user:get_hp() + hp_change)
            itemstack:add_item(replace_with_item) -- note: replace_with_item is optional
            eating[user:get_player_name()] = true -- this is for the hungermod
        end
        return itemstack
    end
end


The mod itself is the following. The trick is at the end.
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
hunger = {}    -- Exported functions

local players_hungry = {}
local hunger_seconds = {}
local health = {}
local health_previous = {}

local START_HUNGER_SECONDS = 720 -- 12 minuets equal one day
local FACTOR_HUNGER_SECONDS = 2
local MIN_HUNGER_SECONDS = 2
local HUNGER_DAMAGE = 1

local timer = 0
if minetest.setting_getbool("enable_damage") == true then

minetest.register_globalstep(function(dtime)
    timer = timer + dtime
    if timer >= .5 then
        timer = timer - .5
    else
        return
    end
    for _,player in ipairs(minetest.get_connected_players()) do
            local player_name = player:get_player_name()
            if players_hungry[player_name] == nil then
                players_hungry[player_name] = {count=0}
            end
            if hunger_seconds[player_name] == nil then
                hunger_seconds[player_name] = START_HUNGER_SECONDS
            end
            players_hungry[player_name].count = players_hungry[player_name].count + .5
            if players_hungry[player_name].count >= hunger_seconds[player_name] then
                if player:get_hp() > 0 then
                    player:set_hp(player:get_hp() - HUNGER_DAMAGE)
                    pos = player:getpos()
                    pos.y=pos.y+1
                    -- minetest.sound_play({name="drowning_gurp"}, {pos = pos, gain = 1.0, max_hear_distance = 16})
                    players_hungry[player_name].count = players_hungry[player_name].count - hunger_seconds[player_name]
                    hunger_seconds[player_name] = math.floor(hunger_seconds[player_name]/FACTOR_HUNGER_SECONDS)
                    if hunger_seconds[player_name] < MIN_HUNGER_SECONDS then
                        hunger_seconds[player_name] = MIN_HUNGER_SECONDS
                    end
                else
                    players_hungry[player_name] = {count=0}
                    hunger_seconds[player_name] = START_HUNGER_SECONDS
                end
            end
    end
end)

minetest.register_on_respawnplayer(function(player)
            local player_name = player:get_player_name()
            players_hungry[player_name] = {count=0}
            hunger_seconds[player_name] = START_HUNGER_SECONDS
end)

minetest.register_globalstep(function(dtime)
    for _,player in ipairs(minetest.get_connected_players()) do
        local player_name = player:get_player_name()
        if eating[player_name] == true then
            print ("essen!")
            eating[player_name] = false
            players_hungry[player_name] = {count=0}
            hunger_seconds[player_name] = START_HUNGER_SECONDS
        end
    end
end)

end

PostPosted: Thu Sep 20, 2012 22:25
by Casimir
Fully working version: http://ompldr.org/vZmttZA/hunger%2020120921.zip (WTFPL)
Installation instructions one post above.

I think it is ready to be moved to release.

PostPosted: Wed Dec 26, 2012 00:34
by Casimir
Updated! See first post.
- made the code easier, more beautiful, smaller.
- due to that there are no more bugs (I know of).

(this took me hours btw.)

PostPosted: Fri Dec 28, 2012 18:21
by jojoa1997
can you make a tool that shows how much hunger we have or a caommand.

PostPosted: Fri Dec 28, 2012 18:46
by Obiewan1111
Wow; This mod is amazing. Can you add a hunger bar, or some sort of communication to the player to tell them when they need to replenish their health.

PostPosted: Fri Dec 28, 2012 18:49
by PilzAdam
Casimir wrote:Installing:
In builtin/item.lua search for the following funktion and ad the marked lines. Then install the mod like every other.
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
eating = {} -- this is for the hungermod

function minetest.item_eat(hp_change, replace_with_item)
    return function(itemstack, user, pointed_thing)  -- closure
        if itemstack:take_item() ~= nil then
            user:set_hp(user:get_hp() + hp_change)
            itemstack:add_item(replace_with_item) -- note: replace_with_item is optional
            eating[user:get_player_name()] = true -- this is for the hungermod
        end
        return itemstack
    end
end

Do you know that you can override this function in your mod? Users dont have to do it themselves.

PostPosted: Fri Dec 28, 2012 20:13
by Casimir
@Adam
No I didn't. Just tell me how. (Or do it.)

@jojoa
cheesecake did that for the drowning mod. While the code (of drowning and hunger) is mostly the same it can be copied very easy.

PostPosted: Fri Dec 28, 2012 20:30
by PilzAdam
Casimir wrote:@Adam
No I didn't. Just tell me how. (Or do it.)

Just copy the code that is in your first post into your init.lua and it overrides the function in builtin.

PostPosted: Sat Dec 29, 2012 21:12
by Casimir
Done.
http://ompldr.org/vZ3Zsag/hunger%2020121229.zip
Use "/giveme hunger:hunger_meter" to get a nice bowl.

PostPosted: Fri Feb 01, 2013 19:30
by Casimir
Changing the hunger when you eat seems no more to work with 0.4.4-d1. And I don't know why. Anyone got an idea?

PostPosted: Mon Feb 04, 2013 05:31
by zoot686
could the mod chat to the chatbox that the player is getting hungry, a handful of ticks before causing injury?

PostPosted: Sat Mar 02, 2013 23:00
by Casimir
PilzAdam wrote:Do you know that you can override this function in your mod? Users dont have to do it themselves.

This no more works. I have no idea why...

PostPosted: Sun Mar 03, 2013 05:04
by kaeza
@Casimir If you are interested, I have revamped this mod for my Survival Modpack. It now correctly handles food only (i.e. if you heal by other means, it won't count as "eating"). Maybe you can take a look at it, and suggest a few changes? :)

PostPosted: Thu Mar 21, 2013 18:23
by Casimir
The confusion now is perfect. When you put it into the minetest_game folder itself it works. In mods it doesn't (even with all other mods removed).

@ kaeza
I don't understand exactly what you mean, but you credited the hungermod wrong ;)

PostPosted: Thu Mar 21, 2013 20:44
by kaeza
Casimir wrote:The confusion now is perfect. When you put it into the minetest_game folder itself it works. In mods it doesn't (even with all other mods removed).

@ kaeza
I don't understand exactly what you mean, but you credited the hungermod wrong ;)

Sorry, derped on that. I'll fix the credits.
I mean that you cannot override minetest.item_eat() unless you make default depend on hunger (or somehow make hunger load before default). That is because the apple's on_use does not call minetest.item_eat() when using the item; it calls a function returned by minetest.item_eat() at initialization.
Hope this is clear enough.

PostPosted: Thu Mar 21, 2013 21:43
by Casimir
Thank you for the explanation. So the solution would be a register_on_eat function. Hopefully someone will do that someday.

PostPosted: Fri Mar 22, 2013 03:44
by onpon4
Do you think this mod will end up getting fixed so it doesn't have random foods not working? I can't really accept that; even the explicit declaration of what's food like what kaeza's hunger mod does would be better, but I like the starvation method in this mod better than the simpler one in kaeza's hunger mod. It's less sudden, and I really like that it eliminates the need for a hunger meter.

PostPosted: Fri Mar 22, 2013 10:10
by Casimir
onpon4 wrote:Do you think this mod will end up getting fixed so it doesn't have random foods not working?

When it works (by putting it into the folder of the game), then it works for all foods, and for every time item_eat is used (even without food).
I might take the time and try to fix the mod, but I cant promise that i will.