function mcl_burning.get_storage(obj) if obj:is_player() then return mcl_burning.storage[obj] else local luaentity = obj:get_luaentity() if luaentity.is_mob then return luaentity.data end return luaentity end 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 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 = minetest.find_nodes_in_area(vector.add(pos, minp), vector.add(pos, maxp), nodenames) return nodes end function mcl_burning.set_on_fire(obj, burn_time) if obj:get_hp() < 0 then return end local storage = mcl_burning.get_storage(obj) 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 if not storage.burn_time or burn_time >= storage.burn_time then if obj:is_player() then mcl_burning.channels[obj]:send_all(tostring(mcl_burning.animation_frames)) mcl_burning.channels[obj]:send_all("start") end storage.burn_time = burn_time storage.fire_damage_timer = 0 local fire_entity = minetest.add_entity(obj:get_pos(), "mcl_burning:fire") 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 end end 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 mcl_burning.channels[obj]:send_all("stop") 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 mcl_util.deal_damage(obj, 1, {type = "on_fire"}) end end end end