mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-12-27 18:39:34 +01:00
9eba0e4860
* Remove unused code that was commented out. The code tried to find fire luaentities in the same spot as the newly created fire luaentity. It may have been intended to optimize getting set on fire multiple times, but it makes no sense as it does not discriminate between fire luaentities attached to the object set on fire and those attached to other objects. The function that this code was in also has a better way to prevent adding multiple fire luaentities in the first place.
172 lines
5.3 KiB
Lua
172 lines
5.3 KiB
Lua
function mcl_burning.get_storage(obj)
|
|
return obj:is_player() and mcl_burning.storage[obj] or obj:get_luaentity()
|
|
end
|
|
|
|
function mcl_burning.is_burning(obj)
|
|
return mcl_burning.get_storage(obj).burn_time
|
|
end
|
|
|
|
function mcl_burning.is_affected_by_rain(obj)
|
|
return mcl_weather.get_weather() == "rain" and mcl_weather.is_outdoor(obj:get_pos())
|
|
end
|
|
|
|
function mcl_burning.get_collisionbox(obj, smaller, storage)
|
|
local cache = storage.collisionbox_cache
|
|
if cache then
|
|
local box = cache[smaller and 2 or 1]
|
|
return box[1], box[2]
|
|
else
|
|
local box = obj:get_properties().collisionbox
|
|
local minp, maxp = vector.new(box[1], box[2], box[3]), vector.new(box[4], box[5], box[6])
|
|
local s_vec = vector.new(0.1, 0.1, 0.1)
|
|
local s_minp = vector.add(minp, s_vec)
|
|
local s_maxp = vector.subtract(maxp, s_vec)
|
|
storage.collisionbox_cache = {{minp, maxp}, {s_minp, s_maxp}}
|
|
return minp, maxp
|
|
end
|
|
end
|
|
|
|
local find_nodes_in_area = minetest.find_nodes_in_area
|
|
|
|
function mcl_burning.get_touching_nodes(obj, nodenames, storage)
|
|
local pos = obj:get_pos()
|
|
local minp, maxp = mcl_burning.get_collisionbox(obj, true, storage)
|
|
local nodes = find_nodes_in_area(vector.add(pos, minp), vector.add(pos, maxp), nodenames)
|
|
return nodes
|
|
end
|
|
|
|
-- Manages the fire animation on a burning player's HUD
|
|
--
|
|
-- Parameters:
|
|
-- player - a valid player object;
|
|
--
|
|
-- If the player already has a fire HUD, updates the burning animation.
|
|
-- If the fire does not have a fire HUD, initializes the HUD.
|
|
--
|
|
function mcl_burning.update_hud(player)
|
|
local animation_frames = tonumber(minetest.settings:get("fire_animation_frames")) or 8
|
|
local hud_flame_animated = "mcl_burning_hud_flame_animated.png^[opacity:180^[verticalframe:" .. animation_frames .. ":"
|
|
|
|
local storage = mcl_burning.get_storage(player)
|
|
if not storage.fire_hud_id then
|
|
storage.animation_frame = 1
|
|
storage.fire_hud_id = player:hud_add({
|
|
hud_elem_type = "image",
|
|
position = {x = 0.5, y = 0.5},
|
|
scale = {x = -100, y = -100},
|
|
text = hud_flame_animated .. storage.animation_frame,
|
|
z_index = 1000,
|
|
})
|
|
else
|
|
storage.animation_frame = storage.animation_frame + 1
|
|
if storage.animation_frame > animation_frames - 1 then
|
|
storage.animation_frame = 0
|
|
end
|
|
player:hud_change(storage.fire_hud_id, "text", hud_flame_animated .. storage.animation_frame)
|
|
end
|
|
end
|
|
|
|
-- Sets and object state as burning and adds a fire animation to the object.
|
|
--
|
|
-- Parameters:
|
|
-- obj - may be a player or a lua_entity;
|
|
-- burn_time - sets the object's burn duration;
|
|
--
|
|
-- If obj is a player, adds a fire animation to the HUD, if obj is a
|
|
-- lua_entity, adds an animated fire entity to obj.
|
|
-- The effective burn duration is modified by obj's armor protection.
|
|
-- If obj was already burning, its burn duration is updated if the current
|
|
-- duration is less than burn_time.
|
|
-- If obj is dead, fireproof or a creative player, this function does nothing.
|
|
--
|
|
function mcl_burning.set_on_fire(obj, burn_time)
|
|
if obj:get_hp() < 0 then
|
|
return
|
|
end
|
|
|
|
local luaentity = obj:get_luaentity()
|
|
if luaentity and luaentity.fire_resistant then
|
|
return
|
|
end
|
|
|
|
if obj:is_player() and minetest.is_creative_enabled(obj:get_player_name()) then
|
|
burn_time = 0
|
|
else
|
|
local max_fire_prot_lvl = 0
|
|
local inv = mcl_util.get_inventory(obj)
|
|
local armor_list = inv and inv:get_list("armor")
|
|
|
|
if armor_list then
|
|
for _, stack in pairs(armor_list) do
|
|
local fire_prot_lvl = mcl_enchanting.get_enchantment(stack, "fire_protection")
|
|
if fire_prot_lvl > max_fire_prot_lvl then
|
|
max_fire_prot_lvl = fire_prot_lvl
|
|
end
|
|
end
|
|
end
|
|
if max_fire_prot_lvl > 0 then
|
|
burn_time = burn_time - math.floor(burn_time * max_fire_prot_lvl * 0.15)
|
|
end
|
|
end
|
|
|
|
local storage = mcl_burning.get_storage(obj)
|
|
if storage.burn_time then
|
|
if burn_time > storage.burn_time then
|
|
storage.burn_time = burn_time
|
|
end
|
|
return
|
|
end
|
|
storage.burn_time = burn_time
|
|
storage.fire_damage_timer = 0
|
|
|
|
local minp, maxp = mcl_burning.get_collisionbox(obj, false, storage)
|
|
local size = vector.subtract(maxp, minp)
|
|
size = vector.multiply(size, vector.new(1.1, 1.2, 1.1))
|
|
size = vector.divide(size, obj:get_properties().visual_size)
|
|
|
|
local fire_entity = minetest.add_entity(obj:get_pos(), "mcl_burning:fire")
|
|
fire_entity:set_properties({visual_size = size})
|
|
fire_entity:set_attach(obj, "", vector.new(0, size.y * 5, 0), vector.new(0, 0, 0))
|
|
|
|
if obj:is_player() then
|
|
mcl_burning.update_hud(obj)
|
|
end
|
|
end
|
|
|
|
function mcl_burning.extinguish(obj)
|
|
if mcl_burning.is_burning(obj) then
|
|
local storage = mcl_burning.get_storage(obj)
|
|
if obj:is_player() then
|
|
if storage.fire_hud_id then
|
|
obj:hud_remove(storage.fire_hud_id)
|
|
end
|
|
mcl_burning.storage[obj] = {}
|
|
else
|
|
storage.burn_time = nil
|
|
storage.fire_damage_timer = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
function mcl_burning.tick(obj, dtime, storage)
|
|
if storage.burn_time then
|
|
storage.burn_time = storage.burn_time - dtime
|
|
|
|
if storage.burn_time <= 0 or mcl_burning.is_affected_by_rain(obj) or #mcl_burning.get_touching_nodes(obj, "group:puts_out_fire", storage) > 0 then
|
|
mcl_burning.extinguish(obj)
|
|
return true
|
|
else
|
|
storage.fire_damage_timer = storage.fire_damage_timer + dtime
|
|
|
|
if storage.fire_damage_timer >= 1 then
|
|
storage.fire_damage_timer = 0
|
|
|
|
local luaentity = obj:get_luaentity()
|
|
|
|
if not luaentity or not luaentity.fire_damage_resistant then
|
|
mcl_util.deal_damage(obj, 1, {type = "on_fire"})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|