From 8477d13c79ed27506ee8a0e09dc327a1cbf5e566 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 1 Oct 2023 04:33:40 +0200 Subject: [PATCH] General effects API overhaul - added a `register_effect()` function - added the withering effect - registered all the old effects under the new API - unified effect names - updated the main effect checker to use the new API - changed some hardcoded values to support the unified effect naming - added new namespaced metadata effects strings - added support for legacy effect player metadata - potions are still using the old effects API - added glue between old API calls and the new API - renamed the effect icons to support the unified effect naming --- mods/ITEMS/mcl_potions/functions.lua | 629 ++++++++++++++++++++++++--- mods/ITEMS/mcl_potions/potions.lua | 2 +- 2 files changed, 562 insertions(+), 69 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 24aa2e402..6f0255f16 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -1,4 +1,5 @@ local EF = {} +<<<<<<< HEAD EF.invisible = {} EF.poisoned = {} EF.regenerating = {} @@ -11,24 +12,358 @@ EF.night_vision = {} EF.fire_proof = {} EF.bad_omen = {} EF.withering = {} +======= + +local registered_effects = {} +>>>>>>> df28ce66d (General effects API overhaul) local EFFECT_TYPES = 0 -for _,_ in pairs(EF) do - EFFECT_TYPES = EFFECT_TYPES + 1 +minetest.register_on_mods_loaded(function() + for _,_ in pairs(EF) do + EFFECT_TYPES = EFFECT_TYPES + 1 + end +end) + + +-- ██████╗░███████╗░██████╗░██╗░██████╗████████╗███████╗██████╗ +-- ██╔══██╗██╔════╝██╔════╝░██║██╔════╝╚══██╔══╝██╔════╝██╔══██╗ +-- ██████╔╝█████╗░░██║░░██╗░██║╚█████╗░░░░██║░░░█████╗░░██████╔╝ +-- ██╔══██╗██╔══╝░░██║░░╚██╗██║░╚═══██╗░░░██║░░░██╔══╝░░██╔══██╗ +-- ██║░░██║███████╗╚██████╔╝██║██████╔╝░░░██║░░░███████╗██║░░██║ +-- ╚═╝░░╚═╝╚══════╝░╚═════╝░╚═╝╚═════╝░░░░╚═╝░░░╚══════╝╚═╝░░╚═╝ +-- +-- ███████╗███████╗███████╗███████╗░█████╗░████████╗░██████╗ +-- ██╔════╝██╔════╝██╔════╝██╔════╝██╔══██╗╚══██╔══╝██╔════╝ +-- █████╗░░█████╗░░█████╗░░█████╗░░██║░░╚═╝░░░██║░░░╚█████╗░ +-- ██╔══╝░░██╔══╝░░██╔══╝░░██╔══╝░░██║░░██╗░░░██║░░░░╚═══██╗ +-- ███████╗██║░░░░░██║░░░░░███████╗╚█████╔╝░░░██║░░░██████╔╝ +-- ╚══════╝╚═╝░░░░░╚═╝░░░░░╚══════╝░╚════╝░░░░╚═╝░░░╚═════╝░ + +local function generate_linear_lvl_to_fac(l1, l2) + local a = l2 - l1 + local b = 2*l1 - l2 + return function(level) + return (a*level + b) + end end +local function generate_rational_lvl_to_fac(l1, l2) + local a = (l1 - l2) / 1.5 + local b = 2*l2 - l1 + return function(level) + if level == 0 then return 0 end + return (a/level + b) + end +end + +local function generate_modifier_func(name, dmg_flag, mod_func) + return function(object, damage, reason) + if EF[name][object] and not reason.flags.bypasses_magic and reason.flags[dmg_flag] then + return mod_func and mod_func(damage) or 0 + end + end +end + +-- API - registers an effect +-- required parameters in def: +-- name - string - effect name in code +-- optional parameters in def: +-- icon - string - file name of the effect icon in HUD - defaults to one based on name +-- res_condition - function(object) - returning true if target is to be resistant to the effect +-- on_start - function(object, factor) - called when dealing the effect +-- on_load - function(object, factor) - called on_joinplayer and on_activate +-- on_step - function(dtime, object, factor, duration) - running every step for all objects with this effect +-- on_hit_timer - function(object, factor, duration) - if defined runs a hit_timer depending on timer_uses_factor value +-- on_end - function(object) - called when the effect wears off +-- particle_color - string - colorstring for particles - defaults to #3000EE +-- uses_factor - bool - whether factor affects the effect +-- lvl1_factor - integer - factor for lvl1 effect - defaults to 1 if uses_factor +-- lvl2_factor - integer - factor for lvl2 effect - defaults to 2 if uses_factor +-- timer_uses_factor - bool - whether hit_timer uses factor (uses_factor must be true) or a constant value (hit_timer_step must be defined) +-- hit_timer_step - float - interval between hit_timer hits +-- damage_modifier - string - damage flag of which damage is changed as defined by modifier_func +-- modifier_func - function(damage) - see damage_modifier, if not defined damage_modifier defaults to 100% resistance +-- modifier_priority - integer - priority passed when registering damage_modifier - defaults to -50 +function mcl_potions.register_effect(def) + local modname = minetest.get_current_modname() + if def.name == nil then + error("Unable to register effect: name is nil") + end + local name = def.name + local pdef = {} + if not def.icon then + pdef.icon = modname.."_effect_"..name..".png" + else + pdef.icon = def.icon + end + pdef.res_condition = def.res_condition + pdef.on_start = def.on_start + pdef.on_load = def.on_load + pdef.on_step = def.on_step + pdef.on_hit_timer = def.on_hit_timer + pdef.on_end = def.on_end + if not def.particle_color then + pdef.particle_color = "#3000EE" + else + pdef.particle_color = def.particle_color + end + if def.uses_factor then + pdef.uses_factor = true + local l1 = def.lvl1_factor or 1 + local l2 = def.lvl2_factor or 2*l1 + if l1 < l2 then + pdef.level_to_factor = generate_linear_lvl_to_fac(l1, l2) + elseif l1 > l2 then + pdef.level_to_factor = generate_rational_lvl_to_fac(l1, l2) + else + error("Can't extrapolate levels from lvl1 and lvl2 bearing the same factor") + end + else + pdef.uses_factor = false + end + if def.on_hit_timer then + if def.timer_uses_factor then + if not def.uses_factor then error("Uses factor but does not use factor?") end + pdef.timer_uses_factor = true + else + if not def.hit_timer_step then error("If hit_timer does not use factor, hit_timer_step must be defined") end + pdef.timer_uses_factor = false + pdef.hit_timer_step = def.hit_timer_step + end + end + if def.damage_modifier then + mcl_damage.register_modifier( + generate_modifier_func(name, def.damage_modifier, def.modifier_func), + def.modifier_priority or -50 + ) + end + registered_effects[name] = pdef + EF[name] = {} +end + +mcl_potions.register_effect({ + name = "invisibility", + on_start = function(object, factor) + mcl_potions.make_invisible(object, true) + end, + on_load = function(object, factor) + mcl_potions.make_invisible(object, true) + end, + on_end = function(object) + mcl_potions.make_invisible(object, false) + end, + particle_color = "#7F8392", + uses_factor = false, +}) + +mcl_potions.register_effect({ + name = "poison", + res_condition = function(object) + local entity = object:get_luaentity() + return (entity and (entity.harmed_by_heal or string.find(entity.name, "spider"))) + end, + on_hit_timer = function(object, factor, duration) + if mcl_util.get_hp(object) - 1 > 0 then + mcl_util.deal_damage(object, 1, {type = "magic"}) + end + end, + particle_color = "#4E9331", + uses_factor = true, + lvl1_factor = 1.25, + lvl2_factor = 0.6, + timer_uses_factor = true, +}) + +mcl_potions.register_effect({ + name = "regeneration", + res_condition = function(object) + local entity = object:get_luaentity() + return (entity and entity.harmed_by_heal) + end, + on_hit_timer = function(object, factor, duration) + local entity = object:get_luaentity() + if object:is_player() then + object:set_hp(math.min(object:get_properties().hp_max or 20, object:get_hp() + 1), { type = "set_hp", other = "regeneration" }) + elseif entity and entity.is_mob then + entity.health = math.min(entity.hp_max, entity.health + 1) + end + end, + particle_color = "#CD5CAB", + uses_factor = true, + lvl1_factor = 2.5, + lvl2_factor = 1.25, + timer_uses_factor = true, +}) + +mcl_potions.register_effect({ + name = "strength", + res_condition = function(object) + return (not object:is_player()) + end, + particle_color = "#932423", +}) + +mcl_potions.register_effect({ + name = "weakness", + res_condition = function(object) + return (not object:is_player()) + end, + particle_color = "#484D48", +}) + +mcl_potions.register_effect({ + name = "water_breathing", + on_step = function(dtime, object, factor, duration) + if not object:is_player() then return end + if object:get_breath() then + hb.hide_hudbar(object, "breath") + if object:get_breath() < 10 then object:set_breath(10) end + end + end, + particle_color = "#2E5299", + uses_factor = false, +}) + +mcl_potions.register_effect({ + name = "leaping", + res_condition = function(object) + return (not object:is_player()) + end, + on_start = function(object, factor) + playerphysics.add_physics_factor(object, "jump", "mcl_potions:leaping", 1+factor) + end, + on_end = function(object) + playerphysics.remove_physics_factor(object, "jump", "mcl_potions:leaping") + end, + particle_color = "#22FF4C", + uses_factor = true, + lvl1_factor = 0.5, + lvl2_factor = 1, +}) + +mcl_potions.register_effect({ + name = "swiftness", + res_condition = function(object) + return (not object:is_player()) + end, + on_start = function(object, factor) + playerphysics.add_physics_factor(object, "speed", "mcl_potions:swiftness", 1+factor) + end, + on_end = function(object) + playerphysics.remove_physics_factor(object, "speed", "mcl_potions:swiftness") + end, + particle_color = "#7CAFC6", + uses_factor = true, + lvl1_factor = 0.2, + lvl2_factor = 0.4, +}) + +mcl_potions.register_effect({ + name = "slowness", + res_condition = function(object) + return (not object:is_player()) + end, + on_start = function(object, factor) + playerphysics.add_physics_factor(object, "speed", "mcl_potions:slowness", 1-factor) + end, + on_end = function(object) + playerphysics.remove_physics_factor(object, "speed", "mcl_potions:slowness") + end, + particle_color = "#5A6C81", + uses_factor = true, + lvl1_factor = 0.15, + lvl2_factor = 0.3, +}) + +mcl_potions.register_effect({ + name = "night_vision", + res_condition = function(object) + return (not object:is_player()) + end, + on_start = function(object, factor) + object:get_meta():set_int("night_vision", 1) + mcl_weather.skycolor.update_sky_color({object}) + end, + on_step = function(dtime, object, factor, duration) + mcl_weather.skycolor.update_sky_color({object}) + end, + on_end = function(object) + local meta = object:get_meta() + meta:set_int("night_vision", 0) + mcl_weather.skycolor.update_sky_color({object}) + end, + particle_color = "#1F1FA1", + uses_factor = false, +}) + +mcl_potions.register_effect({ + name = "fire_resistance", + res_condition = function(object) + return (not object:is_player()) + end, + particle_color = "#E49A3A", + uses_factor = false, + damage_modifier = "is_fire", +}) + +mcl_potions.register_effect({ + name = "bad_omen", + particle_color = "#0b6138", +}) + +mcl_potions.register_effect({ + name = "withering", + res_condition = function(object) + local entity = object:get_luaentity() + return (entity and string.find(entity.name, "wither")) + end, + on_hit_timer = function(object, factor, duration) + if object:is_player() or object:get_luaentity() then + mcl_util.deal_damage(object, 1, {type = "magic"}) + end + end, + particle_color = "#000000", + uses_factor = true, + lvl1_factor = 2, + lvl2_factor = 0.5, + timer_uses_factor = true, +}) + + +-- ██╗░░░██╗██████╗░██████╗░░█████╗░████████╗███████╗ +-- ██║░░░██║██╔══██╗██╔══██╗██╔══██╗╚══██╔══╝██╔════╝ +-- ██║░░░██║██████╔╝██║░░██║███████║░░░██║░░░█████╗░░ +-- ██║░░░██║██╔═══╝░██║░░██║██╔══██║░░░██║░░░██╔══╝░░ +-- ╚██████╔╝██║░░░░░██████╦╝██║░░██║░░░██║░░░███████╗ +-- ░╚═════╝░╚═╝░░░░░╚═════╝░╚═╝░░╚═╝░░░╚═╝░░░╚══════╝ +-- +-- ██╗░░██╗██╗░░░██╗██████╗░ +-- ██║░░██║██║░░░██║██╔══██╗ +-- ███████║██║░░░██║██║░░██║ +-- ██╔══██║██║░░░██║██║░░██║ +-- ██║░░██║╚██████╔╝██████╦╝ +-- ╚═╝░░╚═╝░╚═════╝░╚═════╝░ + local icon_ids = {} local function potions_set_hudbar(player) +<<<<<<< HEAD if EF.withering[player] and EF.regenerating[player] then hb.change_hudbar(player, "health", nil, nil, "mcl_potions_icon_regen_wither.png", nil, "hudbars_bar_health.png") elseif EF.withering[player] then hb.change_hudbar(player, "health", nil, nil, "mcl_potions_icon_wither.png", nil, "hudbars_bar_health.png") elseif EF.poisoned[player] and EF.regenerating[player] then +======= + if EF.withering[player] and EF.regeneration[player] then + hb.change_hudbar(player, "health", nil, nil, "mcl_potions_icon_regen_wither.png", nil, "hudbars_bar_health.png") + elseif EF.withering[player] then + hb.change_hudbar(player, "health", nil, nil, "mcl_potions_icon_wither.png", nil, "hudbars_bar_health.png") + elseif EF.poison[player] and EF.regeneration[player] then +>>>>>>> df28ce66d (General effects API overhaul) hb.change_hudbar(player, "health", nil, nil, "hbhunger_icon_regen_poison.png", nil, "hudbars_bar_health.png") - elseif EF.poisoned[player] then + elseif EF.poison[player] then hb.change_hudbar(player, "health", nil, nil, "hbhunger_icon_health_poison.png", nil, "hudbars_bar_health.png") - elseif EF.regenerating[player] then + elseif EF.regeneration[player] then hb.change_hudbar(player, "health", nil, nil, "hudbars_icon_regenerate.png", nil, "hudbars_bar_health.png") else hb.change_hudbar(player, "health", nil, nil, "hudbars_icon_health.png", nil, "hudbars_bar_health.png") @@ -69,23 +404,17 @@ local function potions_set_icons(player) for i=1, EFFECT_TYPES do local icon = icon_ids[name][i] local effect_name = active_effects[i] - if effect_name == "swift" and EF.swift[player].is_slow then - effect_name = "slow" - end if effect_name == nil then player:hud_change(icon, "text", "blank.png") else player:hud_change(icon, "text", "mcl_potions_effect_"..effect_name..".png^[resize:128x128") end end - end local function potions_set_hud(player) - potions_set_hudbar(player) potions_set_icons(player) - end @@ -103,29 +432,33 @@ end -- ╚█████╔╝██║░░██║███████╗╚█████╔╝██║░╚██╗███████╗██║░░██║ -- ░╚════╝░╚═╝░░╚═╝╚══════╝░╚════╝░╚═╝░░╚═╝╚══════╝╚═╝░░╚═╝ -local is_player, entity, meta - minetest.register_globalstep(function(dtime) + for name, effect in pairs(registered_effects) do + for object, vals in pairs(EF[name]) do + EF[name][object].timer = vals.timer + dtime - -- Check for invisible players - for player, vals in pairs(EF.invisible) do - - EF.invisible[player].timer = EF.invisible[player].timer + dtime - - if player:get_pos() then mcl_potions._add_spawner(player, "#7F8392") end - - if EF.invisible[player].timer >= EF.invisible[player].dur then - mcl_potions.make_invisible(player, false) - EF.invisible[player] = nil - if player:is_player() then - meta = player:get_meta() - meta:set_string("_is_invisible", minetest.serialize(EF.invisible[player])) + if object:get_pos() then mcl_potions._add_spawner(object, effect.particle_color) end + if effect.on_step then effect.on_step(dtime, object, vals.factor, vals.dur) end + if effect.on_hit_timer then + EF[name][object].hit_timer = (vals.hit_timer or 0) + dtime + if EF[name][object].hit_timer >= vals.step then + effect.on_hit_timer(object, vals.factor, vals.dur) + if EF[name][object] then EF[name][object].hit_timer = 0 end + end end - potions_set_hud(player) + if EF[name][object].timer >= vals.dur then + if effect.on_end then effect.on_end(object) end + EF[name][object] = nil + if object:is_player() then + meta = object:get_meta() + meta:set_string("mcl_potions:"..name, minetest.serialize(EF[name][object])) + potions_set_hud(object) + end + end end - end +<<<<<<< HEAD -- Check for withering players for player, vals in pairs(EF.withering) do @@ -402,16 +735,10 @@ minetest.register_globalstep(function(dtime) end +======= +>>>>>>> df28ce66d (General effects API overhaul) end) --- Prevent damage to player with Fire Resistance enabled -mcl_damage.register_modifier(function(obj, damage, reason) - if EF.fire_proof[obj] and not reason.flags.bypasses_magic and reason.flags.is_fire then - return 0 - end -end, -50) - - -- ███████╗███████╗███████╗███████╗░█████╗░████████╗ -- ██╔════╝██╔════╝██╔════╝██╔════╝██╔══██╗╚══██╔══╝ @@ -428,6 +755,7 @@ end, -50) -- ╚══════╝░╚════╝░╚═╝░░╚═╝╚═════╝░╚═╝░░░░╚═════╝░╚═╝░░╚═╝░░░╚═╝░░░╚══════╝ function mcl_potions._clear_cached_player_data(player) +<<<<<<< HEAD EF.invisible[player] = nil EF.poisoned[player] = nil EF.regenerating[player] = nil @@ -440,24 +768,24 @@ function mcl_potions._clear_cached_player_data(player) EF.fire_proof[player] = nil EF.bad_omen[player] = nil EF.withering[player] = nil +======= + for name, effect in pairs(EF) do + effect[player] = nil + end +>>>>>>> df28ce66d (General effects API overhaul) meta = player:get_meta() meta:set_int("night_vision", 0) end function mcl_potions._reset_player_effects(player, set_hud) - if not player:is_player() then return end - mcl_potions.make_invisible(player, false) - - playerphysics.remove_physics_factor(player, "jump", "mcl_potions:leaping") - - playerphysics.remove_physics_factor(player, "speed", "mcl_potions:swiftness") - - mcl_weather.skycolor.update_sky_color({player}) + for name, effect in pairs(registered_effects) do + if effect.on_end then effect.on_end(player) end + end mcl_potions._clear_cached_player_data(player) @@ -467,12 +795,12 @@ function mcl_potions._reset_player_effects(player, set_hud) end function mcl_potions._save_player_effects(player) - if not player:is_player() then return end meta = player:get_meta() +<<<<<<< HEAD meta:set_string("_is_invisible", minetest.serialize(EF.invisible[player])) meta:set_string("_is_poisoned", minetest.serialize(EF.poisoned[player])) meta:set_string("_is_regenerating", minetest.serialize(EF.regenerating[player])) @@ -486,23 +814,90 @@ function mcl_potions._save_player_effects(player) meta:set_string("_has_bad_omen", minetest.serialize(EF.bad_omen[player])) meta:set_string("_is_withering", minetest.serialize(EF.withering[player])) +======= + for name, effect in pairs(registered_effects) do + meta:set_string("mcl_potions:_EF_"..name, minetest.serialize(EF[name][player])) + end +>>>>>>> df28ce66d (General effects API overhaul) end function mcl_potions._load_player_effects(player) - if not player:is_player() then return end meta = player:get_meta() - if minetest.deserialize(meta:get_string("_is_invisible")) then - EF.invisible[player] = minetest.deserialize(meta:get_string("_is_invisible")) - mcl_potions.make_invisible(player, true) + -- handle legacy meta strings + local legacy_invisible = minetest.deserialize(meta:get_string("_is_invisible")) + local legacy_poisoned = minetest.deserialize(meta:get_string("_is_poisoned")) + local legacy_regenerating = minetest.deserialize(meta:get_string("_is_regenerating")) + local legacy_strong = minetest.deserialize(meta:get_string("_is_strong")) + local legacy_weak = minetest.deserialize(meta:get_string("_is_weak")) + local legacy_water_breathing = minetest.deserialize(meta:get_string("_is_water_breathing")) + local legacy_leaping = minetest.deserialize(meta:get_string("_is_leaping")) + local legacy_swift = minetest.deserialize(meta:get_string("_is_swift")) + local legacy_night_vision = minetest.deserialize(meta:get_string("_is_cat")) + local legacy_fireproof = minetest.deserialize(meta:get_string("_is_fire_proof")) + local legacy_bad_omen = minetest.deserialize(meta:get_string("_has_bad_omen")) + local legacy_withering = minetest.deserialize(meta:get_string("_is_withering")) + if legacy_invisible then + EF.invisibility[player] = legacy_invisible + meta:set_string("_is_invisible", "") + end + if legacy_poisoned then + EF.poison[player] = legacy_poisoned + meta:set_string("_is_poisoned", "") + end + if legacy_regenerating then + EF.regeneration[player] = legacy_regenerating + meta:set_string("_is_regenerating", "") + end + if legacy_strong then + EF.strength[player] = legacy_strong + meta:set_string("_is_strong", "") + end + if legacy_weak then + EF.weakness[player] = legacy_weak + meta:set_string("_is_weak", "") + end + if legacy_water_breathing then + EF.water_breathing[player] = legacy_water_breating + meta:set_string("_is_water_breating", "") + end + if legacy_leaping then + EF.leaping[player] = legacy_leaping + meta:set_string("_is_leaping", "") + end + if legacy_swift then + EF.swiftness[player] = legacy_swift + meta:set_string("_is_swift", "") + end + if legacy_night_vision then + EF.night_vision[player] = legacy_night_vision + meta:set_string("_is_cat", "") + end + if legacy_fireproof then + EF.fire_resistance[player] = legacy_fireproof + meta:set_string("_is_fire_proof", "") + end + if legacy_bad_omen then + EF.bad_omen[player] = legacy_bad_omen + meta:set_string("_has_bad_omen", "") + end + if legacy_withering then + EF.withering[player] = legacy_withering + meta:set_string("_is_withering", "") end - if minetest.deserialize(meta:get_string("_is_poisoned")) then - EF.poisoned[player] = minetest.deserialize(meta:get_string("_is_poisoned")) + -- new API effects + on_load for loaded legacy effects + for name, effect in pairs(registered_effects) do + local loaded = minetest.deserialize(meta:get_string("mcl_potions:"..name)) + if loaded then EF[name][player] = loaded end + if EF[name][player] and effect.on_load then + effect.on_load(player, EF[name][player].factor) + end end +<<<<<<< HEAD if minetest.deserialize(meta:get_string("_is_regenerating")) then EF.regenerating[player] = minetest.deserialize(meta:get_string("_is_regenerating")) @@ -544,6 +939,8 @@ function mcl_potions._load_player_effects(player) EF.withering[player] = minetest.deserialize(meta:get_string("_is_withering")) end +======= +>>>>>>> df28ce66d (General effects API overhaul) end -- Returns true if player has given effect @@ -563,12 +960,12 @@ end function mcl_potions.player_clear_effect(player,effect) EF[effect][player] = nil - potions_set_icons(player) + potions_set_hud(player) end minetest.register_on_leaveplayer( function(player) mcl_potions._save_player_effects(player) - mcl_potions._clear_cached_player_data(player) -- clearout the buffer to prevent looking for a player not there + mcl_potions._clear_cached_player_data(player) -- clear the buffer to prevent looking for a player not there icon_ids[player:get_player_name()] = nil end) @@ -578,7 +975,7 @@ minetest.register_on_dieplayer( function(player) end) minetest.register_on_joinplayer( function(player) - mcl_potions._reset_player_effects(player, false) -- make sure there are no wierd holdover effects + mcl_potions._reset_player_effects(player, false) -- make sure there are no weird holdover effects mcl_potions._load_player_effects(player) potions_init_icons(player) -- .after required because player:hud_change doesn't work when called @@ -597,10 +994,8 @@ minetest.register_on_shutdown(function() for _,player in pairs(minetest.get_connected_players()) do mcl_potions._save_player_effects(player) end - end) - -- ░██████╗██╗░░░██╗██████╗░██████╗░░█████╗░██████╗░████████╗██╗███╗░░██╗░██████╗░ -- ██╔════╝██║░░░██║██╔══██╗██╔══██╗██╔══██╗██╔══██╗╚══██╔══╝██║████╗░██║██╔════╝░ -- ╚█████╗░██║░░░██║██████╔╝██████╔╝██║░░██║██████╔╝░░░██║░░░██║██╔██╗██║██║░░██╗░ @@ -727,10 +1122,62 @@ end -- ██║░░░░░╚██████╔╝██║░╚███║╚█████╔╝░░░██║░░░██║╚█████╔╝██║░╚███║██████╔╝ -- ╚═╝░░░░░░╚═════╝░╚═╝░░╚══╝░╚════╝░░░░╚═╝░░░╚═╝░╚════╝░╚═╝░░╚══╝╚═════╝░ +local function target_valid(object, name) + if object:get_hp() <= 0 then return false end + + local entity = object:get_luaentity() + if entity and entity.is_boss then return false end + + if not (registered_effects[name].res_condition + and registered_effects[name].res_condition(object)) then return true end +end + +function mcl_potions.give_effect(name, object, factor, duration) + if not target_valid(object, name) then return false end + + local edef = registered_effects[name] + if not edef then return false end + if not EF[name][object] then + local vals = {dur = duration, timer = 0,} + if edef.uses_factor then vals.factor = factor end + if edef.on_hit_timer then + if edef.timer_uses_factor then vals.step = factor + else vals.step = edef.hit_timer_step end + end + EF[name][object] = vals + if edef.on_start then edef.on_start(object, factor) end + else + local present = EF[name][object] + if not edef.uses_factor or (edef.uses_factor and factor >= present.factor) then + present.dur = math.max(duration, present.dur - present.timer) + present.timer = 0 + if edef.uses_factor then + present.factor = factor + if edef.timer_uses_factor then present.step = factor end + if edef.on_start then edef.on_start(object, factor) end + end + end + end + + if object:is_player() then potions_set_hud(object) end +end + +function mcl_potions.give_effect_by_level(name, object, level, duration) + if level == 0 then return false end + if not registered_effects[name].uses_factor then + return mcl_potions.give_effect(name, object, 0, duration) + end + local factor = registered_effects[name].level_to_factor(level) + return mcl_potions.give_effect(name, object, factor, duration) +end function mcl_potions.healing_func(player, hp) +<<<<<<< HEAD if not player or player:get_hp() <= 0 then return false end +======= + if player:get_hp() <= 0 then return false end +>>>>>>> df28ce66d (General effects API overhaul) local obj = player:get_luaentity() @@ -755,9 +1202,9 @@ function mcl_potions.healing_func(player, hp) mcl_util.deal_damage(player, -hp, {type = "magic"}) end - end +<<<<<<< HEAD function mcl_potions.swiftness_func(player, factor, duration) if not player or player:get_hp() <= 0 then return false end @@ -852,8 +1299,25 @@ function mcl_potions.weakness_func(player, factor, duration) end +======= +>>>>>>> df28ce66d (General effects API overhaul) function mcl_potions.strength_func(player, factor, duration) + return mcl_potions.give_effect("strength", player, factor, duration) +end +function mcl_potions.leaping_func(player, factor, duration) + return mcl_potions.give_effect("leaping", player, factor, duration) +end +function mcl_potions.weakness_func(player, factor, duration) + return mcl_potions.give_effect("weakness", player, factor, duration) +end +function mcl_potions.swiftness_func(player, factor, duration) + return mcl_potions.give_effect("swiftness", player, factor, duration) +end +function mcl_potions.slowness_func(player, factor, duration) + return mcl_potions.give_effect("slowness", player, factor, duration) +end +<<<<<<< HEAD if not player or player:get_hp() <= 0 then return false end local entity = player:get_luaentity() @@ -877,6 +1341,10 @@ function mcl_potions.strength_func(player, factor, duration) potions_set_icons(player) end +======= +function mcl_potions.withering_func(player, factor, duration) + return mcl_potions.give_effect("withering", player, factor, duration) +>>>>>>> df28ce66d (General effects API overhaul) end @@ -909,6 +1377,7 @@ end function mcl_potions.poison_func(player, factor, duration) +<<<<<<< HEAD if not player or player:get_hp() <= 0 then return false end @@ -933,10 +1402,14 @@ function mcl_potions.poison_func(player, factor, duration) potions_set_hud(player) end +======= + return mcl_potions.give_effect("poison", player, factor, duration) +>>>>>>> df28ce66d (General effects API overhaul) end function mcl_potions.regeneration_func(player, factor, duration) +<<<<<<< HEAD if not player or player:get_hp() <= 0 then return false end @@ -961,10 +1434,14 @@ function mcl_potions.regeneration_func(player, factor, duration) potions_set_hud(player) end +======= + return mcl_potions.give_effect("regeneration", player, factor, duration) +>>>>>>> df28ce66d (General effects API overhaul) end function mcl_potions.invisiblility_func(player, null, duration) +<<<<<<< HEAD if not player or player:get_hp() <= 0 then return false end @@ -1015,10 +1492,18 @@ function mcl_potions.water_breathing_func(player, null, duration) potions_set_icons(player) end +======= + return mcl_potions.give_effect("invisibility", player, null, duration) +end + +function mcl_potions.water_breathing_func(player, null, duration) + return mcl_potions.give_effect("water_breathing", player, null, duration) +>>>>>>> df28ce66d (General effects API overhaul) end function mcl_potions.fire_resistance_func(player, null, duration) +<<<<<<< HEAD if not player or player:get_hp() <= 0 then return false end @@ -1041,10 +1526,14 @@ function mcl_potions.fire_resistance_func(player, null, duration) potions_set_icons(player) end +======= + return mcl_potions.give_effect("fire_resistance", player, null, duration) +>>>>>>> df28ce66d (General effects API overhaul) end function mcl_potions.night_vision_func(player, null, duration) +<<<<<<< HEAD if not player or player:get_hp() <= 0 then return false end @@ -1077,6 +1566,9 @@ function mcl_potions.night_vision_func(player, null, duration) potions_set_icons(player) end +======= + return mcl_potions.give_effect("night_vision", player, null, duration) +>>>>>>> df28ce66d (General effects API overhaul) end function mcl_potions._extinguish_nearby_fire(pos, radius) @@ -1131,16 +1623,17 @@ function mcl_potions._extinguish_nearby_fire(pos, radius) end function mcl_potions.bad_omen_func(player, factor, duration) - if not EF.bad_omen[player] then - EF.bad_omen[player] = {dur = duration, timer = 0, factor = factor} - else - local victim = EF.bad_omen[player] - victim.dur = math.max(duration, victim.dur - victim.timer) - victim.timer = 0 - victim.factor = factor - end - - if player:is_player() then - potions_set_icons(player) - end + mcl_potions.give_effect("bad_omen", player, factor, duration) +-- if not EF.bad_omen[player] then +-- EF.bad_omen[player] = {dur = duration, timer = 0, factor = factor} +-- else +-- local victim = EF.bad_omen[player] +-- victim.dur = math.max(duration, victim.dur - victim.timer) +-- victim.timer = 0 +-- victim.factor = factor +-- end +-- +-- if player:is_player() then +-- potions_set_icons(player) +-- end end diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index fd9240b92..8a872f73e 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -535,7 +535,7 @@ local slowness_def = { color = "#5A6C81", effect = 0.85, is_dur = true, - on_use = mcl_potions.swiftness_func, + on_use = mcl_potions.slowness_func, is_II = true, is_plus = true, is_inv = true,