From 7545e29f580972666dceaebed5b0d949620a3658 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Thu, 24 Dec 2020 17:48:40 +0100 Subject: [PATCH] Burning objects --- mods/ENTITIES/mcl_burning/init.lua | 190 +++++++++++++++++++++ mods/ENTITIES/mcl_mobs/api.lua | 13 +- mods/ENTITIES/mobs_mc/blaze.lua | 1 + mods/ENTITIES/mobs_mc/ender_dragon.lua | 3 +- mods/ENTITIES/mobs_mc/ghast.lua | 1 + mods/ENTITIES/mobs_mc/skeleton_wither.lua | 1 + mods/ENTITIES/mobs_mc/slime+magma_cube.lua | 3 +- mods/ENTITIES/mobs_mc/zombiepig.lua | 1 + mods/ITEMS/mcl_armor/armor.lua | 2 +- 9 files changed, 210 insertions(+), 5 deletions(-) create mode 100644 mods/ENTITIES/mcl_burning/init.lua diff --git a/mods/ENTITIES/mcl_burning/init.lua b/mods/ENTITIES/mcl_burning/init.lua new file mode 100644 index 0000000000..768afb3244 --- /dev/null +++ b/mods/ENTITIES/mcl_burning/init.lua @@ -0,0 +1,190 @@ +mcl_burning = {} + +local S = minetest.get_translator("mcl_burning") + +function mcl_burning.play_sound(obj, soundname) + minetest.sound_play(soundname, { + object = obj, + gain = 0.18, + max_hear_distance = 32, + }) +end + +function mcl_burning.get_collisionbox(obj) + local box = obj:get_properties().collisionbox + return vector.new(box[1], box[2], box[3]), vector.new(box[4], box[5], box[6]) +end + +function mcl_burning.is_touching_nodes(obj, nodes) + local pos = obj:get_pos() + local box = obj:get_properties().collisionbox + local minp, maxp = mcl_burning.get_collisionbox(obj) + local nodes = minetest.find_nodes_in_area(vector.add(pos, minp), vector.add(pos, maxp), nodes) + return #nodes > 0 +end + +function mcl_burning.create_particlespawner(obj, burn_time, old_burn_time, old_spawner) + local new_spawner + if old_spawner == 0 then + old_spawner = nil + end + local delete_old_spawner = false + if burn_time and (not old_spawner or burn_time >= old_burn_time) then + delete_old_spawner = true + local minp, maxp = mcl_burning.get_collisionbox(obj) + new_spawner = minetest.add_particlespawner({ + amount = 1000 * burn_time, + time = burn_time, + minpos = minp, + maxpos = maxp, + minvel = {x = -0.5, y = 1, z = -0.5}, + maxvel = {x = 0.5, y = 2, z = -0.5}, + minacc = {x = -0.1, y = 8, z = -0.1}, + maxacc = {x = 0.1, y = 10, z = 0.1}, + minexptime = 0.2, + maxexptime = 0.3, + minsize = 1, + maxsize = 2, + collisiondetection = true, + texture = "fire_basic_flame.png", + attached = obj, + }) + elseif not burn_time and old_spawner then + delete_old_spawner = true + end + if delete_old_spawner and old_spawner then + minetest.delete_particlespawner(old_spawner) + old_spawner = nil + end + return new_spawner or old_spawner +end + +function mcl_burning.analyse(obj, meta, is_player) + if meta then + return meta, is_player + end + is_player = obj:is_player() + if is_player then + meta = obj:get_meta() + else + meta = obj:get_luaentity() + end + return meta, is_player +end + +function mcl_burning.set_burning(obj, burn_time, old_burn_time, meta, is_player) + meta, is_player = mcl_burning.analyse(obj, meta, is_player) + old_burn_time = old_burn_time or mcl_burning.get_burning(obj, meta, is_player) + if burn_time <= 0 then + burn_time = nil + end + if is_player then + if burn_time then + meta:set_float("mcl_burning:burn_time", burn_time) + elseif old_burn_time > 0 then + meta:set_string("mcl_burning:burn_time", "") + mcl_burning.play_sound(obj, "fire_extinguish_flame") + end + local fire_spawner = mcl_burning.create_particlespawner(obj, burn_time, old_burn_time, meta:get_int("mcl_burning:fire_spawner")) + if fire_spawner then + meta:set_int("mcl_burning:fire_spawner", fire_spawner) + else + meta:set_string("mcl_burning:fire_spawner", "") + end + elseif not meta._fire_resistant then + meta._burn_time = burn_time + meta._fire_spawner = mcl_burning.create_particlespawner(obj, burn_time, old_burn_time, meta._fire_spawner) + if not burn_time and old_burn_time > 0 then + mcl_burning.play_sound(obj, "fire_extinguish_flame") + end + end +end + +function mcl_burning.get_burning(obj, meta, is_player) + meta, is_player = mcl_burning.analyse(obj, meta, is_player) + if is_player then + return meta:get_float("mcl_burning:burn_time") + else + return meta._burn_time or 0 + end +end + +function mcl_burning.damage(obj, meta, is_player) + local hp + if is_player then + hp = obj:get_hp() + else + hp = meta.health or 0 + end + if hp <= 0 then + return + end + meta, is_player = mcl_burning.analyse(obj, meta, is_player) + local do_damage = true + if is_player then + if mcl_potions.player_has_effect(obj, "fire_resistance") then + do_damage = false + else + local name = obj:get_player_name() + armor.last_damage_types[name] = "fire" + mcl_death_messages.player_damage(obj, S("@1 burned to a crisp.", name)) + end + end + if do_damage then + if is_player then + obj:set_hp(hp - 1) + else + meta.health = hp - 1 + end + end +end + +local etime = 0 + +function mcl_burning.step(obj, dtime) + local burn_time, old_burn_time, meta, is_player + meta, is_player = mcl_burning.analyse(obj) + old_burn_time = mcl_burning.get_burning(obj, meta, is_player) + burn_time = old_burn_time - dtime + if burn_time < 5 and mcl_burning.is_touching_nodes(obj, {"mcl_fire:fire", "mcl_fire:eternal_fire", "mcl_core:lava_source", "mcl_core:lava_flowing"}) then + burn_time = 5 + end + if burn_time > 0 or old_burn_time > 0 then + if mcl_weather.get_weather() == "rain" and mcl_weather.is_outdoor(obj:get_pos()) or mcl_burning.is_touching_nodes(obj, {"mcl_core:water_source", "mcl_core:water_flowing"}) then + burn_time = math.min(burn_time, 0.25) + end + mcl_burning.set_burning(obj, burn_time, old_burn_time, meta, is_player) + end + if burn_time > 0 then + if math.random() < dtime then + mcl_burning.play_sound(obj, "fire_fire") + end + if etime > 1 then + mcl_burning.damage(obj, meta, is_player) + end + end +end + +minetest.register_globalstep(function(dtime) + if etime > 1 then + etime = 0 + end + etime = etime + dtime + for _, player in ipairs(minetest.get_connected_players()) do + mcl_burning.step(player, dtime) + end +end) + +minetest.register_on_respawnplayer(function(player) + mcl_burning.set_burning(player, 0) +end) + +minetest.register_chatcommand("burn", { + func = function(name, param) + local player = minetest.get_player_by_name(name) + local burn_time = tonumber(param) or 5 + if player then + mcl_burning.set_burning(player, burn_time) + end + end +}) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 8787451888..15232c2469 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -778,6 +778,7 @@ local check_for_death = function(self, cause, cmi_cause) if cause == "lava" or cause == "fire" then item_drop(self, true, 0) else + local cooked = nil local looting = 0 if cause == "hit" then local puncher = cmi_cause.puncher @@ -785,7 +786,10 @@ local check_for_death = function(self, cause, cmi_cause) looting = mcl_enchanting.get_enchantment(puncher:get_wielded_item(), "looting") end end - item_drop(self, nil, looting) + if self._burn_time and self._burn_time > 0 then + cooked = true + end + item_drop(self, cooked, looting) end local pos = self.object:get_pos() @@ -3354,7 +3358,11 @@ end -- main mob function local mob_step = function(self, dtime) - + + if not self.fire_resistant then + mcl_burning.step(self.object, dtime) + end + if use_cmi then cmi.notify_step(self.object, dtime) end @@ -3781,6 +3789,7 @@ minetest.register_entity(name, { suffocation_timer = 0, follow_velocity = def.follow_velocity or 2.4, instant_death = def.instant_death or false, + fire_resistant = def.fire_resistant or false, -- End of MCL2 extensions on_spawn = def.on_spawn, diff --git a/mods/ENTITIES/mobs_mc/blaze.lua b/mods/ENTITIES/mobs_mc/blaze.lua index 3e0af9ab1e..d9275c7ae4 100644 --- a/mods/ENTITIES/mobs_mc/blaze.lua +++ b/mods/ENTITIES/mobs_mc/blaze.lua @@ -74,6 +74,7 @@ mobs:register_mob("mobs_mc:blaze", { makes_footstep_sound = false, fear_height = 0, glow = 14, + fire_resistant = true, }) mobs:spawn_specific("mobs_mc:blaze", mobs_mc.spawn.nether_fortress, {"air"}, 0, minetest.LIGHT_MAX+1, 30, 5000, 3, mobs_mc.spawn_height.nether_min, mobs_mc.spawn_height.nether_max) diff --git a/mods/ENTITIES/mobs_mc/ender_dragon.lua b/mods/ENTITIES/mobs_mc/ender_dragon.lua index 85b72008fb..c579213a0a 100644 --- a/mods/ENTITIES/mobs_mc/ender_dragon.lua +++ b/mods/ENTITIES/mobs_mc/ender_dragon.lua @@ -67,7 +67,8 @@ mobs:register_mob("mobs_mc:enderdragon", { --end end minetest.add_item(own_pos, mobs_mc.items.dragon_egg) - end + end, + fire_resistant = true, }) diff --git a/mods/ENTITIES/mobs_mc/ghast.lua b/mods/ENTITIES/mobs_mc/ghast.lua index 5bd05b8607..679a28c13d 100644 --- a/mods/ENTITIES/mobs_mc/ghast.lua +++ b/mods/ENTITIES/mobs_mc/ghast.lua @@ -62,6 +62,7 @@ mobs:register_mob("mobs_mc:ghast", { fly = true, makes_footstep_sound = false, instant_death = true, + fire_resistant = true, }) diff --git a/mods/ENTITIES/mobs_mc/skeleton_wither.lua b/mods/ENTITIES/mobs_mc/skeleton_wither.lua index 7684dc4094..e4a1f86fc6 100644 --- a/mods/ENTITIES/mobs_mc/skeleton_wither.lua +++ b/mods/ENTITIES/mobs_mc/skeleton_wither.lua @@ -90,6 +90,7 @@ mobs:register_mob("mobs_mc:witherskeleton", { dogshoot_count_max =0.5, fear_height = 4, harmed_by_heal = true, + fire_resistant = true, }) --spawn diff --git a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua index 7437339309..3848d59192 100644 --- a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua +++ b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua @@ -108,7 +108,8 @@ local slime_big = { jump_height = 5.2, fear_height = 0, spawn_small_alternative = "mobs_mc:slime_small", - on_die = spawn_children_on_die("mobs_mc:slime_small", 4, 1.0, 1.5) + on_die = spawn_children_on_die("mobs_mc:slime_small", 4, 1.0, 1.5), + fire_resistant = true, } mobs:register_mob("mobs_mc:slime_big", slime_big) diff --git a/mods/ENTITIES/mobs_mc/zombiepig.lua b/mods/ENTITIES/mobs_mc/zombiepig.lua index 5b79e53b59..08e82f62e6 100644 --- a/mods/ENTITIES/mobs_mc/zombiepig.lua +++ b/mods/ENTITIES/mobs_mc/zombiepig.lua @@ -86,6 +86,7 @@ local pigman = { fear_height = 4, view_range = 16, harmed_by_heal = true, + fire_resistant = true, } mobs:register_mob("mobs_mc:pigman", pigman) diff --git a/mods/ITEMS/mcl_armor/armor.lua b/mods/ITEMS/mcl_armor/armor.lua index 69801d010b..6151a2812d 100644 --- a/mods/ITEMS/mcl_armor/armor.lua +++ b/mods/ITEMS/mcl_armor/armor.lua @@ -540,7 +540,7 @@ minetest.register_on_player_hpchange(function(player, hp_change, reason) epf = epf + blast_protection_level * 2 end local fire_protection_level = enchantments.fire_protection or 0 - if fire_protection_level > 0 and (damage_type == "fireball" or reason.type == "node_damage" and + if fire_protection_level > 0 and (damage_type == "burning" or damage_type == "fireball" or reason.type == "node_damage" and (reason.node == "mcl_fire:fire" or reason.node == "mcl_core:lava_source" or reason.node == "mcl_core:lava_flowing")) then epf = epf + fire_protection_level * 2 end