--[[ Damage mod. This mod introduces a custom "damage" mechanic for players. It is completely separate from Luanti's built-in health system, which is ignored in this game. Players can have 0 to lzr_damage.MAX_DAMAGE. Damage in this mod is just a visual effect on the screen but has no gameplay effect on its own. But it can be queried when the player has reached a certain damage. Damage is never lethal. Players may also receive damage of the type "scorched", which will change the player model and wieldhand texture and wieldhand to a scorched version until player_damage is reduced to 0. The player damage can be added to, or reset to 0. When the player has damage, it will slowly be reduced to 0 again. Damage is mostly useful as an effect to simulate the player being "hurt" without ]] lzr_damage = {} -- Note this game does NOT use regular damage and health, as defined -- by Luanti, it's disabled. The "damage" here applies only to this mod! lzr_damage.MAX_DAMAGE = 4 -- Reduce damage when player didn't take damage every HEAL_TIME -- seconds. local HEAL_TIME = 3.0 -- Player damage increases roughly every second the player is in danger, -- and decreases while out of danger local player_damage = 0 -- If true, player is using the scorched texture local player_is_scorched = false -- Count the time for how many consecutive seconds the player did -- not take damage yet. local safe_timer = 0 local damage_screen local update_damage_screen = function(player) if player_damage == 0 then if damage_screen then player:hud_remove(damage_screen) damage_screen = nil end else local texture = "lzr_damage_screen_"..player_damage..".png" if not damage_screen then damage_screen = player:hud_add({ type = "image", scale = { x = -100, y = -100 }, text = texture, alignment = { x = 1, y = 1 }, position = { x = 0, y = 0 }, z_index = -400, }) else player:hud_change(damage_screen, "text", texture) end end end local update_player_skin = function(player) if player_is_scorched then local state = lzr_gamestate.get_state() if state ~= lzr_gamestate.EDITOR and state ~= lzr_gamestate.DEV then lzr_hand.set_hand(player, "scorched") player_api.set_textures(player, {"character_scorched.png"}) end else lzr_hand.set_hand(player, "normal") player_api.set_textures(player, {"character.png"}) end end lzr_damage.reset_player_damage = function(player) local player_was_scorched = player_is_scorched local player_was_damaged = player_damage > 0 player_damage = 0 player_is_scorched = false if player_was_scorched then update_player_skin(player) end if player_was_damaged then update_damage_screen(player) end end lzr_damage.damage_player = function(player, damage, damage_type) safe_timer = 0 player_damage = player_damage + (damage or 1) if player_damage > lzr_damage.MAX_DAMAGE then player_damage = lzr_damage.MAX_DAMAGE end local gain if player_damage >= 3 then gain = 1 elseif player_damage >= 2 then gain = 0.7 else gain = 0.4 end local texture = "lzr_damage_screen_"..player_damage..".png" if player_damage >= 1 and damage_type == "scorch" then player_is_scorched = true update_player_skin(player) end update_damage_screen(player) minetest.sound_play({name="lzr_damage_damage", gain=gain}, {to_player=player:get_player_name()}, true) end local undamage_player = function(player) player_damage = math.max(0, player_damage - 1) if player_damage == 0 and player_is_scorched then player_is_scorched = false update_player_skin(player) end update_damage_screen(player) end lzr_damage.get_player_damage = function(player) return player_damage end -- Slowly reduce damage to 0 when player hasn’t been -- damaged for a while. minetest.register_globalstep(function(dtime) safe_timer = safe_timer + dtime if safe_timer < HEAL_TIME then return end safe_timer = 0 local players = minetest.get_connected_players() local state = lzr_gamestate.get_state() if state ~= lzr_gamestate.LEVEL and state ~= lzr_gamestate.LEVEL_COMPLETE and state ~= lzr_gamestate.LEVEL_TEST then return end for p=1, #players do local player = players[p] undamage_player(player) end end) -- Reset player damage when entering any state but the level states lzr_gamestate.register_on_enter_state(function(new_state) if new_state ~= lzr_gamestate.LEVEL and new_state ~= lzr_gamestate.LEVEL_COMPLETE and new_state ~= lzr_gamestate.LEVEL_TEST then local player = minetest.get_player_by_name("singleplayer") if player then lzr_damage.reset_player_damage(player) end end end)