diff --git a/init.lua b/init.lua index aed0450..cd62a09 100644 --- a/init.lua +++ b/init.lua @@ -143,63 +143,65 @@ local function set_sprinting(name, sprinting) local player = minetest.get_player_by_name(name) - -- get player physics - local def = player:get_physics_override() + if player then + -- get player physics + local def = player:get_physics_override() ---print ("---", def.speed, def.jump) + --print ("---", def.speed, def.jump) - if sprinting == true and not stamina.players[name].sprint then + if sprinting == true and not stamina.players[name].sprint then - if monoids then + if monoids then - stamina.players[name].sprint = player_monoids.speed:add_change( - player, def.speed + SPRINT_SPEED) + stamina.players[name].sprint = player_monoids.speed:add_change( + player, def.speed + SPRINT_SPEED) - stamina.players[name].jump = player_monoids.jump:add_change( - player, def.jump + SPRINT_JUMP) + stamina.players[name].jump = player_monoids.jump:add_change( + player, def.jump + SPRINT_JUMP) - elseif pova_mod then + elseif pova_mod then - pova.add_override(name, "sprint", - {speed = SPRINT_SPEED, jump = SPRINT_JUMP}) + pova.add_override(name, "sprint", + {speed = SPRINT_SPEED, jump = SPRINT_JUMP}) - pova.do_override(player) + pova.do_override(player) - stamina.players[name].sprint = true - else - player:set_physics_override({ - speed = def.speed + SPRINT_SPEED, - jump = def.jump + SPRINT_JUMP, - }) + stamina.players[name].sprint = true + else + player:set_physics_override({ + speed = def.speed + SPRINT_SPEED, + jump = def.jump + SPRINT_JUMP, + }) - stamina.players[name].sprint = true - end + stamina.players[name].sprint = true + end - elseif sprinting == false - and stamina.players[name] - and stamina.players[name].sprint then + elseif sprinting == false + and stamina.players[name] + and stamina.players[name].sprint then - if monoids then + if monoids then - player_monoids.speed:del_change(player, stamina.players[name].sprint) - player_monoids.jump:del_change(player, stamina.players[name].jump) + player_monoids.speed:del_change(player, stamina.players[name].sprint) + player_monoids.jump:del_change(player, stamina.players[name].jump) - stamina.players[name].sprint = nil - stamina.players[name].jump = nil + stamina.players[name].sprint = nil + stamina.players[name].jump = nil - elseif pova_mod then + elseif pova_mod then - pova.del_override(name, "sprint") - pova.do_override(player) + pova.del_override(name, "sprint") + pova.do_override(player) - stamina.players[name].sprint = nil - else - player:set_physics_override({ - speed = def.speed - SPRINT_SPEED, - jump = def.jump - SPRINT_JUMP, - }) + stamina.players[name].sprint = nil + else + player:set_physics_override({ + speed = def.speed - SPRINT_SPEED, + jump = def.jump - SPRINT_JUMP, + }) - stamina.players[name].sprint = nil + stamina.players[name].sprint = nil + end end end end @@ -207,71 +209,79 @@ end local function head_particle(player, texture) - local prop = player:get_properties() - local pos = player:get_pos() ; pos.y = pos.y + prop.eye_height -- mouth level - local dir = player:get_look_dir() + if player then + local prop = player:get_properties() + local eye_height = prop.eye_height or 1.23 + local pos = player:get_pos() ; pos.y = pos.y + eye_height -- mouth level + local dir = player:get_look_dir() - minetest.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 - }) + minetest.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 end local function drunk_tick() for _,player in ipairs(minetest.get_connected_players()) do - local name = player:get_player_name() + if player then - if name - and stamina.players[name] - and stamina.players[name].drunk then + local name = player:get_player_name() - -- play burp sound every 20 seconds when drunk - local num = stamina.players[name].drunk + if name + and stamina.players[name] + and stamina.players[name].drunk then - if num and num > 0 and math.floor(num / 20) == num / 20 then + -- play burp sound every 20 seconds when drunk + local num = stamina.players[name].drunk - head_particle(player, "bubble.png") + if num and num > 0 and math.floor(num / 20) == num / 20 then - minetest.sound_play("stamina_burp", - {to_player = name, gain = 0.7}, true) - end + head_particle(player, "bubble.png") - stamina.players[name].drunk = stamina.players[name].drunk - 1 + minetest.sound_play("stamina_burp", + {to_player = name, gain = 0.7}, true) + end - if stamina.players[name].drunk < 1 then + stamina.players[name].drunk = stamina.players[name].drunk - 1 - stamina.players[name].drunk = nil - stamina.players[name].units = 0 + if stamina.players[name].drunk < 1 then - if not stamina.players[name].poisoned then + stamina.players[name].drunk = nil + stamina.players[name].units = 0 - player:hud_change(stamina.players[name].hud_id, - "text", "stamina_hud_fg.png") + if not stamina.players[name].poisoned then + + player:hud_change(stamina.players[name].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 - -- 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 end @@ -280,29 +290,32 @@ local function health_tick() for _,player in ipairs(minetest.get_connected_players()) do - local air = player:get_breath() or 0 - local hp = player:get_hp() - local h = get_int_attribute(player) - local name = player:get_player_name() + if player then - if name then + local air = player:get_breath() or 0 + local hp = player:get_hp() + local h = get_int_attribute(player) + local name = player:get_player_name() - -- 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 + if name then - -- 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 stamina.players[name].poisoned then + -- 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 - player:set_hp(hp + STAMINA_HEAL) + -- 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 stamina.players[name].poisoned then - stamina_update_level(player, h - 1) + player:set_hp(hp + STAMINA_HEAL) + + stamina_update_level(player, h - 1) + end end end end @@ -313,82 +326,85 @@ local function action_tick() for _,player in ipairs(minetest.get_connected_players()) do - local controls = player and player:get_player_control() + if player then - -- Determine if the player is walking or jumping - if controls then + local controls = player and player:get_player_control() - if controls.jump then - exhaust_player(player, STAMINA_EXHAUST_JUMP) + -- Determine if the player is walking or jumping + if controls then - elseif controls.up - or controls.down - or controls.left - or controls.right then - exhaust_player(player, STAMINA_EXHAUST_MOVE) + if controls.jump then + exhaust_player(player, STAMINA_EXHAUST_JUMP) + + elseif controls.up + or controls.down + or controls.left + or controls.right then + exhaust_player(player, STAMINA_EXHAUST_MOVE) + end end - end - --- START sprint - if enable_sprint then + --- START sprint + if enable_sprint then - local name = player and player:get_player_name() + local name = player and player:get_player_name() - -- check if player can sprint (stamina must be over 6 points) - if name - and stamina.players[name] - and not stamina.players[name].poisoned - and not stamina.players[name].drunk - and controls and controls.aux1 and controls.up - and not minetest.check_player_privs(player, {fast = true}) - and get_int_attribute(player) > 6 then + -- check if player can sprint (stamina must be over 6 points) + if name + and stamina.players[name] + and not stamina.players[name].poisoned + and not stamina.players[name].drunk + and controls and controls.aux1 and controls.up + and not minetest.check_player_privs(player, {fast = true}) + and get_int_attribute(player) > 6 then - set_sprinting(name, true) + set_sprinting(name, true) - -- create particles behind player when sprinting - if enable_sprint_particles then + -- create particles behind player when sprinting + if enable_sprint_particles then - local pos = player:get_pos() - local node = minetest.get_node({ - x = pos.x, - y = pos.y - 1, - z = pos.z - }) - - if node.name ~= "air" then - - minetest.add_particlespawner({ - amount = 5, - time = 0.01, - minpos = {x = pos.x - 0.25, y = pos.y + 0.1, z = pos.z - 0.25}, - maxpos = {x = pos.x + 0.25, y = pos.y + 0.1, z = pos.z + 0.25}, - minvel = {x = -0.5, y = 1, z = -0.5}, - maxvel = {x = 0.5, y = 2, z = 0.5}, - minacc = {x = 0, y = -5, z = 0}, - maxacc = {x = 0, y = -12, z = 0}, - minexptime = 0.25, - maxexptime = 0.5, - minsize = 0.5, - maxsize = 1.0, - vertical = false, - collisiondetection = false, - texture = "default_dirt.png" + local pos = player:get_pos() + local node = minetest.get_node({ + x = pos.x, + y = pos.y - 1, + z = pos.z }) + if node.name ~= "air" then + + minetest.add_particlespawner({ + amount = 5, + time = 0.01, + minpos = {x = pos.x - 0.25, y = pos.y + 0.1, z = pos.z - 0.25}, + maxpos = {x = pos.x + 0.25, y = pos.y + 0.1, z = pos.z + 0.25}, + minvel = {x = -0.5, y = 1, z = -0.5}, + maxvel = {x = 0.5, y = 2, z = 0.5}, + minacc = {x = 0, y = -5, z = 0}, + maxacc = {x = 0, y = -12, z = 0}, + minexptime = 0.25, + maxexptime = 0.5, + minsize = 0.5, + maxsize = 1.0, + vertical = false, + collisiondetection = false, + texture = "default_dirt.png" + }) + + end end + + -- Lower the player's stamina when sprinting + local level = get_int_attribute(player) + + stamina_update_level(player, + level - (SPRINT_DRAIN * STAMINA_MOVE_TICK)) + + elseif name then + set_sprinting(name, false) end - - -- Lower the player's stamina when sprinting - local level = get_int_attribute(player) - - stamina_update_level(player, - level - (SPRINT_DRAIN * STAMINA_MOVE_TICK)) - - elseif name then - set_sprinting(name, false) end + -- END sprint end - -- END sprint end end @@ -397,35 +413,38 @@ local function poison_tick() for _,player in ipairs(minetest.get_connected_players()) do - local name = player and player:get_player_name() + if player then - if name - and stamina.players[name] - and stamina.players[name].poisoned - and stamina.players[name].poisoned > 0 then + local name = player:get_player_name() - stamina.players[name].poisoned = - stamina.players[name].poisoned - 1 + if name + and stamina.players[name] + and stamina.players[name].poisoned + and stamina.players[name].poisoned > 0 then - local hp = player:get_hp() - 1 + stamina.players[name].poisoned = + stamina.players[name].poisoned - 1 - head_particle(player, "stamina_poison_particle.png") + local hp = player:get_hp() - 1 - if hp > 0 then - player:set_hp(hp, {poison = true}) + head_particle(player, "stamina_poison_particle.png") + + if hp > 0 then + player:set_hp(hp, {poison = true}) + end + + elseif name + and stamina.players[name] + and stamina.players[name].poisoned then + + if not stamina.players[name].drunk then + + player:hud_change(stamina.players[name].hud_id, + "text", "stamina_hud_fg.png") + end + + stamina.players[name].poisoned = nil end - - elseif name - and stamina.players[name] - and stamina.players[name].poisoned then - - if not stamina.players[name].drunk then - - player:hud_change(stamina.players[name].hud_id, - "text", "stamina_hud_fg.png") - end - - stamina.players[name].poisoned = nil end end end @@ -435,11 +454,16 @@ local function stamina_tick() for _,player in ipairs(minetest.get_connected_players()) do - local h = get_int_attribute(player) + if player then + + local h = get_int_attribute(player) + + if h and h > STAMINA_TICK_MIN then + stamina_update_level(player, h - 1) + end - if h and h > STAMINA_TICK_MIN then - stamina_update_level(player, h - 1) end + end end @@ -614,53 +638,57 @@ and minetest.settings:get_bool("enable_stamina") ~= false then local level = STAMINA_VISUAL_MAX -- TODO - if get_int_attribute(player) then + if player then + if get_int_attribute(player) then - level = math.min(get_int_attribute(player), STAMINA_VISUAL_MAX) - else - local meta = player:get_meta() + level = math.min(get_int_attribute(player), STAMINA_VISUAL_MAX) + else + local meta = player:get_meta() - meta:set_string("stamina:level", level) + meta:set_string("stamina:level", level) + end + + local name = player:get_player_name() + + local id = player:hud_add({ + name = "stamina", + hud_elem_type = "statbar", + position = {x = 0.5, y = 1}, + size = {x = 24, y = 24}, + text = "stamina_hud_fg.png", + number = level, + alignment = {x = -1, y = -1}, + offset = {x = -266, y = -110}, + max = 0 + }) + + stamina.players[name] = { + hud_id = id, + exhaustion = 0, + poisoned = nil, + drunk = nil, + sprint = nil + } end - - local name = player:get_player_name() - - local id = player:hud_add({ - name = "stamina", - hud_elem_type = "statbar", - position = {x = 0.5, y = 1}, - size = {x = 24, y = 24}, - text = "stamina_hud_fg.png", - number = level, - alignment = {x = -1, y = -1}, - offset = {x = -266, y = -110}, - max = 0 - }) - - stamina.players[name] = { - hud_id = id, - exhaustion = 0, - poisoned = nil, - drunk = nil, - sprint = nil - } end) minetest.register_on_respawnplayer(function(player) - local name = player:get_player_name() + if player then + local name = player:get_player_name() - if stamina.players[name].poisoned - or stamina.players[name].drunk then - player:hud_change(stamina.players[name].hud_id, "text", "stamina_hud_fg.png") + if stamina.players[name].poisoned + or stamina.players[name].drunk then + player:hud_change(stamina.players[name].hud_id, "text", "stamina_hud_fg.png") + end + + stamina.players[name].exhaustion = 0 + stamina.players[name].poisoned = nil + stamina.players[name].drunk = nil + stamina.players[name].sprint = nil + + stamina_update_level(player, STAMINA_VISUAL_MAX) end - - stamina.players[name].exhaustion = 0 - stamina.players[name].poisoned = nil - stamina.players[name].drunk = nil - stamina.players[name].sprint = nil - - stamina_update_level(player, STAMINA_VISUAL_MAX) end) minetest.register_globalstep(stamina_globaltimer) @@ -686,14 +714,18 @@ else -- create player table on join minetest.register_on_joinplayer(function(player) - stamina.players[player:get_player_name()] = { - poisoned = nil, sprint = nil, drunk = nil, exhaustion = 0} + if player then + stamina.players[player:get_player_name()] = { + poisoned = nil, sprint = nil, drunk = nil, exhaustion = 0} + end end) end -- clear when player leaves minetest.register_on_leaveplayer(function(player) - stamina.players[player:get_player_name()] = nil + if player then + stamina.players[player:get_player_name()] = nil + end end) @@ -705,28 +737,31 @@ and minetest.settings:get_bool("enable_stamina") ~= false then local effect_me = function(pos, player, def) local green = minetest.get_color_escape_sequence("#bada55") - local name = player:get_player_name() + if player then + local name = player:get_player_name() - if def.poison or def.drunk then + if def.poison or def.drunk then - player:hud_change(stamina.players[name].hud_id, - "text", "stamina_hud_poison.png") + 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 + + minetest.chat_send_player(name, + green .. "Seems you have been poisoned!") + + elseif def.drunk and def.drunk > 0 then + + stamina.players[name].drunk = def.drunk + + minetest.chat_send_player(name, + green .. "You seem a little tipsy!") + end end - if def.poison and def.poison > 0 then - - stamina.players[name].poisoned = def.poison - - minetest.chat_send_player(name, - green .. "Seems you have been poisoned!") - - elseif def.drunk and def.drunk > 0 then - - stamina.players[name].drunk = def.drunk - - minetest.chat_send_player(name, - green .. "You seem a little tipsy!") - end end lucky_block:add_blocks({