Redesign damage modifier execution

This commit is contained in:
Elias Fleckenstein 2021-04-18 20:08:08 +02:00
parent a2c3eb95bb
commit d9195cc520
4 changed files with 48 additions and 66 deletions

@ -30,34 +30,23 @@ mcl_damage = {
} }
} }
local old_register_hpchange = minetest.register_on_player_hpchange
function minetest.register_on_player_hpchange(func, modifier)
if modifier then
mcl_damage.register_modifier(func, 0)
else
old_register_hpchange(func, modifier)
end
end
function mcl_damage.register_modifier(func, priority) 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.get_mcl_damage_reason(mt_reason) function mcl_damage.do_modifiers(player, damage, reason)
local mcl_reason = { for _, modf in ipairs(mcl_damage.modifiers) do
type = "generic", damage = modf.func(player, damage, reason) or damage
} if damage == 0 then
return 0
end
end
if mt_reason._mcl_type then return damage
mcl_reason.type = mt_reason._mcl_type end
elseif mt_reason.type == "fall" then
mcl_reason.type = "fall" function mcl_damage.from_punch(mcl_reason, object)
elseif mt_reason.type == "drown" then mcl_reason.direct = object
mcl_reason.type = "drown"
elseif mt_reason.type == "punch" then
mcl_reason.direct = mt_reason.object
if mcl_reason.direct then
local luaentity = mcl_reason.direct:get_luaentity() local luaentity = mcl_reason.direct:get_luaentity()
if luaentity then if luaentity then
if luaentity._is_arrow then if luaentity._is_arrow then
@ -71,7 +60,24 @@ function mcl_damage.get_mcl_damage_reason(mt_reason)
else else
mcl_reason.type = "player" mcl_reason.type = "player"
end end
end end
function mcl_damage.finish_reason(mcl_reason)
mcl_reason.source = mcl_reason.source or mcl_reason.direct
mcl_reason.flags = mcl_damage.types[mcl_reason.type]
end
function mcl_damage.from_mt(mt_reason)
local mcl_reason = {type = "generic"}
if mt_reason._mcl_type then
mcl_reason.type = mt_reason._mcl_type
elseif mt_reason.type == "fall" then
mcl_reason.type = "fall"
elseif mt_reason.type == "drown" then
mcl_reason.type = "drown"
elseif mt_reason.type == "punch" then
mcl_damage.from_punch(mcl_reason, mt_reason.object)
elseif mt_reason.type == "node_damage" and mt_reason.node then elseif mt_reason.type == "node_damage" and mt_reason.node then
if minetest.get_item_group(mt_reason.node, "fire") > 0 then if minetest.get_item_group(mt_reason.node, "fire") > 0 then
mcl_reason.type = "in_fire" mcl_reason.type = "in_fire"
@ -87,8 +93,7 @@ function mcl_damage.get_mcl_damage_reason(mt_reason)
end end
end end
mcl_reason.source = mcl_reason.source or mcl_reason.direct mcl_damage.finish_reason(mcl_reason)
mcl_reason.flags = mcl_damage.types[mcl_reason.type]
return mcl_reason return mcl_reason
end end
@ -97,16 +102,10 @@ function mcl_damage.register_type(name, def)
mcl_damage.types[name] = def mcl_damage.types[name] = def
end end
old_register_hpchange(function(player, hp_change, mt_reason) minetest.register_on_player_hpchange(function(player, hp_change, mt_reason)
local mcl_reason = mcl_damage.get_mcl_damage_reason(mt_reason) if hp_change < 0 then
hp_change = -mcl_damage.do_modifiers(player, -hp_change, mcl_damage.from_mt(mt_reason))
for _, modf in ipairs(mcl_damage.modifiers) do
hp_change = modf.func(player, hp_change, mt_reason, mcl_reason) or hp_change
if hp_change == 0 then
return 0
end end
end
return hp_change return hp_change
end, true) end, true)

@ -1,13 +1,8 @@
function mcl_armor.damage_modifier(obj, hp_change, reason) mcl_damage.register_modifier(function(obj, damage, reason)
if hp_change > 0 then
return hp_change
end
local damage = -hp_change
local flags = reason.flags local flags = reason.flags
if flags.bypasses_armor and flags.bypasses_magic then if flags.bypasses_armor and flags.bypasses_magic then
return hp_change return damage
end end
local uses = math.max(1, math.floor(damage / 4)) local uses = math.max(1, math.floor(damage / 4))
@ -95,5 +90,5 @@ function mcl_armor.damage_modifier(obj, hp_change, reason)
mcl_armor.update(obj) mcl_armor.update(obj)
return -math.floor(damage + 0.5) return math.floor(damage + 0.5)
end end, 0)

@ -155,7 +155,3 @@ end)
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
mcl_armor.player_view_range_factors[player] = nil mcl_armor.player_view_range_factors[player] = nil
end) end)
mcl_damage.register_modifier(function(player, hp_change, _, reason)
return mcl_armor.damage_modifier(player, hp_change, reason)
end)

@ -1,8 +1,5 @@
mcl_criticals = {} mcl_damage.register_modifier(function(obj, damage, reason)
if reason.type == "player" then
function mcl_criticals.modifier(obj, hp_change, reason)
local damage = -hp_change
if damage > 0 and reason.type == "player" then
local hitter = reason.direct local hitter = reason.direct
if mcl_sprint.is_sprinting(hitter) then if mcl_sprint.is_sprinting(hitter) then
obj:add_velocity(hitter:get_velocity()) obj:add_velocity(hitter:get_velocity())
@ -27,12 +24,7 @@ function mcl_criticals.modifier(obj, hp_change, reason)
}) })
minetest.sound_play("mcl_criticals_hit", {object = obj}) minetest.sound_play("mcl_criticals_hit", {object = obj})
-- the minecraft wiki is actually wrong about a crit dealing 150% damage, see minecraft source code -- the minecraft wiki is actually wrong about a crit dealing 150% damage, see minecraft source code
damage = damage + math.random(0, math.floor(damage * 1.5 + 2)) return damage + math.random(0, math.floor(damage * 1.5 + 2))
end end
end end
return -damage
end
mcl_damage.register_modifier(function(player, hp_change, _, mcl_reason)
return mcl_criticals.modifier(player, hp_change, mcl_reason)
end, -100) end, -100)