You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
386 lines
11 KiB
386 lines
11 KiB
local modname = minetest.get_current_modname()
|
|
local modpath = minetest.get_modpath (modname)
|
|
-- NOTE: 30 indicates 10 more beyond the visible bar is allowed.
|
|
|
|
local enable_wonder = minetest.setting_getbool ("enable_wonder")
|
|
unified_hunger = {}
|
|
|
|
-- HUD statbar values
|
|
unified_hunger.hunger = {}
|
|
unified_hunger.hunger_out = {}
|
|
|
|
-- HUD item ids
|
|
local hunger_hud = {}
|
|
|
|
if minetest.setting_getbool ("enable_damage") then
|
|
unified_hunger.enable_damage = true
|
|
else
|
|
unified_hunger.enable_damage = false
|
|
end
|
|
|
|
HUNGER_HUD_TICK = 0.5 -- 0.1
|
|
|
|
--Some hunger settings
|
|
unified_hunger.exhaustion = {} -- Exhaustion is experimental!
|
|
|
|
-- time in seconds after that 1 hunger point is taken
|
|
|
|
local HUNGER_TICK_DEFAULT = 180
|
|
if enable_wonder then
|
|
HUNGER_TICK_DEFAULT = 90
|
|
end
|
|
|
|
HUNGER_HUNGER_TICK = tonumber (minetest.setting_get ("hunger_tick")) or HUNGER_TICK_DEFAULT
|
|
if HUNGER_HUNGER_TICK < 10 then HUNGER_HUNGER_TICK = 10 end
|
|
|
|
HUNGER_EXHAUST_DIG = 1.5 -- exhaustion increased this value after digged node
|
|
HUNGER_EXHAUST_PLACE = 1 -- exhaustion increased this value after placed
|
|
HUNGER_EXHAUST_MOVE = 0.3 -- exhaustion increased this value if player movement detected
|
|
HUNGER_EXHAUST_LVL = 160 -- at what exhaustion player satiation gets lowerd
|
|
|
|
|
|
--[[load custom settings
|
|
local set = io.open(minetest.get_modpath("unified_hunger").."/unified_hunger.conf", "r")
|
|
if set then
|
|
dofile(minetest.get_modpath("unified_hunger").."/unified_hunger.conf")
|
|
set:close()
|
|
end--]]
|
|
|
|
local function custom_hud(player)
|
|
hb.init_hudbar(player, "satiation", unified_hunger.get_hunger(player))
|
|
end
|
|
|
|
local function pull_hunger(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
|
|
unified_hunger.hunger[name] = hgp - 1
|
|
return true
|
|
end
|
|
|
|
local function push_hunger(player)
|
|
local inv = player:get_inventory()
|
|
local name = player:get_player_name()
|
|
local value = unified_hunger.hunger[name]
|
|
if not inv or not value then return nil end
|
|
inv:set_stack("hunger", 1, ItemStack({name = ":", count = value + 1}))
|
|
return true
|
|
end
|
|
|
|
-- Keep these for backwards compatibility
|
|
|
|
function unified_hunger.save_hunger(player)
|
|
push_hunger(player)
|
|
end
|
|
|
|
function unified_hunger.load_hunger(player)
|
|
pull_hunger(player)
|
|
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
|
|
--reset hud image
|
|
end
|
|
if player:get_hp()-1 > 0 then
|
|
player:set_hp(player:get_hp()-1)
|
|
end
|
|
|
|
end
|
|
|
|
function unified_hunger.item_eat (hunger_change,
|
|
replace_with_item, poisen, heal, msg)
|
|
|
|
return function (itemstack, user, pointed_thing)
|
|
if itemstack:take_item() ~= nil and user ~= nil then
|
|
local name = user:get_player_name()
|
|
local h = tonumber(unified_hunger.hunger[name])
|
|
local hp = user:get_hp()
|
|
minetest.sound_play("unified_hunger_eat_generic", {
|
|
object = user,
|
|
max_hear_distance = 10,
|
|
gain = 1.0
|
|
})
|
|
|
|
-- Saturation
|
|
if h < 30 and hunger_change then
|
|
h = h + hunger_change
|
|
if h > 30 then h = 30 end
|
|
unified_hunger.hunger[name] = h
|
|
unified_hunger.set_hunger(user)
|
|
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
|
|
--set hud-img
|
|
poisenp(1.0, poisen, 0, user)
|
|
end
|
|
|
|
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
|
|
|
|
if msg ~= nil then
|
|
local mt = type (msg)
|
|
local send = nil
|
|
|
|
if mt == "string" then
|
|
send = msg
|
|
elseif mt == "table" then
|
|
send = msg [math.random (#msg)]
|
|
end
|
|
|
|
minetest.chat_send_player (name, send)
|
|
end
|
|
end
|
|
return itemstack
|
|
end
|
|
end
|
|
|
|
unified_hunger.overwrite = function (name, satiate, heal, poison,
|
|
replace, msg)
|
|
|
|
if not unified_hunger.enable_damage then
|
|
poison = nil
|
|
end
|
|
name = minetest.registered_aliases [name] or name
|
|
|
|
if minetest.registered_items [name] ~= nil then
|
|
minetest.override_item (name, {
|
|
on_use = unified_hunger.item_eat (satiate,
|
|
replace, poison, heal, msg)
|
|
})
|
|
end
|
|
end
|
|
|
|
local overwrite = unified_hunger.overwrite
|
|
|
|
-- ===================================================================
|
|
|
|
-- player-action based hunger changes
|
|
function unified_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 = unified_hunger.exhaustion[name]
|
|
if exhaus == nil then return end
|
|
local new = HUNGER_EXHAUST_PLACE
|
|
-- placenode event
|
|
if not ext then
|
|
new = HUNGER_EXHAUST_DIG
|
|
end
|
|
-- assume its send by main timer when movement detected
|
|
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(unified_hunger.hunger[name])
|
|
h = h - 1
|
|
if h < 0 then h = 0 end
|
|
unified_hunger.hunger[name] = h
|
|
unified_hunger.set_hunger(player)
|
|
end
|
|
unified_hunger.exhaustion[name] = exhaus
|
|
end
|
|
|
|
--minetest.register_on_placenode(unified_hunger.handle_node_actions)
|
|
minetest.register_on_dignode(unified_hunger.handle_node_actions)
|
|
|
|
-- register satiation hudbar
|
|
hb.register_hudbar(
|
|
"satiation", 0xFFFFFF, "Satiation",
|
|
{
|
|
icon = "unified_hunger_icon.png",
|
|
bgicon = "unified_hunger_bgicon.png",
|
|
bar = "unified_hunger_bar.png"
|
|
},
|
|
20, 30, false
|
|
)
|
|
|
|
-- update hud elemtents if value has changed
|
|
local function update_hud(player)
|
|
local name = player:get_player_name()
|
|
local h_out = tonumber(unified_hunger.hunger_out[name])
|
|
local h = tonumber(unified_hunger.hunger[name])
|
|
if h_out ~= h then
|
|
unified_hunger.hunger_out[name] = h
|
|
hb.change_hudbar(player, "satiation", h)
|
|
end
|
|
end
|
|
|
|
unified_hunger.get_hunger = function(player)
|
|
pull_hunger(player)
|
|
return unified_hunger.hunger[name]
|
|
end
|
|
|
|
unified_hunger.set_hunger = function(player, value)
|
|
local name = player:get_player_name()
|
|
if value > 30 then value = 30 end
|
|
if value < 0 then value = 0 end
|
|
unified_hunger.hunger[name] = value
|
|
return push_hunger(player)
|
|
end
|
|
|
|
|
|
|
|
minetest.register_on_joinplayer(function(player)
|
|
local name = player:get_player_name()
|
|
local inv = player:get_inventory()
|
|
inv:set_size("hunger", 1)
|
|
pull_hunger(player) -- Load hunger[name] (and ensure non-nil).
|
|
unified_hunger.hunger_out[name] = unified_hunger.hunger[name]
|
|
unified_hunger.exhaustion[name] = 0
|
|
custom_hud(player)
|
|
push_hunger(player) -- Save the now non-nil value.
|
|
end)
|
|
|
|
minetest.register_on_respawnplayer(function(player)
|
|
-- reset hunger (and save)
|
|
local name = player:get_player_name()
|
|
unified_hunger.set_hunger(player, 20)
|
|
unified_hunger.exhaustion[name] = 0
|
|
end)
|
|
|
|
-- ===================================================================
|
|
|
|
local param_starve = {
|
|
description = "Be hungry" ,
|
|
params = "" ,
|
|
privs = {} ,
|
|
|
|
func = function (plname, params)
|
|
local player = minetest.env:get_player_by_name (plname)
|
|
unified_hunger.hunger [plname] = 5
|
|
unified_hunger.set_hunger (player)
|
|
minetest.chat_send_player (plname, "O.K. you're hungry")
|
|
|
|
end
|
|
}
|
|
|
|
minetest.register_chatcommand ("starve", param_starve)
|
|
|
|
-- ===================================================================
|
|
|
|
minetest.register_privilege ("satiate", {
|
|
description = "satiate administration" ,
|
|
give_to_singleplayer = false ,
|
|
})
|
|
|
|
local param_satiate = {
|
|
description = "Be satiated" ,
|
|
params = "" ,
|
|
privs = { satiate=true } ,
|
|
|
|
func = function (plname, params)
|
|
local player = minetest.env:get_player_by_name (plname)
|
|
unified_hunger.hunger [plname] = 20
|
|
unified_hunger.set_hunger (player)
|
|
minetest.chat_send_player (plname, "O.K. you're satiated")
|
|
|
|
end
|
|
}
|
|
|
|
minetest.register_chatcommand ("satiate", param_satiate)
|
|
|
|
-- ===================================================================
|
|
|
|
if unified_hunger.enable_damage then
|
|
local main_timer = 0
|
|
local timer = 0
|
|
local timer2 = 0
|
|
|
|
minetest.register_globalstep(function(dtime)
|
|
main_timer = main_timer + dtime
|
|
timer = timer + dtime
|
|
timer2 = timer2 + dtime
|
|
|
|
if main_timer > HUNGER_HUD_TICK
|
|
or timer > 4
|
|
or timer2 > HUNGER_HUNGER_TICK then
|
|
|
|
if main_timer > HUNGER_HUD_TICK then
|
|
main_timer = 0
|
|
end
|
|
|
|
for _,player in pairs(minetest.get_connected_players()) do
|
|
|
|
local name = player:get_player_name()
|
|
local h = tonumber(unified_hunger.hunger[name])
|
|
local hp = player:get_hp()
|
|
|
|
if timer > 4 then
|
|
|
|
-- heal player by 1 hp if not dead and satiation is > 15
|
|
if h > 15
|
|
and hp > 0
|
|
and player:get_breath() > 0 then
|
|
player:set_hp(hp + 1)
|
|
-- or damage player by 1 hp if satiation is < 2
|
|
elseif h <= 1 then
|
|
if hp - 1 >= 0 then
|
|
player:set_hp(hp - 1)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- lower satiation by 1 point after xx seconds
|
|
if timer2 > HUNGER_HUNGER_TICK then
|
|
if h > 0 then
|
|
h = h - 1
|
|
unified_hunger.hunger[name] = h
|
|
unified_hunger.set_hunger(player)
|
|
end
|
|
end
|
|
|
|
-- update hud elements
|
|
update_hud(player)
|
|
|
|
-- Determine if player is walking
|
|
local controls = player:get_player_control()
|
|
if controls.up
|
|
or controls.down
|
|
or controls.left
|
|
or controls.right then
|
|
unified_hunger.handle_node_actions(nil, nil, player)
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
if timer > 4 then
|
|
timer = 0
|
|
end
|
|
|
|
if timer2 > HUNGER_HUNGER_TICK then
|
|
timer2 = 0
|
|
end
|
|
end)
|
|
end -- end if damage enabled
|
|
|