158 lines
4.5 KiB
Lua
158 lines
4.5 KiB
Lua
--[[
|
||
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)
|