Simplify damage pipeline; Add on_death and on_damage callbacks

This commit is contained in:
Elias Fleckenstein 2021-04-25 13:50:07 +02:00
parent 939229cb21
commit 6aecae6eea
2 changed files with 50 additions and 19 deletions

View File

@ -1,5 +1,7 @@
mcl_damage = { mcl_damage = {
modifiers = {}, modifiers = {},
damage_callbacks = {},
death_callbacks = {},
types = { types = {
in_fire = {is_fire = true}, in_fire = {is_fire = true},
lightning_bolt = {is_lightning = true}, lightning_bolt = {is_lightning = true},
@ -35,9 +37,17 @@ function mcl_damage.register_modifier(func, priority)
table.insert(mcl_damage.modifiers, {func = func, priority = priority or 0}) table.insert(mcl_damage.modifiers, {func = func, priority = priority or 0})
end end
function mcl_damage.do_modifiers(player, damage, reason) function mcl_damage.register_on_damage(func)
table.insert(mcl_damage.damage_callbacks, func)
end
function mcl_damage.register_on_death(func)
table.insert(mcl_damage.death_callbacks, func)
end
function mcl_damage.run_modifiers(obj, damage, reason)
for _, modf in ipairs(mcl_damage.modifiers) do for _, modf in ipairs(mcl_damage.modifiers) do
damage = modf.func(player, damage, reason) or damage damage = modf.func(obj, damage, reason) or damage
if damage == 0 then if damage == 0 then
return 0 return 0
end end
@ -46,6 +56,20 @@ function mcl_damage.do_modifiers(player, damage, reason)
return damage return damage
end end
local function run_callbacks(funcs, ...)
for _, func in pairs(funcs) do
func(...)
end
end
function mcl_damage.run_damage_callbacks(obj, damage, reason)
run_callbacks(mcl_damage.damage_callbacks, obj, damage, reason)
end
function mcl_damage.run_death_callbacks(obj, reason)
run_callbacks(mcl_damage.death_callbacks, obj, reason)
end
function mcl_damage.from_punch(mcl_reason, object) function mcl_damage.from_punch(mcl_reason, object)
mcl_reason.direct = object mcl_reason.direct = object
local luaentity = mcl_reason.direct:get_luaentity() local luaentity = mcl_reason.direct:get_luaentity()
@ -69,6 +93,10 @@ function mcl_damage.finish_reason(mcl_reason)
end end
function mcl_damage.from_mt(mt_reason) function mcl_damage.from_mt(mt_reason)
if mt_reason._mcl_reason then
return mt_reason._mcl_reason
end
local mcl_reason = {type = "generic"} local mcl_reason = {type = "generic"}
if mt_reason._mcl_type then if mt_reason._mcl_type then
@ -95,6 +123,7 @@ function mcl_damage.from_mt(mt_reason)
end end
mcl_damage.finish_reason(mcl_reason) mcl_damage.finish_reason(mcl_reason)
mt_reason._mcl_reason = mcl_reason
return mcl_reason return mcl_reason
end end
@ -105,11 +134,24 @@ end
minetest.register_on_player_hpchange(function(player, hp_change, mt_reason) minetest.register_on_player_hpchange(function(player, hp_change, mt_reason)
if hp_change < 0 then if hp_change < 0 then
hp_change = -mcl_damage.do_modifiers(player, -hp_change, mcl_damage.from_mt(mt_reason)) if player:get_hp() <= 0 then
return 0
end
hp_change = -mcl_damage.run_modifiers(player, -hp_change, mcl_damage.from_mt(mt_reason))
end end
return hp_change return hp_change
end, true) end, true)
minetest.register_on_player_hpchange(function(player, hp_change, mt_reason)
if hp_change < 0 then
mcl_damage.run_damage_callbacks(player, -hp_change, mcl_damage.from_mt(mt_reason))
end
end, false)
minetest.register_on_dieplayer(function(player, mt_reason)
mcl_damage.run_death_callbacks(player, mcl_damage.from_mt(mt_reason))
end)
minetest.register_on_mods_loaded(function() minetest.register_on_mods_loaded(function()
table.sort(mcl_damage.modifiers, function(a, b) return a.priority < b.priority end) table.sort(mcl_damage.modifiers, function(a, b) return a.priority < b.priority end)
end) end)

View File

@ -475,32 +475,21 @@ function mcl_util.use_item_durability(itemstack, n)
end end
function mcl_util.deal_damage(target, damage, mcl_reason) function mcl_util.deal_damage(target, damage, mcl_reason)
mcl_reason = mcl_reason or {}
local luaentity = target:get_luaentity() local luaentity = target:get_luaentity()
if luaentity then if luaentity then
if luaentity.deal_damage then if luaentity.deal_damage then
luaentity:deal_damage(damage, mcl_reason) luaentity:deal_damage(damage, mcl_reason or {type = "generic"})
return return
elseif luaentity._cmi_is_mob then elseif luaentity._cmi_is_mob then
local puncher = mcl_reason.direct or target -- local puncher = mcl_reason and mcl_reason.direct or target
target:punch(puncher, 1.0, {full_punch_interval = 1.0, damage_groups = {fleshy = damage}}, vector.direction(puncher:get_pos(), target:get_pos()), damage) -- target:punch(puncher, 1.0, {full_punch_interval = 1.0, damage_groups = {fleshy = damage}}, vector.direction(puncher:get_pos(), target:get_pos()), damage)
luaentity.health = luaentity.health - damage
return return
end end
end end
local mt_reason target:set_hp(target:get_hp() - damage, {_mcl_reason = mcl_reason})
if target:is_player() then
mt_reason = {}
for key, value in pairs(mcl_reason) do
mt_reason["_mcl_" .. key] = value
end
end
target:set_hp(target:get_hp() - damage, mt_reason)
end end
function mcl_util.get_hp(obj) function mcl_util.get_hp(obj)