diff --git a/builtin/game/hunger.lua b/builtin/game/hunger.lua new file mode 100644 index 000000000000..9b66dd06bb1a --- /dev/null +++ b/builtin/game/hunger.lua @@ -0,0 +1,111 @@ +--------------------------------------------------------------------------------- +-- Minetest +-- Copyright (C) 2015 BlockMen +-- +-- This program 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. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License along +-- with this program; if not, write to the Free Software Foundation, Inc., +-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +--------------------------------------------------------------------------------- + + +-- Dont do anything when no damage or hunger +if core.setting_getbool("enable_damage") ~= true then + return +end + + +local hunger_step = 300 -- time in seconds until player looses 1 hunger point +local healing_step = 4 -- Time in seconds after player gets 1 HP (when healing) +local healing = {} + + +function core.heal_timer() + for player_name, check in pairs(healing) do + if check == true then + local player = core.get_player_by_name(player_name) + if player and player:is_player() then + player:set_hp(player:get_hp() + 1) + end + end + + end + + core.after(healing_step, core.heal_timer) +end + + +function core.hunger_timer(player, hunger_change) + player:set_hunger(player:get_hunger() - hunger_change) + core.after(hunger_step, core.hunger_timer, player, hunger_change) +end + + +local function check_healing_state(player) + assert(player:is_player()) + + local name = player:get_player_name() + if not name or name == "" then + return + end + + local is_healing = (healing[name] == true) + + if player:get_hunger() > 3 and player:get_breath() > 0 then + if not is_healing then + healing[name] = true + end + else + healing[name] = nil + end +end + + +function core.hunger_event_handler(player, eventname) + assert(player:is_player()) + + local name = player:get_player_name() + if not name or name == "" then + return + end + + if eventname == "health_changed" then + local hp = player:get_hp() + if hp > 19 then + healing[name] = nil + return + else + check_healing_state(player) + end + end + + if eventname == "breath_changed" or + eventname == "hunger_changed" then + check_healing_state(player) + end +end + + +core.register_on_joinplayer(function(player) + core.after(hunger_step, core.hunger_timer, player, 1) +end) +core.register_on_leaveplayer(function(player) + local name = player:get_player_name() + if not name or name == "" then + return + end + healing[name] = nil +end) +core.register_playerevent(core.hunger_event_handler) + +-- Init healing timer +core.heal_timer() diff --git a/builtin/game/init.lua b/builtin/game/init.lua index a6cfa3bf88cd..973c1749dc39 100644 --- a/builtin/game/init.lua +++ b/builtin/game/init.lua @@ -1,3 +1,21 @@ +--------------------------------------------------------------------------------- +-- Minetest +-- Copyright (C) 2013 celeron55, Perttu Ahola +-- +-- This program 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. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License along +-- with this program; if not, write to the Free Software Foundation, Inc., +-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +--------------------------------------------------------------------------------- local scriptpath = core.get_builtin_path()..DIR_DELIM local commonpath = scriptpath.."common"..DIR_DELIM @@ -26,3 +44,7 @@ dofile(gamepath.."features.lua") dofile(gamepath.."voxelarea.lua") dofile(gamepath.."forceloading.lua") dofile(gamepath.."statbars.lua") + +if core.setting_getbool("enable_hunger") then + dofile(gamepath .. "hunger.lua") +end diff --git a/builtin/game/item.lua b/builtin/game/item.lua index 44ec35cc9d8f..12b44df88e8d 100644 --- a/builtin/game/item.lua +++ b/builtin/game/item.lua @@ -1,4 +1,22 @@ --- Minetest: builtin/item.lua +--------------------------------------------------------------------------------- +-- Minetest +-- Copyright (C) 2013 celeron55, Perttu Ahola +-- +-- This program 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. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License along +-- with this program; if not, write to the Free Software Foundation, Inc., +-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +--------------------------------------------------------------------------------- + local function copy_pointed_thing(pointed_thing) return { @@ -375,22 +393,31 @@ function core.item_drop(itemstack, dropper, pos) -- environment failed end -function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing) +function core.do_item_eat(hunger_change, replace_with_item, itemstack, user, pointed_thing, hp_change, eat_sound) for _, callback in pairs(core.registered_on_item_eats) do - local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing) + local result = callback(hunger_change, replace_with_item, itemstack, user, pointed_thing, hp_change) if result then return result end end if itemstack:take_item() ~= nil then - user:set_hp(user:get_hp() + hp_change) + user:set_hunger(user:get_hunger() + hunger_change) + if hp_change then + user:set_hp(user:get_hp() + hp_change) + end + + -- eating sound + if not eat_sound then + eat_sound = "item_eat" + end + core.sound_play(eat_sound, {to_player = user:get_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 + if inv:room_for_item("main", {name = replace_with_item}) then inv:add_item("main", replace_with_item) else local pos = user:getpos() @@ -403,9 +430,14 @@ function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed return itemstack end -function core.item_eat(hp_change, replace_with_item) +function core.item_eat(hunger_change, replace_with_item, hp_change, eat_sound) + -- With hunger disabled food has to heal (fallback to old behavior) + if core.is_yes(core.setting_getbool("enable_hunger")) == false and not hp_change then + hp_change = hunger_change + end return function(itemstack, user, pointed_thing) -- closure - return core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing) + return core.do_item_eat(hunger_change, replace_with_item, itemstack, + user, pointed_thing, hp_change, eat_sound) end end diff --git a/builtin/game/statbars.lua b/builtin/game/statbars.lua index 61a8b90770a9..86ab2d75b3fb 100644 --- a/builtin/game/statbars.lua +++ b/builtin/game/statbars.lua @@ -1,26 +1,54 @@ - -local health_bar_definition = -{ +--------------------------------------------------------------------------------- +-- Minetest +-- Copyright (C) 2013 celeron55, Perttu Ahola +-- +-- This program 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. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Lesser General Public License for more details. +-- +-- You should have received a copy of the GNU Lesser General Public License along +-- with this program; if not, write to the Free Software Foundation, Inc., +-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +--------------------------------------------------------------------------------- + + +local health_bar_definition = { hud_elem_type = "statbar", - position = { x=0.5, y=1 }, + position = {x= 0.5, y = 1}, text = "heart.png", number = 20, direction = 0, - size = { x=24, y=24 }, - offset = { x=(-10*24)-25, y=-(48+24+16)}, + size = {x = 24, y = 24}, + offset = {x = (-10*24)-25, y = -(48+24+16)}, +} + +local hunger_bar_definition = { + hud_elem_type = "statbar", + position = {x= 0.5, y = 1}, + text = "bread.png", + number = 20, + direction = 0, + size = {x = 24, y = 24}, + offset = {x = 25, y = -(48+24+16)}, } -local breath_bar_definition = -{ +local breath_bar_definition = { hud_elem_type = "statbar", - position = { x=0.5, y=1 }, + position = {x= 0.5, y = 1}, text = "bubble.png", number = 20, direction = 0, - size = { x=24, y=24 }, - offset = {x=25,y=-(48+24+16)}, + size = {x = 24, y = 24}, + offset = {x = 25, y = -(48+48+16)}, } + local hud_ids = {} local function initialize_builtin_statbars(player) @@ -42,6 +70,7 @@ local function initialize_builtin_statbars(player) player:hud_set_flags(player:hud_get_flags()) end + -- health bar if player:hud_get_flags().healthbar and core.is_yes(core.setting_get("enable_damage")) then if hud_ids[name].id_healthbar == nil then @@ -55,6 +84,7 @@ local function initialize_builtin_statbars(player) end end + -- breath bar if (player:get_breath() < 11) then if player:hud_get_flags().breathbar and core.is_yes(core.setting_get("enable_damage")) then @@ -71,8 +101,28 @@ local function initialize_builtin_statbars(player) player:hud_remove(hud_ids[name].id_breathbar) hud_ids[name].id_breathbar = nil end + + -- hungerbar + if player:hud_get_flags().healthbar and + core.is_yes(core.setting_get("enable_damage")) and + core.is_yes(core.setting_getbool("enable_hunger")) then + if hud_ids[name].id_hungerbar == nil then + local hunger = player:get_hunger() + if hunger > 20 then + hunger = 20 + end + hunger_bar_definition.number = hunger + hud_ids[name].id_hungerbar = player:hud_add(hunger_bar_definition) + end + else + if hud_ids[name].id_hungerbar ~= nil then + player:hud_remove(hud_ids[name].id_hungerbar) + hud_ids[name].id_hungerbar = nil + end + end end + local function cleanup_builtin_statbars(player) if not player:is_player() then @@ -88,7 +138,8 @@ local function cleanup_builtin_statbars(player) hud_ids[name] = nil end -local function player_event_handler(player,eventname) + +local function player_event_handler(player, eventname) assert(player:is_player()) local name = player:get_player_name() @@ -101,7 +152,7 @@ local function player_event_handler(player,eventname) initialize_builtin_statbars(player) if hud_ids[name].id_healthbar ~= nil then - player:hud_change(hud_ids[name].id_healthbar,"number",player:get_hp()) + player:hud_change(hud_ids[name].id_healthbar, "number", player:get_hp()) return true end end @@ -110,7 +161,20 @@ local function player_event_handler(player,eventname) initialize_builtin_statbars(player) if hud_ids[name].id_breathbar ~= nil then - player:hud_change(hud_ids[name].id_breathbar,"number",player:get_breath()*2) + player:hud_change(hud_ids[name].id_breathbar, "number", player:get_breath() * 2) + return true + end + end + + if eventname == "hunger_changed" then + initialize_builtin_statbars(player) + + if hud_ids[name].id_hungerbar ~= nil then + local hunger = player:get_hunger() + if hunger > 20 then + hunger = 20 + end + player:hud_change(hud_ids[name].id_hungerbar, "number", hunger) return true end end @@ -123,6 +187,7 @@ local function player_event_handler(player,eventname) return false end + function core.hud_replace_builtin(name, definition) if definition == nil or @@ -134,7 +199,7 @@ function core.hud_replace_builtin(name, definition) if name == "health" then health_bar_definition = definition - for name,ids in pairs(hud_ids) do + for name, ids in pairs(hud_ids) do local player = core.get_player_by_name(name) if player and hud_ids[name].id_healthbar then player:hud_remove(hud_ids[name].id_healthbar) @@ -147,7 +212,7 @@ function core.hud_replace_builtin(name, definition) if name == "breath" then breath_bar_definition = definition - for name,ids in pairs(hud_ids) do + for name, ids in pairs(hud_ids) do local player = core.get_player_by_name(name) if player and hud_ids[name].id_breathbar then player:hud_remove(hud_ids[name].id_breathbar) @@ -157,6 +222,19 @@ function core.hud_replace_builtin(name, definition) return true end + if name == "hunger" then + hunger_bar_definition = definition + + for name, ids in pairs(hud_ids) do + local player = core.get_player_by_name(name) + if player and hud_ids[name].id_hungerbar then + player:hud_remove(hud_ids[name].id_hungerbar) + initialize_builtin_statbars(player) + end + end + return true + end + return false end diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index bf452915ad50..4358e01f8c46 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -669,6 +669,10 @@ item_entity_ttl (Item entity TTL) int 900 # Enable players getting damage and dying. enable_damage (Damage) bool false +# Enable hunger mechanics and starving. +# Has no effect when enable_damage = false +enable_hunger (Hunger) bool false + # A chosen map seed for a new map, leave empty for random. # Will be overridden when creating a new world in the main menu. fixed_map_seed (Fixed map seed) string diff --git a/doc/lua_api.txt b/doc/lua_api.txt index f82c3c2ac59c..94fcfca4f296 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1892,7 +1892,7 @@ Call these functions only at load time! * The provided function should check that the position is protected by the mod calling this function before it prints a message, if it does, to allow for multiple protection mods. -* `minetest.register_on_item_eat(func(hp_change, replace_with_item, itemstack, user, pointed_thing))` +* `minetest.register_on_item_eat(func(hunger_change, replace_with_item, itemstack, user, pointed_thing, hp_change))` * Called when an item is eaten, by `minetest.item_eat` * Return `true` or `itemstack` to cancel the default item eat response (i.e.: hp increase) @@ -2096,7 +2096,7 @@ and `minetest.auth_reload` call the authetification handler. * `minetest.create_detached_inventory(name, callbacks)`: returns an `InvRef` * callbacks: See "Detached inventory callbacks" * Creates a detached inventory. If it already exists, it is cleared. -* `minetest.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)`: +* `minetest.do_item_eat(hunger_change, replace_with_item, itemstack, user, pointed_thing, hp_change, eat_sound)`: returns left over ItemStack * See `minetest.item_eat` and `minetest.register_on_item_eat` @@ -2211,8 +2211,8 @@ These functions return the leftover itemstack. * returns `itemstack, success` * `minetest.item_drop(itemstack, dropper, pos)` * Drop the item -* `minetest.item_eat(hp_change, replace_with_item)` - * Eat the item. +* `minetest.item_eat(hunger_change, replace_with_item, hp_change, eat_sound)` + * Eat the item. Increases saturation and/or health (when enable_hunger disabled) * `replace_with_item` is the itemstring which is added to the inventory. If the player is eating a stack, then replace_with_item goes to a different spot. Can be `nil` @@ -2568,6 +2568,9 @@ This is basically a reference to a C++ `ServerActiveObject` * `0`: player is drowning, * `1`-`10`: remaining number of bubbles * `11`: bubbles bar is not shown +* `get_hunger()`: returns players hunger; 30 = full saturated; 0 = hungry +* `set_hunger(value)`: sets players hunger + * allowed values: 0 - 30 * `set_inventory_formspec(formspec)` * Redefine player's inventory form * Should usually be called in on_joinplayer diff --git a/minetest.conf.example b/minetest.conf.example index 39f80bf68301..de28e335bc3b 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -798,6 +798,11 @@ # type: bool # enable_damage = false +# Enable hunger mechanics and starving. +# Has no effect when enable_damage = false +# type: bool +# enable_hunger = false + # A chosen map seed for a new map, leave empty for random. # Will be overridden when creating a new world in the main menu. # type: string @@ -1243,7 +1248,7 @@ # Choice of 4 mandelbrot set variations. # 1 = 4D "Roundy" mandelbrot set, 2 = 4D "Squarry" mandelbrot set, # 3 = 4D "Mandy Cousin" mandelbrot set, 4 = 4D mandelbrot set variation. -# type: int +# type: int min: 1 max: 4 # mgfractal_formula = 1 # Iterations of the recursive function. @@ -1265,12 +1270,24 @@ # type: float # mgfractal_slice_w = 0.0 -# Julia set only: 4 values determining the 4D shape. +# Julia set only: X value determining the 4D shape. # Range roughly -2 to 2. # type: float # mgfractal_julia_x = 0.33 + +# Julia set only: Y value determining the 4D shape. +# Range roughly -2 to 2. +# type: float # mgfractal_julia_y = 0.33 + +# Julia set only: Z value determining the 4D shape. +# Range roughly -2 to 2. +# type: float # mgfractal_julia_z = 0.33 + +# Julia set only: W value determining the 4D shape. +# Range roughly -2 to 2. +# type: float # mgfractal_julia_w = 0.33 # type: noise_params diff --git a/src/constants.h b/src/constants.h index b606fc4fa114..9d86e5add32e 100644 --- a/src/constants.h +++ b/src/constants.h @@ -93,6 +93,9 @@ with this program; if not, write to the Free Software Foundation, Inc., // Maximal breath of a player #define PLAYER_MAX_BREATH 11 +// Maximal hunger point of a player +#define PLAYER_MAX_HUNGER 30 + // Number of different files to try to save a player to if the first fails // (because of a case-insensitive filesystem) // TODO: Use case-insensitive player names instead of this hack. diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 0fa806c1a11c..54dd1fe2d0c1 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -1177,6 +1177,16 @@ void PlayerSAO::setBreath(u16 breath) m_player->setBreath(breath); } +u16 PlayerSAO::getHunger() const +{ + return m_player->getHunger(); +} + +void PlayerSAO::setHunger(u16 hunger) +{ + m_player->setHunger(hunger); +} + void PlayerSAO::setArmorGroups(const ItemGroupList &armor_groups) { m_armor_groups = armor_groups; diff --git a/src/content_sao.h b/src/content_sao.h index 1f0a68cd859a..c1c9fbc61c7a 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -200,6 +200,8 @@ class PlayerSAO : public ServerActiveObject s16 readDamage(); u16 getBreath() const; void setBreath(u16 breath); + u16 getHunger() const; + void setHunger(u16 hunger); void setArmorGroups(const ItemGroupList &armor_groups); ItemGroupList getArmorGroups(); void setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 3315f4aaa776..cfb040655b23 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -240,6 +240,7 @@ void set_default_settings(Settings *settings) settings->setDefault("strict_protocol_version_checking", "false"); settings->setDefault("creative_mode", "false"); settings->setDefault("enable_damage", "true"); + settings->setDefault("enable_hunger", "true"); settings->setDefault("fixed_map_seed", ""); settings->setDefault("give_initial_stuff", "false"); settings->setDefault("default_password", ""); diff --git a/src/hud.h b/src/hud.h index 65453aec1ae7..e2c810b1e0db 100644 --- a/src/hud.h +++ b/src/hud.h @@ -41,6 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define HUD_FLAG_WIELDITEM_VISIBLE (1 << 3) #define HUD_FLAG_BREATHBAR_VISIBLE (1 << 4) #define HUD_FLAG_MINIMAP_VISIBLE (1 << 5) +#define HUD_FLAG_HUNGERBAR_VISIBLE (1 << 6) #define HUD_PARAM_HOTBAR_ITEMCOUNT 1 #define HUD_PARAM_HOTBAR_IMAGE 2 diff --git a/src/player.cpp b/src/player.cpp index 3ee34d41f0b5..0b878ddac1ed 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -50,6 +50,7 @@ Player::Player(IGameDef *gamedef, const char *name): // protected m_gamedef(gamedef), m_breath(PLAYER_MAX_BREATH), + m_hunger(PLAYER_MAX_HUNGER), m_pitch(0), m_yaw(0), m_speed(0,0,0), @@ -101,7 +102,8 @@ Player::Player(IGameDef *gamedef, const char *name): hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE | - HUD_FLAG_BREATHBAR_VISIBLE | HUD_FLAG_MINIMAP_VISIBLE; + HUD_FLAG_BREATHBAR_VISIBLE | HUD_FLAG_MINIMAP_VISIBLE | + HUD_FLAG_HUNGERBAR_VISIBLE; hud_hotbar_itemcount = HUD_HOTBAR_ITEMCOUNT_DEFAULT; } @@ -163,6 +165,7 @@ void Player::serialize(std::ostream &os) args.setV3F("position", m_position); args.setS32("hp", hp); args.setS32("breath", m_breath); + args.setS32("hunger", m_hunger); args.writeLines(os); @@ -189,14 +192,19 @@ void Player::deSerialize(std::istream &is, std::string playername) setPosition(args.getV3F("position")); try{ hp = args.getS32("hp"); - }catch(SettingNotFoundException &e) { + }catch(SettingNotFoundException &e){ hp = PLAYER_MAX_HP; } try{ m_breath = args.getS32("breath"); - }catch(SettingNotFoundException &e) { + }catch(SettingNotFoundException &e){ m_breath = PLAYER_MAX_BREATH; } + try { + m_hunger = args.getS32("hunger"); + } catch(SettingNotFoundException &e) { + m_hunger = 20; // PLAYER_MAX_HUNGER might be too high for init? + } inventory.deSerialize(is); diff --git a/src/player.h b/src/player.h index c112618761d5..ff9a28a6f400 100644 --- a/src/player.h +++ b/src/player.h @@ -183,6 +183,18 @@ class Player m_breath = breath; } + u16 getHunger() + { + return m_hunger; + } + + virtual void setHunger(u16 hunger) + { + if (hunger != m_hunger) + m_dirty = true; + m_hunger = hunger; + } + f32 getRadPitch() { return -1.0 * m_pitch * core::DEGTORAD; @@ -359,6 +371,8 @@ class Player float local_animation_speed; u16 hp; + u16 m_breath; + u16 m_hunger; float hurt_tilt_timer; float hurt_tilt_strength; @@ -393,7 +407,6 @@ class Player IGameDef *m_gamedef; char m_name[PLAYERNAME_SIZE]; - u16 m_breath; f32 m_pitch; f32 m_yaw; v3f m_speed; diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 52190d60e479..6bc61e36f7b8 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -65,6 +65,7 @@ struct EnumString es_HudBuiltinElement[] = {HUD_FLAG_WIELDITEM_VISIBLE, "wielditem"}, {HUD_FLAG_BREATHBAR_VISIBLE, "breathbar"}, {HUD_FLAG_MINIMAP_VISIBLE, "minimap"}, + {HUD_FLAG_HUNGERBAR_VISIBLE, "hungerbar"}, {0, NULL}, }; @@ -1051,6 +1052,41 @@ int ObjectRef::l_get_breath(lua_State *L) return 1; } +// set_hunger(self, hunger) +int ObjectRef::l_set_hunger(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + PlayerSAO* co = getplayersao(ref); + if (co == NULL) + return 0; + + u16 hunger = rangelim(luaL_checknumber(L, 2), 0, PLAYER_MAX_HUNGER); + u16 old_hunger = co->getHunger(); + co->setHunger(hunger); + + // report to script interface + if (hunger != old_hunger) + getServer(L)->getScriptIface()->player_event(co, "hunger_changed"); + + return 0; +} + +// get_hunger(self) +int ObjectRef::l_get_hunger(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + PlayerSAO* co = getplayersao(ref); + if (co == NULL) + return 0; + + u16 hunger = co->getHunger(); + lua_pushinteger(L, hunger); + + return 1; +} + // set_inventory_formspec(self, formspec) int ObjectRef::l_set_inventory_formspec(lua_State *L) { @@ -1770,5 +1806,7 @@ const luaL_reg ObjectRef::methods[] = { luamethod(ObjectRef, get_eye_offset), luamethod(ObjectRef, set_nametag_attributes), luamethod(ObjectRef, get_nametag_attributes), + luamethod(ObjectRef, get_hunger), + luamethod(ObjectRef, set_hunger), {0,0} }; diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index a4457cc051e5..81e6f5668a11 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -204,9 +204,15 @@ class ObjectRef : public ModApiBase { // set_breath(self, breath) static int l_set_breath(lua_State *L); - // get_breath(self, breath) + // get_breath(self) static int l_get_breath(lua_State *L); + // set_hunger(self, hunger) + static int l_set_hunger(lua_State *L); + + // get_hunger(self) + static int l_get_hunger(lua_State *L); + // set_inventory_formspec(self, formspec) static int l_set_inventory_formspec(lua_State *L); diff --git a/src/settings_translation_file.cpp b/src/settings_translation_file.cpp index 89bd192e4375..8effd14ec985 100644 --- a/src/settings_translation_file.cpp +++ b/src/settings_translation_file.cpp @@ -331,6 +331,8 @@ fake_function() { gettext("Time in seconds for item entity (dropped items) to live.\nSetting it to -1 disables the feature."); gettext("Damage"); gettext("Enable players getting damage and dying."); + gettext("Hunger"); + gettext("Enable hunger mechanics and starving.\nHas no effect when enable_damage = false"); gettext("Fixed map seed"); gettext("A chosen map seed for a new map, leave empty for random.\nWill be overridden when creating a new world in the main menu."); gettext("Default password"); @@ -424,7 +426,7 @@ fake_function() { gettext("Map generation limit"); gettext("Where the map generator stops.\nPlease note:\n- Limited to 31000 (setting above has no effect)\n- The map generator works in groups of 80x80x80 nodes (5x5x5 MapBlocks).\n- Those groups have an offset of -32, -32 nodes from the origin.\n- Only groups which are within the map_generation_limit are generated"); gettext("Mapgen flags"); - gettext("Global map generation attributes.\nFlags that are not specified in the flag string are not modified from the default.\nFlags starting with \"no\" are used to explicitly disable them.\n'trees' and 'flat' flags only have effect in mgv6."); + gettext("Global map generation attributes.\nThe 'trees' flag only has effect in mgv6.\nFlags that are not specified in the flag string are not modified from the default.\nFlags starting with \"no\" are used to explicitly disable them."); gettext("Advanced"); gettext("Chunk size"); gettext("Size of chunks to be generated at once by mapgen, stated in mapblocks (16 nodes)."); @@ -480,33 +482,47 @@ fake_function() { gettext("Mapgen v7 ridge noise parameters"); gettext("Mapgen v7 cave1 noise parameters"); gettext("Mapgen v7 cave2 noise parameters"); + gettext("Mapgen flat"); + gettext("Mapgen flat flags"); + gettext("Map generation attributes specific to Mapgen flat.\nOccasional lakes and hills added to the flat world.\nFlags that are not specified in the flag string are not modified from the default.\nFlags starting with \"no\" are used to explicitly disable them."); + gettext("Mapgen flat ground level"); + gettext("Y of flat ground."); + gettext("Mapgen flat large cave depth"); + gettext("Y of upper limit of large pseudorandom caves."); + gettext("Mapgen flat lake threshold"); + gettext("Terrain noise threshold for lakes.\nControls proportion of world area covered by lakes.\nAdjust towards 0.0 for a larger proportion."); + gettext("Mapgen flat lake steepness"); + gettext("Controls steepness/depth of lake depressions."); + gettext("Mapgen flat hill threshold"); + gettext("Terrain noise threshold for hills.\nControls proportion of world area covered by hills.\nAdjust towards 0.0 for a larger proportion."); + gettext("Mapgen flat hill steepness"); + gettext("Controls steepness/height of hills."); + gettext("Mapgen flat terrain noise parameters"); + gettext("Determines terrain shape.\nThe 3 numbers in brackets control the scale of the\nterrain, the 3 numbers should be identical."); + gettext("Mapgen flat filler depth noise parameters"); + gettext("Mapgen flat cave1 noise parameters"); + gettext("Mapgen flat cave2 noise parameters"); gettext("Mapgen fractal"); gettext("Mapgen fractal flags"); - gettext("Map generation attributes specific to Mapgen fractal.\n'julia' selects a julia set to be generated instead of a mandelbrot set.\nFlags that are not specified in the flag string are not modified from the default.\nFlags starting with \"no\" are used to explicitly disable them."); - gettext("Mapgen fractal mandelbrot iterations"); - gettext("Mandelbrot set: Iterations of the recursive function.\nControls scale of finest detail."); - gettext("Mapgen fractal mandelbrot scale"); - gettext("Mandelbrot set: Approximate (X,Y,Z) scales in nodes."); - gettext("Mapgen fractal mandelbrot offset"); - gettext("Mandelbrot set: (X,Y,Z) offsets from world centre.\nRange roughly -2 to 2, multiply by m_scale for offsets in nodes."); - gettext("Mapgen fractal mandelbrot slice w"); - gettext("Mandelbrot set: W co-ordinate of the generated 3D slice of the 4D shape.\nRange roughly -2 to 2."); - gettext("Mapgen fractal julia iterations"); - gettext("Julia set: Iterations of the recursive function.\nControls scale of finest detail."); - gettext("Mapgen fractal julia scale"); - gettext("Julia set: Approximate (X,Y,Z) scales in nodes."); - gettext("Mapgen fractal julia offset"); - gettext("Julia set: (X,Y,Z) offsets from world centre.\nRange roughly -2 to 2, multiply by j_scale for offsets in nodes."); - gettext("Mapgen fractal julia slice w"); - gettext("Julia set: W co-ordinate of the generated 3D slice of the 4D shape.\nRange roughly -2 to 2."); + gettext("Map generation attributes specific to Mapgen fractal.\nThe 'julia' flag results in the corresponding julia set being generated.\nFlags that are not specified in the flag string are not modified from the default.\nFlags starting with \"no\" are used to explicitly disable them."); + gettext("Mapgen fractal formula"); + gettext("Choice of 4 mandelbrot set variations.\n1 = 4D \"Roundy\" mandelbrot set, 2 = 4D \"Squarry\" mandelbrot set,\n3 = 4D \"Mandy Cousin\" mandelbrot set, 4 = 4D mandelbrot set variation."); + gettext("Mapgen fractal iterations"); + gettext("Iterations of the recursive function.\nControls scale of finest detail."); + gettext("Mapgen fractal scale"); + gettext("Approximate (X,Y,Z) scales in nodes."); + gettext("Mapgen fractal offset"); + gettext("(X,Y,Z) offsets from world centre.\nRange roughly -2 to 2, multiply by 'scale' for offsets in nodes."); + gettext("Mapgen fractal slice w"); + gettext("W co-ordinate of the generated 3D slice of the 4D shape.\nRange roughly -2 to 2."); gettext("Mapgen fractal julia x"); - gettext("Julia set: X value determining the 4D shape.\nRange roughly -2 to 2."); + gettext("Julia set only: X value determining the 4D shape.\nRange roughly -2 to 2."); gettext("Mapgen fractal julia y"); - gettext("Julia set: Y value determining the 4D shape.\nRange roughly -2 to 2."); + gettext("Julia set only: Y value determining the 4D shape.\nRange roughly -2 to 2."); gettext("Mapgen fractal julia z"); - gettext("Julia set: Z value determining the 4D shape.\nRange roughly -2 to 2."); + gettext("Julia set only: Z value determining the 4D shape.\nRange roughly -2 to 2."); gettext("Mapgen fractal julia w"); - gettext("Julia set: W value determining the 4D shape.\nRange roughly -2 to 2."); + gettext("Julia set only: W value determining the 4D shape.\nRange roughly -2 to 2."); gettext("Mapgen fractal seabed noise parameters"); gettext("Mapgen fractal filler depth noise parameters"); gettext("Mapgen fractal cave1 noise parameters");