mods that hopefully work for a TechAge-based pack

This commit is contained in:
2026-09-09 06:27:51 -06:00
parent 4e6b08d194
commit c27db2a537
6234 changed files with 375578 additions and 0 deletions
+92
View File
@@ -0,0 +1,92 @@
Minetest mod "Stamina"
=====================
(C) 2015 - BlockMen
(C) 2016 - Auke Kok <sofar@foo-projects.org>
About this mod:
---------------
This mod adds a stamina, or "hunger" mechanic to Minetest. Actions like
crafting, walking, digging or fighting make the player exhausted. When
enough exhaustion has been accumulated, the player gets more hungry,
and loses stamina.
If a player is low on stamina, they start taking periodical damage,
and ultimately will die if they do not eat food.
Eating food no longer heals the player. Instead, it increases the
stamina of the player. The stamina bar shows how well fed the player
is. More bread pieces means more stamina.
Walking while holding down Aux1 (usually E key) will make player sprint so
long as their stamina bar is 3 or more bread. This will make the player run
that bit faster and jump a tiny bit higher.
Q&A time: Why won't I move the stamina bar to the right?
Answer: this conflicts with the builtin breath bar. To move the
builtin breath bar, I basically have to entirely re-implement it
in lua including timers to catch breath changes for each online
player, which is all a waste of time, just to move a few pixels
around.
For Modders:
------------
This mod intercepts minetest.item_eat(), and applies the hp_change
as stamina change. The value can be positive (increase stamina) or
negative (periodically damage the player by 1 hp).
Callbacks that are registered via minetest.register_on_item_eat()
are called after this mod, so the itemstack will have changed already
when callbacks are called. You can get the original itemstack as 6th
parameter of your function then.
A global function is available for mods to change player stamina levels:
stamina.change_saturation(player, change)
Function to get player saturation level:
stamina.get_saturation(player)
Function to set player saturation level:
stamina.set_saturation(player, level)
Function to check if player is poisoned, returns True if so:
stamina.is_poisoned(player)
Function to check if player is drunk, returns True if so:
stamina.is_drunk(player)
Function to exhaust player:
stamina.exhaust_player(player, change)
Function to enable/disable sprinting:
stamina.set_sprinting(player, sprinting)
TenPlus1 Additions:
-------------------
- Added support for POVA, PlayerMonoids and PlayerPhysics
- Added Pipeworks checks for fake players
- Added 60 second drunk effect when foods have {alcohol=1} group (eat 4 or more)
- Moved exhaustion and hud_id to player table instead of player attributes
- Added 4 lucky block effects
- Ability to drink {food_milk} or {food_milk_glass} food items to counteract poison/drunk
- Added API
- Added FOV effect when sprinting, and alcohol units lowers every saturation tick
- Added double-tap to sprint and 'stamina_double_tap_time' setting, 0 to disable
- Added 'stamina_hud_x' and 'stamina_hud_y' to position hunger bar
- Added 'stamina_disable_aux1' setting to force double-tap and free Aux1 key
- Added 'no_hunger' player priv
- Added stamina.is_drunk and stamina.is_poisoned function
- Added hunger charm that increases stamina by defined level when worn (3d_armor)
+824
View File
@@ -0,0 +1,824 @@
-- Translation support & localize math functions
local S = core.get_translator("stamina")
local math_max, math_min = math.max, math.min
local math_floor, math_random = math.floor, math.random
local get_node = core.get_node
local mod_armor = core.get_modpath("3d_armor")
-- clamp values helper
local function clamp(val, minval, maxval)
return math_max(math_min(val, maxval), minval)
end
-- special privelage
core.register_privilege("no_hunger", {
description = "Stops the player from experiencing hunger",
give_to_singleplayer = false
})
-- global
stamina = {
players = {}, mod = "redo",
-- time in seconds after that 1 stamina point is taken
TICK = tonumber(core.settings:get("stamina_tick")) or 800,
-- stamina ticks won't reduce stamina below this level
TICK_MIN = 4,
-- time in seconds after player gets healed/damaged
HEALTH_TICK = 4,
-- time in seconds after the movement is checked
MOVE_TICK = 0.5,
-- time in seconds after player is poisoned
POISON_TICK = 1.25,
-- time in seconds after player has drunk effects
DRUNK_TICK = 1.0,
-- length of drunk effects
DRUNK_INTERVAL = tonumber(core.settings:get("stamina_drunk_interval")) or 60,
-- exhaustion increased this value after digged node
EXHAUST_DIG = 2,
-- after placing node
EXHAUST_PLACE = 1,
-- if player movement detected
EXHAUST_MOVE = 1.5,
-- if jumping
EXHAUST_JUMP = 5,
-- if player crafts
EXHAUST_CRAFT = 2,
-- if player punches another player
EXHAUST_PUNCH = 40,
-- at what exhaustion player saturation gets lowered
EXHAUST_LVL = 160,
-- number of HP player gets healed after stamina.HEALTH_TICK
HEAL = 1,
-- lower level of saturation needed to get healed
HEAL_LVL = 5,
-- number of HP player gets damaged by stamina after stamina.HEALTH_TICK
STARVE = 1,
-- level of staturation that causes starving
STARVE_LVL = 3,
-- hud bar extends only to 20
VISUAL_MAX = 20,
-- how much faster players can run if satiated.
SPRINT_SPEED = clamp(tonumber(
core.settings:get("stamina_sprint_speed")) or 0.5, 0.0, 1.0),
-- how much higher player can jump if satiated
SPRINT_JUMP = clamp(tonumber(
core.settings:get("stamina_sprint_jump")) or 0.1, 0.0, 1.0),
-- how fast to drain satation while sprinting (0-1)
SPRINT_DRAIN = clamp(tonumber(
core.settings:get("stamina_sprint_drain")) or 0.35, 0.0, 1.0),
enable_sprint = core.settings:get_bool("sprint") ~= false,
enable_sprint_particles = core.settings:get_bool("sprint_particles") ~= false,
-- fov change
fov_change = tonumber(core.settings:get("stamina_fov_multiplier") or 0.9),
-- double tap time
double_tap_time = tonumber(core.settings:get("stamina_double_tap_time") or 0.4),
-- do we disable aux1 to sprint
can_use_aux1 = core.settings:get_bool("stamina_disable_aux1") ~= true
}
-- are we a real player ?
local function is_player(player)
if player and type(player) == "userdata" and core.is_player(player) then
return true
end
end
-- grab stamina level
function stamina.get_saturation(player)
-- are we a real player?
if not is_player(player) then return end
local meta = player:get_meta()
local level = meta and meta:get_string("stamina:level")
if level then return tonumber(level) end
end
-- is player stamina & damage enabled
local stamina_enabled = core.settings:get_bool("enable_stamina") ~= false
local damage_enabled = core.settings:get_bool("enable_damage")
-- update stamina level
function stamina.update_saturation(player, level)
-- pipeworks fake player check
if not is_player(player) then return end
local old = stamina.get_saturation(player)
if level == old then return end -- To suppress HUD update
-- no change in saturation if player has no_hunger priv
if core.check_player_privs(player, {no_hunger = true}) then return end
local meta = player and player:get_meta() ; if not meta then return end
meta:set_string("stamina:level", level)
player:hud_change(stamina.players[player:get_player_name()].hud_id,
"number", math_min(stamina.VISUAL_MAX, level))
end
-- global function for mods to amend stamina level
function stamina.change_saturation(player, change)
local name = player:get_player_name()
if not damage_enabled or not name or not change or change == 0 then return end
local level = stamina.get_saturation(player) + change
level = clamp(level, 0, stamina.VISUAL_MAX)
stamina.update_saturation(player, level)
return true
end
stamina.change = stamina.change_saturation -- for backwards compatibility
-- check for poisoned player
function stamina.is_poisoned(player)
local name = player and player:get_player_name()
local data = stamina.players[name]
return data and data.poisoned and data.poisoned > 0
end
-- check for drunk player
function stamina.is_drunk(player)
local name = player and player:get_player_name()
local data = stamina.players[name]
return data and data.drunk and data.drunk > 0
end
-- reduce stamina level
function stamina.exhaust_player(player, v)
if not is_player(player) or not player.set_attribute then return end
local name = player:get_player_name()
local data = stamina.players[name] ; if not data then return end
local exhaustion = data.exhaustion + v
if exhaustion > stamina.EXHAUST_LVL then
exhaustion = 0
local h = stamina.get_saturation(player)
if h > 0 then stamina.update_saturation(player, h - 1) end
end
data.exhaustion = exhaustion
end
-- physics mod check
local mod_monoids = core.get_modpath("player_monoids")
local mod_pova = core.get_modpath("pova")
local mod_playerphysics = core.get_modpath("playerphysics")
-- attach helpers
local function is_attached(player)
if player:get_attach() then return true end
-- check attached children entities that would disallow sprinting
for _, obj in pairs(player:get_children()) do
local ent = obj:get_luaentity() or {}
if ent.name == "hangglider:glider" then return true end
end
end
-- turn sprint on/off
function stamina.set_sprinting(player, sprinting)
if not player or is_attached(player) then return end
local name = player:get_player_name()
local data = stamina.players[name]
local def = player:get_physics_override() -- get player physics
--print ("---", def.speed, def.jump)
if sprinting == true and not data.sprint then
if mod_pova then
pova.add_override(name, "sprint", {
speed = stamina.SPRINT_SPEED, jump = stamina.SPRINT_JUMP})
pova.do_override(player)
elseif mod_monoids then
player_monoids.speed:add_change(
player, def.speed + stamina.SPRINT_SPEED, "stamina:speed")
player_monoids.jump:add_change(
player, def.jump + stamina.SPRINT_JUMP, "stamina:jump")
elseif mod_playerphysics then
playerphysics.add_physics_factor(player, "speed", "stamina:sprint",
def.speed + stamina.SPRINT_SPEED)
playerphysics.add_physics_factor(player, "jump", "stamina:jump",
def.jump + stamina.SPRINT_JUMP)
else
player:set_physics_override({
speed = def.speed + stamina.SPRINT_SPEED,
jump = def.jump + stamina.SPRINT_JUMP,
})
end
data.sprint = true
if stamina.fov_change ~= 0 then
player:set_fov(stamina.fov_change, true, 0.2)
end
elseif sprinting == false and data.sprint then
if mod_pova then
pova.del_override(name, "sprint")
pova.do_override(player)
elseif mod_monoids then
player_monoids.speed:del_change(player, "stamina:speed")
player_monoids.jump:del_change(player, "stamina:jump")
elseif mod_playerphysics then
playerphysics.remove_physics_factor(player, "stamina:sprint")
playerphysics.remove_physics_factor(player, "stamina:jump")
else
player:set_physics_override({
speed = def.speed - stamina.SPRINT_SPEED,
jump = def.jump - stamina.SPRINT_JUMP,
})
end
data.sprint = nil
if stamina.fov_change ~= 0 then
player:set_fov(0, true, 0.4)
end
end
end
-- particle effect when eating
local function head_particle(player, texture)
local prop = player and player:get_properties() ; if not prop then return end
local pos = player:get_pos() ; pos.y = pos.y + (prop.eye_height or 1.23)
local dir = player:get_look_dir()
core.add_particlespawner({
amount = 5,
time = 0.1,
minpos = pos,
maxpos = pos,
minvel = {x = dir.x - 1, y = dir.y, z = dir.z - 1},
maxvel = {x = dir.x + 1, y = dir.y, z = dir.z + 1},
minacc = {x = 0, y = -5, z = 0},
maxacc = {x = 0, y = -9, z = 0},
minexptime = 1,
maxexptime = 1,
minsize = 1,
maxsize = 2,
texture = texture
})
end
-- drunk check
local function drunk_tick(player, name, data)
if data.drunk then
-- play burp sound every 20 seconds when drunk
local num = data.drunk
if num and num > 0 and math_floor(num / 20) == num / 20 then
head_particle(player, "bubble.png")
core.sound_play("stamina_burp", {to_player = name, gain = 0.7}, true)
end
data.drunk = data.drunk - stamina.DRUNK_TICK
if data.drunk < 1 then
data.drunk = nil ; data.units = 0
if not data.poisoned then
player:hud_change(data.hud_id, "text", "stamina_hud_fg.png")
end
end
-- effect only works when not riding boat/cart/horse etc.
if not player:get_attach() then
local yaw = player:get_look_horizontal() + math_random(-0.5, 0.5)
player:set_look_horizontal(yaw)
end
end
end
-- health check
local function health_tick(player, name, data)
local air = player:get_breath() or 0
local hp = player:get_hp()
local h = stamina.get_saturation(player)
-- if wearing hunger charm increase saturation by 1
if mod_armor then
local level = math_min(armor.def[name].hunger, 4)
if level > 0 then
stamina.update_saturation(player, h + level)
end
end
-- damage player by 1 hp if saturation is < 2
if h and h < stamina.STARVE_LVL and hp > 0 then
player:set_hp(hp - stamina.STARVE, {hunger = true})
end
-- don't heal if drowning or dead or poisoned
if h and h >= stamina.HEAL_LVL and h >= hp and hp > 0 and air > 0
and not data.poisoned then
player:set_hp(hp + stamina.HEAL)
stamina.update_saturation(player, h - 1)
end
end
-- movement check
local function action_tick(player, name, data)
local controls = player and player:get_player_control()
if controls then
if controls.jump then
stamina.exhaust_player(player, stamina.EXHAUST_JUMP)
elseif controls.up or controls.down or controls.left or controls.right then
stamina.exhaust_player(player, stamina.EXHAUST_MOVE)
end
end
--- START sprint
if stamina.enable_sprint and controls then
-- check if player can sprint (stamina must be over 6 points)
if not data.poisoned and not data.drunk and controls.up and not controls.down
and ((controls.aux1 and stamina.can_use_aux1) or data.double_tap)
and not core.check_player_privs(player, {fast = true})
and stamina.get_saturation(player) > 6 then
stamina.set_sprinting(player, true)
-- create particles behind player when sprinting
if stamina.enable_sprint_particles then
local pos = player:get_pos()
local node = get_node({x = pos.x, y = pos.y - 1, z = pos.z})
local def = minetest.registered_nodes[node.name] or {}
if def.drawtype ~= "airlike" and def.drawtype ~= "liquid"
and def.drawtype ~= "flowingliquid" then
local particle_def = {
amount = 5,
time = 0.5,
minpos = {x = -0.3, y = 0.1, z = -0.3},
maxpos = {x = 0.3, y = 0.1, z = 0.3},
minvel = {x = 0, y = 4, z = 0},
maxvel = {x = 0, y = 4, z = 0},
minacc = {x = 0, y = -13, z = 0},
maxacc = {x = 0, y = -13, z = 0},
minexptime = 0.1,
maxexptime = 1,
minsize = 0.5,
maxsize = 1.5,
vertical = false,
collisiondetection = false,
attached = player,
texture = "stamina_sprint_particle.png"
}
if def.type == "node" then
particle_def.node = {name = node.name, param2 = 0}
end
core.add_particlespawner(particle_def)
end
end
-- Lower the player's stamina when sprinting
local level = stamina.get_saturation(player)
stamina.update_saturation(player,
level - (stamina.SPRINT_DRAIN * stamina.MOVE_TICK))
else
stamina.set_sprinting(player, false) ; data.double_tap = false
end
end
end
-- poisoned check
local function poison_tick(player, name, data)
if data.poisoned and data.poisoned > 0 then
data.poisoned = data.poisoned - 1
local hp = player:get_hp() - 1
head_particle(player, "stamina_poison_particle.png")
if hp > 0 then
player:set_hp(hp, {poison = true})
end
elseif data.poisoned then
if not data.drunk then
player:hud_change(data.hud_id, "text", "stamina_hud_fg.png")
end
data.poisoned = nil
end
end
-- stamina check
local function stamina_tick(player, name, data)
local h = player and stamina.get_saturation(player)
if h and h > stamina.TICK_MIN then
stamina.update_saturation(player, h - 1)
end
if data.units and data.units > 0 then
data.units = data.units - 1
end
end
-- check for double tap forward (thanks xXOsielXx)
local function check_for_double_tap(controls, data)
if stamina.double_tap_time == 0 then return end
if controls and controls.up and not data.was_pressing_forward and not controls.down
and not controls.sneak and not data.sprint then
local current_time = core.get_us_time() / 1e6
if (current_time - (data.last_key_time or 0)) < stamina.double_tap_time then
return true
end
data.double_tap = false
data.last_key_time = current_time
end
end
-- check if player double taps
local function double_tap_tick(player, name, data)
local control = player:get_player_control()
local double_tap = check_for_double_tap(control, data)
if double_tap then
data.double_tap = true
end
data.was_pressing_forward = control.up
end
-- Time based stamina functions
local stamina_timer, health_timer, action_timer, poison_timer, drunk_timer = 0,0,0,0,0
local function stamina_globaltimer(dtime)
stamina_timer = stamina_timer + dtime
health_timer = health_timer + dtime
action_timer = action_timer + dtime
poison_timer = poison_timer + dtime
drunk_timer = drunk_timer + dtime
-- loop through all players once only
for _, player in pairs(core.get_connected_players()) do
local name = player and player:get_player_name()
local data = stamina.players[name]
if data then -- nil check
-- check for double taps
double_tap_tick(player, name, data)
-- simulate drunk walking (thanks LumberJ)
if drunk_timer > stamina.DRUNK_TICK then drunk_tick(player, name, data) end
-- hurt player when poisoned
if poison_timer > stamina.POISON_TICK then poison_tick(player, name, data) end
-- sprint control and particle animation
if action_timer > stamina.MOVE_TICK then action_tick(player, name, data) end
-- lower saturation by 1 point after stamina.TICK
if stamina_timer > stamina.TICK then stamina_tick(player, name, data) end
-- heal or damage player, depending on saturation
if health_timer > stamina.HEALTH_TICK then health_tick(player, name, data) end
end
end
-- reset timers where needed
if drunk_timer > stamina.DRUNK_TICK then drunk_timer = 0 end
if poison_timer > stamina.POISON_TICK then poison_timer = 0 end
if action_timer > stamina.MOVE_TICK then action_timer = 0 end
if stamina_timer > stamina.TICK then stamina_timer = 0 end
if health_timer > stamina.HEALTH_TICK then health_timer = 0 end
end
-- stamina and eating functions disabled if damage is disabled
if damage_enabled and core.settings:get_bool("enable_stamina") ~= false then
-- override core.do_item_eat() so we can redirect hp_change to stamina
core.do_item_eat = function(hp_change, replace_with_item, itemstack, user, pointed_thing)
if not is_player(user) then return end -- abort if called by fake player
local old_itemstack = itemstack
itemstack = stamina.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
-- not local since it's called from within core context
function stamina.eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
if not itemstack or not user then return itemstack end
local level = stamina.get_saturation(user) or 0
if level >= stamina.VISUAL_MAX then return itemstack end
local name = user:get_player_name()
local data = stamina.players[name]
if hp_change > 0 then
stamina.update_saturation(user, level + hp_change)
elseif hp_change < 0 then
user:hud_change(data.hud_id, "text", "stamina_hud_poison.png")
data.poisoned = -hp_change
end
-- if {drink=1} or {food=3} groups set then use sip sound instead of eat
local snd, gain = "stamina_eat", 0.7
local item_name = itemstack:get_name() or ""
local item_def = core.registered_items[item_name] or {groups = {}}
if item_def.groups.drink == 1 or item_def.groups.food == 3 then
snd = "stamina_sip" ; gain = 1.0
end
core.sound_play(snd, {to_player = name, gain = gain}, true)
-- particle effect when eating
head_particle(user, (item_def.inventory_image or item_def.wield_image))
-- if player drinks any milk food groups they stop being poisoned or drunk
if item_def.groups.food_milk == 1 or item_def.groups.food_milk_glass == 1 then
data.poisoned = 0 ; data.drunk = 0
end
itemstack:take_item()
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:get_pos()
if pos then core.add_item(pos, replace_with_item) end
end
end
end
-- check for alcohol
local units = item_def.groups.alcohol or 0
if units > 0 then
data.units = (data.units or 0) + 1
if data.units > 3 then
data.drunk = stamina.DRUNK_INTERVAL ; data.units = 0
user:hud_change(data.hud_id, "text", "stamina_hud_poison.png")
core.chat_send_player(name,
core.get_color_escape_sequence("#4b5320")
.. S("You suddenly feel tipsy!"))
end
end
return itemstack
end
core.register_on_joinplayer(function(player)
if not player then return end
local level = stamina.VISUAL_MAX -- TODO
if stamina.get_saturation(player) then
level = math_min(stamina.get_saturation(player), stamina.VISUAL_MAX)
end
local meta = player:get_meta()
if meta then meta:set_string("stamina:level", level) end
local off = {
x = (tonumber(core.settings:get("stamina_hud_x")) or -266),
y = (tonumber(core.settings:get("stamina_hud_y")) or -110)
}
local name = player:get_player_name()
local hud_style = core.has_feature("hud_def_type_field")
local hud_tab = {
name = "stamina",
position = {x = 0.5, y = 1},
size = {x = 24, y = 24},
text = "stamina_hud_fg.png",
number = level,
alignment = {x = -1, y = -1},
offset = off,
max = 0
}
if hud_style then
hud_tab["type"] = "statbar"
else
hud_tab["hud_elem_type"] = "statbar"
end
local id = player:hud_add(hud_tab)
stamina.players[name] = {
hud_id = id, exhaustion = 0, poisoned = nil, drunk = nil, sprint = nil}
end)
core.register_on_respawnplayer(function(player)
local name = player and player:get_player_name() ; if not name then return end
local data = stamina.players[name]
if data.poisoned or data.drunk then
player:hud_change(data.hud_id, "text", "stamina_hud_fg.png")
end
data.exhaustion = 0
data.poisoned = nil
data.drunk = nil
data.sprint = nil
stamina.update_saturation(player, stamina.VISUAL_MAX)
if stamina.fov_change ~= 0 then
player:set_fov(1, true, 0.2)
end
end)
core.register_globalstep(stamina_globaltimer)
core.register_on_placenode(function(pos, oldnode, player, ext)
stamina.exhaust_player(player, stamina.EXHAUST_PLACE)
end)
core.register_on_dignode(function(pos, oldnode, player, ext)
stamina.exhaust_player(player, stamina.EXHAUST_DIG)
end)
core.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
stamina.exhaust_player(player, stamina.EXHAUST_CRAFT)
end)
core.register_on_punchplayer(function(player, hitter, tflp, toolcaps, dir, damage)
stamina.exhaust_player(hitter, stamina.EXHAUST_PUNCH)
end)
else -- create player table on join
core.register_on_joinplayer(function(player)
if player then
stamina.players[player:get_player_name()] = {
poisoned = nil, sprint = nil, drunk = nil, exhaustion = 0}
end
end)
end
-- clear data when player leaves
core.register_on_leaveplayer(function(player)
if player then
stamina.players[player:get_player_name()] = nil
end
end)
-- add lucky blocks (if damage and stamina active)
if core.get_modpath("lucky_block")
and core.settings:get_bool("enable_damage")
and core.settings:get_bool("enable_stamina") ~= false then
dofile(core.get_modpath(core.get_current_modname()) .. "/lucky_block.lua")
end
-- hunger charm
if mod_armor then
table.insert(armor.elements, "charm")
table.insert(armor.attributes, "hunger")
armor:register_armor("stamina:charm_hunger", {
description = S("Hunger Charm\n(wear to slowly increase stamina)"),
inventory_image = "stamina_hunger_charm.png",
-- armor_groups = {fleshy=100},
groups = {armor_charm = 1, armor_hunger = 1},
preview = "blank.png",
texture = "blank.png"
})
end
print("[MOD] Stamina loaded")
+31
View File
@@ -0,0 +1,31 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Code:
- all code LGPL-2.1+
Textures:
- stamina_hud_poison.png - BlockMen (CC-BY 3.0)
- stamina_hud_fg.png - PilzAdam (WTFPL), modified by BlockMen
- stamina_hud_bg.png - PilzAdam (WTFPL), modified by BlockMen
Sounds (CC-BY-3.0):
- stamina_eat.*.ogg - http://www.freesound.org/people/sonictechtonic/sounds/242215/
- stamina_burp.ogg - https://www.freesfx.co.uk/sfx/burp (small burp)
Sounds (Attribution 3.0):
- stamina_sip.1.ogg - https://freesound.org/people/Stevious42/sounds/259640/
Sound (Creative Commons 0):
- stamina_sip.2.ogg - https://freesound.org/people/SeanPorio/sounds/519268/
+6
View File
@@ -0,0 +1,6 @@
# textdomain:stamina
You suddenly feel tipsy!=
You suddenly feel full!=
Seems you have been poisoned!=
Hunger Charm\n(wear to slowly increase stamina)=
+85
View File
@@ -0,0 +1,85 @@
local S = core.get_translator("stamina")
-- colour helpers
local green = core.get_color_escape_sequence("#bada55")
local green2 = core.get_color_escape_sequence("#33ff55")
-- poison and drunk effects function
local effect_me = function(pos, player, def)
local name = player:get_player_name() ; if not name then return end
if def.poison or def.drunk then
player:hud_change(stamina.players[name].hud_id, "text", "stamina_hud_poison.png")
end
if def.poison and def.poison > 0 then
stamina.players[name].poisoned = def.poison
core.chat_send_player(name, green .. S("Seems you have been poisoned!"))
elseif def.drunk and def.drunk > 0 then
stamina.players[name].drunk = def.drunk
core.chat_send_player(name, green .. S("You suddenly feel tipsy!"))
end
end
-- restore stamina function
local full_stamina = function(pos, player, def)
local name = player:get_player_name() ; if not name then return end
stamina.change(player, 100) -- set to 100 incase of default stamina increase
core.chat_send_player(name, green2 .. S("You suddenly feel full!"))
end
-- drop food item with chance of food charm
local food_list = {}
if core.get_modpath("default") then
table.insert(food_list, "default:apple")
table.insert(food_list, "default:blueberries")
table.insert(food_list, "farming:bread")
end
core.after(0.1, function() -- let mods load than add all food items to list
for item, def in pairs(core.registered_items) do
if def.groups.food then
table.insert(food_list, item)
end
end
end)
local food_drop = function(pos, player, def)
local drop = food_list[math.random(#food_list)]
if math.random(100) == 7 then drop = "stamina:charm_hunger" end
local obj = core.add_item(pos, drop)
if obj then
obj:set_velocity({x = math.random() - 0.5, y = 5, z = math.random() - 0.5})
end
end
-- add lucky blocks
lucky_block:add_blocks({
{"cus", full_stamina},
{"cus", effect_me, {poison = 5}},
{"cus", effect_me, {poison = 10}},
{"cus", effect_me, {drunk = 30}},
{"cus", food_drop}
})
+4
View File
@@ -0,0 +1,4 @@
name = stamina
description = Adds stamina, hunger and drunk effects.
optional_depends = default, 3d_armor, player_monoids, pova, lucky_block, playerphysics
min_minetest_version = 5.4
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

+25
View File
@@ -0,0 +1,25 @@
sprint (Enable sprint) bool true
sprint_particles (Enable sprint particles) bool true
enable_stamina (Enable stamina/hunger) bool true
stamina_disable_aux1 (Disable aux1 for sprinting) bool false
stamina_tick (Time in seconds after which 1 saturation point is taken) float 800
stamina_sprint_speed (Extra sprint speed - 0.0 to 1.0) float 0.3
stamina_sprint_jump (Extra sprint jump height - 0.0 to 1.0) float 0.1
stamina_sprint_drain (Sprint stamina drain - 0.0 to 1.0) float 0.35
stamina_fov_multiplier (Sprinting FOV effect - 0 to disable) float 0.9
stamina_double_tap_time (Double-tap time for sprinting - 0 to disable) float 0.4
stamina_drunk_interval (How long is player drunk for) int 60
stamina_hud_x (Hunger X pos [-266 left, 25 right]) int -266
stamina_hud_y (Hunger Y pos [-110 over hearts, -132 one row up]) int -110
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B