Erinfest/mods/ENTITIES/mcl_burning/init.lua

132 lines
3.9 KiB
Lua

local modpath = minetest.get_modpath(minetest.get_current_modname())
mcl_burning = {
-- the storage table holds a list of objects (players,luaentities) and tables
-- associated with these objects. These tables have the following attributes:
-- burn_time:
-- Remaining time that object will burn.
-- fire_damage_timer:
-- Timer for dealing damage every second while burning.
-- fire_hud_id:
-- HUD id of the flames animation on a burning player's HUD.
-- animation_frame:
-- The HUD's current animation frame, used by update_hud().
-- collisionbox_cache:
-- Used by mcl_burning.get_collisionbox() to avoid recalculations.
storage = {}
}
dofile(modpath .. "/api.lua")
local pairs = pairs
local get_connected_players = minetest.get_connected_players
local get_item_group = minetest.get_item_group
minetest.register_globalstep(function(dtime)
for _, player in pairs(get_connected_players()) do
local storage = mcl_burning.storage[player]
if not mcl_burning.tick(player, dtime, storage) and not mcl_burning.is_affected_by_rain(player) then
local nodes = mcl_burning.get_touching_nodes(player, {"group:puts_out_fire", "group:set_on_fire"}, storage)
local burn_time = 0
for _, pos in pairs(nodes) do
local node = minetest.get_node(pos)
if get_item_group(node.name, "puts_out_fire") > 0 then
burn_time = 0
break
end
local value = get_item_group(node.name, "set_on_fire")
if value > burn_time then
burn_time = value
end
end
if burn_time > 0 then
mcl_burning.set_on_fire(player, burn_time)
end
end
end
end)
minetest.register_on_respawnplayer(function(player)
mcl_burning.extinguish(player)
end)
minetest.register_on_joinplayer(function(player)
local storage = {}
local burn_data = player:get_meta():get_string("mcl_burning:data")
if burn_data ~= "" then
storage = minetest.deserialize(burn_data) or storage
end
mcl_burning.storage[player] = storage
if storage.burn_time and storage.burn_time > 0 then
mcl_burning.update_hud(player)
end
end)
local function on_leaveplayer(player)
local storage = mcl_burning.storage[player]
if not storage then
-- For some unexplained reasons, mcl_burning.storage can be `nil` here.
-- Logging this exception to assist in finding the cause of this.
minetest.log("warning", "on_leaveplayer: missing mcl_burning.storage "
.. "for player " .. player:get_player_name())
storage = {}
end
storage.fire_hud_id = nil
player:get_meta():set_string("mcl_burning:data", minetest.serialize(storage))
mcl_burning.storage[player] = nil
end
minetest.register_on_leaveplayer(function(player)
on_leaveplayer(player)
end)
minetest.register_on_shutdown(function()
for _,player in ipairs(minetest.get_connected_players()) do
on_leaveplayer(player)
end
end)
local animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8
minetest.register_entity("mcl_burning:fire", {
initial_properties = {
physical = false,
collisionbox = {0, 0, 0, 0, 0, 0},
visual = "upright_sprite",
textures = {
"mcl_burning_entity_flame_animated.png",
"mcl_burning_entity_flame_animated.png"
},
spritediv = {x = 1, y = animation_frames},
pointable = false,
glow = -1,
backface_culling = false,
},
_mcl_animation_timer = 0,
on_activate = function(self)
self.object:set_sprite({x = 0, y = 0}, animation_frames, 1.0 / animation_frames)
end,
on_step = function(self, dtime)
local parent = self.object:get_attach()
if not parent then
self.object:remove()
return
end
local storage = mcl_burning.get_storage(parent)
if not storage or not storage.burn_time then
self.object:remove()
return
end
if parent:is_player() then
self._mcl_animation_timer = self._mcl_animation_timer + dtime
if self._mcl_animation_timer >= 0.1 then
self._mcl_animation_timer = 0
mcl_burning.update_hud(parent)
end
end
end,
})