forked from VoxeLibre/VoxeLibre
master #5
|
@ -1,13 +1,34 @@
|
|||
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,
|
||||
})
|
||||
mcl_burning = {}
|
||||
|
||||
function mcl_burning.get_default(datatype)
|
||||
local default_table = {string = "", float = 0.0, int = 0, bool = false}
|
||||
return default_table[datatype]
|
||||
end
|
||||
|
||||
function mcl_burning.get(obj, datatype, name)
|
||||
local key
|
||||
if obj:is_player() then
|
||||
local meta = obj:get_meta()
|
||||
return meta["get_" .. datatype](meta, "mcl_burning:" .. name)
|
||||
else
|
||||
local luaentity = obj:get_luaentity()
|
||||
return luaentity["mcl_burning_" .. name] or mcl_burning.get_default(datatype)
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_burning.set(obj, datatype, name, value)
|
||||
if obj:is_player() then
|
||||
local meta = obj:get_meta()
|
||||
meta["set_" .. datatype](meta, "mcl_burning:" .. name, value or mcl_burning.get_default(datatype))
|
||||
else
|
||||
local luaentity = obj:get_luaentity()
|
||||
if mcl_burning.get_default(datatype) == value then
|
||||
value = nil
|
||||
end
|
||||
luaentity["mcl_burning_" .. name] = value
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_burning.get_collisionbox(obj)
|
||||
|
@ -23,168 +44,166 @@ function mcl_burning.is_touching_nodes(obj, 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.damage(obj)
|
||||
local luaentity = obj:get_luaentity()
|
||||
local health
|
||||
|
||||
function mcl_burning.analyse(obj, meta, is_player)
|
||||
if meta then
|
||||
return meta, is_player
|
||||
if luaentity then
|
||||
health = luaentity.health
|
||||
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
|
||||
local hp = health or obj:get_hp()
|
||||
|
||||
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 obj:is_player() then
|
||||
if mcl_potions.player_has_effect(obj, "fire_proof") 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))
|
||||
local deathmsg = S("@1 burned to death.", name)
|
||||
local reason = mcl_burning.get(obj, "string", "reason")
|
||||
if reason ~= "" then
|
||||
deathmsg = S("@1 was burned by @2.", name, reason)
|
||||
end
|
||||
mcl_death_messages.player_damage(obj, deathmsg)
|
||||
end
|
||||
else
|
||||
if luaentity.fire_damage_resistant then
|
||||
do_damage = false
|
||||
end
|
||||
end
|
||||
|
||||
if do_damage then
|
||||
if is_player then
|
||||
obj:set_hp(hp - 1)
|
||||
else
|
||||
meta.health = hp - 1
|
||||
local damage = mcl_burning.get(obj, "float", "damage")
|
||||
if damage == 0 then
|
||||
damage = 1
|
||||
end
|
||||
local new_hp = hp - damage
|
||||
obj:set_hp(new_hp)
|
||||
if health then
|
||||
luaentity.health = new_hp
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local etime = 0
|
||||
function mcl_burning.set_on_fire(obj, burn_time, damage, reason)
|
||||
local luaentity = obj:get_luaentity()
|
||||
if luaentity and luaentity.fire_resistant then
|
||||
return
|
||||
end
|
||||
|
||||
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)
|
||||
local old_burn_time = mcl_burning.get(obj, "float", "burn_time")
|
||||
local max_fire_prot_lvl = 0
|
||||
|
||||
if obj:is_player() then
|
||||
local inv = obj:get_inventory()
|
||||
|
||||
for i = 2, 5 do
|
||||
local stack = inv:get_stack("armor", i)
|
||||
|
||||
local fire_prot_lvl = mcl_enchanting.get_enchantment(stack, "fire_protection")
|
||||
max_fire_prot_lvl = math.max(max_fire_prot_lvl, fire_prot_lvl)
|
||||
end
|
||||
mcl_burning.set_burning(obj, burn_time, old_burn_time, meta, is_player)
|
||||
end
|
||||
if burn_time > 0 then
|
||||
|
||||
if max_fire_prot_lvl > 0 then
|
||||
burn_time = burn_time - math.floor(burn_time * max_fire_prot_lvl * 0.15)
|
||||
end
|
||||
|
||||
if old_burn_time <= burn_time then
|
||||
mcl_burning.set(obj, "float", "burn_time", burn_time)
|
||||
mcl_burning.set(obj, "float", "damage", damage or 0)
|
||||
mcl_burning.set(obj, "string", "reason", reason or "")
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_burning.extinguish(obj)
|
||||
local old_burn_time = mcl_burning.get(obj, "float", "burn_time")
|
||||
|
||||
if old_burn_time > 0 then
|
||||
minetest.sound_play("fire_extinguish_flame", {
|
||||
object = obj,
|
||||
gain = 0.18,
|
||||
max_hear_distance = 32,
|
||||
})
|
||||
|
||||
mcl_burning.delete_particlespawner(obj)
|
||||
|
||||
mcl_burning.set(obj, "float", "damage")
|
||||
mcl_burning.set(obj, "string", "reason")
|
||||
mcl_burning.set(obj, "float", "burn_time")
|
||||
mcl_burning.set(obj, "float", "damage_timer")
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_burning.catch_fire_tick(obj, dtime)
|
||||
local lava_nodes = {"mcl_core:lava_source", "mcl_core:lava_flowing"}
|
||||
local fire_nodes = {"mcl_fire:fire", "mcl_fire:eternal_fire"}
|
||||
local water_nodes = {"mcl_core:water_source", "mcl_core:water_flowing"}
|
||||
|
||||
if mcl_weather.get_weather() == "rain" and mcl_weather.is_outdoor(obj:get_pos()) or mcl_burning.is_touching_nodes(obj, water_nodes) then
|
||||
mcl_burning.extinguish(obj)
|
||||
elseif mcl_burning.is_touching_nodes(obj, lava_nodes) then
|
||||
mcl_burning.set_on_fire(obj, 15)
|
||||
elseif mcl_burning.is_touching_nodes(obj, fire_nodes) then
|
||||
mcl_burning.set_on_fire(obj, 8)
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_burning.tick(obj, dtime)
|
||||
local burn_time = mcl_burning.get(obj, "float", "burn_time") - dtime
|
||||
|
||||
if burn_time <= 0 then
|
||||
mcl_burning.extinguish(obj)
|
||||
else
|
||||
mcl_burning.set(obj, "float", "burn_time", burn_time)
|
||||
|
||||
if math.random() < dtime then
|
||||
mcl_burning.play_sound(obj, "fire_fire")
|
||||
minetest.sound_play("fire_fire", {
|
||||
object = obj,
|
||||
gain = 0.18,
|
||||
max_hear_distance = 32,
|
||||
})
|
||||
end
|
||||
if etime > 1 then
|
||||
mcl_burning.damage(obj, meta, is_player)
|
||||
|
||||
local damage_timer = mcl_burning.get(obj, "float", "damage_timer") + dtime
|
||||
|
||||
if damage_timer >= 1 then
|
||||
damage_timer = 0
|
||||
mcl_burning.damage(obj)
|
||||
end
|
||||
|
||||
mcl_burning.set(obj, "float", "damage_timer", damage_timer)
|
||||
end
|
||||
|
||||
mcl_burning.catch_fire_tick(obj, dtime)
|
||||
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)
|
||||
mcl_burning.tick(player, dtime)
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_respawnplayer(function(player)
|
||||
mcl_burning.set_burning(player, 0)
|
||||
mcl_burning.extinguish(player)
|
||||
end)
|
||||
|
||||
minetest.register_chatcommand("burn", {
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local burn_time = tonumber(param) or 5
|
||||
local sparam = param:split(" ")
|
||||
local burn_time = tonumber(sparam[1]) or 5
|
||||
local damage = tonumber(sparam[2]) or 5
|
||||
if player then
|
||||
mcl_burning.set_burning(player, burn_time)
|
||||
mcl_burning.set_on_fire(player, burn_time, damage)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
|
|
@ -3360,7 +3360,7 @@ end
|
|||
local mob_step = function(self, dtime)
|
||||
|
||||
if not self.fire_resistant then
|
||||
mcl_burning.step(self.object, dtime)
|
||||
mcl_burning.tick(self.object, dtime)
|
||||
end
|
||||
|
||||
if use_cmi then
|
||||
|
@ -3790,6 +3790,7 @@ minetest.register_entity(name, {
|
|||
follow_velocity = def.follow_velocity or 2.4,
|
||||
instant_death = def.instant_death or false,
|
||||
fire_resistant = def.fire_resistant or false,
|
||||
fire_damage_resistant = def.fire_damage_resistant or false,
|
||||
-- End of MCL2 extensions
|
||||
|
||||
on_spawn = def.on_spawn,
|
||||
|
|
|
@ -86,7 +86,7 @@ local pigman = {
|
|||
fear_height = 4,
|
||||
view_range = 16,
|
||||
harmed_by_heal = true,
|
||||
fire_resistant = true,
|
||||
fire_damage_resistant = true,
|
||||
}
|
||||
|
||||
mobs:register_mob("mobs_mc:pigman", pigman)
|
||||
|
|
Loading…
Reference in New Issue