1
0
Fork 0
MineClone2/mods/ENTITIES/mcl_burning/api.lua

184 lines
5.8 KiB
Lua
Raw Permalink Normal View History

2021-04-25 11:09:20 +00:00
function mcl_burning.get_storage(obj)
return obj:is_player() and mcl_burning.storage[obj] or obj:get_luaentity()
2021-01-01 18:25:47 +00:00
end
function mcl_burning.is_burning(obj)
2021-04-25 11:09:20 +00:00
return mcl_burning.get_storage(obj).burn_time
2021-01-01 18:25:47 +00:00
end
function mcl_burning.is_affected_by_rain(obj)
2021-04-25 11:09:20 +00:00
return mcl_weather.get_weather() == "rain" and mcl_weather.is_outdoor(obj:get_pos())
2021-01-01 18:25:47 +00:00
end
2021-04-25 11:09:20 +00:00
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])
2021-01-27 19:11:02 +00:00
local s_vec = vector.new(0.1, 0.1, 0.1)
2021-04-25 11:09:20 +00:00
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
2021-01-27 19:11:02 +00:00
end
2021-01-01 18:25:47 +00:00
end
local find_nodes_in_area = minetest.find_nodes_in_area
2021-04-25 11:09:20 +00:00
function mcl_burning.get_touching_nodes(obj, nodenames, storage)
2021-01-01 18:25:47 +00:00
local pos = obj:get_pos()
2021-04-25 11:09:20 +00:00
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)
2021-01-01 18:25:47 +00:00
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.
--
2021-04-25 14:42:38 +00:00
function mcl_burning.set_on_fire(obj, burn_time)
2021-03-19 10:40:46 +00:00
if obj:get_hp() < 0 then
return
end
2021-01-01 18:25:47 +00:00
local luaentity = obj:get_luaentity()
if luaentity and luaentity.fire_resistant then
return
end
2021-04-25 11:29:07 +00:00
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)
2021-04-25 14:42:38 +00:00
local armor_list = inv and inv:get_list("armor")
2021-04-25 11:29:07 +00:00
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
2021-04-25 11:29:07 +00:00
if max_fire_prot_lvl > 0 then
burn_time = burn_time - math.floor(burn_time * max_fire_prot_lvl * 0.15)
2021-01-01 18:25:47 +00:00
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
2021-01-01 18:25:47 +00:00
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
-- FIXME: does this code make sense? It removes attached fire luaentities from
-- another object that happen to be at the same position.
local fire_luaentity = fire_entity:get_luaentity()
for _, other in pairs(minetest.get_objects_inside_radius(fire_entity:get_pos(), 0)) do
local other_luaentity = other:get_luaentity()
if other_luaentity and other_luaentity.name == "mcl_burning:fire" and other_luaentity ~= fire_luaentity then
other:remove()
break
2021-04-25 11:09:20 +00:00
end
2021-01-01 18:25:47 +00:00
end
end
function mcl_burning.extinguish(obj)
if mcl_burning.is_burning(obj) then
2021-04-25 11:09:20 +00:00
local storage = mcl_burning.get_storage(obj)
2021-01-01 18:25:47 +00:00
if obj:is_player() then
if storage.fire_hud_id then
obj:hud_remove(storage.fire_hud_id)
end
2021-04-25 11:09:20 +00:00
mcl_burning.storage[obj] = {}
else
storage.burn_time = nil
storage.fire_damage_timer = nil
2021-01-01 18:25:47 +00:00
end
end
end
2021-04-25 11:09:20 +00:00
function mcl_burning.tick(obj, dtime, storage)
if storage.burn_time then
storage.burn_time = storage.burn_time - dtime
2021-04-25 11:09:20 +00:00
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
2021-04-25 18:51:13 +00:00
local luaentity = obj:get_luaentity()
if not luaentity or not luaentity.fire_damage_resistant then
mcl_util.deal_damage(obj, 1, {type = "on_fire"})
2021-04-25 11:09:20 +00:00
end
2021-01-01 18:25:47 +00:00
end
end
end
end