From 8477d13c79ed27506ee8a0e09dc327a1cbf5e566 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 1 Oct 2023 04:33:40 +0200 Subject: [PATCH 01/91] 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, From 5750284e8f26418672a08394d29891f9ccd4db15 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Tue, 10 Oct 2023 01:07:26 +0200 Subject: [PATCH 02/91] Improved /effect command and fixes -improved the /effect command, allowing to use effect levels -fixed a bug in level-to-factor conversions -renamed effect icons to follow the new convention --- mods/ITEMS/mcl_potions/commands.lua | 62 ++++++++++-------- mods/ITEMS/mcl_potions/functions.lua | 31 +++++++-- mods/ITEMS/mcl_potions/init.lua | 23 +++---- ...=> mcl_potions_effect_fire_resistance.png} | Bin ...ng => mcl_potions_effect_invisibility.png} | Bin ...oned.png => mcl_potions_effect_poison.png} | Bin ...ng => mcl_potions_effect_regeneration.png} | Bin ...ow.png => mcl_potions_effect_slowness.png} | Bin ...ng.png => mcl_potions_effect_strength.png} | Bin ...t.png => mcl_potions_effect_swiftness.png} | Bin ...ak.png => mcl_potions_effect_weakness.png} | Bin 11 files changed, 74 insertions(+), 42 deletions(-) rename textures/{mcl_potions_effect_fire_proof.png => mcl_potions_effect_fire_resistance.png} (100%) rename textures/{mcl_potions_effect_invisible.png => mcl_potions_effect_invisibility.png} (100%) rename textures/{mcl_potions_effect_poisoned.png => mcl_potions_effect_poison.png} (100%) rename textures/{mcl_potions_effect_regenerating.png => mcl_potions_effect_regeneration.png} (100%) rename textures/{mcl_potions_effect_slow.png => mcl_potions_effect_slowness.png} (100%) rename textures/{mcl_potions_effect_strong.png => mcl_potions_effect_strength.png} (100%) rename textures/{mcl_potions_effect_swift.png => mcl_potions_effect_swiftness.png} (100%) rename textures/{mcl_potions_effect_weak.png => mcl_potions_effect_weakness.png} (100%) diff --git a/mods/ITEMS/mcl_potions/commands.lua b/mods/ITEMS/mcl_potions/commands.lua index 10bf86311..16b3ec01e 100644 --- a/mods/ITEMS/mcl_potions/commands.lua +++ b/mods/ITEMS/mcl_potions/commands.lua @@ -8,23 +8,9 @@ local S = minetest.get_translator(minetest.get_current_modname()) -- ░╚════╝░╚═╝░░╚═╝╚═╝░░╚═╝░░░╚═╝░░░  ░╚════╝░░╚════╝░╚═╝░░░░░╚═╝╚═╝░░░░░╚═╝╚═╝░░╚═╝╚═╝░░╚══╝╚═════╝░╚═════╝░ -local get_chat_function = {} - -get_chat_function["poison"] = mcl_potions.poison_func -get_chat_function["regeneration"] = mcl_potions.regeneration_func -get_chat_function["invisibility"] = mcl_potions.invisiblility_func -get_chat_function["fire_resistance"] = mcl_potions.fire_resistance_func -get_chat_function["night_vision"] = mcl_potions.night_vision_func -get_chat_function["water_breathing"] = mcl_potions.water_breathing_func -get_chat_function["leaping"] = mcl_potions.leaping_func -get_chat_function["swiftness"] = mcl_potions.swiftness_func -get_chat_function["heal"] = mcl_potions.healing_func -get_chat_function["bad_omen"] = mcl_potions.bad_omen_func -get_chat_function["withering"] = mcl_potions.withering_func - minetest.register_chatcommand("effect",{ - params = S(" []"), - description = S("Add a status effect to yourself. Arguments: : name of status effect, e.g. poison. : duration in seconds. : effect strength multiplier (1 = 100%)"), + params = S(" [] []"), + description = S("Add a status effect to yourself. Arguments: : name of status effect, e.g. poison. : duration in seconds. : effect power determinant, bigger level results in more powerful effect for effects that depend on the level, defaults to 1, pass F to use low-level factor instead. : effect strength modifier, can mean different things depending on the effect."), privs = {server = true}, func = function(name, params) @@ -37,22 +23,46 @@ minetest.register_chatcommand("effect",{ if not P[1] then return false, S("Missing effect parameter!") - elseif not tonumber(P[2]) then + elseif P[1] == "list" then + local regs = mcl_potions.get_registered_effects() + local effects = "heal" + for name, _ in pairs(regs) do + effects = effects .. ", " .. name + end + return true, effects + elseif not tonumber(P[2])then return false, S("Missing or invalid duration parameter!") - elseif P[3] and not tonumber(P[3]) then - return false, S("Invalid factor parameter!") - end - -- Default factor = 1 - if not P[3] then - P[3] = 1.0 + elseif P[3] and not tonumber(P[3]) and P[3] ~= "F" then + return false, S("Invalid level parameter!") + elseif P[3] and P[3] == "F" and not P[4] then + return false, S("Missing or invalid factor parameter when level is F!") end - if get_chat_function[P[1]] then - get_chat_function[P[1]](minetest.get_player_by_name(name), tonumber(P[3]), tonumber(P[2])) - return true + -- Default level = 1 + if not P[3] then + P[3] = 1 + end + + if mcl_potions.is_effect_registered(P[1]) then + if P[3] == "F" then + local given = mcl_potions.give_effect(P[1], minetest.get_player_by_name(name), tonumber(P[4]), tonumber(P[2])) + if given then + return true, S("@1 effect given to player @2 for @3 seconds with factor of @4.", P[1], name, P[2], P[4]) + else + return false, S("Giving effect @1 to player @2 failed.", P[1], name) + end + else + local given = mcl_potions.give_effect_by_level(P[1], minetest.get_player_by_name(name), tonumber(P[3]), tonumber(P[2])) + if given then + return true, S("@1 effect on level @2 given to player @3 for @4 seconds.", P[1], P[3], name, P[2]) + else + return false, S("Giving effect @1 to player @2 failed.", P[1], name) + end + end else return false, S("@1 is not an available status effect.", P[1]) end end, }) + diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 6f0255f16..31c811e0b 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -48,7 +48,7 @@ local function generate_linear_lvl_to_fac(l1, l2) end local function generate_rational_lvl_to_fac(l1, l2) - local a = (l1 - l2) / 1.5 + local a = (l1 - l2) * 2 local b = 2*l2 - l1 return function(level) if level == 0 then return 0 end @@ -89,6 +89,15 @@ function mcl_potions.register_effect(def) if def.name == nil then error("Unable to register effect: name is nil") end + if def.name == "list" then + error("Unable to register effect: list is a reserved word") + end + if def.name == "heal" then + error("Unable to register effect: heal is a reserved word") + end + if registered_effects[name] then + error("Effect named "..name.." already registered!") + end local name = def.name local pdef = {} if not def.icon then @@ -141,6 +150,18 @@ function mcl_potions.register_effect(def) EF[name] = {} end +function mcl_potions.get_registered_effects() + return table.copy(registered_effects) +end + +function mcl_potions.is_effect_registered(name) + if registered_effects[name] then + return true + else + return false + end +end + mcl_potions.register_effect({ name = "invisibility", on_start = function(object, factor) @@ -891,7 +912,7 @@ function mcl_potions._load_player_effects(player) -- 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)) + local loaded = minetest.deserialize(meta:get_string("mcl_potions:_EF_"..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) @@ -1133,10 +1154,8 @@ local function target_valid(object, name) 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 edef or not target_valid(object, name) 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 @@ -1160,6 +1179,8 @@ function mcl_potions.give_effect(name, object, factor, duration) end if object:is_player() then potions_set_hud(object) end + + return true end function mcl_potions.give_effect_by_level(name, object, level, duration) diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index 8e4c53cad..8c308f1fb 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -462,17 +462,18 @@ function mcl_potions.get_alchemy(ingr, pot) return false end -mcl_mobs.effect_functions["poison"] = mcl_potions.poison_func -mcl_mobs.effect_functions["regeneration"] = mcl_potions.regeneration_func -mcl_mobs.effect_functions["invisibility"] = mcl_potions.invisiblility_func -mcl_mobs.effect_functions["fire_resistance"] = mcl_potions.fire_resistance_func -mcl_mobs.effect_functions["night_vision"] = mcl_potions.night_vision_func -mcl_mobs.effect_functions["water_breathing"] = mcl_potions.water_breathing_func -mcl_mobs.effect_functions["leaping"] = mcl_potions.leaping_func -mcl_mobs.effect_functions["swiftness"] = mcl_potions.swiftness_func -mcl_mobs.effect_functions["heal"] = mcl_potions.healing_func -mcl_mobs.effect_functions["bad_omen"] = mcl_potions.bad_omen_func -mcl_mobs.effect_functions["withering"] = mcl_potions.withering_func +-- TODO replace all calls to the old API with new API calls in other mods +-- mcl_mobs.effect_functions["poison"] = mcl_potions.poison_func +-- mcl_mobs.effect_functions["regeneration"] = mcl_potions.regeneration_func +-- mcl_mobs.effect_functions["invisibility"] = mcl_potions.invisiblility_func +-- mcl_mobs.effect_functions["fire_resistance"] = mcl_potions.fire_resistance_func +-- mcl_mobs.effect_functions["night_vision"] = mcl_potions.night_vision_func +-- mcl_mobs.effect_functions["water_breathing"] = mcl_potions.water_breathing_func +-- mcl_mobs.effect_functions["leaping"] = mcl_potions.leaping_func +-- mcl_mobs.effect_functions["swiftness"] = mcl_potions.swiftness_func +-- mcl_mobs.effect_functions["heal"] = mcl_potions.healing_func +-- mcl_mobs.effect_functions["bad_omen"] = mcl_potions.bad_omen_func +-- mcl_mobs.effect_functions["withering"] = mcl_potions.withering_func -- give withering to players in a wither rose local etime = 0 diff --git a/textures/mcl_potions_effect_fire_proof.png b/textures/mcl_potions_effect_fire_resistance.png similarity index 100% rename from textures/mcl_potions_effect_fire_proof.png rename to textures/mcl_potions_effect_fire_resistance.png diff --git a/textures/mcl_potions_effect_invisible.png b/textures/mcl_potions_effect_invisibility.png similarity index 100% rename from textures/mcl_potions_effect_invisible.png rename to textures/mcl_potions_effect_invisibility.png diff --git a/textures/mcl_potions_effect_poisoned.png b/textures/mcl_potions_effect_poison.png similarity index 100% rename from textures/mcl_potions_effect_poisoned.png rename to textures/mcl_potions_effect_poison.png diff --git a/textures/mcl_potions_effect_regenerating.png b/textures/mcl_potions_effect_regeneration.png similarity index 100% rename from textures/mcl_potions_effect_regenerating.png rename to textures/mcl_potions_effect_regeneration.png diff --git a/textures/mcl_potions_effect_slow.png b/textures/mcl_potions_effect_slowness.png similarity index 100% rename from textures/mcl_potions_effect_slow.png rename to textures/mcl_potions_effect_slowness.png diff --git a/textures/mcl_potions_effect_strong.png b/textures/mcl_potions_effect_strength.png similarity index 100% rename from textures/mcl_potions_effect_strong.png rename to textures/mcl_potions_effect_strength.png diff --git a/textures/mcl_potions_effect_swift.png b/textures/mcl_potions_effect_swiftness.png similarity index 100% rename from textures/mcl_potions_effect_swift.png rename to textures/mcl_potions_effect_swiftness.png diff --git a/textures/mcl_potions_effect_weak.png b/textures/mcl_potions_effect_weakness.png similarity index 100% rename from textures/mcl_potions_effect_weak.png rename to textures/mcl_potions_effect_weakness.png From d1ca0f23f03b9b5c77392fded486d5e544952c0a Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Thu, 12 Oct 2023 23:11:45 +0200 Subject: [PATCH 03/91] Resolved merge conflict --- mods/ITEMS/mcl_potions/functions.lua | 704 +-------------------------- 1 file changed, 1 insertion(+), 703 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 31c811e0b..d27d7a844 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -1,21 +1,5 @@ local EF = {} -<<<<<<< HEAD -EF.invisible = {} -EF.poisoned = {} -EF.regenerating = {} -EF.strong = {} -EF.weak = {} -EF.water_breathing = {} -EF.leaping = {} -EF.swift = {} -- for swiftness AND slowness -EF.night_vision = {} -EF.fire_proof = {} -EF.bad_omen = {} -EF.withering = {} -======= - local registered_effects = {} ->>>>>>> df28ce66d (General effects API overhaul) local EFFECT_TYPES = 0 minetest.register_on_mods_loaded(function() @@ -368,19 +352,11 @@ mcl_potions.register_effect({ 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.poison[player] then hb.change_hudbar(player, "health", nil, nil, "hbhunger_icon_health_poison.png", nil, "hudbars_bar_health.png") @@ -479,285 +455,6 @@ minetest.register_globalstep(function(dtime) end end end -<<<<<<< HEAD - - -- Check for withering players - for player, vals in pairs(EF.withering) do - - is_player = player:is_player() - entity = player:get_luaentity() - - EF.withering[player].timer = EF.withering[player].timer + dtime - EF.withering[player].hit_timer = (EF.withering[player].hit_timer or 0) + dtime - - if player:get_pos() then mcl_potions._add_spawner(player, "#000000") end - - if EF.withering[player].hit_timer >= EF.withering[player].step then - if is_player or entity then mcl_util.deal_damage(player, 1, {type = "magic"}) end - if EF.withering[player] then EF.withering[player].hit_timer = 0 end - end - - if EF.withering[player] and EF.withering[player].timer >= EF.withering[player].dur then - EF.withering[player] = nil - if is_player then - meta = player:get_meta() - meta:set_string("_is_withering", minetest.serialize(EF.withering[player])) - potions_set_hud(player) - end - end - - end - - -- Check for poisoned players - for player, vals in pairs(EF.poisoned) do - - is_player = player:is_player() - entity = player:get_luaentity() - - EF.poisoned[player].timer = EF.poisoned[player].timer + dtime - EF.poisoned[player].hit_timer = (EF.poisoned[player].hit_timer or 0) + dtime - - if player:get_pos() then mcl_potions._add_spawner(player, "#4E9331") end - - if EF.poisoned[player].hit_timer >= EF.poisoned[player].step then - if mcl_util.get_hp(player) - 1 > 0 then - mcl_util.deal_damage(player, 1, {type = "magic"}) - end - EF.poisoned[player].hit_timer = 0 - end - - if EF.poisoned[player] and EF.poisoned[player].timer >= EF.poisoned[player].dur then - EF.poisoned[player] = nil - if is_player then - meta = player:get_meta() - meta:set_string("_is_poisoned", minetest.serialize(EF.poisoned[player])) - potions_set_hud(player) - end - end - - end - - -- Check for regenerating players - for player, vals in pairs(EF.regenerating) do - - is_player = player:is_player() - entity = player:get_luaentity() - - EF.regenerating[player].timer = EF.regenerating[player].timer + dtime - EF.regenerating[player].heal_timer = (EF.regenerating[player].heal_timer or 0) + dtime - - if player:get_pos() then mcl_potions._add_spawner(player, "#CD5CAB") end - - if EF.regenerating[player].heal_timer >= EF.regenerating[player].step then - - if is_player then - player:set_hp(math.min(player:get_properties().hp_max or 20, player:get_hp() + 1), { type = "set_hp", other = "regeneration" }) - EF.regenerating[player].heal_timer = 0 - elseif entity and entity.is_mob then - entity.health = math.min(entity.hp_max, entity.health + 1) - EF.regenerating[player].heal_timer = 0 - else -- stop regenerating if not a player or mob - EF.regenerating[player] = nil - end - - end - - if EF.regenerating[player] and EF.regenerating[player].timer >= EF.regenerating[player].dur then - EF.regenerating[player] = nil - if is_player then - meta = player:get_meta() - meta:set_string("_is_regenerating", minetest.serialize(EF.regenerating[player])) - potions_set_hud(player) - end - end - - end - - -- Check for water breathing players - for player, vals in pairs(EF.water_breathing) do - - if player:is_player() then - - EF.water_breathing[player].timer = EF.water_breathing[player].timer + dtime - - if player:get_pos() then mcl_potions._add_spawner(player, "#2E5299") end - - if player:get_breath() then - hb.hide_hudbar(player, "breath") - if player:get_breath() < 10 then player:set_breath(10) end - end - - if EF.water_breathing[player].timer >= EF.water_breathing[player].dur then - meta = player:get_meta() - meta:set_string("_is_water_breathing", minetest.serialize(EF.water_breathing[player])) - EF.water_breathing[player] = nil - end - potions_set_hud(player) - - else - EF.water_breathing[player] = nil - end - - end - - -- Check for leaping players - for player, vals in pairs(EF.leaping) do - - if player:is_player() then - - EF.leaping[player].timer = EF.leaping[player].timer + dtime - - if player:get_pos() then mcl_potions._add_spawner(player, "#22FF4C") end - - if EF.leaping[player].timer >= EF.leaping[player].dur then - playerphysics.remove_physics_factor(player, "jump", "mcl_potions:leaping") - EF.leaping[player] = nil - meta = player:get_meta() - meta:set_string("_is_leaping", minetest.serialize(EF.leaping[player])) - end - potions_set_hud(player) - - else - EF.leaping[player] = nil - end - - end - - -- Check for swift players - for player, vals in pairs(EF.swift) do - - if player:is_player() then - - EF.swift[player].timer = EF.swift[player].timer + dtime - - if player:get_pos() then mcl_potions._add_spawner(player, "#7CAFC6") end - - if EF.swift[player].timer >= EF.swift[player].dur then - playerphysics.remove_physics_factor(player, "speed", "mcl_potions:swiftness") - EF.swift[player] = nil - meta = player:get_meta() - meta:set_string("_is_swift", minetest.serialize(EF.swift[player])) - end - potions_set_hud(player) - - else - EF.swift[player] = nil - end - - end - - -- Check for Night Vision equipped players - for player, vals in pairs(EF.night_vision) do - - if player:is_player() then - - EF.night_vision[player].timer = EF.night_vision[player].timer + dtime - - if player:get_pos() then mcl_potions._add_spawner(player, "#1F1FA1") end - - if EF.night_vision[player].timer >= EF.night_vision[player].dur then - EF.night_vision[player] = nil - meta = player:get_meta() - meta:set_string("_is_cat", minetest.serialize(EF.night_vision[player])) - meta:set_int("night_vision", 0) - end - mcl_weather.skycolor.update_sky_color({player}) - potions_set_hud(player) - - else - EF.night_vision[player] = nil - end - - end - - -- Check for Fire Proof players - for player, vals in pairs(EF.fire_proof) do - - if player:is_player() then - - player = player or player:get_luaentity() - - EF.fire_proof[player].timer = EF.fire_proof[player].timer + dtime - - if player:get_pos() then mcl_potions._add_spawner(player, "#E49A3A") end - - if EF.fire_proof[player].timer >= EF.fire_proof[player].dur then - EF.fire_proof[player] = nil - meta = player:get_meta() - meta:set_string("_is_fire_proof", minetest.serialize(EF.fire_proof[player])) - end - potions_set_hud(player) - - else - EF.fire_proof[player] = nil - end - - end - - -- Check for Weak players - for player, vals in pairs(EF.weak) do - - if player:is_player() then - - EF.weak[player].timer = EF.weak[player].timer + dtime - - if player:get_pos() then mcl_potions._add_spawner(player, "#484D48") end - - if EF.weak[player].timer >= EF.weak[player].dur then - EF.weak[player] = nil - meta = player:get_meta() - meta:set_string("_is_weak", minetest.serialize(EF.weak[player])) - end - - else - EF.weak[player] = nil - end - - end - - -- Check for Strong players - for player, vals in pairs(EF.strong) do - - if player:is_player() then - - EF.strong[player].timer = EF.strong[player].timer + dtime - - if player:get_pos() then mcl_potions._add_spawner(player, "#932423") end - - if EF.strong[player].timer >= EF.strong[player].dur then - EF.strong[player] = nil - meta = player:get_meta() - meta:set_string("_is_strong", minetest.serialize(EF.strong[player])) - end - - else - EF.strong[player] = nil - end - - end - - -- Check for Bad Omen - for player, vals in pairs(EF.bad_omen) do - - is_player = player:is_player() - - EF.bad_omen[player].timer = EF.bad_omen[player].timer + dtime - - if player:get_pos() then mcl_potions._add_spawner(player, "#0b6138") end - - if EF.bad_omen[player] and EF.bad_omen[player].timer >= EF.bad_omen[player].dur then - EF.bad_omen[player] = nil - if is_player then - meta = player:get_meta() - meta:set_string("_has_bad_omen", minetest.serialize(EF.bad_omen[player])) - potions_set_hud(player) - end - end - - end - -======= ->>>>>>> df28ce66d (General effects API overhaul) end) @@ -776,24 +473,9 @@ end) -- ╚══════╝░╚════╝░╚═╝░░╚═╝╚═════╝░╚═╝░░░░╚═════╝░╚═╝░░╚═╝░░░╚═╝░░░╚══════╝ function mcl_potions._clear_cached_player_data(player) -<<<<<<< HEAD - EF.invisible[player] = nil - EF.poisoned[player] = nil - EF.regenerating[player] = nil - EF.strong[player] = nil - EF.weak[player] = nil - EF.water_breathing[player] = nil - EF.leaping[player] = nil - EF.swift[player] = nil - EF.night_vision[player] = nil - 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) @@ -821,25 +503,9 @@ function mcl_potions._save_player_effects(player) 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])) - meta:set_string("_is_strong", minetest.serialize(EF.strong[player])) - meta:set_string("_is_weak", minetest.serialize(EF.weak[player])) - meta:set_string("_is_water_breathing", minetest.serialize(EF.water_breathing[player])) - meta:set_string("_is_leaping", minetest.serialize(EF.leaping[player])) - meta:set_string("_is_swift", minetest.serialize(EF.swift[player])) - meta:set_string("_is_cat", minetest.serialize(EF.night_vision[player])) - meta:set_string("_is_fire_proof", minetest.serialize(EF.fire_proof[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) @@ -918,50 +584,6 @@ function mcl_potions._load_player_effects(player) 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")) - end - - if minetest.deserialize(meta:get_string("_is_strong")) then - EF.strong[player] = minetest.deserialize(meta:get_string("_is_strong")) - end - - if minetest.deserialize(meta:get_string("_is_weak")) then - EF.weak[player] = minetest.deserialize(meta:get_string("_is_weak")) - end - - if minetest.deserialize(meta:get_string("_is_water_breathing")) then - EF.water_breathing[player] = minetest.deserialize(meta:get_string("_is_water_breathing")) - end - - if minetest.deserialize(meta:get_string("_is_leaping")) then - EF.leaping[player] = minetest.deserialize(meta:get_string("_is_leaping")) - end - - if minetest.deserialize(meta:get_string("_is_swift")) then - EF.swift[player] = minetest.deserialize(meta:get_string("_is_swift")) - end - - if minetest.deserialize(meta:get_string("_is_cat")) then - EF.night_vision[player] = minetest.deserialize(meta:get_string("_is_cat")) - end - - if minetest.deserialize(meta:get_string("_is_fire_proof")) then - EF.fire_proof[player] = minetest.deserialize(meta:get_string("_is_fire_proof")) - end - - if minetest.deserialize(meta:get_string("_has_bad_omen")) then - EF.bad_omen[player] = minetest.deserialize(meta:get_string("_has_bad_omen")) - end - - if minetest.deserialize(meta:get_string("_is_withering")) then - EF.withering[player] = minetest.deserialize(meta:get_string("_is_withering")) - end - -======= ->>>>>>> df28ce66d (General effects API overhaul) end -- Returns true if player has given effect @@ -1144,7 +766,7 @@ end -- ╚═╝░░░░░░╚═════╝░╚═╝░░╚══╝░╚════╝░░░░╚═╝░░░╚═╝░╚════╝░╚═╝░░╚══╝╚═════╝░ local function target_valid(object, name) - if object:get_hp() <= 0 then return false end + if not object or object:get_hp() <= 0 then return false end local entity = object:get_luaentity() if entity and entity.is_boss then return false end @@ -1193,13 +815,7 @@ function mcl_potions.give_effect_by_level(name, object, level, 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() if obj and obj.harmed_by_heal then hp = -hp end @@ -1225,103 +841,6 @@ function mcl_potions.healing_func(player, hp) end end -<<<<<<< HEAD -function mcl_potions.swiftness_func(player, factor, duration) - - if not player or player:get_hp() <= 0 then return false end - - local entity = player:get_luaentity() - if entity and entity.is_boss then return false end - - if not player:get_meta() then - return false - end - - if not EF.swift[player] then - - EF.swift[player] = {dur = duration, timer = 0, is_slow = factor < 1} - playerphysics.add_physics_factor(player, "speed", "mcl_potions:swiftness", factor) - - else - - local victim = EF.swift[player] - - playerphysics.add_physics_factor(player, "speed", "mcl_potions:swiftness", factor) - victim.dur = math.max(duration, victim.dur - victim.timer) - victim.timer = 0 - victim.is_slow = factor < 1 - - end - - if player:is_player() then - potions_set_icons(player) - end - -end - -function mcl_potions.leaping_func(player, factor, duration) - - if not player or player:get_hp() <= 0 then return false end - - local entity = player:get_luaentity() - if entity and entity.is_boss then return false end - - if not player:get_meta() then - return false - end - - if not EF.leaping[player] then - - EF.leaping[player] = {dur = duration, timer = 0} - playerphysics.add_physics_factor(player, "jump", "mcl_potions:leaping", factor) - - else - - local victim = EF.leaping[player] - - playerphysics.add_physics_factor(player, "jump", "mcl_potions:leaping", factor) - victim.dur = math.max(duration, victim.dur - victim.timer) - victim.timer = 0 - - end - - if player:is_player() then - potions_set_icons(player) - end - -end - - -function mcl_potions.weakness_func(player, factor, duration) - - if not player or player:get_hp() <= 0 then return false end - - local entity = player:get_luaentity() - if entity and entity.is_boss then return false end - - if not EF.weak[player] then - - EF.weak[player] = {dur = duration, timer = 0, factor = factor} - - else - - local victim = EF.weak[player] - - victim.factor = factor - victim.dur = math.max(duration, victim.dur - victim.timer) - victim.timer = 0 - - end - - if player:is_player() then - potions_set_icons(player) - end - -end - - -======= ->>>>>>> df28ce66d (General effects API overhaul) function mcl_potions.strength_func(player, factor, duration) return mcl_potions.give_effect("strength", player, factor, duration) end @@ -1338,258 +857,37 @@ 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() - if entity and entity.is_boss then return false end - - if not EF.strong[player] then - - EF.strong[player] = {dur = duration, timer = 0, factor = factor} - - else - - local victim = EF.strong[player] - - victim.factor = factor - victim.dur = math.max(duration, victim.dur - victim.timer) - victim.timer = 0 - - end - - if player:is_player() then - 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 - - -function mcl_potions.withering_func(player, factor, duration) - - if not player or player:get_hp() <= 0 then return false end - - local entity = player:get_luaentity() - if entity and (entity.is_boss or string.find(entity.name, "wither")) then return false end - - if not EF.withering[player] then - - EF.withering[player] = {step = factor, dur = duration, timer = 0} - - else - - local victim = EF.withering[player] - - victim.step = math.min(victim.step, factor) - victim.dur = math.max(duration, victim.dur - victim.timer) - victim.timer = 0 - - end - - if player:is_player() then - potions_set_hud(player) - end - end function mcl_potions.poison_func(player, factor, duration) -<<<<<<< HEAD - - if not player or player:get_hp() <= 0 then return false end - - local entity = player:get_luaentity() - if entity and (entity.is_boss or entity.harmed_by_heal or string.find(entity.name, "spider")) then return false end - - if not EF.poisoned[player] then - - EF.poisoned[player] = {step = factor, dur = duration, timer = 0} - - else - - local victim = EF.poisoned[player] - - victim.step = math.min(victim.step, factor) - victim.dur = math.max(duration, victim.dur - victim.timer) - victim.timer = 0 - - end - - if player:is_player() then - 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 - - local entity = player:get_luaentity() - if entity and (entity.is_boss or entity.harmed_by_heal) then return false end - - if not EF.regenerating[player] then - - EF.regenerating[player] = {step = factor, dur = duration, timer = 0} - - else - - local victim = EF.regenerating[player] - - victim.step = math.min(victim.step, factor) - victim.dur = math.max(duration, victim.dur - victim.timer) - victim.timer = 0 - - end - - if player:is_player() then - 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 - - local entity = player:get_luaentity() - if entity and entity.is_boss then return false end - - if not EF.invisible[player] then - - EF.invisible[player] = {dur = duration, timer = 0} - mcl_potions.make_invisible(player, true) - - else - - local victim = EF.invisible[player] - - victim.dur = math.max(duration, victim.dur - victim.timer) - victim.timer = 0 - - end - - if player:is_player() then - potions_set_icons(player) - end - -end - -function mcl_potions.water_breathing_func(player, null, duration) - - if not player or player:get_hp() <= 0 then return false end - - local entity = player:get_luaentity() - if entity and entity.is_boss then return false end - - if not EF.water_breathing[player] then - - EF.water_breathing[player] = {dur = duration, timer = 0} - - else - - local victim = EF.water_breathing[player] - - victim.dur = math.max(duration, victim.dur - victim.timer) - victim.timer = 0 - - end - - if player:is_player() then - 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 - - local entity = player:get_luaentity() - if entity and entity.is_boss then return false end - - if not EF.fire_proof[player] then - - EF.fire_proof[player] = {dur = duration, timer = 0} - - else - - local victim = EF.fire_proof[player] - victim.dur = math.max(duration, victim.dur - victim.timer) - victim.timer = 0 - - end - - if player:is_player() then - 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 - - local entity = player:get_luaentity() - if entity and entity.is_boss then return false end - - meta = player:get_meta() - if not EF.night_vision[player] then - - EF.night_vision[player] = {dur = duration, timer = 0} - - else - - local victim = EF.night_vision[player] - - victim.dur = math.max(duration, victim.dur - victim.timer) - victim.timer = 0 - - end - - is_player = player:is_player() - if is_player then - meta:set_int("night_vision", 1) - else - return -- Do not attempt to set night_vision on mobs - end - mcl_weather.skycolor.update_sky_color({player}) - - if player:is_player() then - 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) From 5827a7638d295a83485ad8c396f4ab2763a38bb2 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Thu, 12 Oct 2023 23:51:14 +0200 Subject: [PATCH 04/91] Reimplemented /effect heal and fixed bugs -heal subcommand to the /effect reimplemented -healing_func() from old API standardized, included in new API -(the last point is due to it being substantially different from others) -fixed a few bugs, potential crashes -fixed incorrect withering effect progression -standardized variable naming --- mods/ITEMS/mcl_potions/commands.lua | 20 +++++- mods/ITEMS/mcl_potions/functions.lua | 92 ++++++++++++---------------- 2 files changed, 57 insertions(+), 55 deletions(-) diff --git a/mods/ITEMS/mcl_potions/commands.lua b/mods/ITEMS/mcl_potions/commands.lua index 16b3ec01e..a04f8f079 100644 --- a/mods/ITEMS/mcl_potions/commands.lua +++ b/mods/ITEMS/mcl_potions/commands.lua @@ -9,8 +9,8 @@ local S = minetest.get_translator(minetest.get_current_modname()) minetest.register_chatcommand("effect",{ - params = S(" [] []"), - description = S("Add a status effect to yourself. Arguments: : name of status effect, e.g. poison. : duration in seconds. : effect power determinant, bigger level results in more powerful effect for effects that depend on the level, defaults to 1, pass F to use low-level factor instead. : effect strength modifier, can mean different things depending on the effect."), + params = S("|heal|list [] []"), + description = S("Add a status effect to yourself. Arguments: : name of status effect, e.g. poison. Passing list as effect name lists available effects. Passing heal as effect name heals (or harms) by amount designed by the next parameter. : duration in seconds. (: amount of healing when the effect is heal, passing a negative value subtracts health.) : effect power determinant, bigger level results in more powerful effect for effects that depend on the level, defaults to 1, pass F to use low-level factor instead. : effect strength modifier, can mean different things depending on the effect."), privs = {server = true}, func = function(name, params) @@ -30,7 +30,21 @@ minetest.register_chatcommand("effect",{ effects = effects .. ", " .. name end return true, effects - elseif not tonumber(P[2])then + elseif P[1] == "heal" then + local hp = tonumber(P[2]) + if not hp or hp == 0 then + return false, S("Missing or invalid heal amount parameter!") + else + mcl_potions.healing_func(minetest.get_player_by_name(name), hp) + if hp > 0 then + if hp < 1 then hp = 1 end + return true, S("Player @1 healed by @2 HP.", name, hp) + else + if hp > -1 then hp = -1 end + return true, S("Player @1 harmed by @2 HP.", name, hp) + end + end + elseif not tonumber(P[2]) then return false, S("Missing or invalid duration parameter!") elseif P[3] and not tonumber(P[3]) and P[3] ~= "F" then return false, S("Invalid level parameter!") diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index d27d7a844..a5d05e8f9 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -330,7 +330,7 @@ mcl_potions.register_effect({ particle_color = "#000000", uses_factor = true, lvl1_factor = 2, - lvl2_factor = 0.5, + lvl2_factor = 1, timer_uses_factor = true, }) @@ -444,7 +444,7 @@ minetest.register_globalstep(function(dtime) end end - if EF[name][object].timer >= vals.dur then + if not EF[name][object] or 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 @@ -684,13 +684,13 @@ function mcl_potions.make_invisible(obj_ref, hide) mcl_player.player_set_visibility(obj_ref, true) obj_ref:set_nametag_attributes({ color = { r = 255, g = 255, b = 255, a = 255 } }) end - else + else -- TODO make below section (and preferably other effects on mobs) rely on metadata if hide then local luaentity = obj_ref:get_luaentity() - EF.invisible[obj_ref].old_size = luaentity.visual_size + EF.invisibility[obj_ref].old_size = luaentity.visual_size obj_ref:set_properties({ visual_size = { x = 0, y = 0 } }) else - obj_ref:set_properties({ visual_size = EF.invisible[obj_ref].old_size }) + obj_ref:set_properties({ visual_size = EF.invisibility[obj_ref].old_size }) end end end @@ -814,11 +814,11 @@ function mcl_potions.give_effect_by_level(name, object, level, duration) return mcl_potions.give_effect(name, object, factor, duration) end -function mcl_potions.healing_func(player, hp) - if not player or player:get_hp() <= 0 then return false end - local obj = player:get_luaentity() +function mcl_potions.healing_func(object, hp) + if not object or object:get_hp() <= 0 then return false end + local ent = object:get_luaentity() - if obj and obj.harmed_by_heal then hp = -hp end + if ent and ent.harmed_by_heal then hp = -hp end if hp > 0 then -- at least 1 HP @@ -826,10 +826,10 @@ function mcl_potions.healing_func(player, hp) hp = 1 end - if obj and obj.is_mob then - obj.health = math.max(obj.health + hp, obj.hp_max) - elseif player:is_player() then - player:set_hp(math.min(player:get_hp() + hp, player:get_properties().hp_max), { type = "set_hp", other = "healing" }) + if ent and ent.is_mob then + ent.health = math.min(ent.health + hp, ent.hp_max) + elseif object:is_player() then + object:set_hp(math.min(object:get_hp() + hp, object:get_properties().hp_max), { type = "set_hp", other = "healing" }) end elseif hp < 0 then @@ -837,57 +837,57 @@ function mcl_potions.healing_func(player, hp) hp = -1 end - mcl_util.deal_damage(player, -hp, {type = "magic"}) + mcl_util.deal_damage(object, -hp, {type = "magic"}) end end -function mcl_potions.strength_func(player, factor, duration) - return mcl_potions.give_effect("strength", player, factor, duration) +function mcl_potions.strength_func(object, factor, duration) + return mcl_potions.give_effect("strength", object, factor, duration) end -function mcl_potions.leaping_func(player, factor, duration) - return mcl_potions.give_effect("leaping", player, factor, duration) +function mcl_potions.leaping_func(object, factor, duration) + return mcl_potions.give_effect("leaping", object, factor, duration) end -function mcl_potions.weakness_func(player, factor, duration) - return mcl_potions.give_effect("weakness", player, factor, duration) +function mcl_potions.weakness_func(object, factor, duration) + return mcl_potions.give_effect("weakness", object, factor, duration) end -function mcl_potions.swiftness_func(player, factor, duration) - return mcl_potions.give_effect("swiftness", player, factor, duration) +function mcl_potions.swiftness_func(object, factor, duration) + return mcl_potions.give_effect("swiftness", object, factor, duration) end -function mcl_potions.slowness_func(player, factor, duration) - return mcl_potions.give_effect("slowness", player, factor, duration) +function mcl_potions.slowness_func(object, factor, duration) + return mcl_potions.give_effect("slowness", object, factor, duration) end -function mcl_potions.withering_func(player, factor, duration) - return mcl_potions.give_effect("withering", player, factor, duration) +function mcl_potions.withering_func(object, factor, duration) + return mcl_potions.give_effect("withering", object, factor, duration) end -function mcl_potions.poison_func(player, factor, duration) - return mcl_potions.give_effect("poison", player, factor, duration) +function mcl_potions.poison_func(object, factor, duration) + return mcl_potions.give_effect("poison", object, factor, duration) end -function mcl_potions.regeneration_func(player, factor, duration) - return mcl_potions.give_effect("regeneration", player, factor, duration) +function mcl_potions.regeneration_func(object, factor, duration) + return mcl_potions.give_effect("regeneration", object, factor, duration) end -function mcl_potions.invisiblility_func(player, null, duration) - return mcl_potions.give_effect("invisibility", player, null, duration) +function mcl_potions.invisiblility_func(object, null, duration) + return mcl_potions.give_effect("invisibility", object, null, duration) end -function mcl_potions.water_breathing_func(player, null, duration) - return mcl_potions.give_effect("water_breathing", player, null, duration) +function mcl_potions.water_breathing_func(object, null, duration) + return mcl_potions.give_effect("water_breathing", object, null, duration) end -function mcl_potions.fire_resistance_func(player, null, duration) - return mcl_potions.give_effect("fire_resistance", player, null, duration) +function mcl_potions.fire_resistance_func(object, null, duration) + return mcl_potions.give_effect("fire_resistance", object, null, duration) end -function mcl_potions.night_vision_func(player, null, duration) - return mcl_potions.give_effect("night_vision", player, null, duration) +function mcl_potions.night_vision_func(object, null, duration) + return mcl_potions.give_effect("night_vision", object, null, duration) end function mcl_potions._extinguish_nearby_fire(pos, radius) @@ -941,18 +941,6 @@ function mcl_potions._extinguish_nearby_fire(pos, radius) return exting end -function mcl_potions.bad_omen_func(player, factor, duration) - 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 +function mcl_potions.bad_omen_func(object, factor, duration) + mcl_potions.give_effect("bad_omen", object, factor, duration) end From d85e582e8c307ed3dbb0e0f3a34af9154b82503d Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Fri, 27 Oct 2023 03:19:25 +0200 Subject: [PATCH 05/91] Arabic-to-Roman converter redo -rewrote the Arabic-to-Roman number converter -moved it to mcl_util --- mods/CORE/mcl_util/init.lua | 2 ++ mods/CORE/mcl_util/roman_numerals.lua | 30 +++++++++++++++++ mods/ITEMS/mcl_enchanting/engine.lua | 2 +- mods/ITEMS/mcl_enchanting/init.lua | 1 - mods/ITEMS/mcl_enchanting/mod.conf | 2 +- mods/ITEMS/mcl_enchanting/roman_numerals.lua | 34 -------------------- 6 files changed, 34 insertions(+), 37 deletions(-) create mode 100644 mods/CORE/mcl_util/roman_numerals.lua delete mode 100644 mods/ITEMS/mcl_enchanting/roman_numerals.lua diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index c2ae5391e..4204e218d 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -1,5 +1,7 @@ mcl_util = {} +dofile(minetest.get_modpath(minetest.get_current_modname()).."/roman_numerals.lua") + -- Updates all values in t using values from to*. function table.update(t, ...) for _, to in ipairs {...} do diff --git a/mods/CORE/mcl_util/roman_numerals.lua b/mods/CORE/mcl_util/roman_numerals.lua new file mode 100644 index 000000000..a808e43f1 --- /dev/null +++ b/mods/CORE/mcl_util/roman_numerals.lua @@ -0,0 +1,30 @@ +local converter = { + {1000, "M"}, + {900, "CM"}, + {500, "D"}, + {400, "CD"}, + {100, "C"}, + {90, "XC"}, + {50, "L"}, + {40, "XL"}, + {10, "X"}, + {9, "IX"}, + {5, "V"}, + {4, "IV"}, + {1, "I"} +} + +mcl_util.to_roman = function(number) + local r = "" + local a = number + local i = 1 + while a > 0 do + if a >= converter[i][1] then + a = a - converter[i][1] + r = r.. converter[i][2] + else + i = i + 1 + end + end + return r +end diff --git a/mods/ITEMS/mcl_enchanting/engine.lua b/mods/ITEMS/mcl_enchanting/engine.lua index 67ef72056..dd01d5950 100644 --- a/mods/ITEMS/mcl_enchanting/engine.lua +++ b/mods/ITEMS/mcl_enchanting/engine.lua @@ -56,7 +56,7 @@ end function mcl_enchanting.get_enchantment_description(enchantment, level) local enchantment_def = mcl_enchanting.enchantments[enchantment] return enchantment_def.name .. - (enchantment_def.max_level == 1 and "" or " " .. mcl_enchanting.roman_numerals.toRoman(level)) + (enchantment_def.max_level == 1 and "" or " " .. mcl_util.to_roman(level)) end function mcl_enchanting.get_colorized_enchantment_description(enchantment, level) diff --git a/mods/ITEMS/mcl_enchanting/init.lua b/mods/ITEMS/mcl_enchanting/init.lua index 9f9fbd271..02ed1ee85 100644 --- a/mods/ITEMS/mcl_enchanting/init.lua +++ b/mods/ITEMS/mcl_enchanting/init.lua @@ -11,7 +11,6 @@ mcl_enchanting = { book_animation_steps = {0, 640, 680, 700, 740}, book_animation_loop = {["open"] = true, ["close"] = true}, book_animation_speed = 40, - roman_numerals = dofile(modpath .. "/roman_numerals.lua"), -- https://exercism.io/tracks/lua/exercises/roman-numerals/solutions/73c2fb7521e347209312d115f872fa49 enchantments = {}, overlay = "^[colorize:purple:50", --overlay = "^[invert:rgb^[multiply:#4df44d:50^[invert:rgb", diff --git a/mods/ITEMS/mcl_enchanting/mod.conf b/mods/ITEMS/mcl_enchanting/mod.conf index 610492857..d163fcd55 100644 --- a/mods/ITEMS/mcl_enchanting/mod.conf +++ b/mods/ITEMS/mcl_enchanting/mod.conf @@ -1,5 +1,5 @@ name = mcl_enchanting description = Enchanting for MineClone2 -depends = tt, walkover, mcl_sounds, mcl_colors, mcl_experience +depends = tt, walkover, mcl_sounds, mcl_colors, mcl_experience, mcl_util optional_depends = screwdriver author = Fleckenstein diff --git a/mods/ITEMS/mcl_enchanting/roman_numerals.lua b/mods/ITEMS/mcl_enchanting/roman_numerals.lua deleted file mode 100644 index f40c65406..000000000 --- a/mods/ITEMS/mcl_enchanting/roman_numerals.lua +++ /dev/null @@ -1,34 +0,0 @@ --------------------------------------------------------------------- ---! @file ---! @brief Convert from normal numbers to Roman Numerals ---------------------------------------------------------------------- -local conversionTable = { - { number = 1000, symbol = "M" }, - { number = 900, symbol = "CM" }, - { number = 500, symbol = "D" }, - { number = 400, symbol = "CD" }, - { number = 100, symbol = "C" }, - { number = 90, symbol = "XC" }, - { number = 50, symbol = "L" }, - { number = 40, symbol = "XL" }, - { number = 10, symbol = "X" }, - { number = 9, symbol = "IX" }, - { number = 5, symbol = "V" }, - { number = 4, symbol = "IV" }, - { number = 1, symbol = "I" } -} - -return{ - toRoman = function(number) - local romanNumeral = "" - - for _,table in pairs (conversionTable) do - while(number >= table.number) do - romanNumeral = romanNumeral .. table.symbol - number = number - table.number - end - end - - return romanNumeral - end -} From f1e9c3b5632bbcde1900deb05165fa22adc1a2b7 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Fri, 27 Oct 2023 05:02:43 +0200 Subject: [PATCH 06/91] Translatable effect names and cleanup -added translatable effect names to the API -made /effect utilize those descriptions -cleaned up variables/constants to go with further API changes --- mods/ITEMS/mcl_potions/commands.lua | 14 ++++---- mods/ITEMS/mcl_potions/functions.lua | 51 +++++++++++++++++----------- mods/ITEMS/mcl_potions/init.lua | 11 +++--- 3 files changed, 46 insertions(+), 30 deletions(-) diff --git a/mods/ITEMS/mcl_potions/commands.lua b/mods/ITEMS/mcl_potions/commands.lua index a04f8f079..53245f4fc 100644 --- a/mods/ITEMS/mcl_potions/commands.lua +++ b/mods/ITEMS/mcl_potions/commands.lua @@ -24,9 +24,8 @@ minetest.register_chatcommand("effect",{ if not P[1] then return false, S("Missing effect parameter!") elseif P[1] == "list" then - local regs = mcl_potions.get_registered_effects() local effects = "heal" - for name, _ in pairs(regs) do + for name, _ in pairs(mcl_potions.registered_effects) do effects = effects .. ", " .. name end return true, effects @@ -57,20 +56,21 @@ minetest.register_chatcommand("effect",{ P[3] = 1 end - if mcl_potions.is_effect_registered(P[1]) then + local def = mcl_potions.registered_effects[P[1]] + if def then if P[3] == "F" then local given = mcl_potions.give_effect(P[1], minetest.get_player_by_name(name), tonumber(P[4]), tonumber(P[2])) if given then - return true, S("@1 effect given to player @2 for @3 seconds with factor of @4.", P[1], name, P[2], P[4]) + return true, S("@1 effect given to player @2 for @3 seconds with factor of @4.", def.description, name, P[2], P[4]) else - return false, S("Giving effect @1 to player @2 failed.", P[1], name) + return false, S("Giving effect @1 to player @2 failed.", def.description, name) end else local given = mcl_potions.give_effect_by_level(P[1], minetest.get_player_by_name(name), tonumber(P[3]), tonumber(P[2])) if given then - return true, S("@1 effect on level @2 given to player @3 for @4 seconds.", P[1], P[3], name, P[2]) + return true, S("@1 effect on level @2 given to player @3 for @4 seconds.", def.description, P[3], name, P[2]) else - return false, S("Giving effect @1 to player @2 failed.", P[1], name) + return false, S("Giving effect @1 to player @2 failed.", def.description, name) end end else diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index a5d05e8f9..8aa01c569 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -1,5 +1,8 @@ +local S = minetest.get_translator(minetest.get_current_modname()) + local EF = {} -local registered_effects = {} +mcl_potions.registered_effects = {} +local registered_effects = mcl_potions.registered_effects -- shorthand ref local EFFECT_TYPES = 0 minetest.register_on_mods_loaded(function() @@ -8,7 +11,6 @@ minetest.register_on_mods_loaded(function() end end) - -- ██████╗░███████╗░██████╗░██╗░██████╗████████╗███████╗██████╗ -- ██╔══██╗██╔════╝██╔════╝░██║██╔════╝╚══██╔══╝██╔════╝██╔══██╗ -- ██████╔╝█████╗░░██║░░██╗░██║╚█████╗░░░░██║░░░█████╗░░██████╔╝ @@ -51,7 +53,9 @@ end -- API - registers an effect -- required parameters in def: -- name - string - effect name in code +-- description - translated string - actual effect name in game -- optional parameters in def: +-- get_tt - function(factor) - returns tooltip description text for use with potions -- 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 @@ -70,25 +74,33 @@ end -- 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 + local name = def.name + if name == nil then error("Unable to register effect: name is nil") end - if def.name == "list" then + if type(name) ~= "string" then + error("Unable to register effect: name is not a string") + end + if name == "list" then error("Unable to register effect: list is a reserved word") end - if def.name == "heal" then + if name == "heal" then error("Unable to register effect: heal is a reserved word") end if registered_effects[name] then error("Effect named "..name.." already registered!") end - local name = def.name + if not def.description or type(def.description) ~= "string" then + error("Unable to register effect: description is not a string") + end local pdef = {} + pdef.description = def.description if not def.icon then pdef.icon = modname.."_effect_"..name..".png" else pdef.icon = def.icon end + pdef.get_tt = def.get_tt pdef.res_condition = def.res_condition pdef.on_start = def.on_start pdef.on_load = def.on_load @@ -134,20 +146,9 @@ function mcl_potions.register_effect(def) EF[name] = {} end -function mcl_potions.get_registered_effects() - return table.copy(registered_effects) -end - -function mcl_potions.is_effect_registered(name) - if registered_effects[name] then - return true - else - return false - end -end - mcl_potions.register_effect({ name = "invisibility", + description = S("Invisiblity"), on_start = function(object, factor) mcl_potions.make_invisible(object, true) end, @@ -163,6 +164,7 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "poison", + description = S("Poison"), res_condition = function(object) local entity = object:get_luaentity() return (entity and (entity.harmed_by_heal or string.find(entity.name, "spider"))) @@ -181,6 +183,7 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "regeneration", + description = S("Regeneration"), res_condition = function(object) local entity = object:get_luaentity() return (entity and entity.harmed_by_heal) @@ -202,6 +205,7 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "strength", + description = S("Strength"), res_condition = function(object) return (not object:is_player()) end, @@ -210,6 +214,7 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "weakness", + description = S("Weakness"), res_condition = function(object) return (not object:is_player()) end, @@ -218,6 +223,7 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "water_breathing", + description = S("Water Breathing"), on_step = function(dtime, object, factor, duration) if not object:is_player() then return end if object:get_breath() then @@ -231,6 +237,7 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "leaping", + description = S("Leaping"), res_condition = function(object) return (not object:is_player()) end, @@ -248,6 +255,7 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "swiftness", + description = S("Swiftness"), res_condition = function(object) return (not object:is_player()) end, @@ -265,6 +273,7 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "slowness", + description = S("Slowness"), res_condition = function(object) return (not object:is_player()) end, @@ -282,6 +291,7 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "night_vision", + description = S("Night Vision"), res_condition = function(object) return (not object:is_player()) end, @@ -303,6 +313,7 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "fire_resistance", + description = S("Fire Resistance"), res_condition = function(object) return (not object:is_player()) end, @@ -313,11 +324,13 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "bad_omen", + description = S("Bad Omen"), particle_color = "#0b6138", }) mcl_potions.register_effect({ name = "withering", + description = S("Withering"), res_condition = function(object) local entity = object:get_luaentity() return (entity and string.find(entity.name, "wither")) @@ -696,7 +709,7 @@ function mcl_potions.make_invisible(obj_ref, hide) end -function mcl_potions._use_potion(item, obj, color) +function mcl_potions._use_potion(obj, color) local d = 0.1 local pos = obj:get_pos() minetest.sound_play("mcl_potions_drinking", {pos = pos, max_hear_distance = 6, gain = 1}) diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index 8c308f1fb..6df03db9d 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -8,14 +8,17 @@ mcl_potions = {} -- duration effects of glowstone are a time factor of 1/2 -- splash potion duration effects are reduced by a factor of 3/4 -mcl_potions.II_FACTOR = 2 +mcl_potions.POTENT_FACTOR = 2 mcl_potions.PLUS_FACTOR = 8/3 +mcl_potions.INV_FACTOR = 0.50 mcl_potions.DURATION = 180 -mcl_potions.DURATION_PLUS = mcl_potions.DURATION * mcl_potions.PLUS_FACTOR -mcl_potions.DURATION_2 = mcl_potions.DURATION / mcl_potions.II_FACTOR +mcl_potions.DURATION_INV = mcl_potions.DURATION * mcl_potions.INV_FACTOR + +mcl_potions.II_FACTOR = mcl_potions.POTENT_FACTOR -- TODO remove at some point +mcl_potions.DURATION_PLUS = mcl_potions.DURATION * mcl_potions.PLUS_FACTOR -- TODO remove at some point +mcl_potions.DURATION_2 = mcl_potions.DURATION / mcl_potions.II_FACTOR -- TODO remove at some point -mcl_potions.INV_FACTOR = 0.50 mcl_potions.SPLASH_FACTOR = 0.75 mcl_potions.LINGERING_FACTOR = 0.25 From 9383b903ef45fbc1ae5cf687c825319a16eaf340 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Fri, 27 Oct 2023 05:06:45 +0200 Subject: [PATCH 07/91] Added new potions registering API -added comprehensive potions registering API -new API registers only drinkable potions for now -new API is compatible with very complex tooltips -new API can have multiple effects per potion -no hardcoding for specific potions in the new API --- mods/ITEMS/mcl_potions/potions.lua | 173 ++++++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 8a872f73e..072316136 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -1,5 +1,4 @@ local S = minetest.get_translator(minetest.get_current_modname()) ---local brewhelp = S("Try different combinations to create potions.") local function potion_image(colorstring, opacity) if not opacity then @@ -90,6 +89,178 @@ function return_on_use(def, effect, dur) end end +local function generate_on_use(effects, color, on_use, custom_effect) + return function(itemstack, user, pointed_thing) + if pointed_thing.type == "node" then + if user and not user:get_player_control().sneak then + local node = minetest.get_node(pointed_thing.under) + if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then + return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack + end + end + elseif pointed_thing.type == "object" then + return itemstack + end + + local potency = itemstack:get_meta():get_int("mcl_potions:potion_potent") + local plus = itemstack:get_meta():get_int("mcl_potions:potion_plus") + local ef_level + local dur + for name, details in pairs(effects) do + if details.uses_level then + ef_level = details.level + details.level_scaling * (potency) + else + ef_level = details.level + end + if details.dur_variable then + dur = details.dur * math.pow(mcl_potions.PLUS_FACTOR, plus) + if potency>0 and details.uses_level then + dur = dur / math.pow(mcl_potions.POTENT_FACTOR, potency) + end + else + dur = details.dur + end + mcl_potions.give_effect_by_level(name, user, ef_level, dur) + end + + if on_use then on_use(user, potency+1) end + if custom_effect then custom_effect(user, potency+1) end + + itemstack = minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) + if itemstack then mcl_potions._use_potion(user, color) end + + return itemstack + end +end + +-- API - registers a potion +-- required parameters in def: +-- name - string - potion name in code +-- optional parameters in def: +-- desc_prefix - translated string - part of visible potion name, comes before the word "Potion" +-- desc_suffix - translated string - part of visible potion name, comes after the word "Potion" +-- _tt - translated string - custom tooltip text +-- _dynamic_tt - function(level) - returns custom tooltip text dependent on potion level +-- _longdesc - translated string - text for in-game documentation +-- stack_max - int - max stack size - defaults to 1 +-- image - string - name of a custom texture of the potion icon +-- color - string - colorstring for potion icon when image is not defined - defaults to #0000FF +-- groups - table - item groups definition - +-- - must contain _mcl_potion=1 for tooltip to include dynamic_tt and effects +-- - defaults to {brewitem=1, food=3, can_eat_when_full=1, _mcl_potion=1} +-- _effect_list - table - all the effects dealt by the potion in the format of tables +-- -- the name of each sub-table should be a name of a registered effect, and fields can be the following: +-- -- -- uses_level - bool - whether the level of the potion affects the level of the effect - +-- -- -- - defaults to the uses_factor field of the effect definition +-- -- -- level - int - used as the effect level if uses_level is false and for lvl1 potions - defaults to 1 +-- -- -- level_scaling - int - used as the number of effect levels added per potion level - defaults to 1 - +-- -- -- - this has no effect if uses_level is false +-- -- -- dur - float - duration of the effect in seconds - defaults to mcl_potions.DURATION +-- -- -- dur_variable - bool - whether variants of the potion should have the length of this effect changed - +-- -- -- - defaults to true +-- -- -- - if at least one effect has this set to true, the potion has a "plus" variant +-- uses_level - bool - whether the potion should come at different levels - +-- - defaults to true if uses_level is true for at least one effect, else false +-- drinkable - bool - defaults to true +-- has_splash - bool - defaults to true +-- has_lingering - bool - defaults to true +-- has_arrow - bool - defaults to false +-- has_potent - bool - whether there is a potent (e.g. II) variant - defaults to the value of uses_level +-- default_potent_level - int - effect level used for the potent variant - defaults to 2 +-- custom_on_use - function(user, level) - called when the potion is drunk +-- custom_effect - function(object, level) - called when the potion effects are applied +-- custom_splash_effect - function(pos, level) - called when the splash potion explodes +-- custom_linger_effect - function(pos, radius, level) - called on the lingering potion step +function mcl_potions.register_potion(def) + local modname = minetest.get_current_modname() + local name = def.name + if name == nil then + error("Unable to register potion: name is nil") + end + if type(name) ~= "string" then + error("Unable to register potion: name is not a string") + end + local pdef = {} + pdef.description = S("@1 Potion @2", def.desc_prefix, def.desc_suffix) + pdef._tt_help = def._tt + pdef._dynamic_tt = def._dynamic_tt + local potion_longdesc = def._longdesc + if def._effect_list then + potion_longdesc = potion_intro .. "\n" .. def._longdesc + end + pdef._doc_items_longdesc = potion_longdesc + if def.drinkable ~= false then pdef._doc_items_usagehelp = how_to_drink end + pdef.stack_max = def.stack_max or 1 + local color = def.color or "#0000FF" + pdef.inventory_image = def.image or potion_image(color) + pdef.wield_image = pdef.inventory_image + pdef.groups = def.groups or {brewitem=1, food=3, can_eat_when_full=1, _mcl_potion=1} + + pdef._effect_list = {} + local effect + local uses_level = false + local has_plus = false + for name, details in pairs(def._effect_list) do + effect = mcl_potions.registered_effects[name] + if effect then + local ulvl + if details.uses_level ~= nil then ulvl = details.uses_level + else ulvl = effect.uses_factor end + if ulvl then uses_level = true end + local durvar = true + if details.dur_variable ~= nil then durvar = details.dur_variable end + if durvar then has_plus = true end + pdef._effect_list[name] = { + uses_level = ulvl, + level = details.level or 1, + level_scaling = details.level_scaling or 1, + dur = details.dur or mcl_potions.DURATION, + dur_variable = durvar, + } + else + error("Unable to register potion: effect not registered") + end + end + if def.uses_level ~= nil then uses_level = def.uses_level end + pdef.uses_level = uses_level + if def.has_potent ~= nil then pdef.has_potent = def.has_potent + else pdef.has_potent = uses_level end + pdef.has_plus = has_plus + local on_use + if def.drinkable ~= false then + on_use = generate_on_use(pdef._effect_list, color, def.custom_on_use, def.custom_effect) + end + pdef.on_place = on_use + pdef.on_secondary_use = on_use + + minetest.register_craftitem(modname..":"..name, pdef) + +end + +mcl_potions.register_potion({ + name = "trolling", + desc_prefix = S("Mighty"), + desc_suffix = S("of Trolling"), + _tt = "trololo", + _dynamic_tt = function(level) + return "trolololoooololo" + end, + _longdesc = "Trolololololo", + stack_max = 2, + color = "#00AA00", + _effect_list = { + night_vision = {}, + strength = {}, + swiftness = { + uses_level = false, + level = 2, + }, + poison = { + dur = 10, + }, + }, +}) + local function register_potion(def) From ef2ce7e0d7510861f87b17c926aacb09f40178fa Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Fri, 27 Oct 2023 05:08:23 +0200 Subject: [PATCH 08/91] Added new potion tooltip handling -potion tooltips are now utilizing the power of the new API -potion names change based on metadata -nothing triggers loading the new tooltips beyond the names for now --- mods/HELP/mcl_tt/mod.conf | 2 +- mods/HELP/mcl_tt/snippets_mcl.lua | 46 +++++++++++++++++++++++++++++++ mods/HELP/tt/init.lua | 16 +++++++++++ mods/HELP/tt/mod.conf | 2 +- 4 files changed, 64 insertions(+), 2 deletions(-) diff --git a/mods/HELP/mcl_tt/mod.conf b/mods/HELP/mcl_tt/mod.conf index e442e1320..b9ca12379 100644 --- a/mods/HELP/mcl_tt/mod.conf +++ b/mods/HELP/mcl_tt/mod.conf @@ -1,4 +1,4 @@ name = mcl_tt author = Wuzzy description = Add MCL2 tooltips -depends = tt, mcl_enchanting, mcl_colors +depends = tt, mcl_enchanting, mcl_colors, mcl_util diff --git a/mods/HELP/mcl_tt/snippets_mcl.lua b/mods/HELP/mcl_tt/snippets_mcl.lua index 14fcc1719..410f5e744 100644 --- a/mods/HELP/mcl_tt/snippets_mcl.lua +++ b/mods/HELP/mcl_tt/snippets_mcl.lua @@ -121,3 +121,49 @@ tt.register_snippet(function(itemstring, _, itemstack) return S("Durability: @1", S("@1 uses", remaining_use .."/".. use)) end end) + + +-- Potions info +tt.register_snippet(function(itemstring, _, itemstack) + if not itemstack then return end + local def = itemstack:get_definition() + if def.groups._mcl_potion ~= 1 then return end + + local s = "" + local meta = itemstack:get_meta() + local potency = meta:get_int("mcl_potions:potion_potent") + local plus = meta:get_int("mcl_potions:potion_plus") + if def._dynamic_tt then s = s.. def._dynamic_tt(potency+1).. "\n" end + local effects = def._effect_list + local effect + local dur + local timestamp + local ef_level + local roman_lvl + local factor + local ef_tt + for name, details in pairs(effects) do + effect = mcl_potions.registered_effects[name] + if details.dur_variable then + dur = details.dur * math.pow(mcl_potions.PLUS_FACTOR, plus) + if potency > 0 and details.uses_level then + dur = dur / math.pow(mcl_potions.POTENT_FACTOR, potency) + end + else + dur = details.dur + end + timestamp = math.floor(dur/60)..string.format(":%02d",math.floor(dur % 60)) + if details.uses_level then + ef_level = details.level + details.level_scaling * (potency) + else + ef_level = details.level + end + if ef_level > 1 then roman_lvl = " ".. mcl_util.to_roman(ef_level) + else roman_lvl = "" end + s = s.. effect.description.. roman_lvl.. " (".. timestamp.. ")\n" + if effect.uses_factor then factor = effect.level_to_factor(ef_level) end + if effect.get_tt then ef_tt = effect.get_tt(factor) else ef_tt = "" end + if ef_tt ~= "" then s = s.. ef_tt.. "\n" end + end + return s:trim() +end) diff --git a/mods/HELP/tt/init.lua b/mods/HELP/tt/init.lua index b3f2b8d55..8cc893d47 100644 --- a/mods/HELP/tt/init.lua +++ b/mods/HELP/tt/init.lua @@ -74,6 +74,22 @@ function tt.reload_itemstack_description(itemstack) local orig_desc = def._tt_original_description or def.description if meta:get_string("name") ~= "" then orig_desc = minetest.colorize(tt.NAME_COLOR, meta:get_string("name")) + elseif def.groups._mcl_potion == 1 then + local potency = meta:get_int("mcl_potions:potion_potent") + local plus = meta:get_int("mcl_potions:potion_plus") + if potency > 0 then + local sym_potency = mcl_util.to_roman(potency+1) + orig_desc = orig_desc.. " ".. sym_potency + end + if plus > 0 then + local sym_plus = " " + local i = plus + while i>0 do + i = i - 1 + sym_plus = sym_plus.. "+" + end + orig_desc = orig_desc.. sym_plus + end end local desc = apply_snippets(orig_desc, itemstring, toolcaps or def.tool_capabilities, itemstack) if desc == def.description and meta:get_string("description") == "" then return end diff --git a/mods/HELP/tt/mod.conf b/mods/HELP/tt/mod.conf index 2a260772d..7c4902418 100644 --- a/mods/HELP/tt/mod.conf +++ b/mods/HELP/tt/mod.conf @@ -1,4 +1,4 @@ name = tt author = Wuzzy description = Support for custom tooltip extensions for items -depends = mcl_colors +depends = mcl_colors, mcl_util From 6d927ab1a1ecd97dd667b7064d0d72fef44c4d46 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Fri, 27 Oct 2023 05:09:37 +0200 Subject: [PATCH 09/91] Creative inventory using new potions API -creative inventory utilizes the new potions API -the new fancy tooltips are used there --- mods/HUD/mcl_inventory/creative.lua | 23 ++++++++++++++++++++++- mods/HUD/mcl_inventory/mod.conf | 2 +- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/mods/HUD/mcl_inventory/creative.lua b/mods/HUD/mcl_inventory/creative.lua index 1288bc1d5..95fe7419b 100644 --- a/mods/HUD/mcl_inventory/creative.lua +++ b/mods/HUD/mcl_inventory/creative.lua @@ -105,7 +105,13 @@ minetest.register_on_mods_loaded(function() nonmisc = true end if def.groups.brewitem then - table.insert(inventory_lists["brew"], name) + local str = name + if def.groups._mcl_potion == 1 then + local stack = ItemStack(name) + tt.reload_itemstack_description(stack) + str = stack:to_string() + end + table.insert(inventory_lists["brew"], str) nonmisc = true end if def.groups.craftitem then @@ -117,6 +123,21 @@ minetest.register_on_mods_loaded(function() table.insert(inventory_lists["misc"], name) end + if def.groups._mcl_potion == 1 then + if def.has_potent then + local stack = ItemStack(name) + stack:get_meta():set_int("mcl_potions:potion_potent", 1) + tt.reload_itemstack_description(stack) + table.insert(inventory_lists["brew"], stack:to_string()) + end + if def.has_plus then + local stack = ItemStack(name) + stack:get_meta():set_int("mcl_potions:potion_plus", 1) + tt.reload_itemstack_description(stack) + table.insert(inventory_lists["brew"], stack:to_string()) + end + end + table.insert(inventory_lists["all"], name) end end diff --git a/mods/HUD/mcl_inventory/mod.conf b/mods/HUD/mcl_inventory/mod.conf index 66f175c3b..fc10fe32a 100644 --- a/mods/HUD/mcl_inventory/mod.conf +++ b/mods/HUD/mcl_inventory/mod.conf @@ -2,4 +2,4 @@ name = mcl_inventory author = BlockMen description = Adds the player inventory and creative inventory. depends = mcl_init, mcl_formspec, mcl_enchanting, mcl_gamemode -optional_depends = mcl_armor, mcl_brewing, mcl_potions, mcl_enchanting, mcl_craftguide, mcl_player +optional_depends = mcl_armor, mcl_brewing, mcl_potions, mcl_enchanting, mcl_craftguide, mcl_player, tt From a8fcae0f5115eccc38107e3e676aa3087d5c4e85 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 28 Oct 2023 03:22:28 +0200 Subject: [PATCH 10/91] Fixed variable definitions ("undeclared global") --- mods/ITEMS/mcl_potions/functions.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 8aa01c569..275ec3405 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -490,7 +490,7 @@ function mcl_potions._clear_cached_player_data(player) effect[player] = nil end - meta = player:get_meta() + local meta = player:get_meta() meta:set_int("night_vision", 0) end @@ -514,7 +514,7 @@ function mcl_potions._save_player_effects(player) if not player:is_player() then return end - meta = player:get_meta() + local meta = player:get_meta() for name, effect in pairs(registered_effects) do meta:set_string("mcl_potions:_EF_"..name, minetest.serialize(EF[name][player])) @@ -525,7 +525,7 @@ function mcl_potions._load_player_effects(player) if not player:is_player() then return end - meta = player:get_meta() + local meta = player:get_meta() -- handle legacy meta strings local legacy_invisible = minetest.deserialize(meta:get_string("_is_invisible")) From dc35f43bfa00361f29ac9a0ffdb4feb57cf4e3a5 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Fri, 3 Nov 2023 22:28:00 +0100 Subject: [PATCH 11/91] Potions registering API fully works with creative --- mods/HUD/mcl_inventory/creative.lua | 6 ++++-- mods/ITEMS/mcl_potions/potions.lua | 9 +++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/mods/HUD/mcl_inventory/creative.lua b/mods/HUD/mcl_inventory/creative.lua index 95fe7419b..4898423b0 100644 --- a/mods/HUD/mcl_inventory/creative.lua +++ b/mods/HUD/mcl_inventory/creative.lua @@ -126,13 +126,15 @@ minetest.register_on_mods_loaded(function() if def.groups._mcl_potion == 1 then if def.has_potent then local stack = ItemStack(name) - stack:get_meta():set_int("mcl_potions:potion_potent", 1) + local potency = def._default_potent_level - 1 + stack:get_meta():set_int("mcl_potions:potion_potent", potency) tt.reload_itemstack_description(stack) table.insert(inventory_lists["brew"], stack:to_string()) end if def.has_plus then local stack = ItemStack(name) - stack:get_meta():set_int("mcl_potions:potion_plus", 1) + local extend = def._default_extend_level + stack:get_meta():set_int("mcl_potions:potion_plus", extend) tt.reload_itemstack_description(stack) table.insert(inventory_lists["brew"], stack:to_string()) end diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 072316136..6e022f497 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -8,7 +8,7 @@ local function potion_image(colorstring, opacity) end local how_to_drink = S("Use the “Place” key to drink it.") -local potion_intro = S("Drinking a potion gives you a particular effect.") +local potion_intro = S("Drinking a potion gives you a particular effect or set of effects.") local function time_string(dur) if not dur then @@ -166,7 +166,8 @@ end -- has_lingering - bool - defaults to true -- has_arrow - bool - defaults to false -- has_potent - bool - whether there is a potent (e.g. II) variant - defaults to the value of uses_level --- default_potent_level - int - effect level used for the potent variant - defaults to 2 +-- default_potent_level - int - potion level used for the default potent variant - defaults to 2 +-- default_extend_level - int - extention level (amount of +) used for the default extended variant - defaults to 1 -- custom_on_use - function(user, level) - called when the potion is drunk -- custom_effect - function(object, level) - called when the potion effects are applied -- custom_splash_effect - function(pos, level) - called when the splash potion explodes @@ -225,6 +226,8 @@ function mcl_potions.register_potion(def) pdef.uses_level = uses_level if def.has_potent ~= nil then pdef.has_potent = def.has_potent else pdef.has_potent = uses_level end + pdef._default_potent_level = def.default_potent_level or 2 + pdef._default_extend_level = def.default_extend_level or 1 pdef.has_plus = has_plus local on_use if def.drinkable ~= false then @@ -259,6 +262,8 @@ mcl_potions.register_potion({ dur = 10, }, }, + default_potent_level = 5, + default_extend_level = 3, }) From 83530b42986da841e02642d1824a68601d4694d1 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 7 Jan 2024 22:54:10 +0100 Subject: [PATCH 12/91] Improved potion descriptions * added support for effect descriptions * added descriptions for some effects * fixed a crash --- mods/HELP/mcl_tt/snippets_mcl.lua | 56 ++++++++++++++-------------- mods/ITEMS/mcl_potions/functions.lua | 19 ++++++++++ 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/mods/HELP/mcl_tt/snippets_mcl.lua b/mods/HELP/mcl_tt/snippets_mcl.lua index 410f5e744..c1396790e 100644 --- a/mods/HELP/mcl_tt/snippets_mcl.lua +++ b/mods/HELP/mcl_tt/snippets_mcl.lua @@ -135,35 +135,37 @@ tt.register_snippet(function(itemstring, _, itemstack) local plus = meta:get_int("mcl_potions:potion_plus") if def._dynamic_tt then s = s.. def._dynamic_tt(potency+1).. "\n" end local effects = def._effect_list - local effect - local dur - local timestamp - local ef_level - local roman_lvl - local factor - local ef_tt - for name, details in pairs(effects) do - effect = mcl_potions.registered_effects[name] - if details.dur_variable then - dur = details.dur * math.pow(mcl_potions.PLUS_FACTOR, plus) - if potency > 0 and details.uses_level then - dur = dur / math.pow(mcl_potions.POTENT_FACTOR, potency) + if effects then + local effect + local dur + local timestamp + local ef_level + local roman_lvl + local factor + local ef_tt + for name, details in pairs(effects) do + effect = mcl_potions.registered_effects[name] + if details.dur_variable then + dur = details.dur * math.pow(mcl_potions.PLUS_FACTOR, plus) + if potency > 0 and details.uses_level then + dur = dur / math.pow(mcl_potions.POTENT_FACTOR, potency) + end + else + dur = details.dur end - else - dur = details.dur + timestamp = math.floor(dur/60)..string.format(":%02d",math.floor(dur % 60)) + if details.uses_level then + ef_level = details.level + details.level_scaling * (potency) + else + ef_level = details.level + end + if ef_level > 1 then roman_lvl = " ".. mcl_util.to_roman(ef_level) + else roman_lvl = "" end + s = s.. effect.description.. roman_lvl.. " (".. timestamp.. ")\n" + if effect.uses_factor then factor = effect.level_to_factor(ef_level) end + if effect.get_tt then ef_tt = minetest.colorize("grey", effect.get_tt(factor)) else ef_tt = "" end + if ef_tt ~= "" then s = s.. ef_tt.. "\n" end end - timestamp = math.floor(dur/60)..string.format(":%02d",math.floor(dur % 60)) - if details.uses_level then - ef_level = details.level + details.level_scaling * (potency) - else - ef_level = details.level - end - if ef_level > 1 then roman_lvl = " ".. mcl_util.to_roman(ef_level) - else roman_lvl = "" end - s = s.. effect.description.. roman_lvl.. " (".. timestamp.. ")\n" - if effect.uses_factor then factor = effect.level_to_factor(ef_level) end - if effect.get_tt then ef_tt = effect.get_tt(factor) else ef_tt = "" end - if ef_tt ~= "" then s = s.. ef_tt.. "\n" end end return s:trim() end) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 275ec3405..12b0c08ec 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -165,6 +165,9 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "poison", description = S("Poison"), + get_tt = function(factor) + return S("-1 HP / @1 s", factor) + end, res_condition = function(object) local entity = object:get_luaentity() return (entity and (entity.harmed_by_heal or string.find(entity.name, "spider"))) @@ -184,6 +187,9 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "regeneration", description = S("Regeneration"), + get_tt = function(factor) + return S("+1 HP / @1 s", factor) + end, res_condition = function(object) local entity = object:get_luaentity() return (entity and entity.harmed_by_heal) @@ -238,6 +244,10 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "leaping", description = S("Leaping"), + get_tt = function(factor) + if factor > 0 then return S("+@1% jumping power", math.floor(factor*100)) end + return S("-@1% jumping power", math.floor(-factor*100)) + end, res_condition = function(object) return (not object:is_player()) end, @@ -256,6 +266,9 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "swiftness", description = S("Swiftness"), + get_tt = function(factor) + return S("+@1% running speed", math.floor(factor*100)) + end, res_condition = function(object) return (not object:is_player()) end, @@ -274,6 +287,9 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "slowness", description = S("Slowness"), + get_tt = function(factor) + return S("-@1% running speed", math.floor(factor*100)) + end, res_condition = function(object) return (not object:is_player()) end, @@ -331,6 +347,9 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "withering", description = S("Withering"), + get_tt = function(factor) + return S("-1 HP / @1 s, can kill", factor) + end, res_condition = function(object) local entity = object:get_luaentity() return (entity and string.find(entity.name, "wither")) From 7d3e2d3dbce3d4f9eb0c6a49ffef1cb54dcc6c94 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 7 Jan 2024 22:56:58 +0100 Subject: [PATCH 13/91] Implemented missing potion registering functionality * improved support for custom (non-status) effects * added support for splash potions * added support for lingering potions * added support for tipped arrows * removed the old registration --- mods/ITEMS/mcl_potions/lingering.lua | 92 ++++++++++++++----- mods/ITEMS/mcl_potions/potions.lua | 112 ++++++++++++++++++------ mods/ITEMS/mcl_potions/splash.lua | 70 +++++++++++---- mods/ITEMS/mcl_potions/tipped_arrow.lua | 65 ++++++++++++-- 4 files changed, 268 insertions(+), 71 deletions(-) diff --git a/mods/ITEMS/mcl_potions/lingering.lua b/mods/ITEMS/mcl_potions/lingering.lua index 46d94cad3..68da35146 100644 --- a/mods/ITEMS/mcl_potions/lingering.lua +++ b/mods/ITEMS/mcl_potions/lingering.lua @@ -11,8 +11,8 @@ end local lingering_effect_at = {} -local function add_lingering_effect(pos, color, def, is_water, instant) - lingering_effect_at[pos] = {color = color, timer = 30, def = def, is_water = is_water} +local function add_lingering_effect(pos, color, def, is_water, potency, plus) + lingering_effect_at[pos] = {color = color, timer = 30, def = def, is_water = is_water, potency = potency, plus = plus} end local function linger_particles(pos, d, texture, color) @@ -55,23 +55,52 @@ minetest.register_globalstep(function(dtime) end linger_particles(pos, d, texture, vals.color) - -- Extinguish fire if water bottle - if vals.is_water then - if mcl_potions._extinguish_nearby_fire(pos, d) then - vals.timer = vals.timer - 3.25 - end +-- -- Extinguish fire if water bottle +-- if vals.is_water then +-- if mcl_potions._extinguish_nearby_fire(pos, d) then +-- vals.timer = vals.timer - 3.25 +-- end +-- end + + if vals.def.while_lingering and vals.def.while_lingering(pos, d, vals.potency+1) then + vals.timer = vals.timer - 3.25 end -- Affect players and mobs for _, obj in pairs(minetest.get_objects_inside_radius(pos, d)) do local entity = obj:get_luaentity() - if obj:is_player() or entity.is_mob then + if obj:is_player() or entity and entity.is_mob then + local applied = false + if vals.def._effect_list then + local ef_level + local dur + for name, details in pairs(vals.def._effect_list) do + if details.uses_level then + ef_level = details.level + details.level_scaling * (vals.potency) + else + ef_level = details.level + end + if details.dur_variable then + dur = details.dur * math.pow(mcl_potions.PLUS_FACTOR, vals.plus) + if vals.potency>0 and details.uses_level then + dur = dur / math.pow(mcl_potions.POTENT_FACTOR, vals.potency) + end + else + dur = details.dur + end + dur = dur * mcl_potions.SPLASH_FACTOR + if mcl_potions.give_effect_by_level(name, obj, ef_level, dur) then + applied = true + end + end + end - vals.def.potion_fun(obj) - -- TODO: Apply timer penalty only if the potion effect was acutally applied - vals.timer = vals.timer - 3.25 + if vals.def.custom_effect and vals.def.custom_effect(obj, vals.potency+1) then + applied = true + end + if applied then vals.timer = vals.timer - 3.25 end end end @@ -87,31 +116,42 @@ end) function mcl_potions.register_lingering(name, descr, color, def) - local id = "mcl_potions:"..name.."_lingering" - local longdesc = def.longdesc + local longdesc = def._longdesc if not def.no_effect then - longdesc = S("A throwable potion that will shatter on impact, where it creates a magic cloud that lingers around for a while. Any player or mob inside the cloud will receive the potion's effect, possibly repeatedly.") + longdesc = S("A throwable potion that will shatter on impact, where it creates a magic cloud that lingers around for a while. Any player or mob inside the cloud will receive the potion's effect or set of effects, possibly repeatedly.") if def.longdesc then - longdesc = longdesc .. "\n" .. def.longdesc + longdesc = longdesc .. "\n" .. def._longdesc end end minetest.register_craftitem(id, { description = descr, - _tt_help = def.tt, + _tt_help = def._tt, + _dynamic_tt = def._dynamic_tt, _doc_items_longdesc = longdesc, _doc_items_usagehelp = S("Use the “Punch” key to throw it."), + stack_max = def.stack_max, + _effect_list = def._effect_list, + uses_level = def.uses_level, + has_potent = def.has_potent, + has_plus = def.has_plus, + _default_potent_level = def._default_potent_level, + _default_extend_level = def._default_extend_level, inventory_image = lingering_image(color), - groups = {brewitem=1, not_in_creative_inventory=0, bottle=1}, + groups = {brewitem=1, bottle=1, _mcl_potion=1}, on_use = function(item, placer, pointed_thing) local velocity = 10 local dir = placer:get_look_dir(); local pos = placer:getpos(); minetest.sound_play("mcl_throwing_throw", {pos = pos, gain = 0.4, max_hear_distance = 16}, true) local obj = minetest.add_entity({x=pos.x+dir.x,y=pos.y+2+dir.y,z=pos.z+dir.z}, id.."_flying") - obj:setvelocity({x=dir.x*velocity,y=dir.y*velocity,z=dir.z*velocity}) - obj:setacceleration({x=dir.x*-3, y=-9.8, z=dir.z*-3}) - obj:get_luaentity()._thrower = placer:get_player_name() + obj:set_velocity({x=dir.x*velocity,y=dir.y*velocity,z=dir.z*velocity}) + obj:set_acceleration({x=dir.x*-3, y=-9.8, z=dir.z*-3}) + local ent = obj:get_luaentity() + ent._thrower = placer:get_player_name() + ent._potency = item:get_meta():get_int("mcl_potions:potion_potent") + ent._plus = item:get_meta():get_int("mcl_potions:potion_plus") + ent._effect_list = def._effect_list if not minetest.is_creative_enabled(placer:get_player_name()) then item:take_item() end @@ -126,6 +166,10 @@ function mcl_potions.register_lingering(name, descr, color, def) local velocity = 22 obj:set_velocity({x=dropdir.x*velocity,y=dropdir.y*velocity,z=dropdir.z*velocity}) obj:set_acceleration({x=dropdir.x*-3, y=-9.8, z=dropdir.z*-3}) + local ent = obj:get_luaentity() + ent._potency = item:get_meta():get_int("mcl_potions:potion_potent") + ent._plus = item:get_meta():get_int("mcl_potions:potion_plus") + ent._effect_list = def._effect_list end }) @@ -148,7 +192,9 @@ function mcl_potions.register_lingering(name, descr, color, def) end if n ~= "air" and n ~= "mcl_portals:portal" and n ~= "mcl_portals:portal_end" and g == 0 or mcl_potions.is_obj_hit(self, pos) then minetest.sound_play("mcl_potions_breaking_glass", {pos = pos, max_hear_distance = 16, gain = 1}) - add_lingering_effect(pos, color, def, name == "water") + local potency = self._potency or 0 + local plus = self._plus or 0 + add_lingering_effect(pos, color, def, name == "water", potency, plus) local texture if name == "water" then texture = "mcl_particles_droplet_bottle.png" @@ -160,9 +206,7 @@ function mcl_potions.register_lingering(name, descr, color, def) end end linger_particles(pos, d, texture, color) - if name == "water" then - mcl_potions._extinguish_nearby_fire(pos, d) - end + if def.on_splash then def.on_splash(pos, potency+1) end self.object:remove() end end, diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 6e022f497..1b66a955d 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -145,7 +145,7 @@ end -- stack_max - int - max stack size - defaults to 1 -- image - string - name of a custom texture of the potion icon -- color - string - colorstring for potion icon when image is not defined - defaults to #0000FF --- groups - table - item groups definition - +-- groups - table - item groups definition for the regular potion, not splash or lingering - -- - must contain _mcl_potion=1 for tooltip to include dynamic_tt and effects -- - defaults to {brewitem=1, food=3, can_eat_when_full=1, _mcl_potion=1} -- _effect_list - table - all the effects dealt by the potion in the format of tables @@ -168,10 +168,10 @@ end -- has_potent - bool - whether there is a potent (e.g. II) variant - defaults to the value of uses_level -- default_potent_level - int - potion level used for the default potent variant - defaults to 2 -- default_extend_level - int - extention level (amount of +) used for the default extended variant - defaults to 1 --- custom_on_use - function(user, level) - called when the potion is drunk --- custom_effect - function(object, level) - called when the potion effects are applied --- custom_splash_effect - function(pos, level) - called when the splash potion explodes --- custom_linger_effect - function(pos, radius, level) - called on the lingering potion step +-- custom_on_use - function(user, level) - called when the potion is drunk, returns true on success +-- custom_effect - function(object, level) - called when the potion effects are applied, returns true on success +-- custom_splash_effect - function(pos, level) - called when the splash potion explodes, returns true on success +-- custom_linger_effect - function(pos, radius, level) - called on the lingering potion step, returns true on success function mcl_potions.register_potion(def) local modname = minetest.get_current_modname() local name = def.name @@ -201,25 +201,28 @@ function mcl_potions.register_potion(def) local effect local uses_level = false local has_plus = false - for name, details in pairs(def._effect_list) do - effect = mcl_potions.registered_effects[name] - if effect then - local ulvl - if details.uses_level ~= nil then ulvl = details.uses_level - else ulvl = effect.uses_factor end - if ulvl then uses_level = true end - local durvar = true - if details.dur_variable ~= nil then durvar = details.dur_variable end - if durvar then has_plus = true end - pdef._effect_list[name] = { - uses_level = ulvl, - level = details.level or 1, - level_scaling = details.level_scaling or 1, - dur = details.dur or mcl_potions.DURATION, - dur_variable = durvar, - } - else - error("Unable to register potion: effect not registered") + if def._effect_list then + for name, details in pairs(def._effect_list) do + no_effects = false + effect = mcl_potions.registered_effects[name] + if effect then + local ulvl + if details.uses_level ~= nil then ulvl = details.uses_level + else ulvl = effect.uses_factor end + if ulvl then uses_level = true end + local durvar = true + if details.dur_variable ~= nil then durvar = details.dur_variable end + if durvar then has_plus = true end + pdef._effect_list[name] = { + uses_level = ulvl, + level = details.level or 1, + level_scaling = details.level_scaling or 1, + dur = details.dur or mcl_potions.DURATION, + dur_variable = durvar, + } + else + error("Unable to register potion: effect not registered") + end end end if def.uses_level ~= nil then uses_level = def.uses_level end @@ -238,6 +241,59 @@ function mcl_potions.register_potion(def) minetest.register_craftitem(modname..":"..name, pdef) + if def.has_splash or def.has_splash == nil then + local splash_desc = S("Splash @1 Potion @2", def.desc_prefix, def.desc_suffix) + local sdef = {} + sdef._tt = def._tt + sdef._dynamic_tt = def._dynamic_tt + sdef._longdesc = def._longdesc + sdef.stack_max = pdef.stack_max + sdef._effect_list = pdef._effect_list + sdef.uses_level = uses_level + sdef.has_potent = pdef.has_potent + sdef.has_plus = has_plus + sdef._default_potent_level = pdef._default_potent_level + sdef._default_extend_level = pdef._default_extend_level + sdef.custom_effect = def.custom_effect + sdef.on_splash = def.custom_splash_effect + if not def._effect_list then sdef.instant = true end + mcl_potions.register_splash(name, splash_desc, color, sdef) + end + + if def.has_lingering or def.has_lingering == nil then + local ling_desc = S("Lingering @1 Potion @2", def.desc_prefix, def.desc_suffix) + local ldef = {} + ldef._tt = def._tt + ldef._longdesc = def._longdesc + ldef.stack_max = pdef.stack_max + ldef._effect_list = pdef._effect_list + ldef.uses_level = uses_level + ldef.has_potent = pdef.has_potent + ldef.has_plus = has_plus + ldef._default_potent_level = pdef._default_potent_level + ldef._default_extend_level = pdef._default_extend_level + ldef.custom_effect = def.custom_effect + ldef.on_splash = def.custom_splash_effect + ldef.while_lingering = def.custom_linger_effect + if not def._effect_list then ldef.instant = true end + mcl_potions.register_lingering(name, ling_desc, color, ldef) + end + + if def.has_arrow then + local arr_desc = S("@1 Arrow @2", def.desc_prefix, def.desc_suffix) + local adef = {} + adef._tt = def._tt + adef._longdesc = def._longdesc + adef._effect_list = pdef._effect_list + adef.uses_level = uses_level + adef.has_potent = pdef.has_potent + adef.has_plus = has_plus + adef._default_potent_level = pdef._default_potent_level + adef._default_extend_level = pdef._default_extend_level + adef.custom_effect = def.custom_effect + if not def._effect_list then adef.instant = true end + mcl_potions.register_arrow(name, arr_desc, color, adef) + end end mcl_potions.register_potion({ @@ -264,6 +320,8 @@ mcl_potions.register_potion({ }, default_potent_level = 5, default_extend_level = 3, + custom_splash_effect = mcl_potions._extinguish_nearby_fire, + has_arrow = true, }) @@ -811,9 +869,9 @@ local defs = { awkward_def, mundane_def, thick_def, dragon_breath_def, slowness_def, leaping_def, withering_def, poison_def, regeneration_def, invisibility_def, water_breathing_def, fire_resistance_def} -for _, def in ipairs(defs) do - register_potion(def) -end +-- for _, def in ipairs(defs) do +-- register_potion(def) +-- end diff --git a/mods/ITEMS/mcl_potions/splash.lua b/mods/ITEMS/mcl_potions/splash.lua index 0b8aedeab..33515c161 100644 --- a/mods/ITEMS/mcl_potions/splash.lua +++ b/mods/ITEMS/mcl_potions/splash.lua @@ -13,20 +13,28 @@ end function mcl_potions.register_splash(name, descr, color, def) local id = "mcl_potions:"..name.."_splash" - local longdesc = def.longdesc + local longdesc = def._longdesc if not def.no_effect then - longdesc = S("A throwable potion that will shatter on impact, where it gives all nearby players and mobs a status effect.") - if def.longdesc then - longdesc = longdesc .. "\n" .. def.longdesc + longdesc = S("A throwable potion that will shatter on impact, where it gives all nearby players and mobs a status effect or a set of status effects.") + if def._longdesc then + longdesc = longdesc .. "\n" .. def._longdesc end end minetest.register_craftitem(id, { description = descr, - _tt_help = def.tt, + _tt_help = def._tt, + _dynamic_tt = def._dynamic_tt, _doc_items_longdesc = longdesc, _doc_items_usagehelp = S("Use the “Punch” key to throw it."), + stack_max = def.stack_max, + _effect_list = def._effect_list, + uses_level = def.uses_level, + has_potent = def.has_potent, + has_plus = def.has_plus, + _default_potent_level = def._default_potent_level, + _default_extend_level = def._default_extend_level, inventory_image = splash_image(color), - groups = {brewitem=1, not_in_creative_inventory=0, bottle=1}, + groups = {brewitem=1, bottle=1, _mcl_potion=1}, on_use = function(item, placer, pointed_thing) local velocity = 10 local dir = placer:get_look_dir(); @@ -35,7 +43,11 @@ function mcl_potions.register_splash(name, descr, color, def) local obj = minetest.add_entity({x=pos.x+dir.x,y=pos.y+2+dir.y,z=pos.z+dir.z}, id.."_flying") obj:set_velocity({x=dir.x*velocity,y=dir.y*velocity,z=dir.z*velocity}) obj:set_acceleration({x=dir.x*-3, y=-9.8, z=dir.z*-3}) - obj:get_luaentity()._thrower = placer:get_player_name() + local ent = obj:get_luaentity() + ent._thrower = placer:get_player_name() + ent._potency = item:get_meta():get_int("mcl_potions:potion_potent") + ent._plus = item:get_meta():get_int("mcl_potions:potion_plus") + ent._effect_list = def._effect_list if not minetest.is_creative_enabled(placer:get_player_name()) then item:take_item() end @@ -50,6 +62,10 @@ function mcl_potions.register_splash(name, descr, color, def) local velocity = 22 obj:set_velocity({x=dropdir.x*velocity,y=dropdir.y*velocity,z=dropdir.z*velocity}) obj:set_acceleration({x=dropdir.x*-3, y=-9.8, z=dropdir.z*-3}) + local ent = obj:get_luaentity() + ent._potency = item:get_meta():get_int("mcl_potions:potion_potent") + ent._plus = item:get_meta():get_int("mcl_potions:potion_plus") + ent._effect_list = def._effect_list end }) @@ -103,10 +119,10 @@ function mcl_potions.register_splash(name, descr, color, def) texture = texture.."^[colorize:"..color..":127" }) - if name == "water" then - mcl_potions._extinguish_nearby_fire(pos) - end - self.object:remove() + local potency = self._potency or 0 + local plus = self._plus or 0 + + if def.on_splash then def.on_splash(pos, potency+1) end for _,obj in pairs(minetest.get_objects_inside_radius(pos, 4)) do local entity = obj:get_luaentity() @@ -114,13 +130,37 @@ function mcl_potions.register_splash(name, descr, color, def) local pos2 = obj:get_pos() local rad = math.floor(math.sqrt((pos2.x-pos.x)^2 + (pos2.y-pos.y)^2 + (pos2.z-pos.z)^2)) - if rad > 0 then - def.potion_fun(obj, redux_map[rad]) - else - def.potion_fun(obj, 1) + + if def._effect_list then + local ef_level + local dur + for name, details in pairs(def._effect_list) do + if details.uses_level then + ef_level = details.level + details.level_scaling * (potency) + else + ef_level = details.level + end + if details.dur_variable then + dur = details.dur * math.pow(mcl_potions.PLUS_FACTOR, plus) + if potency>0 and details.uses_level then + dur = dur / math.pow(mcl_potions.POTENT_FACTOR, potency) + end + else + dur = details.dur + end + dur = dur * mcl_potions.SPLASH_FACTOR + if rad > 0 then + mcl_potions.give_effect_by_level(name, obj, ef_level, redux_map[rad]*dur) + else + mcl_potions.give_effect_by_level(name, obj, ef_level, dur) + end + end end + + if def.custom_effect then def.custom_effect(obj, potency+1) end -- TODO use redux_map end end + self.object:remove() end end, diff --git a/mods/ITEMS/mcl_potions/tipped_arrow.lua b/mods/ITEMS/mcl_potions/tipped_arrow.lua index c0def3983..9ba127172 100644 --- a/mods/ITEMS/mcl_potions/tipped_arrow.lua +++ b/mods/ITEMS/mcl_potions/tipped_arrow.lua @@ -37,16 +37,23 @@ local arrow_tt = minetest.registered_items["mcl_bows:arrow"]._tt_help or "" function mcl_potions.register_arrow(name, desc, color, def) - local longdesc = def.longdesc or "" + local longdesc = def._longdesc or "" + local tt = def._tt or "" minetest.register_craftitem("mcl_potions:"..name.."_arrow", { description = desc, - _tt_help = arrow_tt .. "\n" .. def.tt, + _tt_help = arrow_tt .. "\n" .. tt, _doc_items_longdesc = arrow_longdesc .. "\n" .. S("This particular arrow is tipped and will give an effect when it hits a player or mob.") .. "\n" .. longdesc, _doc_items_usagehelp = how_to_shoot, + _effect_list = def._effect_list, + uses_level = def.uses_level, + has_potent = def.has_potent, + has_plus = def.has_plus, + _default_potent_level = def._default_potent_level, + _default_extend_level = def._default_extend_level, inventory_image = "mcl_bows_arrow_inv.png^(mcl_potions_arrow_inv.png^[colorize:"..color..":100)", - groups = { ammo=1, ammo_bow=1, brewitem=1}, + groups = { ammo=1, ammo_bow=1, brewitem=1, _mcl_potion=1}, _on_dispense = function(itemstack, dispenserpos, droppos, dropnode, dropdir) -- Shoot arrow local shootpos = vector.add(dispenserpos, vector.multiply(dropdir, 0.51)) @@ -264,6 +271,9 @@ function mcl_potions.register_arrow(name, desc, color, def) end end + local potency = self._potency or 0 + local plus = self._plus or 0 + -- Punch target object but avoid hurting enderman. if lua then if lua.name ~= "mobs_mc:rover" then @@ -271,14 +281,59 @@ function mcl_potions.register_arrow(name, desc, color, def) full_punch_interval=1.0, damage_groups={fleshy=self._damage}, }, nil) - def.potion_fun(obj) + if def._effect_list then + local ef_level + local dur + for name, details in pairs(def._effect_list) do + if details.uses_level then + ef_level = details.level + details.level_scaling * (potency) + else + ef_level = details.level + end + if details.dur_variable then + dur = details.dur * math.pow(mcl_potions.PLUS_FACTOR, plus) + if potency>0 and details.uses_level then + dur = dur / math.pow(mcl_potions.POTENT_FACTOR, potency) + end + else + dur = details.dur + end + mcl_potions.give_effect_by_level(name, obj, ef_level, dur) + end + end + if def.custom_effect then def.custom_effect(obj, potency+1) end end else obj:punch(self.object, 1.0, { full_punch_interval=1.0, damage_groups={fleshy=self._damage}, }, nil) - def.potion_fun(obj) + if def._effect_list then + local ef_level + local dur + for name, details in pairs(def._effect_list) do + if details.uses_level then + ef_level = details.level + details.level_scaling * (potency) + else + ef_level = details.level + end + if details.dur_variable then + dur = details.dur * math.pow(mcl_potions.PLUS_FACTOR, plus) + if potency>0 and details.uses_level then + dur = dur / math.pow(mcl_potions.POTENT_FACTOR, potency) + end + else + dur = details.dur + end + dur = dur * mcl_potions.SPLASH_FACTOR + if rad > 0 then + mcl_potions.give_effect_by_level(name, obj, ef_level, redux_map[rad]*dur) + else + mcl_potions.give_effect_by_level(name, obj, ef_level, dur) + end + end + end + if def.custom_effect then def.custom_effect(obj, potency+1) end end if is_player then From 93572d71f2acb26211a603861f7df1e483678b0f Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 7 Jan 2024 23:19:05 +0100 Subject: [PATCH 14/91] Added support for varied descriptions --- mods/ITEMS/mcl_potions/potions.lua | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 1b66a955d..940bbec4c 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -182,7 +182,15 @@ function mcl_potions.register_potion(def) error("Unable to register potion: name is not a string") end local pdef = {} - pdef.description = S("@1 Potion @2", def.desc_prefix, def.desc_suffix) + if def.desc_prefix and def.desc_suffix then + pdef.description = S("@1 Potion @2", def.desc_prefix, def.desc_suffix) + elseif def.desc_prefix then + pdef.description = S("@1 Potion", def.desc_prefix) + elseif def.desc_suffix then + pdef.description = S("Potion @1", def.desc_suffix) + else + pdef.description = S("Strange Potion") + end pdef._tt_help = def._tt pdef._dynamic_tt = def._dynamic_tt local potion_longdesc = def._longdesc @@ -242,7 +250,7 @@ function mcl_potions.register_potion(def) minetest.register_craftitem(modname..":"..name, pdef) if def.has_splash or def.has_splash == nil then - local splash_desc = S("Splash @1 Potion @2", def.desc_prefix, def.desc_suffix) + local splash_desc = S("Splash @1", pdef.description) local sdef = {} sdef._tt = def._tt sdef._dynamic_tt = def._dynamic_tt @@ -261,7 +269,7 @@ function mcl_potions.register_potion(def) end if def.has_lingering or def.has_lingering == nil then - local ling_desc = S("Lingering @1 Potion @2", def.desc_prefix, def.desc_suffix) + local ling_desc = S("Lingering @1", pdef.description) local ldef = {} ldef._tt = def._tt ldef._longdesc = def._longdesc @@ -280,7 +288,16 @@ function mcl_potions.register_potion(def) end if def.has_arrow then - local arr_desc = S("@1 Arrow @2", def.desc_prefix, def.desc_suffix) + local arr_desc + if def.desc_prefix and def.desc_suffix then + arr_desc = S("@1 Arrow @2", def.desc_prefix, def.desc_suffix) + elseif def.desc_prefix then + arr_desc = S("@1 Arrow", def.desc_prefix) + elseif def.desc_suffix then + arr_desc = S("Arrow @1", def.desc_suffix) + else + arr_desc = S("Strange Tipped Arrow") + end local adef = {} adef._tt = def._tt adef._longdesc = def._longdesc From 0b1cc6ad5745c91f58050363dd2661db7d802baf Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 8 Jan 2024 00:25:30 +0100 Subject: [PATCH 15/91] Fixed splash and lingering potions * descriptions * scaling --- mods/HELP/mcl_tt/snippets_mcl.lua | 10 ++++++++-- mods/ITEMS/mcl_potions/lingering.lua | 9 +++++---- mods/ITEMS/mcl_potions/splash.lua | 13 ++++++++++--- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/mods/HELP/mcl_tt/snippets_mcl.lua b/mods/HELP/mcl_tt/snippets_mcl.lua index c1396790e..7b25f0750 100644 --- a/mods/HELP/mcl_tt/snippets_mcl.lua +++ b/mods/HELP/mcl_tt/snippets_mcl.lua @@ -133,7 +133,13 @@ tt.register_snippet(function(itemstring, _, itemstack) local meta = itemstack:get_meta() local potency = meta:get_int("mcl_potions:potion_potent") local plus = meta:get_int("mcl_potions:potion_plus") - if def._dynamic_tt then s = s.. def._dynamic_tt(potency+1).. "\n" end + local sl_factor = 1 + if def.groups.splash_potion == 1 then + sl_factor = mcl_potions.SPLASH_FACTOR + elseif def.groups.ling_potion == 1 then + sl_factor = mcl_potions.LINGERING_FACTOR + end + if def._dynamic_tt then s = s.. def._dynamic_tt((potency+1)*sl_factor).. "\n" end local effects = def._effect_list if effects then local effect @@ -146,7 +152,7 @@ tt.register_snippet(function(itemstring, _, itemstack) for name, details in pairs(effects) do effect = mcl_potions.registered_effects[name] if details.dur_variable then - dur = details.dur * math.pow(mcl_potions.PLUS_FACTOR, plus) + dur = details.dur * math.pow(mcl_potions.PLUS_FACTOR, plus) * sl_factor if potency > 0 and details.uses_level then dur = dur / math.pow(mcl_potions.POTENT_FACTOR, potency) end diff --git a/mods/ITEMS/mcl_potions/lingering.lua b/mods/ITEMS/mcl_potions/lingering.lua index 68da35146..646ff16ff 100644 --- a/mods/ITEMS/mcl_potions/lingering.lua +++ b/mods/ITEMS/mcl_potions/lingering.lua @@ -86,18 +86,19 @@ minetest.register_globalstep(function(dtime) if vals.potency>0 and details.uses_level then dur = dur / math.pow(mcl_potions.POTENT_FACTOR, vals.potency) end + dur = dur * mcl_potions.LINGERING_FACTOR else dur = details.dur end - dur = dur * mcl_potions.SPLASH_FACTOR if mcl_potions.give_effect_by_level(name, obj, ef_level, dur) then applied = true end end end - if vals.def.custom_effect and vals.def.custom_effect(obj, vals.potency+1) then - applied = true + if vals.def.custom_effect + and vals.def.custom_effect(obj, (vals.potency+1) * mcl_potions.LINGERING_FACTOR) then + applied = true end if applied then vals.timer = vals.timer - 3.25 end @@ -138,7 +139,7 @@ function mcl_potions.register_lingering(name, descr, color, def) _default_potent_level = def._default_potent_level, _default_extend_level = def._default_extend_level, inventory_image = lingering_image(color), - groups = {brewitem=1, bottle=1, _mcl_potion=1}, + groups = {brewitem=1, bottle=1, ling_potion=1, _mcl_potion=1}, on_use = function(item, placer, pointed_thing) local velocity = 10 local dir = placer:get_look_dir(); diff --git a/mods/ITEMS/mcl_potions/splash.lua b/mods/ITEMS/mcl_potions/splash.lua index 33515c161..e14bf2c1a 100644 --- a/mods/ITEMS/mcl_potions/splash.lua +++ b/mods/ITEMS/mcl_potions/splash.lua @@ -34,7 +34,7 @@ function mcl_potions.register_splash(name, descr, color, def) _default_potent_level = def._default_potent_level, _default_extend_level = def._default_extend_level, inventory_image = splash_image(color), - groups = {brewitem=1, bottle=1, _mcl_potion=1}, + groups = {brewitem=1, bottle=1, splash_potion=1, _mcl_potion=1}, on_use = function(item, placer, pointed_thing) local velocity = 10 local dir = placer:get_look_dir(); @@ -145,10 +145,10 @@ function mcl_potions.register_splash(name, descr, color, def) if potency>0 and details.uses_level then dur = dur / math.pow(mcl_potions.POTENT_FACTOR, potency) end + dur = dur * mcl_potions.SPLASH_FACTOR else dur = details.dur end - dur = dur * mcl_potions.SPLASH_FACTOR if rad > 0 then mcl_potions.give_effect_by_level(name, obj, ef_level, redux_map[rad]*dur) else @@ -157,7 +157,14 @@ function mcl_potions.register_splash(name, descr, color, def) end end - if def.custom_effect then def.custom_effect(obj, potency+1) end -- TODO use redux_map + if def.custom_effect then + local power = (potency+1) * mcl_potions.SPLASH_FACTOR + if rad > 0 then + def.custom_effect(obj, redux_map[rad] * power) + else + def.custom_effect(obj, power) + end + end end end self.object:remove() From 5a7a533bf6eff1535933b3467a8ace850ba92b2c Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 8 Jan 2024 00:25:47 +0100 Subject: [PATCH 16/91] Added missing effect descriptions --- mods/ITEMS/mcl_potions/functions.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 12b0c08ec..efc4896fa 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -149,6 +149,9 @@ end mcl_potions.register_effect({ name = "invisibility", description = S("Invisiblity"), + get_tt = function(factor) + return S("body is invisible") + end, on_start = function(object, factor) mcl_potions.make_invisible(object, true) end, @@ -230,6 +233,9 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "water_breathing", description = S("Water Breathing"), + get_tt = function(factor) + return S("limitless breathing under water") + end, on_step = function(dtime, object, factor, duration) if not object:is_player() then return end if object:get_breath() then @@ -308,6 +314,9 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "night_vision", description = S("Night Vision"), + get_tt = function(factor) + return S("improved vision during the night") + end, res_condition = function(object) return (not object:is_player()) end, @@ -330,6 +339,9 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "fire_resistance", description = S("Fire Resistance"), + get_tt = function(factor) + return S("resistance to fire damage") + end, res_condition = function(object) return (not object:is_player()) end, From a429a462cda50991e7562e6956ae7cfe217ada0c Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 8 Jan 2024 00:26:36 +0100 Subject: [PATCH 17/91] Fixed tipped arrow descriptions --- mods/ITEMS/mcl_potions/tipped_arrow.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ITEMS/mcl_potions/tipped_arrow.lua b/mods/ITEMS/mcl_potions/tipped_arrow.lua index 9ba127172..808eff61e 100644 --- a/mods/ITEMS/mcl_potions/tipped_arrow.lua +++ b/mods/ITEMS/mcl_potions/tipped_arrow.lua @@ -42,6 +42,7 @@ function mcl_potions.register_arrow(name, desc, color, def) minetest.register_craftitem("mcl_potions:"..name.."_arrow", { description = desc, _tt_help = arrow_tt .. "\n" .. tt, + _dynamic_tt = def._dynamic_tt, _doc_items_longdesc = arrow_longdesc .. "\n" .. S("This particular arrow is tipped and will give an effect when it hits a player or mob.") .. "\n" .. longdesc, From 3663a62374b67d19a3807ba4b385d53b56023331 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 8 Jan 2024 00:26:56 +0100 Subject: [PATCH 18/91] Added a constant to the API --- mods/ITEMS/mcl_potions/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index 6df03db9d..550ddc27d 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -14,6 +14,7 @@ mcl_potions.INV_FACTOR = 0.50 mcl_potions.DURATION = 180 mcl_potions.DURATION_INV = mcl_potions.DURATION * mcl_potions.INV_FACTOR +mcl_potions.DURATION_POISON = 45 mcl_potions.II_FACTOR = mcl_potions.POTENT_FACTOR -- TODO remove at some point mcl_potions.DURATION_PLUS = mcl_potions.DURATION * mcl_potions.PLUS_FACTOR -- TODO remove at some point From eac63f93d5f9c594f4f69767aee60705a6ddfca6 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 8 Jan 2024 00:27:24 +0100 Subject: [PATCH 19/91] Re-registered potions under new API --- mods/ITEMS/mcl_potions/potions.lua | 221 ++++++++++++++--------------- 1 file changed, 108 insertions(+), 113 deletions(-) diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 940bbec4c..6ba67938d 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -272,6 +272,7 @@ function mcl_potions.register_potion(def) local ling_desc = S("Lingering @1", pdef.description) local ldef = {} ldef._tt = def._tt + ldef._dynamic_tt = def._dynamic_tt ldef._longdesc = def._longdesc ldef.stack_max = pdef.stack_max ldef._effect_list = pdef._effect_list @@ -300,6 +301,7 @@ function mcl_potions.register_potion(def) end local adef = {} adef._tt = def._tt + adef._dynamic_tt = def._dynamic_tt adef._longdesc = def._longdesc adef._effect_list = pdef._effect_list adef.uses_level = uses_level @@ -671,45 +673,29 @@ end -- ╚═════╝░╚══════╝╚═╝░░░░░╚═╝╚═╝░░╚══╝╚═╝░░░╚═╝░░░╚═╝░╚════╝░╚═╝░░╚══╝╚═════╝░ -local awkward_def = { +mcl_potions.register_potion({ name = "awkward", - description_potion = S("Awkward Potion"), - description_splash = S("Awkward Splash Potion"), - description_lingering = S("Awkward Lingering Potion"), - no_arrow = true, - no_effect = true, + desc_prefix = S("Awkward"), _tt = S("No effect"), _longdesc = S("Has an awkward taste and is used for brewing potions."), color = "#0000FF", - groups = {brewitem=1, food=3, can_eat_when_full=1, bottle=1}, - on_use = minetest.item_eat(0, "mcl_potions:glass_bottle"), -} +}) -local mundane_def = { +mcl_potions.register_potion({ name = "mundane", - description_potion = S("Mundane Potion"), - description_splash = S("Mundane Splash Potion"), - description_lingering = S("Mundane Lingering Potion"), - no_arrow = true, - no_effect = true, + desc_prefix = S("Mundane"), _tt = S("No effect"), - _longdesc = S("Has a terrible taste and is not useful for brewing potions."), + _longdesc = S("Has a terrible taste and is not really useful for brewing potions."), color = "#0000FF", - on_use = minetest.item_eat(0, "mcl_potions:glass_bottle"), -} +}) -local thick_def = { +mcl_potions.register_potion({ name = "thick", - description_potion = S("Thick Potion"), - description_splash = S("Thick Splash Potion"), - description_lingering = S("Thick Lingering Potion"), - no_arrow = true, - no_effect = true, + desc_prefix = S("Thick"), _tt = S("No effect"), - _longdesc = S("Has a bitter taste and is not useful for brewing potions."), + _longdesc = S("Has a bitter taste and is not really useful for brewing potions."), color = "#0000FF", - on_use = minetest.item_eat(0, "mcl_potions:glass_bottle"), -} +}) local dragon_breath_def = { name = "dragon_breath", @@ -738,146 +724,155 @@ local healing_def = { is_II = true, } +mcl_potions.register_potion({ + name = "healing", + desc_suffix = S("of Healing"), + _dynamic_tt = function(level) + return S("+@1 HP", 4 * level) + end, + _longdesc = S("Instantly heals."), + color = "#F82423", + uses_level = true, + has_arrow = true, + custom_effect = function(object, level) + return mcl_potions.healing_func(object, 4 * level) + end, +}) -local harming_def = { +mcl_potions.register_potion({ name = "harming", - description = S("Harming"), - _tt = S("-6 HP"), - _tt_II = S("-12 HP"), + desc_suffix = S("of Harming"), + _dynamic_tt = function(level) + return S("-@1 HP", 6 * level) + end, _longdesc = S("Instantly deals damage."), color = "#430A09", - effect = -6, - instant = true, - on_use = mcl_potions.healing_func, - is_II = true, - is_inv = true, -} + uses_level = true, + has_arrow = true, + custom_effect = function(object, level) + return mcl_potions.healing_func(object, -6 * level) + end, +}) -local night_vision_def = { +mcl_potions.register_potion({ name = "night_vision", - description = S("Night Vision"), + desc_suffix = S("of Night Vision"), _tt = nil, _longdesc = S("Increases the perceived brightness of light under a dark sky."), color = "#1F1FA1", - effect = nil, - is_dur = true, - on_use = mcl_potions.night_vision_func, - is_plus = true, -} + _effect_list = { + night_vision = {}, + }, + has_arrow = true, +}) -local swiftness_def = { +mcl_potions.register_potion({ name = "swiftness", - description = S("Swiftness"), + desc_suffix = S("of Swiftness"), _tt = nil, _longdesc = S("Increases walking speed."), color = "#7CAFC6", - effect = 1.2, - is_dur = true, - on_use = mcl_potions.swiftness_func, - is_II = true, - is_plus = true, -} + _effect_list = { + swiftness = {}, + }, + has_arrow = true, +}) -local slowness_def = { +mcl_potions.register_potion({ name = "slowness", - description = S("Slowness"), + desc_suffix = S("of Slowness"), _tt = nil, _longdesc = S("Decreases walking speed."), color = "#5A6C81", - effect = 0.85, - is_dur = true, - on_use = mcl_potions.slowness_func, - is_II = true, - is_plus = true, - is_inv = true, -} + _effect_list = { + slowness = {dur=mcl_potions.DURATION_INV}, + }, + has_arrow = true, +}) -local leaping_def = { +mcl_potions.register_potion({ name = "leaping", - description = S("Leaping"), + desc_suffix = S("of Leaping"), _tt = nil, _longdesc = S("Increases jump strength."), color = "#22FF4C", - effect = 1.15, - is_dur = true, - on_use = mcl_potions.leaping_func, - is_II = true, - is_plus = true, -} + _effect_list = { + leaping = {}, + }, + has_arrow = true, +}) -local withering_def = { +mcl_potions.register_potion({ name = "withering", - description = S("Withering"), + desc_suffix = S("of Withering"), _tt = nil, _longdesc = S("Applies the withering effect which deals damage at a regular interval and can kill."), color = "#000000", - effect = 4, - is_dur = true, - on_use = mcl_potions.withering_func, - is_II = true, - is_plus = true, - is_inv = true, -} + _effect_list = { + withering = {dur=mcl_potions.DURATION_POISON}, + }, + has_arrow = true, +}) -local poison_def = { +mcl_potions.register_potion({ name = "poison", - description = S("Poison"), + desc_suffix = S("of Poison"), _tt = nil, _longdesc = S("Applies the poison effect which deals damage at a regular interval."), color = "#4E9331", - effect = 2.5, - is_dur = true, - on_use = mcl_potions.poison_func, - is_II = true, - is_plus = true, - is_inv = true, -} + _effect_list = { + poison = {dur=mcl_potions.DURATION_POISON}, + }, + has_arrow = true, +}) -local regeneration_def = { +mcl_potions.register_potion({ name = "regeneration", - description = S("Regeneration"), + desc_suffix = S("of Regeneration"), _tt = nil, _longdesc = S("Regenerates health over time."), color = "#CD5CAB", - effect = 2.5, - is_dur = true, - on_use = mcl_potions.regeneration_func, - is_II = true, - is_plus = true, -} + _effect_list = { + regeneration = {dur=mcl_potions.DURATION_POISON}, + }, + has_arrow = true, +}) -local invisibility_def = { +mcl_potions.register_potion({ name = "invisibility", - description = S("Invisibility"), + desc_suffix = S("of Invisibility"), _tt = nil, _longdesc = S("Grants invisibility."), color = "#7F8392", - is_dur = true, - on_use = mcl_potions.invisiblility_func, - is_plus = true, -} + _effect_list = { + invisibility = {}, + }, + has_arrow = true, +}) -local water_breathing_def = { +mcl_potions.register_potion({ name = "water_breathing", - description = S("Water Breathing"), + desc_suffix = S("of Water Breathing"), _tt = nil, _longdesc = S("Grants limitless breath underwater."), color = "#2E5299", - is_dur = true, - on_use = mcl_potions.water_breathing_func, - is_plus = true, -} + _effect_list = { + water_breathing = {}, + }, + has_arrow = true, +}) -local fire_resistance_def = { +mcl_potions.register_potion({ name = "fire_resistance", - description = S("Fire Resistance"), + desc_suffix = S("of Fire Resistance"), _tt = nil, _longdesc = S("Grants immunity to damage from heat sources like fire."), color = "#E49A3A", - is_dur = true, - on_use = mcl_potions.fire_resistance_func, - is_plus = true, -} + _effect_list = { + fire_resistance = {}, + }, + has_arrow = true, +}) From b84d36b3ff57ec80cb9e15062d7408d826df7410 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 8 Jan 2024 00:41:08 +0100 Subject: [PATCH 20/91] Registered dragon breath and pruned code * removed old registration code * added to the API the `nocreative` field * registered the bottled dragon's breath as an item --- mods/ITEMS/mcl_potions/lingering.lua | 4 +- mods/ITEMS/mcl_potions/potions.lua | 366 +----------------------- mods/ITEMS/mcl_potions/splash.lua | 4 +- mods/ITEMS/mcl_potions/tipped_arrow.lua | 4 +- 4 files changed, 23 insertions(+), 355 deletions(-) diff --git a/mods/ITEMS/mcl_potions/lingering.lua b/mods/ITEMS/mcl_potions/lingering.lua index 646ff16ff..ea0d0f36c 100644 --- a/mods/ITEMS/mcl_potions/lingering.lua +++ b/mods/ITEMS/mcl_potions/lingering.lua @@ -125,6 +125,8 @@ function mcl_potions.register_lingering(name, descr, color, def) longdesc = longdesc .. "\n" .. def._longdesc end end + local groups = {brewitem=1, bottle=1, ling_potion=1, _mcl_potion=1} + if def.nocreative then groups.not_in_creative_inventory = 1 end minetest.register_craftitem(id, { description = descr, _tt_help = def._tt, @@ -139,7 +141,7 @@ function mcl_potions.register_lingering(name, descr, color, def) _default_potent_level = def._default_potent_level, _default_extend_level = def._default_extend_level, inventory_image = lingering_image(color), - groups = {brewitem=1, bottle=1, ling_potion=1, _mcl_potion=1}, + groups = groups, on_use = function(item, placer, pointed_thing) local velocity = 10 local dir = placer:get_look_dir(); diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 6ba67938d..5f941b2fb 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -148,6 +148,7 @@ end -- groups - table - item groups definition for the regular potion, not splash or lingering - -- - must contain _mcl_potion=1 for tooltip to include dynamic_tt and effects -- - defaults to {brewitem=1, food=3, can_eat_when_full=1, _mcl_potion=1} +-- nocreative - bool - adds a not_in_creative_inventory=1 group - defaults to false -- _effect_list - table - all the effects dealt by the potion in the format of tables -- -- the name of each sub-table should be a name of a registered effect, and fields can be the following: -- -- -- uses_level - bool - whether the level of the potion affects the level of the effect - @@ -204,6 +205,7 @@ function mcl_potions.register_potion(def) pdef.inventory_image = def.image or potion_image(color) pdef.wield_image = pdef.inventory_image pdef.groups = def.groups or {brewitem=1, food=3, can_eat_when_full=1, _mcl_potion=1} + if def.nocreative then pdef.groups.not_in_creative_inventory = 1 end pdef._effect_list = {} local effect @@ -255,6 +257,7 @@ function mcl_potions.register_potion(def) sdef._tt = def._tt sdef._dynamic_tt = def._dynamic_tt sdef._longdesc = def._longdesc + sdef.nocreative = def.nocreative sdef.stack_max = pdef.stack_max sdef._effect_list = pdef._effect_list sdef.uses_level = uses_level @@ -274,6 +277,7 @@ function mcl_potions.register_potion(def) ldef._tt = def._tt ldef._dynamic_tt = def._dynamic_tt ldef._longdesc = def._longdesc + ldef.nocreative = def.nocreative ldef.stack_max = pdef.stack_max ldef._effect_list = pdef._effect_list ldef.uses_level = uses_level @@ -303,6 +307,7 @@ function mcl_potions.register_potion(def) adef._tt = def._tt adef._dynamic_tt = def._dynamic_tt adef._longdesc = def._longdesc + adef.nocreative = def.nocreative adef._effect_list = pdef._effect_list adef.uses_level = uses_level adef.has_potent = pdef.has_potent @@ -326,6 +331,7 @@ mcl_potions.register_potion({ _longdesc = "Trolololololo", stack_max = 2, color = "#00AA00", + nocreative = true, _effect_list = { night_vision = {}, strength = {}, @@ -344,319 +350,6 @@ mcl_potions.register_potion({ }) -local function register_potion(def) - - local dur = mcl_potions.DURATION - - if def.is_inv then - dur = dur * mcl_potions.INV_FACTOR - end - if def.name == "poison" or def.name == "regeneration" or def.name == "withering" then - dur = 45 - end - - local on_use = nil - - if def.on_use then - on_use = return_on_use(def, def.effect, dur) - end - - local function get_tt(tt, effect, dur) - local _tt - if effect and def.is_dur then - _tt = perc_string(effect).." | "..time_string(dur) - if def.name == "poison" or def.name == "regeneration" or def.name == "withering" then - _tt = S("1 HP/@1s | @2", effect, time_string(dur)) - end - elseif def.name == "healing" or def.name == "harming" then - _tt = S("@1 HP", effect) - else - _tt = tt or time_string(dur) or S("No effect") - end - return _tt - end - - local function get_splash_fun(effect, sp_dur) - if def.is_dur then - return function(player, redx) def.on_use(player, effect, sp_dur*redx) end - elseif def.effect then - return function(player, redx) def.on_use(player, effect*redx, sp_dur) end - end - -- covers case of no effect (water, awkward, mundane) - return function() end - end - - local function get_lingering_fun(effect, ling_dur) - if def.is_dur then - return function(player) def.on_use(player, effect, ling_dur) end - elseif def.effect then - return function(player) def.on_use(player, effect*0.5, ling_dur) end - end - -- covers case of no effect (water, awkward, mundane) - return function() end - end - - local function get_arrow_fun(effect, dur) - if def.is_dur then - return function(player) def.on_use(player, effect, dur) end - elseif def.effect then - return function(player) def.on_use(player, effect, dur) end - end - -- covers case of no effect (water, awkward, mundane) - return function() end - end - - local desc - if not def.no_potion then - if def.description_potion then - desc = def.description_potion - else - desc = S("@1 Potion", def.description) - end - else - desc = def.description - end - local potion_longdesc = def._longdesc - if not def.no_effect then - potion_longdesc = potion_intro .. "\n" .. def._longdesc - end - local potion_usagehelp - local basic_potion_tt - if def.name ~= "dragon_breath" then - potion_usagehelp = how_to_drink - basic_potion_tt = get_tt(def._tt, def.effect, dur) - end - - minetest.register_craftitem("mcl_potions:"..def.name, { - description = desc, - _tt_help = basic_potion_tt, - _doc_items_longdesc = potion_longdesc, - _doc_items_usagehelp = potion_usagehelp, - stack_max = def.stack_max or 1, - inventory_image = def.image or potion_image(def.color), - wield_image = def.image or potion_image(def.color), - groups = def.groups or {brewitem=1, food=3, can_eat_when_full=1, bottle=1}, - on_place = on_use, - on_secondary_use = on_use, - }) - - -- Register Splash and Lingering - local splash_dur = dur * mcl_potions.SPLASH_FACTOR - local ling_dur = dur * mcl_potions.LINGERING_FACTOR - - local splash_def = { - tt = get_tt(def._tt, def.effect, splash_dur), - longdesc = def._longdesc, - potion_fun = get_splash_fun(def.effect, splash_dur), - no_effect = def.no_effect, - instant = def.instant, - } - - local ling_def - if def.name == "healing" or def.name == "harming" then - ling_def = { - tt = get_tt(def._tt, def.effect*mcl_potions.LINGERING_FACTOR, ling_dur), - longdesc = def._longdesc, - potion_fun = get_lingering_fun(def.effect*mcl_potions.LINGERING_FACTOR, ling_dur), - no_effect = def.no_effect, - instant = def.instant, - } - else - ling_def = { - tt = get_tt(def._tt, def.effect, ling_dur), - longdesc = def._longdesc, - potion_fun = get_lingering_fun(def.effect, ling_dur), - no_effect = def.no_effect, - instant = def.instant, - } - end - - local arrow_def = { - tt = get_tt(def._tt, def.effect, dur/8.), - longdesc = def._longdesc, - potion_fun = get_arrow_fun(def.effect, dur/8.), - no_effect = def.no_effect, - instant = def.instant, - } - - if def.color and not def.no_throwable then - local desc - if def.description_splash then - desc = def.description_splash - else - desc = S("Splash @1 Potion", def.description) - end - mcl_potions.register_splash(def.name, desc, def.color, splash_def) - if def.description_lingering then - desc = def.description_lingering - else - desc = S("Lingering @1 Potion", def.description) - end - mcl_potions.register_lingering(def.name, desc, def.color, ling_def) - if not def.no_arrow then - mcl_potions.register_arrow(def.name, S("Arrow of @1", def.description), def.color, arrow_def) - end - end - - if def.is_II then - - local desc_mod = S(" II") - - local effect_II - if def.name == "healing" or def.name == "harming" then - effect_II = def.effect*mcl_potions.II_FACTOR - elseif def.name == "poison" or def.name == "regeneration" then - effect_II = 1.2 - elseif def.name == "withering" then - effect_II = 2 - else - effect_II = def.effect^mcl_potions.II_FACTOR - end - - local dur_2 = dur / mcl_potions.II_FACTOR - if def.name == "poison" then dur_2 = dur_2 - 1 end - - if def.name == "slowness" then - dur_2 = 20 - effect_II = 0.40 - desc_mod = S(" IV") - end - - on_use = return_on_use(def, effect_II, dur_2) - - minetest.register_craftitem("mcl_potions:"..def.name.."_2", { - description = S("@1 Potion@2", def.description, desc_mod), - _tt_help = get_tt(def._tt_2, effect_II, dur_2), - _doc_items_longdesc = potion_longdesc, - _doc_items_usagehelp = potion_usagehelp, - stack_max = def.stack_max or 1, - inventory_image = def.image or potion_image(def.color), - wield_image = def.image or potion_image(def.color), - groups = def.groups or {brewitem=1, food=3, can_eat_when_full=1, bottle=1}, - on_place = on_use, - on_secondary_use = on_use, - }) - - -- Register Splash and Lingering - local splash_dur_2 = dur_2 * mcl_potions.SPLASH_FACTOR - local ling_dur_2 = dur_2 * mcl_potions.LINGERING_FACTOR - - local splash_def_2 - if def.name == "healing" then - splash_def_2 = { - tt = get_tt(def._tt_2, 7, splash_dur_2), - longdesc = def._longdesc, - potion_fun = get_splash_fun(7, splash_dur_2), - no_effect = def.no_effect, - instant = def.instant, - } - else - splash_def_2 = { - tt = get_tt(def._tt_2, effect_II, splash_dur_2), - longdesc = def._longdesc, - potion_fun = get_splash_fun(effect_II, splash_dur_2), - no_effect = def.no_effect, - instant = def.instant, - } - end - - - local ling_def_2 - if def.name == "healing" or def.name == "harming" then - ling_def_2 = { - tt = get_tt(def._tt_2, effect_II*mcl_potions.LINGERING_FACTOR, ling_dur_2), - longdesc = def._longdesc, - potion_fun = get_lingering_fun(effect_II*mcl_potions.LINGERING_FACTOR, ling_dur_2), - no_effect = def.no_effect, - instant = def.instant, - } - else - ling_def_2 = { - tt = get_tt(def._tt_2, effect_II, ling_dur_2), - longdesc = def._longdesc, - potion_fun = get_lingering_fun(effect_II, ling_dur_2), - no_effect = def.no_effect, - instant = def.instant, - } - end - - local arrow_def_2 = { - tt = get_tt(def._tt_2, effect_II, dur_2/8.), - longdesc = def._longdesc, - potion_fun = get_arrow_fun(effect_II, dur_2/8.), - no_effect = def.no_effect, - instant = def.instant, - } - - if def.color and not def.no_throwable then - mcl_potions.register_splash(def.name.."_2", S("Splash @1@2 Potion", def.description, desc_mod), def.color, splash_def_2) - mcl_potions.register_lingering(def.name.."_2", S("Lingering @1@2 Potion", def.description, desc_mod), def.color, ling_def_2) - if not def.no_arrow then - mcl_potions.register_arrow(def.name.."_2", S("Arrow of @1@2", def.description, desc_mod), def.color, arrow_def_2) - end - end - - end - - if def.is_plus then - - local dur_pl = dur * mcl_potions.PLUS_FACTOR - if def.name == "poison" or def.name == "regeneration" or def.name == "withering" then - dur_pl = 90 - end - - on_use = return_on_use(def, def.effect, dur_pl) - - minetest.register_craftitem("mcl_potions:"..def.name.."_plus", { - description = S("@1 + Potion", def.description), - _tt_help = get_tt(def._tt_plus, def.effect, dur_pl), - _doc_items_longdesc = potion_longdesc, - _doc_items_usagehelp = potion_usagehelp, - stack_max = 1, - inventory_image = def.image or potion_image(def.color), - wield_image = def.image or potion_image(def.color), - groups = def.groups or {brewitem=1, food=3, can_eat_when_full=1, bottle=1}, - on_place = on_use, - on_secondary_use = on_use, - }) - - -- Register Splash - local splash_dur_pl = dur_pl * mcl_potions.SPLASH_FACTOR - local ling_dur_pl = dur_pl * mcl_potions.LINGERING_FACTOR - - local splash_def_pl = { - tt = get_tt(def._tt_plus, def.effect, splash_dur_pl), - longdesc = def._longdesc, - potion_fun = get_splash_fun(def.effect, splash_dur_pl), - no_effect = def.no_effect, - instant = def.instant, - } - local ling_def_pl = { - tt = get_tt(def._tt_plus, def.effect, ling_dur_pl), - longdesc = def._longdesc, - potion_fun = get_lingering_fun(def.effect, ling_dur_pl), - no_effect = def.no_effect, - instant = def.instant, - } - local arrow_def_pl = { - tt = get_tt(def._tt_pl, def.effect, dur_pl/8.), - longdesc = def._longdesc, - potion_fun = get_arrow_fun(def.effect, dur_pl/8.), - no_effect = def.no_effect, - instant = def.instant, - } - if def.color and not def.no_throwable then - mcl_potions.register_splash(def.name.."_plus", S("Splash @1 + Potion", def.description), def.color, splash_def_pl) - mcl_potions.register_lingering(def.name.."_plus", S("Lingering @1 + Potion", def.description), def.color, ling_def_pl) - if not def.no_arrow then - mcl_potions.register_arrow(def.name.."_plus", S("Arrow of @1 +", def.description), def.color, arrow_def_pl) - end - end - - end - -end - -- ██████╗░░█████╗░████████╗██╗░█████╗░███╗░░██╗ -- ██╔══██╗██╔══██╗╚══██╔══╝██║██╔══██╗████╗░██║ @@ -673,6 +366,14 @@ end -- ╚═════╝░╚══════╝╚═╝░░░░░╚═╝╚═╝░░╚══╝╚═╝░░░╚═╝░░░╚═╝░╚════╝░╚═╝░░╚══╝╚═════╝░ +minetest.register_craftitem("mcl_potions:dragon_breath", { + description = S("Dragon's Breath"), + _longdesc = S("This item is used in brewing and can be combined with splash potions to create lingering potions."), + image = "mcl_potions_dragon_breath.png", + groups = { brewitem = 1, bottle = 1 }, + stack_max = 64, +}) + mcl_potions.register_potion({ name = "awkward", desc_prefix = S("Awkward"), @@ -697,33 +398,6 @@ mcl_potions.register_potion({ color = "#0000FF", }) -local dragon_breath_def = { - name = "dragon_breath", - description = S("Dragon's Breath"), - no_arrow = true, - no_potion = true, - no_throwable = true, - no_effect = true, - _longdesc = S("This item is used in brewing and can be combined with splash potions to create lingering potions."), - image = "mcl_potions_dragon_breath.png", - groups = { brewitem = 1, bottle = 1 }, - on_use = nil, - stack_max = 64, -} - -local healing_def = { - name = "healing", - description = S("Healing"), - _tt = S("+4 HP"), - _tt_2 = S("+8 HP"), - _longdesc = S("Instantly heals."), - color = "#F82423", - effect = 4, - instant = true, - on_use = mcl_potions.healing_func, - is_II = true, -} - mcl_potions.register_potion({ name = "healing", desc_suffix = S("of Healing"), @@ -876,18 +550,6 @@ mcl_potions.register_potion({ -local defs = { awkward_def, mundane_def, thick_def, dragon_breath_def, - healing_def, harming_def, night_vision_def, swiftness_def, - slowness_def, leaping_def, withering_def, poison_def, regeneration_def, - invisibility_def, water_breathing_def, fire_resistance_def} - --- for _, def in ipairs(defs) do --- register_potion(def) --- end - - - - -- minetest.register_craftitem("mcl_potions:weakness", { -- description = S("Weakness"), -- _tt_help = TODO, diff --git a/mods/ITEMS/mcl_potions/splash.lua b/mods/ITEMS/mcl_potions/splash.lua index e14bf2c1a..2fb9f362c 100644 --- a/mods/ITEMS/mcl_potions/splash.lua +++ b/mods/ITEMS/mcl_potions/splash.lua @@ -20,6 +20,8 @@ function mcl_potions.register_splash(name, descr, color, def) longdesc = longdesc .. "\n" .. def._longdesc end end + local groups = {brewitem=1, bottle=1, splash_potion=1, _mcl_potion=1} + if def.nocreative then groups.not_in_creative_inventory = 1 end minetest.register_craftitem(id, { description = descr, _tt_help = def._tt, @@ -34,7 +36,7 @@ function mcl_potions.register_splash(name, descr, color, def) _default_potent_level = def._default_potent_level, _default_extend_level = def._default_extend_level, inventory_image = splash_image(color), - groups = {brewitem=1, bottle=1, splash_potion=1, _mcl_potion=1}, + groups = groups, on_use = function(item, placer, pointed_thing) local velocity = 10 local dir = placer:get_look_dir(); diff --git a/mods/ITEMS/mcl_potions/tipped_arrow.lua b/mods/ITEMS/mcl_potions/tipped_arrow.lua index 808eff61e..a6a1b71bc 100644 --- a/mods/ITEMS/mcl_potions/tipped_arrow.lua +++ b/mods/ITEMS/mcl_potions/tipped_arrow.lua @@ -39,6 +39,8 @@ function mcl_potions.register_arrow(name, desc, color, def) local longdesc = def._longdesc or "" local tt = def._tt or "" + local groups = {ammo=1, ammo_bow=1, brewitem=1, _mcl_potion=1} + if def.nocreative then groups.not_in_creative_inventory = 1 end minetest.register_craftitem("mcl_potions:"..name.."_arrow", { description = desc, _tt_help = arrow_tt .. "\n" .. tt, @@ -54,7 +56,7 @@ function mcl_potions.register_arrow(name, desc, color, def) _default_potent_level = def._default_potent_level, _default_extend_level = def._default_extend_level, inventory_image = "mcl_bows_arrow_inv.png^(mcl_potions_arrow_inv.png^[colorize:"..color..":100)", - groups = { ammo=1, ammo_bow=1, brewitem=1, _mcl_potion=1}, + groups = groups, _on_dispense = function(itemstack, dispenserpos, droppos, dropnode, dropdir) -- Shoot arrow local shootpos = vector.add(dispenserpos, vector.multiply(dropdir, 0.51)) From 209299b79147c1dd8538f1fadff4aee048d3474a Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 10 Jan 2024 21:57:15 +0100 Subject: [PATCH 21/91] Improved /effect command return messages Also improved the name of a variable --- mods/ITEMS/mcl_potions/commands.lua | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/mods/ITEMS/mcl_potions/commands.lua b/mods/ITEMS/mcl_potions/commands.lua index 53245f4fc..7b420f801 100644 --- a/mods/ITEMS/mcl_potions/commands.lua +++ b/mods/ITEMS/mcl_potions/commands.lua @@ -10,7 +10,7 @@ local S = minetest.get_translator(minetest.get_current_modname()) minetest.register_chatcommand("effect",{ params = S("|heal|list [] []"), - description = S("Add a status effect to yourself. Arguments: : name of status effect, e.g. poison. Passing list as effect name lists available effects. Passing heal as effect name heals (or harms) by amount designed by the next parameter. : duration in seconds. (: amount of healing when the effect is heal, passing a negative value subtracts health.) : effect power determinant, bigger level results in more powerful effect for effects that depend on the level, defaults to 1, pass F to use low-level factor instead. : effect strength modifier, can mean different things depending on the effect."), + description = S("Add a status effect to yourself. Arguments: : name of status effect. Passing \"list\" as effect name lists available effects. Passing \"heal\" as effect name heals (or harms) by amount designed by the next parameter. : duration in seconds. (: amount of healing when the effect is \"heal\", passing a negative value subtracts health.) : effect power determinant, bigger level results in more powerful effect for effects that depend on the level (no changes for other effects), defaults to 1, pass F to use low-level factor instead. : effect strength modifier, can mean different things depending on the effect, no changes for effects that do not depend on level/factor."), privs = {server = true}, func = function(name, params) @@ -25,8 +25,8 @@ minetest.register_chatcommand("effect",{ return false, S("Missing effect parameter!") elseif P[1] == "list" then local effects = "heal" - for name, _ in pairs(mcl_potions.registered_effects) do - effects = effects .. ", " .. name + for effect, _ in pairs(mcl_potions.registered_effects) do + effects = effects .. ", " .. effect end return true, effects elseif P[1] == "heal" then @@ -61,14 +61,22 @@ minetest.register_chatcommand("effect",{ if P[3] == "F" then local given = mcl_potions.give_effect(P[1], minetest.get_player_by_name(name), tonumber(P[4]), tonumber(P[2])) if given then - return true, S("@1 effect given to player @2 for @3 seconds with factor of @4.", def.description, name, P[2], P[4]) + if def.uses_factor then + return true, S("@1 effect given to player @2 for @3 seconds with factor of @4.", def.description, name, P[2], P[4]) + else + return true, S("@1 effect given to player @2 for @3 seconds.", def.description, name, P[2]) + end else return false, S("Giving effect @1 to player @2 failed.", def.description, name) end else local given = mcl_potions.give_effect_by_level(P[1], minetest.get_player_by_name(name), tonumber(P[3]), tonumber(P[2])) if given then - return true, S("@1 effect on level @2 given to player @3 for @4 seconds.", def.description, P[3], name, P[2]) + if def.uses_factor then + return true, S("@1 effect on level @2 given to player @3 for @4 seconds.", def.description, P[3], name, P[2]) + else + return true, S("@1 effect given to player @2 for @3 seconds.", def.description, name, P[2]) + end else return false, S("Giving effect @1 to player @2 failed.", def.description, name) end From a6c9bc8a0118661a256162dfc864942b92305947 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Thu, 11 Jan 2024 00:23:41 +0100 Subject: [PATCH 22/91] Improved effects HUD and fixes * Fixed some effects not being replaced correctly with higher levels * Implemented an old FIXME (MTE 5.3.0 fixed underlying bug) * Added a way to obtain an approximate level of effect from factor * Added effect level to HUD under the icon * Added effect timer to HUD under the icon --- mods/ITEMS/mcl_potions/functions.lua | 115 +++++++++++++++++++++------ 1 file changed, 89 insertions(+), 26 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index efc4896fa..51236c17d 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -33,6 +33,14 @@ local function generate_linear_lvl_to_fac(l1, l2) end end +local function generate_linear_fac_to_lvl(l1, l2) + local a = 1/(l2 - l1) + local b = -(2*l1 - l2) * a + return function(factor) + return math.round(a*factor + b) + end +end + local function generate_rational_lvl_to_fac(l1, l2) local a = (l1 - l2) * 2 local b = 2*l2 - l1 @@ -42,6 +50,15 @@ local function generate_rational_lvl_to_fac(l1, l2) end end +local function generate_rational_fac_to_lvl(l1, l2) + local a = (l1 - l2) * 2 + local b = 2*l2 - l1 + return function(factor) + if factor == 0 then return math.huge end + return math.round(a/(factor - 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 @@ -118,8 +135,12 @@ function mcl_potions.register_effect(def) local l2 = def.lvl2_factor or 2*l1 if l1 < l2 then pdef.level_to_factor = generate_linear_lvl_to_fac(l1, l2) + pdef.factor_to_level = generate_linear_fac_to_lvl(l1, l2) + pdef.inv_factor = false elseif l1 > l2 then pdef.level_to_factor = generate_rational_lvl_to_fac(l1, l2) + pdef.factor_to_level = generate_rational_fac_to_lvl(l1, l2) + pdef.inv_factor = true else error("Can't extrapolate levels from lvl1 and lvl2 bearing the same factor") end @@ -417,7 +438,8 @@ local function potions_init_icons(player) icon_ids[name] = {} for e=1, EFFECT_TYPES do local x = -52 * e - 2 - local id = player:hud_add({ + local id = {} + id.img = player:hud_add({ hud_elem_type = "image", text = "blank.png", position = { x = 1, y = 0 }, @@ -426,6 +448,28 @@ local function potions_init_icons(player) alignment = { x = 1, y = 1 }, z_index = 100, }) + id.label = player:hud_add({ + hud_elem_type = "text", + text = "", + position = { x = 1, y = 0 }, + offset = { x = x+22, y = 50 }, + scale = { x = 50, y = 15 }, + alignment = { x = 0, y = 1 }, + z_index = 100, + style = 1, + number = 0xFFFFFF, + }) + id.timestamp = player:hud_add({ + hud_elem_type = "text", + text = "", + position = { x = 1, y = 0 }, + offset = { x = x+22, y = 65 }, + scale = { x = 50, y = 15 }, + alignment = { x = 0, y = 1 }, + z_index = 100, + style = 1, + number = 0xFFFFFF, + }) table.insert(icon_ids[name], id) end end @@ -438,19 +482,38 @@ local function potions_set_icons(player) local active_effects = {} for effect_name, effect in pairs(EF) do if effect[player] then - table.insert(active_effects, effect_name) + active_effects[effect_name] = effect[player] end end - for i=1, EFFECT_TYPES do - local icon = icon_ids[name][i] - local effect_name = active_effects[i] - 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") + local i = 1 + for effect_name, def in pairs(registered_effects) do + local icon = icon_ids[name][i].img + local label = icon_ids[name][i].label + local timestamp = icon_ids[name][i].timestamp + local vals = active_effects[effect_name] + if vals then + player:hud_change(icon, "text", def.icon .. "^[resize:128x128") + if def.uses_factor then + local level = def.factor_to_level(vals.factor) + if level == math.huge then level = "∞" + else level = mcl_util.to_roman(level) end + player:hud_change(label, "text", level) + else + player:hud_change(label, "text", "") + end + local dur = math.round(vals.dur-vals.timer) + player:hud_change(timestamp, "text", math.floor(dur/60)..string.format(":%02d",math.floor(dur % 60))) + EF[effect_name][player].hud_index = i + i = i + 1 end end + while i < EFFECT_TYPES do + player:hud_change(icon_ids[name][i].img, "text", "blank.png") + player:hud_change(icon_ids[name][i].label, "text", "") + player:hud_change(icon_ids[name][i].timestamp, "text", "") + i = i + 1 + end end local function potions_set_hud(player) @@ -496,6 +559,10 @@ minetest.register_globalstep(function(dtime) meta:set_string("mcl_potions:"..name, minetest.serialize(EF[name][object])) potions_set_hud(object) end + elseif object:is_player() then + local dur = math.round(vals.dur-vals.timer) + object:hud_change(icon_ids[object:get_player_name()][vals.hud_index].timestamp, + "text", math.floor(dur/60)..string.format(":%02d",math.floor(dur % 60))) end end end @@ -665,15 +732,7 @@ minetest.register_on_joinplayer( function(player) 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 - -- in same tick as player:hud_add - -- (see ) - -- FIXME: Remove minetest.after - minetest.after(3, function(player) - if player and player:is_player() then - potions_set_hud(player) - end - end, player) + potions_set_hud(player) end) minetest.register_on_shutdown(function() @@ -833,14 +892,18 @@ function mcl_potions.give_effect(name, object, factor, duration) 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 + if not edef.uses_factor or (edef.uses_factor and + (not edef.inv_factor and factor >= present.factor + or edef.inv_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 + else + return false end end From 40580843d531fdc3f5d9e39f6dc509d8bc7fee8b Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 13 Jan 2024 05:20:33 +0100 Subject: [PATCH 23/91] New effect icons --- textures/mcl_potions_effect_absorbtion.png | Bin 0 -> 130 bytes textures/mcl_potions_effect_bad_luck.png | Bin 0 -> 101 bytes textures/mcl_potions_effect_bad_omen.png | Bin 156 -> 126 bytes textures/mcl_potions_effect_blindness.png | Bin 0 -> 125 bytes textures/mcl_potions_effect_conduit_power.png | Bin 0 -> 124 bytes textures/mcl_potions_effect_darkness.png | Bin 0 -> 114 bytes textures/mcl_potions_effect_dolphin_grace.png | Bin 0 -> 152 bytes textures/mcl_potions_effect_fatigue.png | Bin 0 -> 147 bytes textures/mcl_potions_effect_fire_resistance.png | Bin 121 -> 149 bytes textures/mcl_potions_effect_food_poisoning.png | Bin 126 -> 128 bytes textures/mcl_potions_effect_glowing.png | Bin 0 -> 147 bytes textures/mcl_potions_effect_haste.png | Bin 0 -> 130 bytes textures/mcl_potions_effect_health_boost.png | Bin 0 -> 115 bytes textures/mcl_potions_effect_hero_of_village.png | Bin 0 -> 136 bytes textures/mcl_potions_effect_invisibility.png | Bin 124 -> 146 bytes textures/mcl_potions_effect_leaping.png | Bin 122 -> 118 bytes textures/mcl_potions_effect_levitation.png | Bin 0 -> 135 bytes textures/mcl_potions_effect_luck.png | Bin 0 -> 135 bytes textures/mcl_potions_effect_nausea.png | Bin 0 -> 138 bytes textures/mcl_potions_effect_night_vision.png | Bin 112 -> 148 bytes textures/mcl_potions_effect_poison.png | Bin 123 -> 147 bytes textures/mcl_potions_effect_regeneration.png | Bin 138 -> 138 bytes textures/mcl_potions_effect_resistance.png | Bin 0 -> 111 bytes textures/mcl_potions_effect_saturation.png | Bin 0 -> 134 bytes textures/mcl_potions_effect_slow_falling.png | Bin 0 -> 124 bytes textures/mcl_potions_effect_slowness.png | Bin 118 -> 152 bytes textures/mcl_potions_effect_strength.png | Bin 114 -> 142 bytes textures/mcl_potions_effect_swiftness.png | Bin 122 -> 129 bytes textures/mcl_potions_effect_water_breathing.png | Bin 142 -> 137 bytes textures/mcl_potions_effect_weakness.png | Bin 129 -> 134 bytes 30 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 textures/mcl_potions_effect_absorbtion.png create mode 100644 textures/mcl_potions_effect_bad_luck.png create mode 100644 textures/mcl_potions_effect_blindness.png create mode 100644 textures/mcl_potions_effect_conduit_power.png create mode 100644 textures/mcl_potions_effect_darkness.png create mode 100644 textures/mcl_potions_effect_dolphin_grace.png create mode 100644 textures/mcl_potions_effect_fatigue.png create mode 100644 textures/mcl_potions_effect_glowing.png create mode 100644 textures/mcl_potions_effect_haste.png create mode 100644 textures/mcl_potions_effect_health_boost.png create mode 100644 textures/mcl_potions_effect_hero_of_village.png create mode 100644 textures/mcl_potions_effect_levitation.png create mode 100644 textures/mcl_potions_effect_luck.png create mode 100644 textures/mcl_potions_effect_nausea.png create mode 100644 textures/mcl_potions_effect_resistance.png create mode 100644 textures/mcl_potions_effect_saturation.png create mode 100644 textures/mcl_potions_effect_slow_falling.png diff --git a/textures/mcl_potions_effect_absorbtion.png b/textures/mcl_potions_effect_absorbtion.png new file mode 100644 index 0000000000000000000000000000000000000000..114f64e2df9c8484a245f7eae294d3acb5b4fa5a GIT binary patch literal 130 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4kiW$h6xih%orFLJUv|;Lo_BPZ`im^jnk0f zYL7@n5#-$To1z86c^DSpH$vhzopr07=3rC;$Ke literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_bad_luck.png b/textures/mcl_potions_effect_bad_luck.png new file mode 100644 index 0000000000000000000000000000000000000000..f950d489ff1edab78ac1d2da2b3881933f70b91c GIT binary patch literal 101 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4kiW$h6xih%orFLbUa-gLo_BPZ`im^jnj~! z@a#G%B|#@<$J~Nckqm{77w?w@+6Ua{U!rO^Nr2&hn1g_QqWTpE1_lOCS3j3^P6VJLo_BPZ`im^jnk0f zFVdQ&MBb@01D0~O8@`> literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_darkness.png b/textures/mcl_potions_effect_darkness.png new file mode 100644 index 0000000000000000000000000000000000000000..fc72daeb0819ee06535b7ffd21e010c013e5d0f0 GIT binary patch literal 114 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4kiW$h6xih%orFLEInNuLo_BPZ`im^jnlBf z;9>(4FUwZNDF-7fz8pxsXqs@fS*O*Nd6t|>;Tx$3RR*jtCD$nXGkbC{=zg@DYHVlM R%fP_E;OXk;vd$@?2>^BzAsPSx literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_dolphin_grace.png b/textures/mcl_potions_effect_dolphin_grace.png new file mode 100644 index 0000000000000000000000000000000000000000..ac640819de3098e6e39a9900d6bba4e04d0aa9f5 GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4kiW$h6xih%orFL;yqm)Lo_BPZ`im^jnj}} zW6n(}B|#@<$J~Nc4&I6{2T}v)u#~GV3raE7s5|g9P^a#|V)ot33tt|T^x9F=>Ce0@ z{lcLsM!Xp+o8&Keu=yPR(4rZ5uuEU=gG!JHuZkjrL(wzopr E0O!3iH~;_u literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_fatigue.png b/textures/mcl_potions_effect_fatigue.png new file mode 100644 index 0000000000000000000000000000000000000000..13b724c2ad6c7cace908d5c93070b7b7ba9392ad GIT binary patch literal 147 zcmV;E0Brw>P)l>v|#eFy>o005AYXf^-<09;8#K~yM_W3aKdCJ8YB@wrA#A`wCZF=k`Y zfTk0|MUzFh0aG(!4RC|uZ0s74O~O=7zy>ru$RxU_afK$u8t~{r3k;N)#^q@&F^x4? lu(Uk4}=PV3c!eg0RWLJ5k;)|(76Br002ov JPDHLkV1i7oBEbLv diff --git a/textures/mcl_potions_effect_food_poisoning.png b/textures/mcl_potions_effect_food_poisoning.png index f29be56a5ec743b9c52e707e6ac1908994d9cd28..8fb969e6e1d7731dd80b63da489d6d650e4e3d14 100644 GIT binary patch delta 110 zcmV-!0FnQGfB}#gXb1uT005AYXf^-<07pqgK~yNuW3aKdCJ8YB@q~SOL?QwjAW~=~ zWg0MDj86kDtFUW;lUNZx4R|cUsR64E1T+vE4+JBTG8-^mOjRe5miS0Q057FV&J5bE QIRF3v07*qoM6N<$f)4*7i2wiq delta 108 zcmV-y0F(cK0e+AeW&r~L001RDZ6W{w00vM@R7E^HJD|69b(d&@0000pNkl;r2PY6Z*a!eA`wfJ?x;vBr O0000P)Erf@qnfQiyzP&ifIFun8u$p@c97`f@&ZM0RU{2!af9l;Y$Dj002ovPDHLkV1mh( BGI0O^ literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_haste.png b/textures/mcl_potions_effect_haste.png new file mode 100644 index 0000000000000000000000000000000000000000..54dd34740ea9c49d85d9f8d5dbf7c612fff3d289 GIT binary patch literal 130 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4kiW$h6xih%orFLJUv|;Lo_BPZ`im^jnk0f z<9~S`7o{30gR{q0GOiAKWA-4hYhB}lpgDC4*Vz8dQ(Mr;BJJ^k+0ahyO(v5RhgAPj gPm!gnHBuf<3`x6F1!FbpbQwUVy85}Sb4q9e0Q$)%4FCWD literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_health_boost.png b/textures/mcl_potions_effect_health_boost.png new file mode 100644 index 0000000000000000000000000000000000000000..a20ae5ccc0218bc25df4c04dbb33053b77435d68 GIT binary patch literal 115 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4kiW$h6xih%orFLtUO&DLo_BPZ`im^jnk0f zV?7(2l3*7b2eYsJECnZKwa!q1SmsSuYnntXI4^swX`0e{DPu#BWrU{_Lw3u9xBK~W SLm3zt7(8A5T-G@yGywqI86RZ; literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_hero_of_village.png b/textures/mcl_potions_effect_hero_of_village.png new file mode 100644 index 0000000000000000000000000000000000000000..c0462a40fe6b9a9b58010f7001478c90a22b4557 GIT binary patch literal 136 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4kiW$h6xih%orFL{5@S9Lo_BPZ`im^jnlB< zgOs_FpcrpN&yl5#4c-?_9$ah-@S4b$qUggLF{kCew1qS0WucVE8?8BSYMC@|IL;i# o`$MVko0Nx#l!}VoBmsu+k1jUeQvW%Pfq{X+)78&qol`;+0PP|xssI20 literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_invisibility.png b/textures/mcl_potions_effect_invisibility.png index db0afb575cd2e63a78891b20ef736e9207bd51e6..138111efa8cad58784a7771884474763008b425f 100644 GIT binary patch delta 128 zcmV-`0Du2{k^ztydI$ml005AYXf^-<09i>yK~yMHW3aKdCJ8YB@#Lu+h(y>mAe%>6 z1Ew4BX@IcNRHG?CXh4&|Gzdilnvqz!*fk)VjVXxT1~f!%8}J}38Zg5I*(!7m$c{#1 iz}XaNAQC|}kc0phUo`ww;$$HJ0000}UuU0000nNklR diff --git a/textures/mcl_potions_effect_leaping.png b/textures/mcl_potions_effect_leaping.png index 8fbf25ae84585c966112f2dc0e9d693ca6bc461c..3b9d5500eb1242c1dd9c63c1dfedeb967379c643 100644 GIT binary patch delta 99 zcmV-p0G$7Nc90le2m$~A0FaSrHUIzsJxN4CR49>Su(7r#2{8b1;{RzxA}kuv%)_Sv zmkMNY>`uaJJcNtTfZrL!+JMy_qC#mT`2ksq&VC>X0RZP}V7QOipL75K002ovPDHLk FV1f|fCOH5A delta 103 zcmV-t0GR)FdXN}m0RsR403|(bA^-pY22e~?MLat@hj(rX3MNGW001vZL_t&t9b;f% zU?}VZp~^mn#B&UZd<^w`47L9lO5+&H;~47e80!B4m4HYv0{}jU4af_zZx;Xn002ov JPDHLkV1o4qAmRW3 diff --git a/textures/mcl_potions_effect_levitation.png b/textures/mcl_potions_effect_levitation.png new file mode 100644 index 0000000000000000000000000000000000000000..ca8b6db1d039cf29608985d121e8edb0ab23c349 GIT binary patch literal 135 zcmV;20C@k2P)ZC zv9=}&F#z$D&?iJ9>>A*P5v2jm0R%Llsl(KRQv*bh1{z5A1IeL;>|Mg~faZFv0fo?j p>2$R4CEz4XmrzLqv5Ai)1OU+EP$j*Q`J?~<002ovPDHLkV1lu6FYEvS literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_luck.png b/textures/mcl_potions_effect_luck.png new file mode 100644 index 0000000000000000000000000000000000000000..46df46a0393a07323f19dfef67d21ed10bafc992 GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4kiW$h6xih%orFL{5)M8Lo_BPZ`im^jnlB9 zK%aRchb!|To)FO!O%XW?XO?;}>#0Ay+;Desg-vfLbD95R&UhWE0?Ga~PFATCADORJ ns0ysfc(uW6;?y4=P7FO!b2t~VUoB=}U|{fc^>bP0l+XkKb)_lU literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_nausea.png b/textures/mcl_potions_effect_nausea.png new file mode 100644 index 0000000000000000000000000000000000000000..1b291ee4915e3eb0efcddf86bcd662e13b5a0462 GIT binary patch literal 138 zcmV;50CoR~P)ab|Q;|%P?CSV9TE@5$9bPSPL-K{b$s05u7dutSEN`v3p{07*qoM6N<$f~&PI2><{9 literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_night_vision.png b/textures/mcl_potions_effect_night_vision.png index f4263968adfd1266d8fecec29605a9e8b1f8c6c3..e5d7f1a2d08a0ebc4292dc0fba348f87b1671eaa 100644 GIT binary patch delta 130 zcmV-|0Db>(lmUxR{#J207*qoM6N<$g0*HUv;Y7A delta 94 zcmbQjSTI2%f{~elfkD+aSBZgvfi1u%#MQ>yI-@@HQre|2APG+w#}E$Lzopr022Tm1ONa4 diff --git a/textures/mcl_potions_effect_poison.png b/textures/mcl_potions_effect_poison.png index 9d8cd5815c83731773b64e3b01114276f5499f7a..014b4314c565b15891767c2867580e83b1634094 100644 GIT binary patch delta 129 zcmV-{0Dk{_lL3$zdk6vm005AYXf^-<09r{zK~yM_W3aKdCJ8YB@r(`SL?UzzxHQAX zDboOPBBnYt5?uqPh1fN~m14CJi<7X*VRa;m4Vb3l)PU&*G^b(@R;=MmtOiV9;nRTC jR|GWRib}E)A4v!R!+A`HhwP$d00000NkvXXu0mjf5$!Sj delta 105 zcmV-v0G9ug0eg@bV*vvI001RDZ6W{w00vM@R7E^HJ6)Dy$Hy2Y0000mNkl36O7PlrR00000 LNkvXXu0mjfQY|2% diff --git a/textures/mcl_potions_effect_regeneration.png b/textures/mcl_potions_effect_regeneration.png index dfb82bba9553ca3881de5f388c2bc652d3d8ca86..1c5b7d502a96e30ab0a01fec8a80cd2648afd038 100644 GIT binary patch delta 121 zcmV-<0EYjH0g3^T7;*>#0001xk!Usm002=*L_t(2kz=s2wk8QN0Pz)_RYW4nG{7xI zQ-Lgq(17MpG}UlHoEoqqs@gz;2CN~2MFU&{mj>+dfXhkvA`Vjn;h4tsJ>jH*$3JAH bC6W*TV-+YsZ?aRX00000NkvXXu0mjfDh@2^ delta 121 zcmV-<0EYjH0g3^T7;*vw0001Dofq-|000S4OjJcYJ3GTACGCcGMUh|70000yNkl#Pc=gzpKbghRMoNy}O--)`C2 ba;Cu#bLtQ8`}+Gx00000NkvXXu0mjfDPS~-h=wxn@pT0!UJsXsiN7@8s<-JWQ6Lz{tt Ofx*+&&t;ucLK6V=;~`=I literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_saturation.png b/textures/mcl_potions_effect_saturation.png new file mode 100644 index 0000000000000000000000000000000000000000..13bbd41e81d2956f5ca27f716f9b899ba95366ac GIT binary patch literal 134 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4kiW$h6xih%orFLd_7$pLo_BPZ`im^jnk0f z&Lz8`4Y}c{5%WygaywalhOfsSg%B^W{0R53Fi$U~8)4aFJOicgV0e mO*GK6`J2>+idiZw3>*xmeB7p!3>g?07(8A5T-G@yGywo~9w&ML literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_slow_falling.png b/textures/mcl_potions_effect_slow_falling.png new file mode 100644 index 0000000000000000000000000000000000000000..5e82afc91186e0bf3c20048bb6372f68619075d4 GIT binary patch literal 124 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4kiW$h6xih%orFLoIPC}Lp07OZ`im^jnj~! z@X?|FE=nc58M6$}9!g@K(|yw6VnZhXGK*cj0``elnWrCmr()uAfPcpx>s5_hQXDFF clLQ!8BYI~3T=;h(0|Nttr>mdKI;Vst08vUOtpET3 literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_effect_slowness.png b/textures/mcl_potions_effect_slowness.png index 464d270a9ef1f0def41fc1cb6a0d90fdb6587512..eafff9d3578679817dcfe94168d2c927af540b1c 100644 GIT binary patch delta 135 zcmV;20C@j)m;sO&e+U8q005AYXf^-<0AEQ&K~yM_m6A~k03ZlMy_cP^b9B%83z>5k zNLcu0%51oQg$?&L_hXbmlm9|@2LRRENhGr)2(iCcmn p(YTsy5jiKNhLp>NJK4ZuMih$KHFaQ9B7!XDK_4X$K0000jscJub_fCh005AYXf^-<098puK~yMHW3aKdCJ8YB@tIUvA`w0fSjDNQ z0q$Zno%l4Mk@z$qn~iK0J`K2Bg+&9Jc|>Wzv;zopr0KgO<7ytkO diff --git a/textures/mcl_potions_effect_water_breathing.png b/textures/mcl_potions_effect_water_breathing.png index 3ced75eba39a07d8176c66e1fb9f92502290cc75..80a1054f7293ee645b1f05cd502cbd3d2eb3a677 100644 GIT binary patch delta 120 zcmV-;0EhpM0f_;S7;y*!0001xk!Usm002-)L_t(2kz=s2wk8QN0I_DrIU*4j4FtJl zX@HAD7oH3aH+FdIUe}5SgQX30000WI}qOd268@sWf8 X8 Date: Sat, 13 Jan 2024 05:49:02 +0100 Subject: [PATCH 24/91] Improved damage mods in effects, resistance effect --- mods/ITEMS/mcl_potions/functions.lua | 32 ++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 51236c17d..010b6268c 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -60,11 +60,16 @@ local function generate_rational_fac_to_lvl(l1, l2) end local function generate_modifier_func(name, dmg_flag, mod_func) - return function(object, damage, reason) + if dmg_flag ~= "" then 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 + return mod_func and mod_func(damage, EF[name][object]) or 0 end end + else return function(object, damage, reason) + if EF[name][object] and not reason.flags.bypasses_magic then + return mod_func and mod_func(damage, EF[name][object]) or 0 + end + end end end -- API - registers an effect @@ -86,8 +91,8 @@ end -- 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 +-- damage_modifier - string - damage flag of which damage is changed as defined by modifier_func, pass empty string for all damage +-- modifier_func - function(damage, effect_vals) - 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() @@ -371,6 +376,25 @@ mcl_potions.register_effect({ damage_modifier = "is_fire", }) +mcl_potions.register_effect({ + name = "resistance", + description = S("Resistance"), + get_tt = function(factor) + return S("resist @1% of incoming damage", math.floor(factor*100)) + end, + res_condition = function(object) + return (not object:is_player()) + end, + particle_color = "#2552A5", + uses_factor = true, + lvl1_factor = 0.2, + lvl2_factor = 0.4, + damage_modifier = "", + modifier_func = function(damage, effect_vals) + return damage - (effect_vals.factor)*damage + end, +}) + mcl_potions.register_effect({ name = "bad_omen", description = S("Bad Omen"), From fce73ab2bff82e391d2323ddd7120c81807ee765 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 14 Jan 2024 08:46:36 +0100 Subject: [PATCH 25/91] Added some missing effects and improved API * added a way to have a damage modifier relying on type instead of flag * added Slow Falling * added Levitation * added Health Boost * added Absorption --- mods/HUD/hudbars/init.lua | 4 +- mods/ITEMS/mcl_potions/functions.lua | 117 +++++++++++++++++- mods/PLAYER/mcl_hunger/init.lua | 6 +- ....png => mcl_potions_effect_absorption.png} | Bin textures/mcl_potions_icon_absorb.png | Bin 0 -> 128 bytes 5 files changed, 117 insertions(+), 10 deletions(-) rename textures/{mcl_potions_effect_absorbtion.png => mcl_potions_effect_absorption.png} (100%) create mode 100644 textures/mcl_potions_icon_absorb.png diff --git a/mods/HUD/hudbars/init.lua b/mods/HUD/hudbars/init.lua index 505ff403b..7f86a959d 100644 --- a/mods/HUD/hudbars/init.lua +++ b/mods/HUD/hudbars/init.lua @@ -521,7 +521,9 @@ end local function update_health(player) local hp_max = player:get_properties().hp_max - hb.change_hudbar(player, "health", player:get_hp(), hp_max) + local hp = player:get_hp() + if hp > hp_max then hp = hp_max end + hb.change_hudbar(player, "health", hp, hp_max) end -- update built-in HUD bars diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 010b6268c..0486e782d 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -59,14 +59,19 @@ local function generate_rational_fac_to_lvl(l1, l2) end end -local function generate_modifier_func(name, dmg_flag, mod_func) - if dmg_flag ~= "" then return function(object, damage, reason) - if EF[name][object] and not reason.flags.bypasses_magic and reason.flags[dmg_flag] then +local function generate_modifier_func(name, dmg_flag, mod_func, is_type) + if dmg_flag == "" then return function(object, damage, reason) + if EF[name][object] and not reason.flags.bypasses_magic then + return mod_func and mod_func(damage, EF[name][object]) or 0 + end + end + elseif is_type then return function(object, damage, reason) + if EF[name][object] and not reason.flags.bypasses_magic and reason.type == dmg_flag then return mod_func and mod_func(damage, EF[name][object]) or 0 end end else return function(object, damage, reason) - if EF[name][object] and not reason.flags.bypasses_magic then + if EF[name][object] and not reason.flags.bypasses_magic and reason.flags[dmg_flag] then return mod_func and mod_func(damage, EF[name][object]) or 0 end end end @@ -92,6 +97,7 @@ end -- 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, pass empty string for all damage +-- dmg_mod_is_type - bool - damage_modifier string is used as type instead of flag of damage, defaults to false -- modifier_func - function(damage, effect_vals) - 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) @@ -164,7 +170,7 @@ function mcl_potions.register_effect(def) end if def.damage_modifier then mcl_damage.register_modifier( - generate_modifier_func(name, def.damage_modifier, def.modifier_func), + generate_modifier_func(name, def.damage_modifier, def.modifier_func, def.dmg_mod_is_type), def.modifier_priority or -50 ) end @@ -295,6 +301,28 @@ mcl_potions.register_effect({ lvl2_factor = 1, }) +mcl_potions.register_effect({ + name = "slow_falling", + description = S("Slow Falling"), + get_tt = function(factor) + return S("decreases gravity effects") + end, + res_condition = function(object) + return (not object:is_player()) + end, + on_start = function(object, factor) + playerphysics.add_physics_factor(object, "gravity", "mcl_potions:slow_falling", 0.5) + end, + on_step = function(dtime, object, factor, duration) + local vel = object:get_velocity().y + if vel < -3 then object:add_velocity(vector.new(0,-3-vel,0)) end + end, + on_end = function(object) + playerphysics.remove_physics_factor(object, "gravity", "mcl_potions:slow_falling") + end, + particle_color = "#ACCCFF", +}) + mcl_potions.register_effect({ name = "swiftness", description = S("Swiftness"), @@ -337,6 +365,22 @@ mcl_potions.register_effect({ lvl2_factor = 0.3, }) +mcl_potions.register_effect({ + name = "levitation", + description = S("Levitation"), + get_tt = function(factor) + return S("moves you upwards at @1 nodes/s", factor) + end, + on_step = function(dtime, object, factor, duration) + local vel = object:get_velocity().y + if vel damage then + effect_vals.absorb = absorb - damage + else + carryover = damage - absorb + effect_vals.absorb = 0 + end + return carryover + end, +}) + mcl_potions.register_effect({ name = "fire_resistance", description = S("Fire Resistance"), @@ -438,6 +540,8 @@ mcl_potions.register_effect({ -- ██║░░██║╚██████╔╝██████╦╝ -- ╚═╝░░╚═╝░╚═════╝░╚═════╝░ +hb.register_hudbar("absorption", 0xFFFFFF, S("Absorption"), {bar = "[fill:2x16:#B59500", icon = "mcl_potions_icon_absorb.png"}, 0, 0, 0, false) + local icon_ids = {} local function potions_set_hudbar(player) @@ -496,6 +600,7 @@ local function potions_init_icons(player) }) table.insert(icon_ids[name], id) end + hb.init_hudbar(player, "absorption") end local function potions_set_icons(player) diff --git a/mods/PLAYER/mcl_hunger/init.lua b/mods/PLAYER/mcl_hunger/init.lua index 45606cd61..03cd2a0a3 100644 --- a/mods/PLAYER/mcl_hunger/init.lua +++ b/mods/PLAYER/mcl_hunger/init.lua @@ -247,13 +247,13 @@ minetest.register_globalstep(function(dtime) food_tick_timer = 0 -- let hunger work always - if player_health > 0 and player_health <= 20 then + if player_health > 0 then --mcl_hunger.exhaust(player_name, mcl_hunger.EXHAUST_HUNGER) -- later for hunger status effect mcl_hunger.update_exhaustion_hud(player) end if food_level >= 18 then -- slow regeneration - if player_health > 0 and player_health < 20 then + if player_health > 0 and player_health < player:get_properties().hp_max then player:set_hp(player_health+1) mcl_hunger.exhaust(player_name, mcl_hunger.EXHAUST_REGEN) mcl_hunger.update_exhaustion_hud(player) @@ -270,7 +270,7 @@ minetest.register_globalstep(function(dtime) end elseif food_tick_timer > max_tick_timer and food_level == 20 and food_saturation_level > 0 then -- fast regeneration - if player_health > 0 and player_health < 20 then + if player_health > 0 and player_health < player:get_properties().hp_max then food_tick_timer = 0 player:set_hp(player_health+1) mcl_hunger.exhaust(player_name, mcl_hunger.EXHAUST_REGEN) diff --git a/textures/mcl_potions_effect_absorbtion.png b/textures/mcl_potions_effect_absorption.png similarity index 100% rename from textures/mcl_potions_effect_absorbtion.png rename to textures/mcl_potions_effect_absorption.png diff --git a/textures/mcl_potions_icon_absorb.png b/textures/mcl_potions_icon_absorb.png new file mode 100644 index 0000000000000000000000000000000000000000..f1f671f6bee660af7b3a33ea5cc35014de449fc2 GIT binary patch literal 128 zcmeAS@N?(olHy`uVBq!ia0y~yVBiE{4mJh`h6fYb1Q-|?+&x_!LnOkJ6BNY$>_7Bd zzAf?3basgY5(^*nX)+!D5#XE9T5$0DI)Oj47+sn3Tn$lhf4{FYv33Vk=1fq{X+)78&qol`;+06sq|{r~^~ literal 0 HcmV?d00001 From 007500613adddcc5a14ad83c3cb23bbc8247d224 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 14 Jan 2024 10:19:19 +0100 Subject: [PATCH 26/91] Added food poisoning and saturation effects --- mods/ITEMS/mcl_potions/functions.lua | 52 +++++++++++++++++++++++ mods/PLAYER/mcl_hunger/hunger.lua | 13 ++---- mods/PLAYER/mcl_hunger/register_foods.lua | 8 ++-- 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 0486e782d..7ee2fd967 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -525,6 +525,50 @@ mcl_potions.register_effect({ timer_uses_factor = true, }) +mcl_potions.register_effect({ + name = "food_poisoning", + description = S("Food Poisoning"), + get_tt = function(factor) + return S("exhausts by @1 per second", factor) + end, + res_condition = function(object) + return (not object:is_player()) + end, + on_start = function(object, factor) + hb.change_hudbar(object, "hunger", nil, nil, "mcl_hunger_icon_foodpoison.png", nil, "mcl_hunger_bar_foodpoison.png") + if mcl_hunger.debug then + hb.change_hudbar(object, "exhaustion", nil, nil, nil, nil, "mcl_hunger_bar_foodpoison.png") + end + end, + on_step = function(dtime, object, factor, duration) + mcl_hunger.exhaust(object:get_player_name(), dtime*factor) + end, + on_end = function(object) + mcl_hunger.reset_bars_poison_hunger(object) + end, + particle_color = "#83A061", + uses_factor = true, + lvl1_factor = 100, + lvl2_factor = 200, +}) + +mcl_potions.register_effect({ + name = "saturation", + description = S("Saturation"), + get_tt = function(factor) + return S("saturates by @1 per second", factor) + end, + res_condition = function(object) + return (not object:is_player()) + end, + on_step = function(dtime, object, factor, duration) + mcl_hunger.set_hunger(object, math.min(mcl_hunger.get_hunger(object)+dtime*factor, 20)) + mcl_hunger.saturate(object:get_player_name(), dtime*factor) + end, + particle_color = "#CEAE29", + uses_factor = true, +}) + -- ██╗░░░██╗██████╗░██████╗░░█████╗░████████╗███████╗ -- ██║░░░██║██╔══██╗██╔══██╗██╔══██╗╚══██╔══╝██╔════╝ @@ -841,6 +885,14 @@ function mcl_potions.player_get_effect(player, effect_name) return EF[effect_name][player] end +function mcl_potions.player_get_effect_level(player, effect_name) + if not EF[effect_name] then return end + local effect = EF[effect_name][player] + if not effect then return 0 end + if not registered_effects[effect_name].uses_factor then return 1 end + return registered_effects[effect_name].factor_to_level(effect.factor) +end + function mcl_potions.player_clear_effect(player,effect) EF[effect][player] = nil potions_set_hud(player) diff --git a/mods/PLAYER/mcl_hunger/hunger.lua b/mods/PLAYER/mcl_hunger/hunger.lua index de6369359..afca9553b 100644 --- a/mods/PLAYER/mcl_hunger/hunger.lua +++ b/mods/PLAYER/mcl_hunger/hunger.lua @@ -99,7 +99,7 @@ function mcl_hunger.reset_bars_poison_hunger(player) end end --- Poison player +-- Poison player TODO remove this function local function poisonp(tick, time, time_left, damage, exhaustion, name) if not mcl_hunger.active then return @@ -186,15 +186,8 @@ function mcl_hunger.item_eat(hunger_change, replace_with_item, poisontime, poiso do_poison = true end if do_poison then - -- Set food poison bars - if exhaust and exhaust > 0 then - hb.change_hudbar(user, "hunger", nil, nil, "mcl_hunger_icon_foodpoison.png", nil, "mcl_hunger_bar_foodpoison.png") - if mcl_hunger.debug then - hb.change_hudbar(user, "exhaustion", nil, nil, nil, nil, "mcl_hunger_bar_foodpoison.png") - end - mcl_hunger.poison_hunger[name] = mcl_hunger.poison_hunger[name] + 1 - end - poisonp(1, poisontime, 0, poison, exhaust, user:get_player_name()) + local level = mcl_potions.player_get_effect_level(user, "food_poisoning") + mcl_potions.give_effect_by_level("food_poisoning", user, level+exhaust, poisontime) end end diff --git a/mods/PLAYER/mcl_hunger/register_foods.lua b/mods/PLAYER/mcl_hunger/register_foods.lua index a68dde1c1..ee33e9332 100644 --- a/mods/PLAYER/mcl_hunger/register_foods.lua +++ b/mods/PLAYER/mcl_hunger/register_foods.lua @@ -1,7 +1,7 @@ -- Apply food poisoning effect as long there are no real status effect. --- TODO: Remove this when food poisoning a status effect in mcl_potions. +-- TODO: Sanitize this now that Food Poisoning is now an effect in mcl_potions -- Normal poison damage is set to 0 because it's handled elsewhere. -mcl_hunger.register_food("mcl_mobitems:rotten_flesh", 4, "", 30, 0, 100, 80) -mcl_hunger.register_food("mcl_mobitems:chicken", 2, "", 30, 0, 100, 30) -mcl_hunger.register_food("mcl_fishing:pufferfish_raw", 1, "", 15, 0, 300) +mcl_hunger.register_food("mcl_mobitems:rotten_flesh", 4, "", 30, 0, 1, 80) +mcl_hunger.register_food("mcl_mobitems:chicken", 2, "", 30, 0, 1, 30) +mcl_hunger.register_food("mcl_fishing:pufferfish_raw", 1, "", 15, 0, 3) From a8054e8112cc6f34aaf859f5f11f548117201289 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 14 Jan 2024 10:53:33 +0100 Subject: [PATCH 27/91] Add hero of the village effect --- mods/ITEMS/mcl_potions/functions.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 7ee2fd967..f435d55ea 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -500,7 +500,13 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "bad_omen", description = S("Bad Omen"), - particle_color = "#0b6138", + particle_color = "#472331", +}) + +mcl_potions.register_effect({ + name = "hero_of_village", + description = S("Hero of the Village"), + particle_color = "#006D2A", }) mcl_potions.register_effect({ From 3f5cea30464a06e4c3897342fb6b2208e04c7bdb Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 15 Jan 2024 23:48:58 +0100 Subject: [PATCH 28/91] Added HP hudbar look modifier API (for now in mcl_potions) --- mods/ITEMS/mcl_potions/functions.lua | 80 +++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index f435d55ea..2bc9cd8ff 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -592,25 +592,77 @@ mcl_potions.register_effect({ hb.register_hudbar("absorption", 0xFFFFFF, S("Absorption"), {bar = "[fill:2x16:#B59500", icon = "mcl_potions_icon_absorb.png"}, 0, 0, 0, false) -local icon_ids = {} +local hp_hudbar_modifiers = {} + +-- API - registers a HP hudbar modifier +-- required parameters in def: +-- predicate - function(player) - returns true if player fulfills the requirements (eg. has the effects) for the hudbar look +-- icon - string - name of the icon to which the modifier should change the HP hudbar heart +-- priority - signed int - lower gets checked first, and first fulfilled predicate applies its modifier +function mcl_potions.register_hp_hudbar_modifier(def) + if type(def.predicate) ~= "function" then error("Predicate must be a function") end + if not def.icon then error("No icon provided") end + if not def.priority then error("No priority provided") end + table.insert(hp_hudbar_modifiers, { + predicate = def.predicate, + icon = def.icon, + priority = def.priority, + }) + table.sort(hp_hudbar_modifiers, function(a, b) return a.priority <= b.priority end) +end + +mcl_potions.register_hp_hudbar_modifier({ + predicate = function(player) + if EF.withering[player] and EF.regeneration[player] then return true end + end, + icon = "mcl_potions_icon_regen_wither.png", + priority = -30, +}) + +mcl_potions.register_hp_hudbar_modifier({ + predicate = function(player) + if EF.withering[player] then return true end + end, + icon = "mcl_potions_icon_wither.png", + priority = -20, +}) + +mcl_potions.register_hp_hudbar_modifier({ + predicate = function(player) + if EF.poison[player] and EF.regeneration[player] then return true end + end, + icon = "hbhunger_icon_regen_poison.png", + priority = -10, +}) + +mcl_potions.register_hp_hudbar_modifier({ + predicate = function(player) + if EF.poison[player] then return true end + end, + icon = "hbhunger_icon_health_poison.png", + priority = 0, +}) + +mcl_potions.register_hp_hudbar_modifier({ + predicate = function(player) + if EF.regeneration[player] then return true end + end, + icon = "hudbars_icon_regenerate.png", + priority = 10, +}) local function potions_set_hudbar(player) - 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 - hb.change_hudbar(player, "health", nil, nil, "hbhunger_icon_regen_poison.png", nil, "hudbars_bar_health.png") - elseif EF.poison[player] then - hb.change_hudbar(player, "health", nil, nil, "hbhunger_icon_health_poison.png", nil, "hudbars_bar_health.png") - 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") + for _, mod in pairs(hp_hudbar_modifiers) do + if mod.predicate(player) then + hb.change_hudbar(player, "health", nil, nil, mod.icon, nil, "hudbars_bar_health.png") + return + end end - + hb.change_hudbar(player, "health", nil, nil, "hudbars_icon_health.png", nil, "hudbars_bar_health.png") end +local icon_ids = {} + local function potions_init_icons(player) local name = player:get_player_name() icon_ids[name] = {} From 5610fa1c4b4e03962e05f3512c42e0d358cd8266 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Tue, 16 Jan 2024 02:03:39 +0100 Subject: [PATCH 29/91] Added frost effect --- mods/ITEMS/mcl_potions/functions.lua | 61 +++++++++++++++++++++- textures/mcl_potions_effect_frost.png | Bin 0 -> 139 bytes textures/mcl_potions_frost_hud.png | Bin 0 -> 80572 bytes textures/mcl_potions_icon_frost.png | Bin 0 -> 138 bytes textures/mcl_potions_icon_regen_frost.png | Bin 0 -> 151 bytes 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 textures/mcl_potions_effect_frost.png create mode 100644 textures/mcl_potions_frost_hud.png create mode 100644 textures/mcl_potions_icon_frost.png create mode 100644 textures/mcl_potions_icon_regen_frost.png diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 2bc9cd8ff..000720a31 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -531,6 +531,49 @@ mcl_potions.register_effect({ timer_uses_factor = true, }) +mcl_potions.register_effect({ + name = "frost", + description = S("Frost"), + get_tt = function(factor) + return S("-1 HP / 1 s, can kill, -@1% running speed", math.floor(factor*100)) + end, + res_condition = function(object) + return (not object:is_player()) + end, + on_start = function(object, factor) + mcl_burning.extinguish(object) + playerphysics.add_physics_factor(object, "speed", "mcl_potions:frost", 1-factor) + EF.frost[object].vignette = object:hud_add({ + hud_elem_type = "image", + position = {x = 0.5, y = 0.5}, + scale = {x = -101, y = -101}, + text = "mcl_potions_frost_hud.png", + z_index = -400 + }) + 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, + on_end = function(object) + playerphysics.remove_physics_factor(object, "speed", "mcl_potions:frost") + if not EF.frost[object] then return end + object:hud_remove(EF.frost[object].vignette) + end, + particle_color = "#5B7DAA", + uses_factor = true, + lvl1_factor = 0.1, + lvl2_factor = 0.2, + timer_uses_factor = false, + hit_timer_step = 1, + damage_modifier = "is_fire", + modifier_func = function(damage, effect_vals) + effect_vals.timer = effect_vals.dur + return 0 + end, +}) + mcl_potions.register_effect({ name = "food_poisoning", description = S("Food Poisoning"), @@ -643,12 +686,28 @@ mcl_potions.register_hp_hudbar_modifier({ priority = 0, }) +mcl_potions.register_hp_hudbar_modifier({ + predicate = function(player) + if EF.frost[player] and EF.regeneration[player] then return true end + end, + icon = "mcl_potions_icon_regen_frost.png", + priority = 10, +}) + +mcl_potions.register_hp_hudbar_modifier({ + predicate = function(player) + if EF.frost[player] then return true end + end, + icon = "mcl_potions_icon_frost.png", + priority = 20, +}) + mcl_potions.register_hp_hudbar_modifier({ predicate = function(player) if EF.regeneration[player] then return true end end, icon = "hudbars_icon_regenerate.png", - priority = 10, + priority = 30, }) local function potions_set_hudbar(player) diff --git a/textures/mcl_potions_effect_frost.png b/textures/mcl_potions_effect_frost.png new file mode 100644 index 0000000000000000000000000000000000000000..6a008d25cf4ecc63114d2324974d04674468dbb0 GIT binary patch literal 139 zcmV;60CfL}P)rAor>KLnA))T tfgBr1^8-1dL}omY5YyzOC1N#@gaBjvcE*H!tjPcX002ovPDHLkV1fb+FS7su literal 0 HcmV?d00001 diff --git a/textures/mcl_potions_frost_hud.png b/textures/mcl_potions_frost_hud.png new file mode 100644 index 0000000000000000000000000000000000000000..282c713f13f3fc04de22d246b15e168bee66851b GIT binary patch literal 80572 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 FV1jSdHCq4x literal 0 HcmV?d00001 From 31adc45da9f2b3eaab476fe715a0a6c3d15000b3 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 17 Jan 2024 01:38:24 +0100 Subject: [PATCH 30/91] Added blindness effect (also improved TT descriptions of some effects) --- mods/ITEMS/mcl_potions/functions.lua | 37 +++++++++++++++++++++++-- textures/mcl_potions_blindness_hud.png | Bin 0 -> 9583 bytes 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 textures/mcl_potions_blindness_hud.png diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 000720a31..802fdac6e 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -369,7 +369,7 @@ mcl_potions.register_effect({ name = "levitation", description = S("Levitation"), get_tt = function(factor) - return S("moves you upwards at @1 nodes/s", factor) + return S("moves body upwards at @1 nodes/s", factor) end, on_step = function(dtime, object, factor, duration) local vel = object:get_velocity().y @@ -410,7 +410,7 @@ mcl_potions.register_effect({ name = "health_boost", description = S("Health Boost"), get_tt = function(factor) - return S("increases HP by @1", factor) + return S("HP increased by @1", factor) end, res_condition = function(object) return (not object:is_player()) @@ -574,6 +574,39 @@ mcl_potions.register_effect({ end, }) +mcl_potions.register_effect({ + name = "blindness", + description = "Blindness", + get_tt = function(factor) + return S("impaired sight") + end, + res_condition = function(object) + return (not object:is_player()) + end, + on_start = function(object, factor) + EF.blindness[object].vignette = object:hud_add({ + hud_elem_type = "image", + position = {x = 0.5, y = 0.5}, + scale = {x = -101, y = -101}, + text = "mcl_potions_blindness_hud.png", + z_index = -401 + }) + mcl_fovapi.apply_modifier(object, "mcl_potions:blindness") + end, + on_end = function(object) + mcl_fovapi.remove_modifier(object, "mcl_potions:blindness") + if not EF.blindness[object] then return end + object:hud_remove(EF.blindness[object].vignette) + end, + particle_color = "#686868", + uses_factor = false, +}) +mcl_fovapi.register_modifier({ + name = "mcl_potions:blindness", + fov_factor = 0.6, + time = 1, +}) + mcl_potions.register_effect({ name = "food_poisoning", description = S("Food Poisoning"), diff --git a/textures/mcl_potions_blindness_hud.png b/textures/mcl_potions_blindness_hud.png new file mode 100644 index 0000000000000000000000000000000000000000..ac5be885bd278d4735867db39694bbc3480d2975 GIT binary patch literal 9583 zcmWmKi9Zwmf`>DE5}McC~4%_+(&X$O0J==a%H3< zhPizt%O^svIm*rC8g~31zklHM4?JHfb~YA50x|*s0HG_EW`6+y0RR9pf)@aA#1DpVmR@G$Dm$MFj_lioMMa zPEJ4m=`e^M8f-Os2wEY``XCxtm~IO=thI$!z|07uarf6YJpkumZFAZ-qZMPsSyCpj zHi&>3uWzjr!XED85x|@M@_^-ig8(N*e+VLwX&Ibtg(ghFc--CkrAU>%l{O<1Ih?mx zl7f%^pwf{?I{d!%B0s1*YGDht=Wm-4sty{OXK39`Vy1Y7X2#zH?J}dVcPble&ju~9 zweZAC(^Ai3>Tnm)_}xb&?Cf68Ef^96E^U&U**1bnxn1QAp`PU)jwknQ#5dvsl(trv3&(H|j1PysujNo*NJp6O)Wa09 zX|1AE>VJHafOVDJDn?!pTX&PzdA)HsKlo~sHhme=%L+%E-cGE=-QD;vN#Wkx^-I=rGByo(Em(ZOV-n5sOdK+@#37X+q+pR)6Yge z%}@B<>~X=yX>8wXC#o+@!xYWrTW#Gj|G^|t>Oj>#T5=BO)uthse+Md2T%$5ex49T0 zHPmwAo)MDg<^fHxRrEk1{Gs_FZq5Tb10~u%-otz4Pa^nBSS@*PzPyK2sU~Oh>)9*! zy2RS=%4Unwx+y2r6_Napj-1q-3wkW14m>SX5~q+v6na}DEmUQuBl|Be^G#Qm%u)fv zK}5cTr{Cf$4OG`Q?Qg1P7xpAV1LXoxGF(4SRoOv0g`QL@&?E|NP^A07e}AAK<<`ea zqPq6gIeeSDt`#++!M9UXa}s#GAyk8s#&GjZ9mz~zSbjug=iJ_Lt7O$fdFk!^*6HHM zQPq;r^K&~^qbn)SG~)48_IRiKlsxQ{FYAPD>thr#8-{Ne6gM4xl0#7Oq!N`YnU#p- zs&Gq*U1D-9AR`ye1dqn-Wfb-p#!)||Va|Q)Pkx`;tRYS85WGpFEwdc=$tz=O=A=6i z;nIyxX60p!=x|WVx27DbEDyN0bwP_0*u7+!veSfOH}(qZpSnD3oe=N5-vmF&?H_w$mMT<_Mr7J6`hQbSwN=9;FO>R;`}VtW=m zChv2(ssps#nCE**`aSJ&wSc}NA3@)YxbMEi^tykI!OB@A{1}R; zbWmQ7?b~ub#dQIUoiuK$iu1e1vD@TH#=7C3Pm}(0wo>NrD2DcoJ!-EbzozWguWe{q z3)g=FllG0i_MT^47TtPvWUW{2&+hSRJoXqghbApvaaw3hpS;W@o4dsR$K&9gVFU>~4GbGAn|6|6OzTL+X}5G)p~7Ihi%F z>PK%U7F(1|BL*_yfP9zLjGc6S71$}6&u{EjcHmsbjpX(zqMTMp=UM0C)^*6$Flqoy znm)|b^J3btFqfDIP+}gMpkm@a)YB@PYE-%ByaQbOTjNBKUR_s=AbA%`>ycTs0`ALl zjz4QJkrGSh<6Y@wTm8zQa4au!Ss^z7x=fcv*7qVtnqx$J2$Srjc_5|~+?*84g()r`?GJojM4@EpB z$50k)ja=uqFZ*!dBuEH^JC(Meo)a$V2`ZBgVdm}P+QIr#U}Ab}gCV|cWcM5Yo%wKa zra(AZvtzO?;>deH#q&~`{Evj9AzA++@=Hjkf6=PZFm;*hOq|GcnibUr1bYmgecfwF zp)~uCOkQTv9YibkaG_Ac;{Aa{MMtmEVm-mjGuSv1H^ZOH7e?Y9<;5am)w?rXh{_xz z%vsPdHb|G6(eGCjLpsjbg?d^_R&IRz%vLKm$?gmJk#yM*@;<#)y+?#`Lh)6b1zoe~ z?*5Hq;57LX!cZCs)}{7v_deeESviFNNU!T4EB3pj=y(@3-XK2VL`Rq1Y3W-mC~pO% zg@q4L+%jA7CxDvDAG@K62#(}G$&dg=vQv+Ao{W}@C8z!HlJj3DeV^?4k7)A*GcGvq z4@^w9FS@{$IPfi_GMiu%li|$@yc(2g=c&sHfl!U&F*tv+T0c8_dOEoIl7|qOOi}#z z9QI4D8}lBXi=U6Kmc|Q&AhTND%#GZyIU7B)-A&>zqC9 zHqzD;v&J|rUI{H4U;gp|d}Qn8vFen94nrwXD&5rvoXpO>!F|_n_Kt+UZ!~8S9(Oc2 zw&NDM=F2{`TAD8Ad-!lGLRGZ3(cy#g^!Wx;DM-1NSD>z9-o^qE`)OK4%7wVR`q+%> zCDVF~Zvjg5Fl9Ry4+J1ujo3K0wd#ruVy2AgMvT>g_RGn=x!qECduf4%|b-Ix>wi25&gFBhajZu)&M$RH16Z&p3QbS$_Hl&rYd>;J+I1q zFXiG5{}S_*%FCpz(R%&^8ZSY0!`%x6UaL`qY7Y~LG=#nf8s;tpWGG5`li&D;@(CxZ z%Ab2WiUjk;`wb^Mo{1TZ`h-3A_n-39V5~$0|1ZvmYUAr(O2eof%Dwr6kpwK}#>&9= zruUOQeM?PKY zu8g6oL9lW4r9J4uu1{QtlhBP6$)Z~k+1bf{d`?o&G=m*px8|a_y37tEL#-c$(jhR| zbt_t5q{JF+F08_%|5xpQ(k#x4(j8*u??Pf_?;l@|DriI=9H~&CYd#yy{8ve!K(G^gn1U_kR3<9ygzRo)5IML;>gvCf4IYD!7Jj}w0`q_ahrV|P ziC<22-fQQte@MUj59GUAgjYZ2Y~Ww5pzUAaoBv0ecAd=H2cVk_|A--khOW-41aO7T?7Npipj`uEla^g|xnmIws4FzHI2giy8qENg$YLU`Z% z=$$WduU1*%ulANN!mXFX_@)(Cr8$XVUtgwjA(PAF@ywT{tM8dp<%7;kmmYG?y@#T` z^`*c~G49RR&TM8?n2Ky|^K0EZ4UIMvUoSPxbvgKwR?2Sx=yeIjv_tJV1*tTG^b{!^ zk9Gc25HG6Q>=@($~&JJpy#3N?lHKPI^*0)NuI5HpcKLV45)8& zuAjJB3SIBhxReCZKh+zk86(`xt6s@-TaSacUuoi-9a4}TE8q_niWDaHtvIJffK~+J z%Iz9ytTC(df2@gh?D_d;r&tn$XIE4m#-O~%4gZu%;$g8Gofq|*`IH!r_qUy!qa|r| z(=-_9h7t|f&RUNwTINHNJoFvjjgZBE>E|WoB#$x-EaKMxgdn4zhxJg5iju1Mdv6 zM>)Mva11!@u6~}x4>PD=#T|Z&HdtTrSX+Fv7t(B4bhxEg|9PiI}@ z!7n%^lTvxQa%s;X>Ge!=`bi2a+r=Y1qUgm4Ml6WHyGpmB&g>gyIn@CAQd2-WtM z2dplgw{JDwnDnMO_hn8it>fXwx_38TUpPoEtZSGO5;~R<4I`6|A9n#nj3m&SYkHcL z;lDL`$DnDmDer{mh%RMeF!+oS-#lE`W|cO?v5)7yp1YygUER_F1)Vx8ub-S3hU0RL z=h?2m>HZ;EhApdZ@t9Cm?>mV}cw~sSw_jd<%-k;~{tmc;Srq-U;}`mY`Mn z3mdS8=a&sBhl9{x^0BeF@TeSfviPHg&>dH_ss4sI@5CwCC}M3Ru?D~McTbU;5pUq$ zELrAPsPo1~=YUNg?F{2W*S@{<<`u!{=rv21b|~=_Pmy5OT9y4Nv+So$C5v@;^OQif zvLufZMZ?M)H>H1sdm37FODNS^otLqlFBhosa8I_kYL8ImB9&@h`@a@Zei zJbSN8!=d*cYK?weaBdBa6*K=~?Y(|7F1P||NQsW`8;Duht5P1|Rn^KYop1=i=)f&Z zJ#S5W`2zvOlsk`|gZmDDLy5;(igQZV@R48phh$|Oq>smNn=M}3Tyco8)TK(W)90He z-W+FY2zr{j3yM3!4ZdK1n$_c<$>}$mo_pJ>ZS`P~dlLbBkUfbK;J7wuZ2jPa6q`~= zlOZiVP%!_UsLc~K6+|wJP@&iGZ{E{s7jh(uNBw|;0dQ2L0L{#j_V%G<&nl>_;gcEj z4_^@twZQKudSMp`J?DqHdAh1`WcRuqa&n^i3UVwPAurFiQ8n6&_j=M7lINVmh(m zOn9_9ZxNb!t>^XM5x%UXQ|rE;*`^>{R{Q8<2}?WlR>@^ z7&5uyKxXq(m10sk=hdGL>4z%hweRPVKp)&ZZ|Bz_K_;Mb70S7(9E%aT#}F10UxGGHvVvkpz*p!;Y5p`E4C= zC-#meZ`;&&66n3+R;}y@`a0@zCbUN5ZVUC#)n&#-@p|)DqE$6>Z5AUB3RAtu{2Lsn*-ijKEN;&BnFQ5*>xBW(hCb z)jAw%*PJAZR-v=Id+1y_Eu=kOP*sNCtz4u3(W#8)EYZ0Y2!xJarJI)JINTw9>!5tlY&g&YwY3u%z7QNSGknE5Ea>vg_yeOa&<_&4mKzvZl6_!aO4wDgdRdc7j!J$aB^uG#Q$x%N{#cd*m9@QfU3UW~XV{YDOmzQTpTS6{`$uJT?a< zQj1QTx1t|J=-j%OJL4L7m<>#jLJ9A<9qNC2*#Q`xxGtxRoWK>NH%Z8A_RI+E*CR0}+z z#H)fNbj7tjJ)KKIv(Y!QARpo-D6&X>l-{ygfTwO*lGprOg=nGNem-A=*-bZCGxwy{#>|<}dA%MoK z&*r|muG40nEv&a#qI4WcG&^l_)}CNJb4m)2?92P@Qu!rrlA~isPM6Ur*8B`PNYM%T z7ig~e;seu((Yg6WSy9FTJT9=a_XcC4rD3zFdyBn{_|A{rPzzB%x&YRkFU>1b11H`aIb0oJa>%WKORx2LoRVh zTzqs6{ef2z)6kUCH?|u_AH3lX=xS*dkp>`63kxNbrVtjn;^$ zz>68!Z>Cz^_(hD>0p`s}B0?hiCE!ANrw&B8Cw|C5^J^us%J2=tBU3sbk+s*1X)<e|Y06(XdMo~4;J2Z%E*1qrYz z?*7Mxy90CDsy^)Yv#c-p2dLz!{GonqjZwuBsR|6d4% zx{wGB3@tpu^ZMYhtV?SCB6KErm-R&2Q`vz4+wje>%)+P?2g1^fg&G}xeXQOzs9+mo z+nQhg=@YphEe$1&s{~KH;hhyJKVY@h}SWoj`c}486ntzh{`)|o7A9xJH z(wB_JmIJyZk2-R%_e%N{PP|f__c@jSlgL-?tTjOPf>0Ogi2f^qXZ>JDKN2`&XDH}y znro!UkvWnHkA53|wCT&);kzPXUD)A7C0}Y)!{T+8{PnB<4f7RZkVp`%jv`0>T# zk4pyb`4W)N&*hmdeHo=ZdC6=gqSDqnn#XQI?al|W(9p>{o6X1c4PH|wA;-}A8h{z2 z4j}JH35`l0fHYL;@s?aiQ2Z3GgnkDRktK~75+I68n;j6xNo0pzzGaC=A|-GKzC@>C zg5ER6UsGHOh-Y#dF?CX|4R!2yM&tf_O_S0Xb098s&y9QP78^&~VnwD7kz}E&lBi)Z zpRbsXb3bWTT23x8xhHzJ|KBVY5}?<`Y<))M?oD$pc96O@$If4W6|`$8*hn~bcGD;Y z5oR-zPfsv@_0l=PL;yHwW&GVZQ6S1xD3srv;F=Q$2N*r^-qZ-cs$;({@Ilfb zL4lYw{nnH)j~MLnS+CR$*B73=FzG3bH}q|}*v%zghw(>_-_!Git9I4&`-w54l7JP7 zq9))_MahdTC0il=3PQ}I$JC0_9-*?QCAivsn78YRnk5jj98=%~KFwAuG0AH?@MZCh z_B1$XJt?ijI~?8ggC&l zxOLJESxt;LgxcI`jDzb5Op(gjrqa<)KanN7%A0?%H_`eyh)oGcAweD6iAuEFDrn1p z?U~tk!{XUvVTicRWK0vvM;$aMAcJSQ4`U82+~Na(Ds;{wMk$~FD+%6K$LPNm`S!ev zQ2PU+u{#3y`5wC$$Wm3g9jq1?5Uj8v!jPQwlV+l{xHswFla(q*NxwF)+p)8qsHrid z+E$XL7#Ol_h}DFSS9?UX7k3zwj*OO=fnkxUVu6bEj9uj`i}-6I$8rh46J>tn9g0cZfVC;Oo% z-bgx6OJ5RDT69r&;2pik6+H#~OQkF$$)i*>Wl#MyJM}h`vCE@3qH z-pe0`Qwm7nK60o-7Fx`nbbU)&W_;m|#7a|ievG?8pIU?Jiw;#AKX~-dbc9emP6^z{ z2~_z0F9Wa1!3#i6w-=v=-Ex;>9I#$HO;=@09fu_oA@R!@v2AKymsXBFK*pVxi}8ZC}71CJYG!P3TXyZoCNdMQv!Q%JTa4l5OnZF_u#Tbx?3NuNgZUmE#cXT(#jy67Wc z1L${kV*I2-=i6?yF|@8TQxzA}q4q-9D&#j;so&x#$KU&MFu|eB!OvXk(uDoezdeSJ zICwbt-R#)3Q6+Y6UM{*Ld1rD~0h_^eY61@bZYa&N`g3^yK#m2bWtIw$7Je%;Q`p>@qhW0#ex$KJkZdRA*NUNQd08FEBysQr3~*G6uM0K1pIG;9fk=wJ2xaI`o%!tnsK%bh z6Q?aH7_-|m-R$*Swhx7%%I{Vo$=k7}()F*IO~Vn_(b_sUPw+NYeyIWUW@GG=o%>Xt zH_3d;%2ZyW!554zW7l&x(_vAa7Uu+(9IqwQCn7D#T0jsa)hJ(8fR^Upb&oVSH>CZ7~2hU`){jV zHs#^C8z)`Se0NI@3Hlnb$C($}<;^VVHXt_?_G6xB-agtzCPN7M6{efLfm3ceUEIa< z@&1$`_D3zCA3@|ZzQh-#G*^61>f#3IWGch76GhSUiVN~(&XVu1wq;boybB4}IdDMg z=Cxtuf-czTB}_dZ_1&C8;vVhZLJ)tkW`fSvH*GGWOOf z?yEZS{FdsIA^~7y1jbeL@52AT`uzhWb5#DyMRGed>3mru*ZT-;?7pp|^nBU6|9h0$ znP_UBMt@(-%l1}4e+g-`ROPBq7$-+-sP%TXc^^z5#H;&x9A0-+=EXUB**P%8*e$o% za8Qp#K9?e$qLgp~qq*l6IoV!{1H4{IXnnb;vAY@b9JK)t5PVISF3ghx>)L{%fWgZR z4M^xLyZ4I-vyP`a0LJ-C?Xwh!WY2{+ZJcs38KQSco19?x#AES#00}v*6fYp;;8H6{ zfKb0cV+8ny%slabY){C!?63xic8>0=!s|JAd46ohrE~d=a&@nM=2^)6|DWp0WgD|< I6VKTH18Lj>g8%>k literal 0 HcmV?d00001 From 92a77a7dbbc640422c9cfb9ac2f8ce8c86e4f403 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 20 Jan 2024 00:01:06 +0100 Subject: [PATCH 31/91] Fixed graphical features of some effects * loading fixed (by adding on_load) * absorption bar never reaching end fixed --- mods/ITEMS/mcl_potions/functions.lua | 30 +++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 802fdac6e..a1a193fda 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -437,9 +437,12 @@ mcl_potions.register_effect({ return (not object:is_player()) end, on_start = function(object, factor) - hb.change_hudbar(object, "absorption", factor, math.floor(factor/20+1)*20) + hb.change_hudbar(object, "absorption", factor, (math.floor(factor/20-0.05)+1)*20) EF.absorption[object].absorb = factor end, + on_load = function(object, factor) + minetest.after(0, function() hb.change_hudbar(object, "absorption", nil, (math.floor(factor/20-0.05)+1)*20) end) + end, on_step = function(dtime, object, factor, duration) hb.change_hudbar(object, "absorption", EF.absorption[object].absorb) end, @@ -551,6 +554,15 @@ mcl_potions.register_effect({ z_index = -400 }) end, + on_load = function(object, factor) + EF.frost[object].vignette = object:hud_add({ + hud_elem_type = "image", + position = {x = 0.5, y = 0.5}, + scale = {x = -101, y = -101}, + text = "mcl_potions_frost_hud.png", + z_index = -400 + }) + 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"}) @@ -593,6 +605,16 @@ mcl_potions.register_effect({ }) mcl_fovapi.apply_modifier(object, "mcl_potions:blindness") end, + on_load = function(object, factor) + EF.blindness[object].vignette = object:hud_add({ + hud_elem_type = "image", + position = {x = 0.5, y = 0.5}, + scale = {x = -101, y = -101}, + text = "mcl_potions_blindness_hud.png", + z_index = -401 + }) + mcl_fovapi.apply_modifier(object, "mcl_potions:blindness") + end, on_end = function(object) mcl_fovapi.remove_modifier(object, "mcl_potions:blindness") if not EF.blindness[object] then return end @@ -622,6 +644,12 @@ mcl_potions.register_effect({ hb.change_hudbar(object, "exhaustion", nil, nil, nil, nil, "mcl_hunger_bar_foodpoison.png") end end, + on_load = function(object, factor) -- TODO refactor and add hunger bar modifier API + hb.change_hudbar(object, "hunger", nil, nil, "mcl_hunger_icon_foodpoison.png", nil, "mcl_hunger_bar_foodpoison.png") + if mcl_hunger.debug then + hb.change_hudbar(object, "exhaustion", nil, nil, nil, nil, "mcl_hunger_bar_foodpoison.png") + end + end, on_step = function(dtime, object, factor, duration) mcl_hunger.exhaust(object:get_player_name(), dtime*factor) end, From aa4ff1827d01a2466998ceba9da3249135e6b88a Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 22 Jan 2024 02:13:08 +0100 Subject: [PATCH 32/91] Added nausea --- mods/ITEMS/mcl_potions/functions.lua | 48 ++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index a1a193fda..afbbc2128 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -629,6 +629,54 @@ mcl_fovapi.register_modifier({ time = 1, }) +mcl_potions.register_effect({ + name = "nausea", + description = S("Nausea"), + get_tt = function(factor) + return S("not feeling very well...") + end, + res_condition = function(object) + return (not object:is_player()) + end, + on_start = function(object, factor) + object:set_lighting({ + saturation = -1.0, + }) + end, + on_hit_timer = function(object, factor, duration) + if EF.nausea[object].high then + mcl_fovapi.remove_modifier(object, "mcl_potions:nausea_high") + mcl_fovapi.apply_modifier(object, "mcl_potions:nausea_low") + EF.nausea[object].high = false + else + mcl_fovapi.apply_modifier(object, "mcl_potions:nausea_high") + mcl_fovapi.remove_modifier(object, "mcl_potions:nausea_low") + EF.nausea[object].high = true + end + end, + on_end = function(object) + object:set_lighting({ + saturation = 1.0, + }) + mcl_fovapi.remove_modifier(object, "mcl_potions:nausea_high") + mcl_fovapi.remove_modifier(object, "mcl_potions:nausea_low") + end, + particle_color = "#60AA30", + uses_factor = false, + timer_uses_factor = false, + hit_timer_step = 1, +}) +mcl_fovapi.register_modifier({ + name = "mcl_potions:nausea_high", + fov_factor = 2.2, + time = 1, +}) +mcl_fovapi.register_modifier({ + name = "mcl_potions:nausea_low", + fov_factor = 0.2, + time = 1, +}) + mcl_potions.register_effect({ name = "food_poisoning", description = S("Food Poisoning"), From 65b923c43ce98efe6b3aa82f13943cad66b508c4 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 22 Jan 2024 04:45:19 +0100 Subject: [PATCH 33/91] Added darkness --- mods/ENVIRONMENT/mcl_weather/skycolor.lua | 27 +++++++------ mods/ITEMS/mcl_potions/functions.lua | 46 +++++++++++++++++++++++ 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/mods/ENVIRONMENT/mcl_weather/skycolor.lua b/mods/ENVIRONMENT/mcl_weather/skycolor.lua index 6d9efd47a..edadbbeb8 100644 --- a/mods/ENVIRONMENT/mcl_weather/skycolor.lua +++ b/mods/ENVIRONMENT/mcl_weather/skycolor.lua @@ -120,20 +120,25 @@ mcl_weather.skycolor = { override_day_night_ratio = function(player, ratio) local meta = player:get_meta() local has_night_vision = meta:get_int("night_vision") == 1 + local has_darkness = meta:get_int("darkness") == 1 local is_visited_shepherd = meta:get_int("mcl_shepherd:special") == 1 local arg - -- Apply night vision only for dark sky - local is_dark = minetest.get_timeofday() > 0.8 or minetest.get_timeofday() < 0.2 or mcl_weather.state ~= "none" - local pos = player:get_pos() - local dim = mcl_worlds.pos_to_dimension(pos) - if (has_night_vision or is_visited_shepherd) and is_dark and dim ~= "nether" and dim ~= "end" then - if ratio == nil then - arg = NIGHT_VISION_RATIO - else - arg = math.max(ratio, NIGHT_VISION_RATIO) - end + if has_darkness and not is_visited_shepherd then + arg = 0 else - arg = ratio + -- Apply night vision only for dark sky + local is_dark = minetest.get_timeofday() > 0.8 or minetest.get_timeofday() < 0.2 or mcl_weather.state ~= "none" + local pos = player:get_pos() + local dim = mcl_worlds.pos_to_dimension(pos) + if (has_night_vision or is_visited_shepherd) and is_dark and dim ~= "nether" and dim ~= "end" then + if ratio == nil then + arg = NIGHT_VISION_RATIO + else + arg = math.max(ratio, NIGHT_VISION_RATIO) + end + else + arg = ratio + end end player:override_day_night_ratio(arg) end, diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index afbbc2128..6a1d14a5f 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -406,6 +406,52 @@ mcl_potions.register_effect({ uses_factor = false, }) +mcl_potions.register_effect({ + name = "darkness", + description = S("Darkness"), + get_tt = function(factor) + return S("surrounded by darkness") + end, + res_condition = function(object) + return (not object:is_player()) + end, + on_start = function(object, factor) + object:get_meta():set_int("darkness", 1) + mcl_weather.skycolor.update_sky_color({object}) + object:set_sky({fog = { + fog_distance = 10, + }}) + EF.darkness[object].flash = 0.6 + end, + on_step = function(dtime, object, factor, duration) + if object:get_meta():get_int("night_vision") ~= 1 then + local flash = EF.darkness[object].flash + if flash < 0.1 then EF.darkness[object].flashdir = true + elseif flash > 0.6 then EF.darkness[object].flashdir = false end + flash = EF.darkness[object].flashdir and (flash + dtime) or (flash - dtime) + object:set_sky({fog = { + fog_start = flash, + }}) + EF.darkness[object].flash = flash + else + object:set_sky({fog = { + fog_start = 0.99, + }}) + end + mcl_weather.skycolor.update_sky_color({object}) + end, + on_end = function(object) + object:get_meta():set_int("darkness", 0) + mcl_weather.skycolor.update_sky_color({object}) + object:set_sky({fog = { + fog_distance = -1, + fog_start = -1, + }}) + end, + particle_color = "#000000", + uses_factor = false, +}) + mcl_potions.register_effect({ name = "health_boost", description = S("Health Boost"), From 394b090c8398df017b58e837c30a86a4f485db76 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 22 Jan 2024 21:49:26 +0100 Subject: [PATCH 34/91] Improved the darkness effect --- mods/ENVIRONMENT/mcl_weather/skycolor.lua | 3 ++- mods/ITEMS/mcl_potions/functions.lua | 14 ++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/mods/ENVIRONMENT/mcl_weather/skycolor.lua b/mods/ENVIRONMENT/mcl_weather/skycolor.lua index edadbbeb8..87952845b 100644 --- a/mods/ENVIRONMENT/mcl_weather/skycolor.lua +++ b/mods/ENVIRONMENT/mcl_weather/skycolor.lua @@ -124,7 +124,8 @@ mcl_weather.skycolor = { local is_visited_shepherd = meta:get_int("mcl_shepherd:special") == 1 local arg if has_darkness and not is_visited_shepherd then - arg = 0 + if has_night_vision then arg = 0.1 + else arg = 0 end else -- Apply night vision only for dark sky local is_dark = minetest.get_timeofday() > 0.8 or minetest.get_timeofday() < 0.2 or mcl_weather.state ~= "none" diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 6a1d14a5f..55fa79c45 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -259,7 +259,7 @@ mcl_potions.register_effect({ res_condition = function(object) return (not object:is_player()) end, - particle_color = "#484D48", + particle_color = "#485D48", }) mcl_potions.register_effect({ @@ -419,14 +419,14 @@ mcl_potions.register_effect({ object:get_meta():set_int("darkness", 1) mcl_weather.skycolor.update_sky_color({object}) object:set_sky({fog = { - fog_distance = 10, + fog_distance = factor, }}) EF.darkness[object].flash = 0.6 end, on_step = function(dtime, object, factor, duration) if object:get_meta():get_int("night_vision") ~= 1 then local flash = EF.darkness[object].flash - if flash < 0.1 then EF.darkness[object].flashdir = true + if flash < 0.2 then EF.darkness[object].flashdir = true elseif flash > 0.6 then EF.darkness[object].flashdir = false end flash = EF.darkness[object].flashdir and (flash + dtime) or (flash - dtime) object:set_sky({fog = { @@ -435,7 +435,7 @@ mcl_potions.register_effect({ EF.darkness[object].flash = flash else object:set_sky({fog = { - fog_start = 0.99, + fog_start = 0.9, }}) end mcl_weather.skycolor.update_sky_color({object}) @@ -449,7 +449,9 @@ mcl_potions.register_effect({ }}) end, particle_color = "#000000", - uses_factor = false, + uses_factor = true, + lvl1_factor = 30, + lvl2_factor = 20, }) mcl_potions.register_effect({ @@ -573,7 +575,7 @@ mcl_potions.register_effect({ mcl_util.deal_damage(object, 1, {type = "magic"}) end end, - particle_color = "#000000", + particle_color = "#292929", uses_factor = true, lvl1_factor = 2, lvl2_factor = 1, From b6484a6d153d6865e31f1054451efa3329f60b73 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 22 Jan 2024 22:02:05 +0100 Subject: [PATCH 35/91] Added time_override to FOV API time_override can be used when applying or removing modifiers --- mods/PLAYER/mcl_fovapi/init.lua | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/mods/PLAYER/mcl_fovapi/init.lua b/mods/PLAYER/mcl_fovapi/init.lua index 92815d833..43dcfe403 100644 --- a/mods/PLAYER/mcl_fovapi/init.lua +++ b/mods/PLAYER/mcl_fovapi/init.lua @@ -75,7 +75,7 @@ minetest.register_on_respawnplayer(function(player) mcl_fovapi.remove_all_modifiers(player) end) -function mcl_fovapi.apply_modifier(player, modifier_name) +function mcl_fovapi.apply_modifier(player, modifier_name, time_override) if not player or not modifier_name then return end @@ -106,13 +106,14 @@ function mcl_fovapi.apply_modifier(player, modifier_name) minetest.log("FOV::Modifier applied to player:" .. player_name .. " modifier: " .. modifier_name) end + local time = time_override or modifier.time -- modifier apply code. if modifier.exclusive == true then -- if exclusive, reset the player's fov, and apply the new fov. if modifier.is_multiplier then player:set_fov(0, false, 0) end - player:set_fov(modifier.fov_factor, modifier.is_multiplier, modifier.time) + player:set_fov(modifier.fov_factor, modifier.is_multiplier, time) else -- not exclusive? let's apply it in the mix. local fov_factor, is_mult = player:get_fov() @@ -126,15 +127,15 @@ function mcl_fovapi.apply_modifier(player, modifier_name) fov_factor = (fov_factor + modifier.fov_factor) / 2 end if modifier.is_multiplier and is_mult then - player:set_fov(fov_factor, true, modifier.time) + player:set_fov(fov_factor, true, time) else - player:set_fov(fov_factor, false, modifier.time) + player:set_fov(fov_factor, false, time) end end end -function mcl_fovapi.remove_modifier(player, modifier_name) +function mcl_fovapi.remove_modifier(player, modifier_name, time_override) if not player or not modifier_name then return end @@ -159,9 +160,10 @@ function mcl_fovapi.remove_modifier(player, modifier_name) applied[k] = mcl_fovapi.registered_modifiers[k] end + local time = time_override or modifier.reset_time local elem = next if elem(applied) == nil then - player:set_fov(0, false, modifier.reset_time) + player:set_fov(0, false, time) return end local exc = false @@ -191,7 +193,7 @@ function mcl_fovapi.remove_modifier(player, modifier_name) fov_factor = fov_factor * x.fov_factor end end - player:set_fov(fov_factor, not non_multiplier_added, modifier.reset_time) + player:set_fov(fov_factor, not non_multiplier_added, time) end if mcl_fovapi.registered_modifiers[modifier_name].on_end then From e0396424467c2e393bc3060b7fa6ca289e1941d0 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 22 Jan 2024 22:06:39 +0100 Subject: [PATCH 36/91] Improved nausea --- mods/ITEMS/mcl_potions/functions.lua | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 55fa79c45..27d07cff5 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -693,12 +693,12 @@ mcl_potions.register_effect({ end, on_hit_timer = function(object, factor, duration) if EF.nausea[object].high then - mcl_fovapi.remove_modifier(object, "mcl_potions:nausea_high") - mcl_fovapi.apply_modifier(object, "mcl_potions:nausea_low") + mcl_fovapi.remove_modifier(object, "mcl_potions:nausea_high", factor) + mcl_fovapi.apply_modifier(object, "mcl_potions:nausea_low", factor) EF.nausea[object].high = false else - mcl_fovapi.apply_modifier(object, "mcl_potions:nausea_high") - mcl_fovapi.remove_modifier(object, "mcl_potions:nausea_low") + mcl_fovapi.apply_modifier(object, "mcl_potions:nausea_high", factor) + mcl_fovapi.remove_modifier(object, "mcl_potions:nausea_low", factor) EF.nausea[object].high = true end end, @@ -710,9 +710,10 @@ mcl_potions.register_effect({ mcl_fovapi.remove_modifier(object, "mcl_potions:nausea_low") end, particle_color = "#60AA30", - uses_factor = false, - timer_uses_factor = false, - hit_timer_step = 1, + uses_factor = true, + lvl1_factor = 2, + lvl2_factor = 1, + timer_uses_factor = true, }) mcl_fovapi.register_modifier({ name = "mcl_potions:nausea_high", From 03c73b7820c12a6e55325b33568766e191a5acd5 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 22 Jan 2024 22:12:13 +0100 Subject: [PATCH 37/91] Improved descriptions --- mods/ITEMS/mcl_potions/functions.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 27d07cff5..b2d44432b 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -410,7 +410,7 @@ mcl_potions.register_effect({ name = "darkness", description = S("Darkness"), get_tt = function(factor) - return S("surrounded by darkness") + return S("surrounded by darkness\nnot seeing anything beyond @1 nodes", factor) end, res_condition = function(object) return (not object:is_player()) @@ -681,7 +681,7 @@ mcl_potions.register_effect({ name = "nausea", description = S("Nausea"), get_tt = function(factor) - return S("not feeling very well...") + return S("not feeling very well...\nfrequency: @1 / 1 s", factor) end, res_condition = function(object) return (not object:is_player()) From 0e339472585064bacd7851ad7be1a031af6640b7 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Tue, 23 Jan 2024 01:18:07 +0100 Subject: [PATCH 38/91] Renamed some functions and variables * changed names referring to player where it does support mobs * also added an is_player() check in one function --- mods/ENVIRONMENT/mcl_raids/init.lua | 8 ++++---- mods/ITEMS/mcl_campfires/api.lua | 2 +- mods/ITEMS/mcl_nether/init.lua | 2 +- mods/ITEMS/mcl_potions/functions.lua | 23 ++++++++++++----------- mods/PLAYER/mcl_hunger/hunger.lua | 2 +- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/mods/ENVIRONMENT/mcl_raids/init.lua b/mods/ENVIRONMENT/mcl_raids/init.lua index 8e7c644ae..208ee93e0 100644 --- a/mods/ENVIRONMENT/mcl_raids/init.lua +++ b/mods/ENVIRONMENT/mcl_raids/init.lua @@ -104,7 +104,7 @@ function mcl_raids.promote_to_raidcaptain(c) -- object mcl_raids.drop_obanner(pos) if cmi_cause and cmi_cause.type == "punch" and cmi_cause.puncher:is_player() then awards.unlock(cmi_cause.puncher:get_player_name(), "mcl:voluntary_exile") - local lv = mcl_potions.player_get_effect(cmi_cause.puncher, "bad_omen") + local lv = mcl_potions.get_effect(cmi_cause.puncher, "bad_omen") if not lv then lv = 0 else lv = lv.factor end lv = math.max(5,lv + 1) @@ -296,7 +296,7 @@ mcl_events.register_event("raid",{ --minetest.log("Cond start raid") local r = {} for _,p in pairs(minetest.get_connected_players()) do - if mcl_potions.player_has_effect(p,"bad_omen") then + if mcl_potions.has_effect(p,"bad_omen") then local raid_pos = mcl_raids.find_village(p:get_pos()) if raid_pos then --minetest.log("We have a raid position. Start raid") @@ -310,7 +310,7 @@ mcl_events.register_event("raid",{ self.mobs = {} self.health_max = 1 self.health = 0 - local lv = mcl_potions.player_get_effect(minetest.get_player_by_name(self.player), "bad_omen") + local lv = mcl_potions.get_effect(minetest.get_player_by_name(self.player), "bad_omen") if lv and lv.factor and lv.factor > 1 then self.max_stage = 6 end end, cond_progress = function(self) @@ -331,7 +331,7 @@ mcl_events.register_event("raid",{ end, on_complete = function(self) awards.unlock(self.player,"mcl:hero_of_the_village") - mcl_potions.player_clear_effect(minetest.get_player_by_name(self.player),"bad_omen") + mcl_potions.clear_effect(minetest.get_player_by_name(self.player),"bad_omen") make_firework(self.pos,os.time()) end, }) diff --git a/mods/ITEMS/mcl_campfires/api.lua b/mods/ITEMS/mcl_campfires/api.lua index 7fa495edb..ba6a55960 100644 --- a/mods/ITEMS/mcl_campfires/api.lua +++ b/mods/ITEMS/mcl_campfires/api.lua @@ -380,7 +380,7 @@ minetest.register_globalstep(function(dtime) etime = 0 for _,pl in pairs(minetest.get_connected_players()) do local armor_feet = pl:get_inventory():get_stack("armor", 5) - if pl and pl:get_player_control().sneak or (minetest.global_exists("mcl_enchanting") and mcl_enchanting.has_enchantment(armor_feet, "frost_walker")) or (minetest.global_exists("mcl_potions") and mcl_potions.player_has_effect(pl, "fire_proof")) then + if pl and pl:get_player_control().sneak or (minetest.global_exists("mcl_enchanting") and mcl_enchanting.has_enchantment(armor_feet, "frost_walker")) or (minetest.global_exists("mcl_potions") and mcl_potions.has_effect(pl, "fire_proof")) then return end burn_in_campfire(pl) diff --git a/mods/ITEMS/mcl_nether/init.lua b/mods/ITEMS/mcl_nether/init.lua index 252768df5..3a57ae427 100644 --- a/mods/ITEMS/mcl_nether/init.lua +++ b/mods/ITEMS/mcl_nether/init.lua @@ -135,7 +135,7 @@ minetest.register_node("mcl_nether:magma", { -- From walkover mod on_walk_over = function(loc, nodeiamon, player) local armor_feet = player:get_inventory():get_stack("armor", 5) - if player and player:get_player_control().sneak or (minetest.global_exists("mcl_enchanting") and mcl_enchanting.has_enchantment(armor_feet, "frost_walker")) or (minetest.global_exists("mcl_potions") and mcl_potions.player_has_effect(player, "fire_proof")) then + if player and player:get_player_control().sneak or (minetest.global_exists("mcl_enchanting") and mcl_enchanting.has_enchantment(armor_feet, "frost_walker")) or (minetest.global_exists("mcl_potions") and mcl_potions.has_effect(player, "fire_proof")) then return end -- Hurt players standing on top of this block diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index b2d44432b..796e82ebe 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -1145,32 +1145,33 @@ function mcl_potions._load_player_effects(player) end end --- Returns true if player has given effect -function mcl_potions.player_has_effect(player, effect_name) +-- Returns true if object has given effect +function mcl_potions.has_effect(object, effect_name) if not EF[effect_name] then return false end - return EF[effect_name][player] ~= nil + return EF[effect_name][object] ~= nil end -function mcl_potions.player_get_effect(player, effect_name) - if not EF[effect_name] or not EF[effect_name][player] then +function mcl_potions.get_effect(object, effect_name) + if not EF[effect_name] or not EF[effect_name][object] then return false end - return EF[effect_name][player] + return EF[effect_name][object] end -function mcl_potions.player_get_effect_level(player, effect_name) +function mcl_potions.get_effect_level(object, effect_name) if not EF[effect_name] then return end - local effect = EF[effect_name][player] + local effect = EF[effect_name][object] if not effect then return 0 end if not registered_effects[effect_name].uses_factor then return 1 end return registered_effects[effect_name].factor_to_level(effect.factor) end -function mcl_potions.player_clear_effect(player,effect) - EF[effect][player] = nil - potions_set_hud(player) +function mcl_potions.clear_effect(object, effect) + EF[effect][object] = nil + if not object:is_player() then return end + potions_set_hud(object) end minetest.register_on_leaveplayer( function(player) diff --git a/mods/PLAYER/mcl_hunger/hunger.lua b/mods/PLAYER/mcl_hunger/hunger.lua index afca9553b..c0ba9fb91 100644 --- a/mods/PLAYER/mcl_hunger/hunger.lua +++ b/mods/PLAYER/mcl_hunger/hunger.lua @@ -186,7 +186,7 @@ function mcl_hunger.item_eat(hunger_change, replace_with_item, poisontime, poiso do_poison = true end if do_poison then - local level = mcl_potions.player_get_effect_level(user, "food_poisoning") + local level = mcl_potions.get_effect_level(user, "food_poisoning") mcl_potions.give_effect_by_level("food_poisoning", user, level+exhaust, poisontime) end end From 456d205161eb99bba331d0b57da997571386ffb5 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 24 Jan 2024 00:28:24 +0100 Subject: [PATCH 39/91] Added strength and weakness effects * also highest effect level displayed in HUD set to 3000 * also improved indicating effects with strange factors in HUD --- mods/ENTITIES/mcl_mobs/combat.lua | 7 ++++++ mods/ITEMS/mcl_potions/functions.lua | 34 +++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/combat.lua b/mods/ENTITIES/mcl_mobs/combat.lua index 4bbfcd119..f6ee2f429 100644 --- a/mods/ENTITIES/mcl_mobs/combat.lua +++ b/mods/ENTITIES/mcl_mobs/combat.lua @@ -605,6 +605,13 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir) * tmp * ((armor[group] or 0) / 100.0) end + -- strength and weakness effects + local strength = mcl_potions.get_effect(hitter, "strength") + local weakness = mcl_potions.get_effect(hitter, "weakness") + local str_fac = strength and strength.factor or 1 + local weak_fac = weakness and weakness.factor or 1 + damage = damage * str_fac * weak_fac + if weapon then local fire_aspect_level = mcl_enchanting.get_enchantment(weapon, "fire_aspect") if fire_aspect_level > 0 then diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 796e82ebe..72252c910 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -54,7 +54,7 @@ local function generate_rational_fac_to_lvl(l1, l2) local a = (l1 - l2) * 2 local b = 2*l2 - l1 return function(factor) - if factor == 0 then return math.huge end + if (factor - b) == 0 then return math.huge end return math.round(a/(factor - b)) end end @@ -247,21 +247,41 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "strength", description = S("Strength"), - res_condition = function(object) - return (not object:is_player()) + get_tt = function(factor) + return S("+@1% melee damage", factor-1) end, particle_color = "#932423", + uses_factor = true, + lvl1_factor = 1.3, + lvl2_factor = 1.6, }) mcl_potions.register_effect({ name = "weakness", description = S("Weakness"), - res_condition = function(object) - return (not object:is_player()) + get_tt = function(factor) + return S("-@1% melee damage", 1-factor) end, particle_color = "#485D48", + uses_factor = true, + lvl1_factor = 0.8, + lvl2_factor = 0.6, }) +-- implementation of strength and weakness effects +-- mobs have this implemented in mcl_mobs/combat.lua in mob_class:on_punch() +mcl_damage.register_modifier(function(object, damage, reason) + if reason.direct and reason.direct == reason.source then + local hitter = reason.direct + local strength = EF.strength[hitter] + local weakness = EF.weakness[hitter] + if not strength and not weakness then return end + local str_fac = strength and strength.factor or 1 + local weak_fac = weakness and weakness.factor or 1 + return damage * str_fac * weak_fac + end +end, 0) + mcl_potions.register_effect({ name = "water_breathing", description = S("Water Breathing"), @@ -944,7 +964,9 @@ local function potions_set_icons(player) player:hud_change(icon, "text", def.icon .. "^[resize:128x128") if def.uses_factor then local level = def.factor_to_level(vals.factor) - if level == math.huge then level = "∞" + if level > 3000 or level == math.huge then level = "∞" + elseif level < 0 then level = "???" + elseif level == 0 then level = "0" else level = mcl_util.to_roman(level) end player:hud_change(label, "text", level) else From bf82241e82fe912fac215aec6bacbf5541944b1d Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 24 Jan 2024 02:37:24 +0100 Subject: [PATCH 40/91] Added dolphin's grace --- mods/ITEMS/mcl_potions/functions.lua | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 72252c910..cdcb04f1b 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -299,6 +299,27 @@ mcl_potions.register_effect({ uses_factor = false, }) +mcl_potions.register_effect({ + name = "dolphin_grace", + description = S("Dolphin's Grace"), + get_tt = function(factor) + return S("swimming gracefully") + end, + on_hit_timer = function(object, factor, duration) + local node = minetest.get_node_or_nil(object:get_pos()) + if node and minetest.registered_nodes[node.name] + and minetest.get_item_group(node.name, "liquid") ~= 0 then + playerphysics.add_physics_factor(object, "speed", "mcl_potions:dolphin", 2) + else + playerphysics.remove_physics_factor(object, "speed", "mcl_potions:dolphin", 2) + end + end, + particle_color = "#6AABFD", + uses_factor = false, + timer_uses_factor = false, + hit_timer_step = 1, +}) + mcl_potions.register_effect({ name = "leaping", description = S("Leaping"), From 1ac81e440c8fa4ef18c5a5f3493d046262fff595 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 24 Jan 2024 05:16:13 +0100 Subject: [PATCH 41/91] Added haste and fatigue --- mods/ITEMS/mcl_potions/functions.lua | 57 ++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index cdcb04f1b..c17478e7c 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -817,6 +817,63 @@ mcl_potions.register_effect({ uses_factor = true, }) +mcl_potions.register_effect({ + name = "haste", + description = S("Haste"), + res_condition = function(object) + return (not object:is_player()) + end, + particle_color = "#FFFF00", + uses_factor = true, + lvl1_factor = 0.2, + lvl2_factor = 0.4, +}) + +mcl_potions.register_effect({ + name = "fatigue", + description = S("Fatigue"), + res_condition = function(object) + return (not object:is_player()) + end, + particle_color = "#64643D", + uses_factor = true, + lvl1_factor = 0.3, + lvl2_factor = 0.09, +}) + +-- implementation of haste and fatigue effects for digging +minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing) + local item = puncher:get_wielded_item() + local meta = item:get_meta() + local haste = EF.haste[puncher] + local fatigue = EF.fatigue[puncher] + local item_haste = meta:get_float("mcl_potions:haste") + local item_fatig = 1 - meta:get_float("mcl_potions:fatigue") + local h_fac + if haste then h_fac = haste.factor + else h_fac = 0 end + local f_fac + if fatigue then f_fac = fatigue.factor + else f_fac = 1 end + if f_fac < 0 then f_fac = 0 end + if item_haste ~= h_fac or item_fatig ~= f_fac then + meta:set_float("mcl_potions:haste", h_fac) + meta:set_float("mcl_potions:fatigue", 1 - f_fac) + meta:set_tool_capabilities() + local toolcaps = item:get_tool_capabilities() +-- if not toolcaps or not toolcaps.groupcaps then return end + for name, group in pairs(toolcaps.groupcaps) do + local t = group.times + for i=1, #t do + t[i] = t[i] / (1+h_fac) / f_fac + end + end + -- TODO attack speed change? + meta:set_tool_capabilities(toolcaps) + puncher:set_wielded_item(item) + end +end) + -- ██╗░░░██╗██████╗░██████╗░░█████╗░████████╗███████╗ -- ██║░░░██║██╔══██╗██╔══██╗██╔══██╗╚══██╔══╝██╔════╝ From 0c4094596e39a72a93c66814df72474aa93a7673 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 3 Feb 2024 05:37:55 +0100 Subject: [PATCH 42/91] Improved haste and fatigue effects * fixed a few crashes related to unusual effect levels * added haste and fatigue combat functionality * added some cleanup to avoid hangover unstackable items * capped the slowdown from fatigue at 5 minutes digging time * (despite the above, if a tool has a longer time set in definition, that still works) * removed an unused "global" variable --- mods/ENTITIES/mcl_mobs/combat.lua | 2 + mods/ITEMS/mcl_potions/functions.lua | 62 +++++++++++++++++++++++----- mods/ITEMS/mcl_potions/potions.lua | 1 - 3 files changed, 53 insertions(+), 12 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/combat.lua b/mods/ENTITIES/mcl_mobs/combat.lua index f6ee2f429..99878be2e 100644 --- a/mods/ENTITIES/mcl_mobs/combat.lua +++ b/mods/ENTITIES/mcl_mobs/combat.lua @@ -534,6 +534,8 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir) if self.protected and minetest.is_protected(mob_pos, hitter:get_player_name()) then return end + + mcl_potions.update_haste_and_fatigue(hitter) end local time_now = minetest.get_us_time() diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index c17478e7c..df0608d87 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -841,38 +841,61 @@ mcl_potions.register_effect({ lvl2_factor = 0.09, }) --- implementation of haste and fatigue effects for digging -minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing) - local item = puncher:get_wielded_item() +-- implementation of haste and fatigue effects +local LONGEST_MINING_TIME = 300 +function mcl_potions.update_haste_and_fatigue(player) + local item = player:get_wielded_item() local meta = item:get_meta() - local haste = EF.haste[puncher] - local fatigue = EF.fatigue[puncher] + local haste = EF.haste[player] + local fatigue = EF.fatigue[player] local item_haste = meta:get_float("mcl_potions:haste") local item_fatig = 1 - meta:get_float("mcl_potions:fatigue") local h_fac if haste then h_fac = haste.factor else h_fac = 0 end + if h_fac < 0 then h_fac = 0 end local f_fac if fatigue then f_fac = fatigue.factor else f_fac = 1 end if f_fac < 0 then f_fac = 0 end if item_haste ~= h_fac or item_fatig ~= f_fac then - meta:set_float("mcl_potions:haste", h_fac) - meta:set_float("mcl_potions:fatigue", 1 - f_fac) + if h_fac ~= 0 then meta:set_float("mcl_potions:haste", h_fac) + else meta:set_string("mcl_potions:haste", "") end + if f_fac ~= 1 then meta:set_float("mcl_potions:fatigue", 1 - f_fac) + else meta:set_string("mcl_potions:fatigue", "") end meta:set_tool_capabilities() + mcl_enchanting.update_groupcaps(item) + if h_fac == 0 and f_fac == 1 then + player:set_wielded_item(item) + return + end local toolcaps = item:get_tool_capabilities() --- if not toolcaps or not toolcaps.groupcaps then return end + toolcaps.full_punch_interval = toolcaps.full_punch_interval / (1+h_fac) / f_fac for name, group in pairs(toolcaps.groupcaps) do local t = group.times for i=1, #t do - t[i] = t[i] / (1+h_fac) / f_fac + if f_fac == 0 then + t[i] = t[i] > LONGEST_MINING_TIME and t[i] or LONGEST_MINING_TIME + else + local old_time = t[i] + t[i] = t[i] / (1+h_fac) / f_fac + if old_time < LONGEST_MINING_TIME and t[i] > LONGEST_MINING_TIME then + t[i] = LONGEST_MINING_TIME + end + end end end - -- TODO attack speed change? meta:set_tool_capabilities(toolcaps) - puncher:set_wielded_item(item) + player:set_wielded_item(item) end +end +minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing) + mcl_potions.update_haste_and_fatigue(puncher) end) +minetest.register_on_punchplayer(function(player, hitter) + mcl_potions.update_haste_and_fatigue(hitter) +end) +-- update when hitting mob implemented in mcl_mobs/combat.lua -- ██╗░░░██╗██████╗░██████╗░░█████╗░████████╗███████╗ @@ -1131,6 +1154,22 @@ end) -- ███████╗╚█████╔╝██║░░██║██████╔╝██╔╝░░░██████╔╝██║░░██║░░╚██╔╝░░███████╗ -- ╚══════╝░╚════╝░╚═╝░░╚═╝╚═════╝░╚═╝░░░░╚═════╝░╚═╝░░╚═╝░░░╚═╝░░░╚══════╝ +function mcl_potions._reset_haste_fatigue_item_meta(player) + local inv = player:get_inventory() + if not inv then return end + local lists = inv:get_lists() + for _, list in pairs(lists) do + for _, item in pairs(list) do + local meta = item:get_meta() + meta:set_string("mcl_potions:haste", "") + meta:set_string("mcl_potions:fatigue", "") + meta:set_tool_capabilities() + mcl_enchanting.update_groupcaps(item) + end + end + inv:set_lists(lists) +end + function mcl_potions._clear_cached_player_data(player) for name, effect in pairs(EF) do effect[player] = nil @@ -1288,6 +1327,7 @@ end) minetest.register_on_joinplayer( function(player) mcl_potions._reset_player_effects(player, false) -- make sure there are no weird holdover effects mcl_potions._load_player_effects(player) + mcl_potions._reset_haste_fatigue_item_meta(player) potions_init_icons(player) potions_set_hud(player) end) diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 5f941b2fb..0422bfb90 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -213,7 +213,6 @@ function mcl_potions.register_potion(def) local has_plus = false if def._effect_list then for name, details in pairs(def._effect_list) do - no_effects = false effect = mcl_potions.registered_effects[name] if effect then local ulvl From 6d7fe9104711e99fba914d6cb97dcb21bd303c57 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Tue, 19 Mar 2024 01:25:38 +0100 Subject: [PATCH 43/91] Capped fatigue effect on punching This fixes a crash, too Also updates toolcaps on gamemode change --- mods/ITEMS/mcl_potions/functions.lua | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index df0608d87..7fbf3a6d5 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -843,7 +843,9 @@ mcl_potions.register_effect({ -- implementation of haste and fatigue effects local LONGEST_MINING_TIME = 300 +local LONGEST_PUNCH_INTERVAL = 10 function mcl_potions.update_haste_and_fatigue(player) + if mcl_gamemode.get_gamemode(player) == "creative" then return end local item = player:get_wielded_item() local meta = item:get_meta() local haste = EF.haste[player] @@ -870,7 +872,12 @@ function mcl_potions.update_haste_and_fatigue(player) return end local toolcaps = item:get_tool_capabilities() - toolcaps.full_punch_interval = toolcaps.full_punch_interval / (1+h_fac) / f_fac + if f_fac == 0 then + local fpi = toolcaps.full_punch_interval + toolcaps.full_punch_interval = fpi > LONGEST_PUNCH_INTERVAL and fpi or LONGEST_PUNCH_INTERVAL + else + toolcaps.full_punch_interval = toolcaps.full_punch_interval / (1+h_fac) / f_fac + end for name, group in pairs(toolcaps.groupcaps) do local t = group.times for i=1, #t do @@ -1169,6 +1176,7 @@ function mcl_potions._reset_haste_fatigue_item_meta(player) end inv:set_lists(lists) end +mcl_gamemode.register_on_gamemode_change(mcl_potions._reset_haste_fatigue_item_meta) function mcl_potions._clear_cached_player_data(player) for name, effect in pairs(EF) do From ddbc7cd8266292939809460247628c17e4b77d58 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 20 Mar 2024 01:47:00 +0100 Subject: [PATCH 44/91] Haste and fatigue expanded and improved * abstracted and refactored some parts of haste and fatigue * added and exposed new mcl_potions API functions * fixed haste and fatigue not altering the hand * mcl_meshhand now calls into mcl_potions when resetting the hand --- mods/ITEMS/mcl_potions/functions.lua | 136 ++++++++++++++++++++------- mods/PLAYER/mcl_meshhand/init.lua | 7 +- 2 files changed, 108 insertions(+), 35 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 7fbf3a6d5..3fbf6663c 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -4,6 +4,9 @@ local EF = {} mcl_potions.registered_effects = {} local registered_effects = mcl_potions.registered_effects -- shorthand ref +-- effects affecting item speed utilize numerous hacks, so they have to be counted separately +local item_speed_effects = {} + local EFFECT_TYPES = 0 minetest.register_on_mods_loaded(function() for _,_ in pairs(EF) do @@ -90,6 +93,7 @@ end -- 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 +-- after_end - function(object) - called when the effect wears off, after purging the data of the effect -- 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 @@ -100,6 +104,14 @@ end -- dmg_mod_is_type - bool - damage_modifier string is used as type instead of flag of damage, defaults to false -- modifier_func - function(damage, effect_vals) - see damage_modifier, if not defined damage_modifier defaults to 100% resistance -- modifier_priority - integer - priority passed when registering damage_modifier - defaults to -50 +-- affects_item_speed - table +-- -- if provided, effect gets added to the item_speed_effects table, this should be true if the effect affects item speeds, +-- -- otherwise it won't work properly with other such effects (like haste and fatigue) +-- -- -- factor_is_positive - bool - whether values of factor between 0 and 1 should be considered +factor% or speed multiplier +-- -- -- - obviously +factor% is positive and speed multiplier is negative interpretation +-- -- -- - values of factor higher than 1 will have a positive effect regardless +-- -- -- - values of factor lower than 0 will have a negative effect regardless +-- -- -- - open an issue on our tracker if you have a usage that isn't supported by this API function mcl_potions.register_effect(def) local modname = minetest.get_current_modname() local name = def.name @@ -176,6 +188,7 @@ function mcl_potions.register_effect(def) end registered_effects[name] = pdef EF[name] = {} + item_speed_effects[name] = def.affects_item_speed end mcl_potions.register_effect({ @@ -817,16 +830,68 @@ mcl_potions.register_effect({ uses_factor = true, }) +-- constants relevant for effects altering mining and attack speed +local LONGEST_MINING_TIME = 300 +local LONGEST_PUNCH_INTERVAL = 10 +mcl_potions.LONGEST_MINING_TIME = LONGEST_MINING_TIME +mcl_potions.LONGEST_PUNCH_INTERVAL = LONGEST_PUNCH_INTERVAL + +function mcl_potions.apply_haste_fatigue(toolcaps, h_fac, f_fac) + if f_fac == 0 then + local fpi = toolcaps.full_punch_interval + toolcaps.full_punch_interval = fpi > LONGEST_PUNCH_INTERVAL and fpi or LONGEST_PUNCH_INTERVAL + else + toolcaps.full_punch_interval = toolcaps.full_punch_interval / (1+h_fac) / f_fac + end + for name, group in pairs(toolcaps.groupcaps) do + local t = group.times + for i=1, #t do + if f_fac == 0 then + t[i] = t[i] > LONGEST_MINING_TIME and t[i] or LONGEST_MINING_TIME + else + local old_time = t[i] + t[i] = t[i] / (1+h_fac) / f_fac + if old_time < LONGEST_MINING_TIME and t[i] > LONGEST_MINING_TIME then + t[i] = LONGEST_MINING_TIME + end + end + end + end + return toolcaps +end + +function mcl_potions.hf_update_internal(hand, object) + local meta = hand:get_meta() + local h_fac = mcl_potions.get_total_haste(object) + local f_fac = mcl_potions.get_total_fatigue(object) + local toolcaps = hand:get_tool_capabilities() + meta:set_tool_capabilities(mcl_potions.apply_haste_fatigue(toolcaps, h_fac, f_fac)) + return hand +end + +local function haste_fatigue_hand_update(object) + local inventory = object:get_inventory() + if not inventory or inventory:get_size("hand") < 1 then return end + local hand = inventory:get_stack("hand", 1) + inventory:set_stack("hand", 1, mcl_potions.hf_update_internal(hand, object)) +end + mcl_potions.register_effect({ name = "haste", description = S("Haste"), res_condition = function(object) return (not object:is_player()) end, + on_start = haste_fatigue_hand_update, + after_end = function(object) + haste_fatigue_hand_update(object) + mcl_potions._reset_haste_fatigue_item_meta(object) + end, particle_color = "#FFFF00", uses_factor = true, lvl1_factor = 0.2, lvl2_factor = 0.4, + affects_item_speed = {factor_is_positive = true}, }) mcl_potions.register_effect({ @@ -835,31 +900,27 @@ mcl_potions.register_effect({ res_condition = function(object) return (not object:is_player()) end, + on_start = haste_fatigue_hand_update, + after_end = function(object) + haste_fatigue_hand_update(object) + mcl_potions._reset_haste_fatigue_item_meta(object) + end, particle_color = "#64643D", uses_factor = true, lvl1_factor = 0.3, lvl2_factor = 0.09, + affects_item_speed = {}, }) -- implementation of haste and fatigue effects -local LONGEST_MINING_TIME = 300 -local LONGEST_PUNCH_INTERVAL = 10 function mcl_potions.update_haste_and_fatigue(player) if mcl_gamemode.get_gamemode(player) == "creative" then return end local item = player:get_wielded_item() local meta = item:get_meta() - local haste = EF.haste[player] - local fatigue = EF.fatigue[player] local item_haste = meta:get_float("mcl_potions:haste") local item_fatig = 1 - meta:get_float("mcl_potions:fatigue") - local h_fac - if haste then h_fac = haste.factor - else h_fac = 0 end - if h_fac < 0 then h_fac = 0 end - local f_fac - if fatigue then f_fac = fatigue.factor - else f_fac = 1 end - if f_fac < 0 then f_fac = 0 end + local h_fac = mcl_potions.get_total_haste(player) + local f_fac = mcl_potions.get_total_fatigue(player) if item_haste ~= h_fac or item_fatig ~= f_fac then if h_fac ~= 0 then meta:set_float("mcl_potions:haste", h_fac) else meta:set_string("mcl_potions:haste", "") end @@ -872,39 +933,22 @@ function mcl_potions.update_haste_and_fatigue(player) return end local toolcaps = item:get_tool_capabilities() - if f_fac == 0 then - local fpi = toolcaps.full_punch_interval - toolcaps.full_punch_interval = fpi > LONGEST_PUNCH_INTERVAL and fpi or LONGEST_PUNCH_INTERVAL - else - toolcaps.full_punch_interval = toolcaps.full_punch_interval / (1+h_fac) / f_fac - end - for name, group in pairs(toolcaps.groupcaps) do - local t = group.times - for i=1, #t do - if f_fac == 0 then - t[i] = t[i] > LONGEST_MINING_TIME and t[i] or LONGEST_MINING_TIME - else - local old_time = t[i] - t[i] = t[i] / (1+h_fac) / f_fac - if old_time < LONGEST_MINING_TIME and t[i] > LONGEST_MINING_TIME then - t[i] = LONGEST_MINING_TIME - end - end - end - end - meta:set_tool_capabilities(toolcaps) + meta:set_tool_capabilities(mcl_potions.apply_haste_fatigue(toolcaps, h_fac, f_fac)) player:set_wielded_item(item) end + haste_fatigue_hand_update(player, h_fac, f_fac) end minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing) mcl_potions.update_haste_and_fatigue(puncher) end) minetest.register_on_punchplayer(function(player, hitter) + if not hitter:is_player() then return end -- TODO implement haste and fatigue support for mobs? mcl_potions.update_haste_and_fatigue(hitter) end) -- update when hitting mob implemented in mcl_mobs/combat.lua + -- ██╗░░░██╗██████╗░██████╗░░█████╗░████████╗███████╗ -- ██║░░░██║██╔══██╗██╔══██╗██╔══██╗╚══██╔══╝██╔════╝ -- ██║░░░██║██████╔╝██║░░██║███████║░░░██║░░░█████╗░░ @@ -1132,6 +1176,7 @@ minetest.register_globalstep(function(dtime) if not EF[name][object] or EF[name][object].timer >= vals.dur then if effect.on_end then effect.on_end(object) end EF[name][object] = nil + if effect.after_end then effect.after_end(object) end if object:is_player() then meta = object:get_meta() meta:set_string("mcl_potions:"..name, minetest.serialize(EF[name][object])) @@ -1315,6 +1360,31 @@ function mcl_potions.get_effect_level(object, effect_name) return registered_effects[effect_name].factor_to_level(effect.factor) end +function mcl_potions.get_total_haste(object) + local accum_factor = 1 + for name, def in pairs(item_speed_effects) do + if EF[name][object] then + local factor = EF[name][object].factor + if def.factor_is_positive then factor = factor + 1 end + if factor > 1 then accum_factor = accum_factor * factor end + end + end + return accum_factor - 1 +end + +function mcl_potions.get_total_fatigue(object) + local accum_factor = 1 + for name, def in pairs(item_speed_effects) do + if EF[name][object] then + local factor = EF[name][object].factor + if def.factor_is_positive then factor = factor + 1 end + if factor <= 0 then return 0 end + if factor < 1 then accum_factor = accum_factor * factor end + end + end + return accum_factor +end + function mcl_potions.clear_effect(object, effect) EF[effect][object] = nil if not object:is_player() then return end diff --git a/mods/PLAYER/mcl_meshhand/init.lua b/mods/PLAYER/mcl_meshhand/init.lua index c42ff8081..44eb3e2b9 100644 --- a/mods/PLAYER/mcl_meshhand/init.lua +++ b/mods/PLAYER/mcl_meshhand/init.lua @@ -76,13 +76,16 @@ else end function mcl_meshhand.update_player(player) + local hand if mcl_skins_enabled then local node_id = mcl_skins.get_node_id_by_player(player) - player:get_inventory():set_stack("hand", 1, "mcl_meshhand:" .. node_id) + hand = ItemStack("mcl_meshhand:" .. node_id) else local creative = minetest.is_creative_enabled(player:get_player_name()) - player:get_inventory():set_stack("hand", 1, "mcl_meshhand:hand" .. (creative and "_crea" or "_surv")) + hand = ItemStack("mcl_meshhand:hand" .. (creative and "_crea" or "_surv")) end + if not mcl_potions then player:get_inventory():set_stack("hand", 1, hand) end + player:get_inventory():set_stack("hand", 1, mcl_potions.hf_update_internal(hand, player)) end minetest.register_on_joinplayer(function(player) From 5263740a808e6f1c86ea2f756b7302cf2d111527 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 20 Mar 2024 02:11:00 +0100 Subject: [PATCH 45/91] Added conduit power --- mods/ITEMS/mcl_potions/functions.lua | 38 ++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 3fbf6663c..677e81f51 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -912,6 +912,40 @@ mcl_potions.register_effect({ affects_item_speed = {}, }) +mcl_potions.register_effect({ + name = "conduit_power", + description = S("Conduit Power"), + res_condition = function(object) + return (not object:is_player()) + end, + on_start = haste_fatigue_hand_update, + on_step = function(dtime, object, factor, duration) + if not object:is_player() then return end + local node = minetest.get_node_or_nil(object:get_pos()) + if node and minetest.registered_nodes[node.name] + and minetest.get_item_group(node.name, "liquid") ~= 0 + and minetest.get_item_group(node.name, "water") ~= 0 then + EF.conduit_power[object].blocked = nil + if object:get_breath() then + hb.hide_hudbar(object, "breath") + if object:get_breath() < 10 then object:set_breath(10) end + end + -- TODO implement improved underwater vision with this effect + else + EF.conduit_power[object].blocked = true + end + end, + after_end = function(object) + haste_fatigue_hand_update(object) + mcl_potions._reset_haste_fatigue_item_meta(object) + end, + particle_color = "#1FB1BA", + uses_factor = true, + lvl1_factor = 0.2, + lvl2_factor = 0.4, + affects_item_speed = {factor_is_positive = true}, +}) + -- implementation of haste and fatigue effects function mcl_potions.update_haste_and_fatigue(player) if mcl_gamemode.get_gamemode(player) == "creative" then return end @@ -1363,7 +1397,7 @@ end function mcl_potions.get_total_haste(object) local accum_factor = 1 for name, def in pairs(item_speed_effects) do - if EF[name][object] then + if EF[name][object] and not EF[name][object].blocked then local factor = EF[name][object].factor if def.factor_is_positive then factor = factor + 1 end if factor > 1 then accum_factor = accum_factor * factor end @@ -1375,7 +1409,7 @@ end function mcl_potions.get_total_fatigue(object) local accum_factor = 1 for name, def in pairs(item_speed_effects) do - if EF[name][object] then + if EF[name][object] and not EF[name][object].blocked then local factor = EF[name][object].factor if def.factor_is_positive then factor = factor + 1 end if factor <= 0 then return 0 end From bbe2964d483b4dbe1d40e8f022cf18db24676939 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 20 Mar 2024 22:45:47 +0100 Subject: [PATCH 46/91] Added some effect descriptions --- mods/ITEMS/mcl_potions/functions.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 677e81f51..f1ddfad41 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -861,6 +861,7 @@ function mcl_potions.apply_haste_fatigue(toolcaps, h_fac, f_fac) end function mcl_potions.hf_update_internal(hand, object) + -- TODO add a check for creative mode? local meta = hand:get_meta() local h_fac = mcl_potions.get_total_haste(object) local f_fac = mcl_potions.get_total_fatigue(object) @@ -879,6 +880,9 @@ end mcl_potions.register_effect({ name = "haste", description = S("Haste"), + get_tt = function(factor) + return S("+@1% mining and attack speed", math.floor(factor*100)) + end, res_condition = function(object) return (not object:is_player()) end, @@ -897,6 +901,9 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "fatigue", description = S("Fatigue"), + get_tt = function(factor) + return S("-@1% mining and attack speed", math.floor((1-factor)*100)) + end, res_condition = function(object) return (not object:is_player()) end, @@ -915,6 +922,9 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "conduit_power", description = S("Conduit Power"), + get_tt = function(factor) + return S("+@1% mining and attack speed in water\nlimitless breathing under water", math.floor(factor*100)) + end, res_condition = function(object) return (not object:is_player()) end, From c503a5fb8c6e72919979678785fbcc82464543c8 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Thu, 21 Mar 2024 01:10:20 +0100 Subject: [PATCH 47/91] Added luck and bad luck effects They're no-op for now --- mods/ITEMS/mcl_potions/functions.lua | 32 ++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index f1ddfad41..db50c7058 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -602,6 +602,38 @@ mcl_potions.register_effect({ end, }) +mcl_potions.register_effect({ + name = "luck", + description = S("Luck"), + particle_color = "#7BFF42", + res_condition = function(object) + return (not object:is_player()) + end, + on_start = function(object, factor) +-- mcl_luck.add_luck_modifier(object, "mcl_potions:luck", factor) + end, + on_end = function(object) +-- mcl_luck.remove_luck_modifier(object, "mcl_potions:luck") + end, + uses_factor = true, +}) + +mcl_potions.register_effect({ + name = "bad_luck", + description = S("Bad Luck"), + particle_color = "#887343", + res_condition = function(object) + return (not object:is_player()) + end, + on_start = function(object, factor) +-- mcl_luck.add_luck_modifier(object, "mcl_potions:bad_luck", -factor) + end, + on_end = function(object) +-- mcl_luck.remove_luck_modifier(object, "mcl_potions:bad_luck") + end, + uses_factor = true, +}) + mcl_potions.register_effect({ name = "bad_omen", description = S("Bad Omen"), From b28467d34839d13f6c511e256df193364db8afc7 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Thu, 21 Mar 2024 01:27:11 +0100 Subject: [PATCH 48/91] Added mcl_luck API Luck and Bad Luck effects use the mcl_luck API now The API is unused for now --- mods/ITEMS/mcl_potions/functions.lua | 14 ++++++++---- mods/PLAYER/mcl_luck/init.lua | 33 ++++++++++++++++++++++++++++ mods/PLAYER/mcl_luck/mod.conf | 3 +++ 3 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 mods/PLAYER/mcl_luck/init.lua create mode 100644 mods/PLAYER/mcl_luck/mod.conf diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index db50c7058..50cde6bae 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -610,10 +610,13 @@ mcl_potions.register_effect({ return (not object:is_player()) end, on_start = function(object, factor) --- mcl_luck.add_luck_modifier(object, "mcl_potions:luck", factor) + mcl_luck.apply_luck_modifier(object:get_player_name(), "mcl_potions:luck", factor) + end, + on_load = function(object, factor) + mcl_luck.apply_luck_modifier(object:get_player_name(), "mcl_potions:luck", factor) end, on_end = function(object) --- mcl_luck.remove_luck_modifier(object, "mcl_potions:luck") + mcl_luck.remove_luck_modifier(object:get_player_name(), "mcl_potions:luck") end, uses_factor = true, }) @@ -626,10 +629,13 @@ mcl_potions.register_effect({ return (not object:is_player()) end, on_start = function(object, factor) --- mcl_luck.add_luck_modifier(object, "mcl_potions:bad_luck", -factor) + mcl_luck.apply_luck_modifier(object:get_player_name(), "mcl_potions:bad_luck", -factor) + end, + on_load = function(object, factor) + mcl_luck.apply_luck_modifier(object:get_player_name(), "mcl_potions:bad_luck", -factor) end, on_end = function(object) --- mcl_luck.remove_luck_modifier(object, "mcl_potions:bad_luck") + mcl_luck.remove_luck_modifier(object:get_player_name(), "mcl_potions:bad_luck") end, uses_factor = true, }) diff --git a/mods/PLAYER/mcl_luck/init.lua b/mods/PLAYER/mcl_luck/init.lua new file mode 100644 index 000000000..275cea52f --- /dev/null +++ b/mods/PLAYER/mcl_luck/init.lua @@ -0,0 +1,33 @@ +mcl_luck = {} + +-- table indexed by player name +-- each entry for each player contains list of modifiers applied to the player +-- modifiers are listed by their name (defined when applying them) +-- all modifiers are dynamic (they are removed when the player leaves game and on server shutdown) +local applied_luck = {} + +function mcl_luck.apply_luck_modifier(player_name, modifier_name, amount) + applied_luck[player_name][modifier_name] = amount +end + +function mcl_luck.remove_luck_modifier(player_name, modifier_name) + applied_luck[player_name][modifier_name] = nil +end + +function mcl_luck.get_luck(player_name) + local luck = 0 + for _, amount in pairs(applied_luck[player_name]) do + luck = luck + amount + end + return luck +end + +minetest.register_on_joinplayer(function(player) + local player_name = player:get_player_name() + applied_luck[player_name] = {} +end) + +minetest.register_on_leaveplayer(function(player) + local player_name = player:get_player_name() + applied_luck[player_name] = nil +end) diff --git a/mods/PLAYER/mcl_luck/mod.conf b/mods/PLAYER/mcl_luck/mod.conf new file mode 100644 index 000000000..395c888bb --- /dev/null +++ b/mods/PLAYER/mcl_luck/mod.conf @@ -0,0 +1,3 @@ +name = mcl_luck +author = Herowl +description = An API for handling luck, it can be polled by random events. From 42778a3a6dc388aa88566077defb02abf893b347 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Thu, 21 Mar 2024 03:10:05 +0100 Subject: [PATCH 49/91] Made some random rolls affected by mcl_luck * xp bottle * bow and crossbow crits * megacrits added for mcl_bows, achievable only by (mcl_)luck --- mods/HUD/mcl_experience/bottle.lua | 11 ++++++++--- mods/HUD/mcl_experience/mod.conf | 2 +- mods/ITEMS/mcl_bows/bow.lua | 8 ++++---- mods/ITEMS/mcl_bows/crossbow.lua | 8 ++++---- mods/ITEMS/mcl_bows/mod.conf | 2 +- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/mods/HUD/mcl_experience/bottle.lua b/mods/HUD/mcl_experience/bottle.lua index 62a3fb9ca..50f96656f 100644 --- a/mods/HUD/mcl_experience/bottle.lua +++ b/mods/HUD/mcl_experience/bottle.lua @@ -14,7 +14,7 @@ minetest.register_entity("mcl_experience:bottle",{ local n = node.name if n ~= "air" and n ~= "mcl_portals:portal" and n ~= "mcl_portals:portal_end" and minetest.get_item_group(n, "liquid") == 0 then minetest.sound_play("mcl_potions_breaking_glass", {pos = pos, max_hear_distance = 16, gain = 1}) - mcl_experience.throw_xp(pos, math.random(3, 11)) + mcl_experience.throw_xp(pos, math.random(3, 11) + (self._luck or 0)) minetest.add_particlespawner({ amount = 50, time = 0.1, @@ -40,13 +40,18 @@ minetest.register_entity("mcl_experience:bottle",{ end, }) -local function throw_xp_bottle(pos, dir, velocity) +local function throw_xp_bottle(pos, dir, velocity, user) minetest.sound_play("mcl_throwing_throw", {pos = pos, gain = 0.4, max_hear_distance = 16}, true) local obj = minetest.add_entity(pos, "mcl_experience:bottle") obj:set_velocity(vector.multiply(dir, velocity)) local acceleration = vector.multiply(dir, -3) acceleration.y = -9.81 obj:set_acceleration(acceleration) + if user then + local ent = obj:get_luaentity() + local luck = mcl_luck.get_luck(user:get_player_name()) + ent._luck = luck + end end minetest.register_craftitem("mcl_experience:bottle", { @@ -55,7 +60,7 @@ minetest.register_craftitem("mcl_experience:bottle", { wield_image = "mcl_experience_bottle.png", stack_max = 64, on_use = function(itemstack, placer, pointed_thing) - throw_xp_bottle(vector.add(placer:get_pos(), vector.new(0, 1.5, 0)), placer:get_look_dir(), 10) + throw_xp_bottle(vector.add(placer:get_pos(), vector.new(0, 1.5, 0)), placer:get_look_dir(), 10, placer) if not minetest.is_creative_enabled(placer:get_player_name()) then itemstack:take_item() end diff --git a/mods/HUD/mcl_experience/mod.conf b/mods/HUD/mcl_experience/mod.conf index a8e992c06..1e0c09c31 100644 --- a/mods/HUD/mcl_experience/mod.conf +++ b/mods/HUD/mcl_experience/mod.conf @@ -1,4 +1,4 @@ name = mcl_experience author = oilboi description = eXPerience mod -depends = mcl_gamemode +depends = mcl_gamemode, mcl_luck diff --git a/mods/ITEMS/mcl_bows/bow.lua b/mods/ITEMS/mcl_bows/bow.lua index 3d22c6df6..9f381f501 100644 --- a/mods/ITEMS/mcl_bows/bow.lua +++ b/mods/ITEMS/mcl_bows/bow.lua @@ -270,10 +270,10 @@ controls.register_on_release(function(player, key, time) local is_critical = false if charge >= BOW_CHARGE_TIME_FULL then speed = BOW_MAX_SPEED - local r = math.random(1,5) - if r == 1 then - -- 20% chance for critical hit - damage = 10 + local r = math.random(1,5) + mcl_luck.get_luck(player:get_player_name()) + if r > 4 then + -- 20% chance for critical hit (by default) + damage = 10 + math.floor((r-5)/5) -- mega crit (over crit) with high luck is_critical = true else damage = 9 diff --git a/mods/ITEMS/mcl_bows/crossbow.lua b/mods/ITEMS/mcl_bows/crossbow.lua index 54c6d7da2..c1cb7f8be 100644 --- a/mods/ITEMS/mcl_bows/crossbow.lua +++ b/mods/ITEMS/mcl_bows/crossbow.lua @@ -322,10 +322,10 @@ controls.register_on_press(function(player, key, time) -- Fully charged local is_critical = false speed = BOW_MAX_SPEED - local r = math.random(1,5) - if r == 1 then - -- 20% chance for critical hit - damage = 10 + local r = math.random(1,5) + mcl_luck.get_luck(player:get_player_name()) + if r > 4 then + -- 20% chance for critical hit (by default) + damage = 10 + math.floor((r-5)/5) -- mega crit (over crit) with high luck is_critical = true else damage = 9 diff --git a/mods/ITEMS/mcl_bows/mod.conf b/mods/ITEMS/mcl_bows/mod.conf index 0fdd666a3..61fb52ddb 100644 --- a/mods/ITEMS/mcl_bows/mod.conf +++ b/mods/ITEMS/mcl_bows/mod.conf @@ -1,6 +1,6 @@ name = mcl_bows author = Arcelmi description = This mod adds bows and arrows for MineClone 2. -depends = controls, mcl_particles, mcl_enchanting, mcl_init, mcl_util, mcl_shields, mcl_fovapi +depends = controls, mcl_particles, mcl_enchanting, mcl_init, mcl_util, mcl_shields, mcl_fovapi, mcl_luck optional_depends = awards, mcl_achievements, mcl_core, mcl_mobitems, playerphysics, doc, doc_identifier, mesecons_button From 7cd0cfede867027019780066d5921811bdd36b9b Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 24 Mar 2024 05:46:01 +0100 Subject: [PATCH 50/91] Further (mcl_)luck functionality * XP from mob breeding impacted by luck * eye of ender explosion chance impacted by luck * fishing loot impacted by luck * melee critical damage impacted by luck * also fixed 2 scripts marked as "executable" --- mods/ENTITIES/mcl_mobs/breeding.lua | 3 ++- mods/ENTITIES/mcl_mobs/mod.conf | 2 +- mods/ENTITIES/mcl_mobs/spawning.lua | 0 mods/HUD/mcl_achievements/init.lua | 0 mods/ITEMS/mcl_end/eye_of_ender.lua | 9 ++++++--- mods/ITEMS/mcl_end/mod.conf | 2 +- mods/ITEMS/mcl_fishing/init.lua | 4 ++-- mods/ITEMS/mcl_fishing/mod.conf | 2 +- mods/PLAYER/mcl_criticals/init.lua | 27 ++++++++++++++++++++++++++- mods/PLAYER/mcl_criticals/mod.conf | 2 +- 10 files changed, 40 insertions(+), 11 deletions(-) mode change 100755 => 100644 mods/ENTITIES/mcl_mobs/spawning.lua mode change 100755 => 100644 mods/HUD/mcl_achievements/init.lua diff --git a/mods/ENTITIES/mcl_mobs/breeding.lua b/mods/ENTITIES/mcl_mobs/breeding.lua index 7b5d91119..90e625db8 100644 --- a/mods/ENTITIES/mcl_mobs/breeding.lua +++ b/mods/ENTITIES/mcl_mobs/breeding.lua @@ -78,6 +78,7 @@ function mob_class:feed_tame(clicker, feed_count, breed, tame, notake) self.food = 0 self.horny = true self.persistent = true + self._luck = mcl_luck.get_luck(clicker:get_player_name()) end end @@ -273,7 +274,7 @@ function mob_class:check_breeding() return end - mcl_experience.throw_xp(pos, math.random(1, 7)) + mcl_experience.throw_xp(pos, math.random(1, 7) + (parent1._luck or 0) + (parent2._luck or 0)) -- custom breed function if parent1.on_breed then diff --git a/mods/ENTITIES/mcl_mobs/mod.conf b/mods/ENTITIES/mcl_mobs/mod.conf index 9c10e9a2b..927c1c905 100644 --- a/mods/ENTITIES/mcl_mobs/mod.conf +++ b/mods/ENTITIES/mcl_mobs/mod.conf @@ -1,5 +1,5 @@ name = mcl_mobs author = PilzAdam description = Adds a mob API for mods to add animals or monsters, etc. -depends = mcl_particles +depends = mcl_particles, mcl_luck optional_depends = mcl_weather, mcl_explosions, mcl_hunger, mcl_worlds, invisibility, lucky_block, cmi, doc_identifier, mcl_armor, mcl_portals, mcl_experience, mcl_sculk diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua old mode 100755 new mode 100644 diff --git a/mods/HUD/mcl_achievements/init.lua b/mods/HUD/mcl_achievements/init.lua old mode 100755 new mode 100644 diff --git a/mods/ITEMS/mcl_end/eye_of_ender.lua b/mods/ITEMS/mcl_end/eye_of_ender.lua index b5adc7cb6..065d7657e 100644 --- a/mods/ITEMS/mcl_end/eye_of_ender.lua +++ b/mods/ITEMS/mcl_end/eye_of_ender.lua @@ -28,8 +28,8 @@ minetest.register_entity("mcl_end:ender_eye", { self._age = self._age + dtime if self._age >= 3 then -- End of life - local r = math.random(1,5) - if r == 1 then + local r = math.random(1,15) + self._luck + if r <= 3 then -- 20% chance to get destroyed completely. -- 100% if in Creative Mode self.object:remove() @@ -85,11 +85,12 @@ minetest.register_craftitem("mcl_end:ender_eye", { if user == nil then return end + local player_name = user:get_player_name() local origin = user:get_pos() origin.y = origin.y + 1.5 local strongholds = mcl_structures.registered_structures["end_shrine"].static_pos local dim = mcl_worlds.pos_to_dimension(origin) - local is_creative = minetest.is_creative_enabled(user:get_player_name()) + local is_creative = minetest.is_creative_enabled(player_name) -- Just drop the eye of ender if there are no strongholds if #strongholds <= 0 or dim ~= "overworld" then @@ -124,6 +125,8 @@ minetest.register_craftitem("mcl_end:ender_eye", { -- Throw it! local obj = minetest.add_entity(origin, "mcl_end:ender_eye") local dir + local ent = obj:get_luaentity() + ent._luck = mcl_luck.get_luck(player_name) if lowest_dist <= 25 then local velocity = 4 diff --git a/mods/ITEMS/mcl_end/mod.conf b/mods/ITEMS/mcl_end/mod.conf index 3547074cf..3666ace19 100644 --- a/mods/ITEMS/mcl_end/mod.conf +++ b/mods/ITEMS/mcl_end/mod.conf @@ -1,2 +1,2 @@ name = mcl_end -depends = screwdriver, mcl_sounds, mcl_util, doc_items, mcl_worlds, mcl_structures, mcl_stonecutter +depends = screwdriver, mcl_sounds, mcl_util, doc_items, mcl_worlds, mcl_structures, mcl_stonecutter, mcl_luck diff --git a/mods/ITEMS/mcl_fishing/init.lua b/mods/ITEMS/mcl_fishing/init.lua index ca9c3b2e3..e3bf181f5 100644 --- a/mods/ITEMS/mcl_fishing/init.lua +++ b/mods/ITEMS/mcl_fishing/init.lua @@ -62,8 +62,8 @@ local fish = function(itemstack, player, pointed_thing) local junk_values = {10, 8.1, 6.1, 4.2} local luck_of_the_sea = math.min(mcl_enchanting.get_enchantment(itemstack, "luck_of_the_sea"), 3) local index = luck_of_the_sea + 1 - local fish_value = fish_values[index] - local junk_value = junk_values[index] + fish_value + local fish_value = fish_values[index] - mcl_luck.get_luck(ent.player) + local junk_value = junk_values[index] + fish_value - mcl_luck.get_luck(ent.player) if r <= fish_value then -- Fish items = mcl_loot.get_loot({ diff --git a/mods/ITEMS/mcl_fishing/mod.conf b/mods/ITEMS/mcl_fishing/mod.conf index 71bde6146..1af715aaf 100644 --- a/mods/ITEMS/mcl_fishing/mod.conf +++ b/mods/ITEMS/mcl_fishing/mod.conf @@ -1,3 +1,3 @@ name = mcl_fishing description = Adds fish and fishing poles to go fishing. -depends = mcl_core, mcl_sounds, mcl_loot, mcl_mobs, mcl_enchanting, mcl_throwing, mcl_colors, mcl_buckets +depends = mcl_core, mcl_sounds, mcl_loot, mcl_mobs, mcl_enchanting, mcl_throwing, mcl_colors, mcl_buckets, mcl_luck diff --git a/mods/PLAYER/mcl_criticals/init.lua b/mods/PLAYER/mcl_criticals/init.lua index 3e292d165..d30647004 100644 --- a/mods/PLAYER/mcl_criticals/init.lua +++ b/mods/PLAYER/mcl_criticals/init.lua @@ -23,7 +23,32 @@ mcl_damage.register_modifier(function(obj, damage, reason) texture = "mcl_particles_crit.png^[colorize:#bc7a57:127", }) minetest.sound_play("mcl_criticals_hit", {object = obj}) - return damage * math.random(1.5, 2.5) + local crit_mod + local CRIT_MIN = 1.5 + local CRIT_DIFF = 1 + if hitter:is_player() then + local luck = mcl_luck.get_luck(hitter:get_player_name()) + if luck ~= 0 then + local a, d + if luck > 0 then + d = -0.5 + a = d - math.abs(luck) + elseif luck < 0 then + a = -0.5 + d = a - math.abs(luck) + else + minetest.log("warning", "[mcl_criticals] luck is not a number") -- this technically can't happen, but want to catch such cases + end + if a then + local x = math.random() + crit_mod = CRIT_DIFF * (a * x) / (d - luck * x) + CRIT_MIN + end + end + end + if not crit_mod then + crit_mod = math.random(CRIT_MIN, CRIT_MIN + CRIT_DIFF) + end + return damage * crit_mod end end end, -100) diff --git a/mods/PLAYER/mcl_criticals/mod.conf b/mods/PLAYER/mcl_criticals/mod.conf index 5b0b91330..0ae588aa6 100644 --- a/mods/PLAYER/mcl_criticals/mod.conf +++ b/mods/PLAYER/mcl_criticals/mod.conf @@ -1,2 +1,2 @@ name = mcl_criticals -depends = mcl_damage +depends = mcl_damage, mcl_luck From 6dab6158b96437086f9d58a5d41c02abdd96001c Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 31 Mar 2024 04:34:19 +0200 Subject: [PATCH 51/91] Reserve some more keywords in register_effect() --- mods/ITEMS/mcl_potions/functions.lua | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 50cde6bae..e3ec67d90 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -121,11 +121,8 @@ function mcl_potions.register_effect(def) if type(name) ~= "string" then error("Unable to register effect: name is not a string") end - if name == "list" then - error("Unable to register effect: list is a reserved word") - end - if name == "heal" then - error("Unable to register effect: heal is a reserved word") + if name == "list" or name == "heal" or name == "remove" or name == "clear" then + error("Unable to register effect: " .. name .. " is a reserved word") end if registered_effects[name] then error("Effect named "..name.." already registered!") From 7ae31790bff5464117311c73d7a765c5d8396a11 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 1 Apr 2024 03:43:49 +0200 Subject: [PATCH 52/91] Fixed running on_end for effects that aren't ending --- mods/ITEMS/mcl_potions/functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index e3ec67d90..ac0fdd3de 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -1317,7 +1317,7 @@ function mcl_potions._reset_player_effects(player, set_hud) end for name, effect in pairs(registered_effects) do - if effect.on_end then effect.on_end(player) end + if EF[name][player] and effect.on_end then effect.on_end(player) end end mcl_potions._clear_cached_player_data(player) From 09be413e3f317752508ff5fdd488fe2bedfc42b7 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 1 Apr 2024 04:38:05 +0200 Subject: [PATCH 53/91] Added glowing effect Also added on_save_effect callback to run cleanup --- mods/ITEMS/mcl_potions/functions.lua | 69 +++++++++++++++++++++++++ textures/mcl_potions_glow_waypoint.png | Bin 0 -> 252 bytes 2 files changed, 69 insertions(+) create mode 100644 textures/mcl_potions_glow_waypoint.png diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index ac0fdd3de..e12e61fa5 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -94,6 +94,7 @@ end -- 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 -- after_end - function(object) - called when the effect wears off, after purging the data of the effect +-- on_save_effect - function(object - called when the effect is to be serialized for saving (supposed to do cleanup) -- 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 @@ -144,6 +145,7 @@ function mcl_potions.register_effect(def) pdef.on_step = def.on_step pdef.on_hit_timer = def.on_hit_timer pdef.on_end = def.on_end + pdef.on_save_effect = def.on_save_effect if not def.particle_color then pdef.particle_color = "#3000EE" else @@ -505,6 +507,72 @@ mcl_potions.register_effect({ lvl2_factor = 20, }) +local GLOW_DISTANCE = 30 +local CLOSE_GLOW_LIMIT = 3 +local MIN_GLOW_SCALE = 1 +local MAX_GLOW_SCALE = 4 +local SCALE_DIFF = MAX_GLOW_SCALE - MIN_GLOW_SCALE +local SCALE_FACTOR = (GLOW_DISTANCE - CLOSE_GLOW_LIMIT) / SCALE_DIFF +local abs = math.abs +mcl_potions.register_effect({ + name = "glowing", + description = S("Glowing"), + get_tt = function(factor) + return S("more visible at all times") + end, + on_start = function(object, factor) + EF.glowing[object].waypoints = {} + end, + on_step = function(dtime, object, factor, duration) + local pos = object:get_pos() + if not pos then return end + local x, y, z = pos.x, pos.y, pos.z + for _, player in pairs(minetest.get_connected_players()) do + local pp = player:get_pos() + if pp and player ~= object then + local hud_id = EF.glowing[object].waypoints[player] + if abs(pp.x-x) < GLOW_DISTANCE and abs(pp.y-y) < GLOW_DISTANCE + and abs(pp.z-z) < GLOW_DISTANCE then + local distance = vector.distance(pos, pp) + local scale + if distance <= CLOSE_GLOW_LIMIT then scale = MAX_GLOW_SCALE + elseif distance >= GLOW_DISTANCE then scale = MIN_GLOW_SCALE + else scale = (GLOW_DISTANCE - distance) / SCALE_FACTOR + MIN_GLOW_SCALE end + if hud_id then + player:hud_change(hud_id, "world_pos", pos) + player:hud_change(hud_id, "scale", {x = scale, y = scale}) + else + EF.glowing[object].waypoints[player] = player:hud_add({ + hud_elem_type = "image_waypoint", + position = {x = 0.5, y = 0.5}, + scale = {x = scale, y = scale}, + text = "mcl_potions_glow_waypoint.png", + alignment = {x = 0, y = -1}, + world_pos = pos, + }) + end + elseif hud_id then + player:hud_remove(hud_id) + EF.glowing[object].waypoints[player] = nil + end + end + end + end, + on_end = function(object) + for player, hud_id in pairs(EF.glowing[object].waypoints) do + if player:get_pos() then player:hud_remove(hud_id) end + end + end, + on_save_effect = function(object) + for player, hud_id in pairs(EF.glowing[object].waypoints) do + if player:get_pos() then player:hud_remove(hud_id) end + end + EF.glowing[object].waypoints = {} + end, + particle_color = "#FFFF00", + uses_factor = false, +}) + mcl_potions.register_effect({ name = "health_boost", description = S("Health Boost"), @@ -1334,6 +1402,7 @@ function mcl_potions._save_player_effects(player) local meta = player:get_meta() for name, effect in pairs(registered_effects) do + if effect.on_save_effect and EF[name][player] then effect.on_save_effect(player) end meta:set_string("mcl_potions:_EF_"..name, minetest.serialize(EF[name][player])) end end diff --git a/textures/mcl_potions_glow_waypoint.png b/textures/mcl_potions_glow_waypoint.png new file mode 100644 index 0000000000000000000000000000000000000000..1e5afedfbec5e8968c5d8199ea038f91a82b486b GIT binary patch literal 252 zcmV~FYthh!q5 Date: Mon, 1 Apr 2024 06:58:33 +0200 Subject: [PATCH 54/91] Brewing somewhat works with the new API --- mods/ITEMS/mcl_brewing/init.lua | 2 +- mods/ITEMS/mcl_potions/init.lua | 150 +++++++++++++++-------------- mods/ITEMS/mcl_potions/potions.lua | 7 ++ 3 files changed, 88 insertions(+), 71 deletions(-) diff --git a/mods/ITEMS/mcl_brewing/init.lua b/mods/ITEMS/mcl_brewing/init.lua index 306129320..cdac3429e 100644 --- a/mods/ITEMS/mcl_brewing/init.lua +++ b/mods/ITEMS/mcl_brewing/init.lua @@ -82,7 +82,7 @@ local function brewable(inv) for i=1,stand_size do - bottle = inv:get_stack("stand", i):get_name() + bottle = inv:get_stack("stand", i) alchemy = mcl_potions.get_alchemy(ingredient, bottle) if alchemy then diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index 550ddc27d..3f9955630 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -29,6 +29,7 @@ dofile(modpath .. "/splash.lua") dofile(modpath .. "/lingering.lua") dofile(modpath .. "/tipped_arrow.lua") dofile(modpath .. "/potions.lua") +local potions = mcl_potions.registered_potions minetest.register_craftitem("mcl_potions:fermented_spider_eye", { description = S("Fermented Spider Eye"), @@ -370,97 +371,110 @@ local output_table = { ["mcl_potions:awkward"] = awkward_table, } - -local enhancement_table = {} -local extension_table = {} -local potions = {} - -for i, potion in ipairs({"healing","harming","swiftness","slowness", - "leaping","poison","regeneration","invisibility","fire_resistance", - -- "weakness","strength", - "water_breathing","night_vision", "withering"}) do - - table.insert(potions, potion) - - if potion ~= "invisibility" and potion ~= "night_vision" and potion ~= "weakness" and potion ~= "water_breathing" and potion ~= "fire_resistance" then - enhancement_table["mcl_potions:"..potion] = "mcl_potions:"..potion.."_2" - enhancement_table["mcl_potions:"..potion.."_splash"] = "mcl_potions:"..potion.."_2_splash" - table.insert(potions, potion.."_2") - end - - if potion ~= "healing" and potion ~= "harming" then - extension_table["mcl_potions:"..potion.."_splash"] = "mcl_potions:"..potion.."_plus_splash" - extension_table["mcl_potions:"..potion] = "mcl_potions:"..potion.."_plus" - table.insert(potions, potion.."_plus") - end - -end - -for i, potion in ipairs({"awkward", "mundane", "thick", "water"}) do - table.insert(potions, potion) -end - - local inversion_table = { ["mcl_potions:healing"] = "mcl_potions:harming", - ["mcl_potions:healing_2"] = "mcl_potions:harming_2", ["mcl_potions:swiftness"] = "mcl_potions:slowness", - ["mcl_potions:swiftness_plus"] = "mcl_potions:slowness_plus", ["mcl_potions:leaping"] = "mcl_potions:slowness", - ["mcl_potions:leaping_plus"] = "mcl_potions:slowness_plus", ["mcl_potions:night_vision"] = "mcl_potions:invisibility", - ["mcl_potions:night_vision_plus"] = "mcl_potions:invisibility_plus", ["mcl_potions:poison"] = "mcl_potions:harming", - ["mcl_potions:poison_2"] = "mcl_potions:harming_2", - ["mcl_potions:healing_splash"] = "mcl_potions:harming_splash", - ["mcl_potions:healing_2_splash"] = "mcl_potions:harming_2_splash", - ["mcl_potions:swiftness_splash"] = "mcl_potions:slowness_splash", - ["mcl_potions:swiftness_plus_splash"] = "mcl_potions:slowness_plus_splash", - ["mcl_potions:leaping_splash"] = "mcl_potions:slowness_splash", - ["mcl_potions:leaping_plus_splash"] = "mcl_potions:slowness_plus_splash", - ["mcl_potions:night_vision_splash"] = "mcl_potions:invisibility_splash", - ["mcl_potions:night_vision_plus_splash"] = "mcl_potions:invisibility_plus_splash", - ["mcl_potions:poison_splash"] = "mcl_potions:harming_splash", - ["mcl_potions:poison_2_splash"] = "mcl_potions:harming_2_splash", +-- ["mcl_potions:healing_splash"] = "mcl_potions:harming_splash", +-- ["mcl_potions:swiftness_splash"] = "mcl_potions:slowness_splash", +-- ["mcl_potions:leaping_splash"] = "mcl_potions:slowness_splash", +-- ["mcl_potions:night_vision_splash"] = "mcl_potions:invisibility_splash", +-- ["mcl_potions:poison_splash"] = "mcl_potions:harming_splash", } - local splash_table = {} local lingering_table = {} -for i, potion in ipairs(potions) do - splash_table["mcl_potions:"..potion] = "mcl_potions:"..potion.."_splash" - lingering_table["mcl_potions:"..potion.."_splash"] = "mcl_potions:"..potion.."_lingering" +for potion, def in pairs(potions) do + if def.has_splash then + splash_table[potion] = potion.."_splash" + end + if def.has_lingering then + lingering_table[potion.."_splash"] = potion.."_lingering" + end end local mod_table = { - ["mesecons:wire_00000000_off"] = extension_table, ["mcl_potions:fermented_spider_eye"] = inversion_table, - ["mcl_nether:glowstone_dust"] = enhancement_table, ["mcl_mobitems:gunpowder"] = splash_table, ["mcl_potions:dragon_breath"] = lingering_table, } --- Compare two ingredients for compatable alchemy +local function extend_dur(potionstack) + local def = potions[potionstack:get_name()] + if not def then return false end -- somehow, it initially always fails + if not def.has_plus then return false end -- bail out if can't be extended + local potionstack = ItemStack(potionstack) + local meta = potionstack:get_meta() + local potent = meta:get_int("mcl_potions:potion_potent") + local plus = meta:get_int("mcl_potions:potion_plus") + if plus == 0 then + if potent ~= 0 then + meta:set_int("mcl_potions:potion_potent", 0) + end + meta:set_int("mcl_potions:potion_plus", def._default_extend_level) + tt.reload_itemstack_description(potionstack) + return potionstack + end + return false +end + +local function enhance_pow(potionstack) + local def = potions[potionstack:get_name()] + if not def then return false end -- somehow, it initially always fails + if not def.has_potent then return false end -- bail out if has no potent variant + local potionstack = ItemStack(potionstack) + local meta = potionstack:get_meta() + local potent = meta:get_int("mcl_potions:potion_potent") + local plus = meta:get_int("mcl_potions:potion_plus") + if potent == 0 then + if plus ~= 0 then + meta:set_int("mcl_potions:potion_plus", 0) + end + meta:set_int("mcl_potions:potion_potent", def._default_potent_level-1) + tt.reload_itemstack_description(potionstack) + return potionstack + end + return false +end + +local meta_mod_table = { + ["mesecons:wire_00000000_off"] = extend_dur, + ["mcl_nether:glowstone_dust"] = enhance_pow, +} + +-- Find an alchemical recipe for given ingredient and potion +-- returns outcome function mcl_potions.get_alchemy(ingr, pot) - if output_table[pot] then + local brew_selector = output_table[pot:get_name()] + if brew_selector and brew_selector[ingr] then + local meta = pot:get_meta():to_table() + local alchemy = ItemStack(brew_selector[ingr]) + local metaref = alchemy:get_meta() + metaref:from_table(meta) + tt.reload_itemstack_description(alchemy) + return alchemy + end - local brew_table = output_table[pot] - - if brew_table[ingr] then - return brew_table[ingr] + brew_selector = mod_table[ingr] + if brew_selector then + local brew = brew_selector[pot:get_name()] + if brew then + local meta = pot:get_meta():to_table() + local alchemy = ItemStack(brew) + local metaref = alchemy:get_meta() + metaref:from_table(meta) + tt.reload_itemstack_description(alchemy) + return alchemy end end - if mod_table[ingr] then - - local brew_table = mod_table[ingr] - - if brew_table[pot] then - return brew_table[pot] - end - + if meta_mod_table[ingr] then + local brew_func = meta_mod_table[ingr] + if brew_func then return brew_func(pot) end end return false @@ -493,10 +507,6 @@ minetest.register_globalstep(function(dtime) end) mcl_wip.register_wip_item("mcl_potions:night_vision") -mcl_wip.register_wip_item("mcl_potions:night_vision_plus") mcl_wip.register_wip_item("mcl_potions:night_vision_splash") -mcl_wip.register_wip_item("mcl_potions:night_vision_plus_splash") mcl_wip.register_wip_item("mcl_potions:night_vision_lingering") -mcl_wip.register_wip_item("mcl_potions:night_vision_plus_lingering") mcl_wip.register_wip_item("mcl_potions:night_vision_arrow") -mcl_wip.register_wip_item("mcl_potions:night_vision_plus_arrow") diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 0422bfb90..3c6b62070 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -1,5 +1,7 @@ local S = minetest.get_translator(minetest.get_current_modname()) +mcl_potions.registered_potions = {} + local function potion_image(colorstring, opacity) if not opacity then opacity = 127 @@ -268,6 +270,7 @@ function mcl_potions.register_potion(def) sdef.on_splash = def.custom_splash_effect if not def._effect_list then sdef.instant = true end mcl_potions.register_splash(name, splash_desc, color, sdef) + pdef.has_splash = true end if def.has_lingering or def.has_lingering == nil then @@ -289,6 +292,7 @@ function mcl_potions.register_potion(def) ldef.while_lingering = def.custom_linger_effect if not def._effect_list then ldef.instant = true end mcl_potions.register_lingering(name, ling_desc, color, ldef) + pdef.has_lingering = true end if def.has_arrow then @@ -316,7 +320,10 @@ function mcl_potions.register_potion(def) adef.custom_effect = def.custom_effect if not def._effect_list then adef.instant = true end mcl_potions.register_arrow(name, arr_desc, color, adef) + pdef.has_arrow = true end + + mcl_potions.registered_potions[modname..":"..name] = pdef end mcl_potions.register_potion({ From c4bedb37e068f1c89326695fa3698f2d5197e4d9 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Tue, 2 Apr 2024 03:57:14 +0200 Subject: [PATCH 55/91] Brewing fully works with the new system --- mods/ITEMS/mcl_potions/init.lua | 4 ++-- mods/ITEMS/mcl_potions/potions.lua | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index 3f9955630..4c46ec9bd 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -405,7 +405,7 @@ local mod_table = { local function extend_dur(potionstack) local def = potions[potionstack:get_name()] - if not def then return false end -- somehow, it initially always fails + if not def then return false end if not def.has_plus then return false end -- bail out if can't be extended local potionstack = ItemStack(potionstack) local meta = potionstack:get_meta() @@ -424,7 +424,7 @@ end local function enhance_pow(potionstack) local def = potions[potionstack:get_name()] - if not def then return false end -- somehow, it initially always fails + if not def then return false end if not def.has_potent then return false end -- bail out if has no potent variant local potionstack = ItemStack(potionstack) local meta = potionstack:get_meta() diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 3c6b62070..0f59a3b97 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -250,6 +250,7 @@ function mcl_potions.register_potion(def) pdef.on_place = on_use pdef.on_secondary_use = on_use + local internal_def = table.copy(pdef) minetest.register_craftitem(modname..":"..name, pdef) if def.has_splash or def.has_splash == nil then @@ -270,7 +271,7 @@ function mcl_potions.register_potion(def) sdef.on_splash = def.custom_splash_effect if not def._effect_list then sdef.instant = true end mcl_potions.register_splash(name, splash_desc, color, sdef) - pdef.has_splash = true + internal_def.has_splash = true end if def.has_lingering or def.has_lingering == nil then @@ -292,7 +293,7 @@ function mcl_potions.register_potion(def) ldef.while_lingering = def.custom_linger_effect if not def._effect_list then ldef.instant = true end mcl_potions.register_lingering(name, ling_desc, color, ldef) - pdef.has_lingering = true + internal_def.has_lingering = true end if def.has_arrow then @@ -320,10 +321,10 @@ function mcl_potions.register_potion(def) adef.custom_effect = def.custom_effect if not def._effect_list then adef.instant = true end mcl_potions.register_arrow(name, arr_desc, color, adef) - pdef.has_arrow = true + internal_def.has_arrow = true end - mcl_potions.registered_potions[modname..":"..name] = pdef + mcl_potions.registered_potions[modname..":"..name] = internal_def end mcl_potions.register_potion({ From a9c2a89f1634d7ff1163fdc0d5c0d7b5e3011344 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Tue, 2 Apr 2024 05:03:27 +0200 Subject: [PATCH 56/91] New brewing recipes registering API Also migrated all recipes to the new system --- mods/ITEMS/mcl_potions/init.lua | 142 +++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 22 deletions(-) diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index 4c46ec9bd..b8b47dba7 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -337,9 +337,28 @@ minetest.register_craft({ }) + +local output_table = { } + +-- API +-- registers a potion that can be combined with multiple ingredients for different outcomes +-- out_table contains the recipes for those outcomes +function mcl_potions.register_ingredient_potion(input, out_table) + if output_table[input] then + error("Attempt to register the same ingredient twice!") + end + if type(input) ~= "string" then + error("Invalid argument! input must be a string") + end + if type(out_table) ~= "table" then + error("Invalid argument! out_table must be a table") + end + output_table[input] = out_table +end + local water_table = { ["mcl_nether:nether_wart_item"] = "mcl_potions:awkward", - -- ["mcl_potions:fermented_spider_eye"] = "mcl_potions:weakness", + ["mcl_potions:fermented_spider_eye"] = "mcl_potions:weakness", ["mcl_potions:speckled_melon"] = "mcl_potions:mundane", ["mcl_core:sugar"] = "mcl_potions:mundane", ["mcl_mobitems:magma_cream"] = "mcl_potions:mundane", @@ -351,25 +370,71 @@ local water_table = { ["mcl_nether:glowstone_dust"] = "mcl_potions:thick", ["mcl_mobitems:gunpowder"] = "mcl_potions:water_splash" } +-- API +-- register a potion recipe brewed from water +function mcl_potions.register_water_brew(ingr, potion) + if water_table[ingr] then + error("Attempt to register the same ingredient twice!") + end + if type(ingr) ~= "string" then + error("Invalid argument! ingr must be a string") + end + if type(potion) ~= "string" then + error("Invalid argument! potion must be a string") + end + water_table[ingr] = potion +end +mcl_potions.register_ingredient_potion("mcl_potions:river_water", water_table) +mcl_potions.register_ingredient_potion("mcl_potions:water", water_table) local awkward_table = { ["mcl_potions:speckled_melon"] = "mcl_potions:healing", ["mcl_farming:carrot_item_gold"] = "mcl_potions:night_vision", ["mcl_core:sugar"] = "mcl_potions:swiftness", ["mcl_mobitems:magma_cream"] = "mcl_potions:fire_resistance", - -- ["mcl_mobitems:blaze_powder"] = "mcl_potions:strength", + ["mcl_mobitems:blaze_powder"] = "mcl_potions:strength", ["mcl_fishing:pufferfish_raw"] = "mcl_potions:water_breathing", ["mcl_mobitems:ghast_tear"] = "mcl_potions:regeneration", ["mcl_mobitems:spider_eye"] = "mcl_potions:poison", ["mcl_flowers:wither_rose"] = "mcl_potions:withering", ["mcl_mobitems:rabbit_foot"] = "mcl_potions:leaping", } +-- API +-- register a potion recipe brewed from awkward potion +function mcl_potions.register_awkward_brew(ingr, potion) + if awkward_table[ingr] then + error("Attempt to register the same ingredient twice!") + end + if type(ingr) ~= "string" then + error("Invalid argument! ingr must be a string") + end + if type(potion) ~= "string" then + error("Invalid argument! potion must be a string") + end + awkward_table[ingr] = potion +end +mcl_potions.register_ingredient_potion("mcl_potions:awkward", awkward_table) -local output_table = { - ["mcl_potions:river_water"] = water_table, - ["mcl_potions:water"] = water_table, - ["mcl_potions:awkward"] = awkward_table, -} +-- TODO mundane and thick potion recipes + + +local mod_table = { } + +-- API +-- registers a brewing recipe altering the potion using a table +-- this is supposed to substitute one item with another +function mcl_potions.register_table_modifier(ingr, modifier) + if mod_table[ingr] then + error("Attempt to register the same ingredient twice!") + end + if type(ingr) ~= "string" then + error("Invalid argument! ingr must be a string") + end + if type(modifier) ~= "table" then + error("Invalid argument! modifier must be a table") + end + mod_table[ingr] = modifier +end local inversion_table = { ["mcl_potions:healing"] = "mcl_potions:harming", @@ -377,16 +442,37 @@ local inversion_table = { ["mcl_potions:leaping"] = "mcl_potions:slowness", ["mcl_potions:night_vision"] = "mcl_potions:invisibility", ["mcl_potions:poison"] = "mcl_potions:harming", --- ["mcl_potions:healing_splash"] = "mcl_potions:harming_splash", --- ["mcl_potions:swiftness_splash"] = "mcl_potions:slowness_splash", --- ["mcl_potions:leaping_splash"] = "mcl_potions:slowness_splash", --- ["mcl_potions:night_vision_splash"] = "mcl_potions:invisibility_splash", --- ["mcl_potions:poison_splash"] = "mcl_potions:harming_splash", } +-- API +function mcl_potions.register_inversion_recipe(input, output) + if inversion_table[input] then + error("Attempt to register the same input twice!") + end + if type(input) ~= "string" then + error("Invalid argument! input must be a string") + end + if type(output) ~= "string" then + error("Invalid argument! output must be a string") + end + inversion_table[input] = output +end +local function fill_inversion_table() -- autofills with splash and lingering inversion recipes + local filling_table = { } + for input, output in pairs(inversion_table) do + if potions[input].has_splash and potions[output].has_splash then + filling_table[input.."_splash"] = output .. "_splash" + if potions[input].has_lingering and potions[output].has_lingering then + filling_table[input.."_lingering"] = output .. "_lingering" + end + end + end + table.update(inversion_table, filling_table) + mcl_potions.register_table_modifier("mcl_potions:fermented_spider_eye", inversion_table) +end +minetest.register_on_mods_loaded(fill_inversion_table) local splash_table = {} local lingering_table = {} - for potion, def in pairs(potions) do if def.has_splash then splash_table[potion] = potion.."_splash" @@ -395,13 +481,27 @@ for potion, def in pairs(potions) do lingering_table[potion.."_splash"] = potion.."_lingering" end end +mcl_potions.register_table_modifier("mcl_mobitems:gunpowder", splash_table) +mcl_potions.register_table_modifier("mcl_potions:dragon_breath", lingering_table) -local mod_table = { - ["mcl_potions:fermented_spider_eye"] = inversion_table, - ["mcl_mobitems:gunpowder"] = splash_table, - ["mcl_potions:dragon_breath"] = lingering_table, -} +local meta_mod_table = { } + +-- API +-- registers a brewing recipe altering the potion using a function +-- this is supposed to be a recipe that changes metadata only +function mcl_potions.register_meta_modifier(ingr, mod_func) + if meta_mod_table[ingr] then + error("Attempt to register the same ingredient twice!") + end + if type(ingr) ~= "string" then + error("Invalid argument! ingr must be a string") + end + if type(mod_func) ~= "function" then + error("Invalid argument! mod_func must be a function") + end + meta_mod_table[ingr] = mod_func +end local function extend_dur(potionstack) local def = potions[potionstack:get_name()] @@ -421,6 +521,7 @@ local function extend_dur(potionstack) end return false end +mcl_potions.register_meta_modifier("mesecons:wire_00000000_off", extend_dur) local function enhance_pow(potionstack) local def = potions[potionstack:get_name()] @@ -440,11 +541,8 @@ local function enhance_pow(potionstack) end return false end +mcl_potions.register_meta_modifier("mcl_nether:glowstone_dust", enhance_pow) -local meta_mod_table = { - ["mesecons:wire_00000000_off"] = extend_dur, - ["mcl_nether:glowstone_dust"] = enhance_pow, -} -- Find an alchemical recipe for given ingredient and potion -- returns outcome From ced2741686d7e9681121e96cfad31ca3d9ba6011 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 8 Apr 2024 22:58:16 +0200 Subject: [PATCH 57/91] Added strength and weakness potions Also fixed potent slowness potion level Also fixed slowness and swiftness effect descriptions --- mods/ITEMS/mcl_potions/functions.lua | 4 +- mods/ITEMS/mcl_potions/potions.lua | 142 +++++---------------------- 2 files changed, 25 insertions(+), 121 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index e12e61fa5..5e9eec315 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -260,7 +260,7 @@ mcl_potions.register_effect({ name = "strength", description = S("Strength"), get_tt = function(factor) - return S("+@1% melee damage", factor-1) + return S("+@1% melee damage", 100*(factor-1)) end, particle_color = "#932423", uses_factor = true, @@ -272,7 +272,7 @@ mcl_potions.register_effect({ name = "weakness", description = S("Weakness"), get_tt = function(factor) - return S("-@1% melee damage", 1-factor) + return S("-@1% melee damage", 100*(1-factor)) end, particle_color = "#485D48", uses_factor = true, diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 0f59a3b97..3ebb3aad8 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -468,6 +468,7 @@ mcl_potions.register_potion({ _effect_list = { slowness = {dur=mcl_potions.DURATION_INV}, }, + default_potent_level = 4, has_arrow = true, }) @@ -555,124 +556,27 @@ mcl_potions.register_potion({ has_arrow = true, }) +mcl_potions.register_potion({ + name = "strength", + desc_suffix = S("of Strength"), + _tt = nil, + _longdesc = S("Increases attack power."), + color = "#932423", + _effect_list = { + strength = {}, + }, + has_arrow = true, +}) +mcl_potions.register_potion({ + name = "weakness", + desc_suffix = S("of Weakness"), + _tt = nil, + _longdesc = S("Decreases attack power."), + color = "#484D48", + _effect_list = { + weakness = {}, + }, + has_arrow = true, +}) --- minetest.register_craftitem("mcl_potions:weakness", { --- description = S("Weakness"), --- _tt_help = TODO, --- _doc_items_longdesc = brewhelp, --- wield_image = potion_image("#484D48"), --- inventory_image = potion_image("#484D48"), --- groups = { brewitem=1, food=3, can_eat_when_full=1 }, --- stack_max = 1, --- --- on_place = function(itemstack, user, pointed_thing) --- mcl_potions.weakness_func(user, -4, mcl_potions.DURATION*mcl_potions.INV_FACTOR) --- minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) --- mcl_potions._use_potion(itemstack, user, "#484D48") --- return itemstack --- end, --- --- on_secondary_use = function(itemstack, user, pointed_thing) --- mcl_potions.weakness_func(user, -4, mcl_potions.DURATION*mcl_potions.INV_FACTOR) --- minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) --- mcl_potions._use_potion(itemstack, user, "#484D48") --- return itemstack --- end --- }) --- --- minetest.register_craftitem("mcl_potions:weakness_plus", { --- description = S("Weakness +"), --- _tt_help = TODO, --- _doc_items_longdesc = brewhelp, --- wield_image = potion_image("#484D48"), --- inventory_image = potion_image("#484D48"), --- groups = { brewitem=1, food=3, can_eat_when_full=1 }, --- stack_max = 1, --- --- on_place = function(itemstack, user, pointed_thing) --- mcl_potions.weakness_func(user, -4, mcl_potions.DURATION_2*mcl_potions.INV_FACTOR) --- minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) --- mcl_potions._use_potion(itemstack, user, "#484D48") --- return itemstack --- end, --- --- on_secondary_use = function(itemstack, user, pointed_thing) --- mcl_potions.weakness_func(user, -4, mcl_potions.DURATION_2*mcl_potions.INV_FACTOR) --- minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) --- mcl_potions._use_potion(itemstack, user, "#484D48") --- return itemstack --- end --- }) --- --- minetest.register_craftitem("mcl_potions:strength", { --- description = S("Strength"), --- _tt_help = TODO, --- _doc_items_longdesc = brewhelp, --- wield_image = potion_image("#932423"), --- inventory_image = potion_image("#932423"), --- groups = { brewitem=1, food=3, can_eat_when_full=1 }, --- stack_max = 1, --- --- on_place = function(itemstack, user, pointed_thing) --- mcl_potions.weakness_func(user, 3, mcl_potions.DURATION) --- minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) --- mcl_potions._use_potion(itemstack, user, "#932423") --- return itemstack --- end, --- --- on_secondary_use = function(itemstack, user, pointed_thing) --- mcl_potions.weakness_func(user, 3, mcl_potions.DURATION) --- minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) --- mcl_potions._use_potion(itemstack, user, "#932423") --- return itemstack --- end --- }) --- --- minetest.register_craftitem("mcl_potions:strength_2", { --- description = S("Strength II"), --- _tt_help = TODO, --- _doc_items_longdesc = brewhelp, --- wield_image = potion_image("#932423"), --- inventory_image = potion_image("#932423"), --- groups = { brewitem=1, food=3, can_eat_when_full=1 }, --- stack_max = 1, --- --- on_place = function(itemstack, user, pointed_thing) --- mcl_potions.weakness_func(user, 6, mcl_potions.DURATION_2) --- minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) --- mcl_potions._use_potion(itemstack, user, "#932423") --- return itemstack --- end, --- --- on_secondary_use = function(itemstack, user, pointed_thing) --- mcl_potions.weakness_func(user, 6, mcl_potions.DURATION_2) --- minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) --- mcl_potions._use_potion(itemstack, user, "#932423") --- return itemstack --- end --- }) --- --- minetest.register_craftitem("mcl_potions:strength_plus", { --- description = S("Strength +"), --- _tt_help = TODO, --- _doc_items_longdesc = brewhelp, --- wield_image = potion_image("#932423"), --- inventory_image = potion_image("#932423"), --- groups = { brewitem=1, food=3, can_eat_when_full=1 }, --- stack_max = 1, --- --- on_place = function(itemstack, user, pointed_thing) --- mcl_potions.weakness_func(user, 3, mcl_potions.DURATION_PLUS) --- minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) --- mcl_potions._use_potion(itemstack, user, "#932423") --- return itemstack --- end, --- --- on_secondary_use = function(itemstack, user, pointed_thing) --- mcl_potions.weakness_func(user, 3, mcl_potions.DURATION_PLUS) --- minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) --- mcl_potions._use_potion(itemstack, user, "#932423") --- return itemstack --- end --- }) From 8cfe96a955ebfcb7dab8cd9c65c399ef57b84901 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Tue, 9 Apr 2024 00:25:31 +0200 Subject: [PATCH 58/91] Added potions for new effects * also added some new brewing recipes --- mods/ITEMS/mcl_potions/functions.lua | 2 +- mods/ITEMS/mcl_potions/init.lua | 18 +++ mods/ITEMS/mcl_potions/potions.lua | 228 ++++++++++++++++++++++++++- 3 files changed, 246 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 5e9eec315..9a2b760d1 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -569,7 +569,7 @@ mcl_potions.register_effect({ end EF.glowing[object].waypoints = {} end, - particle_color = "#FFFF00", + particle_color = "#FFFF77", uses_factor = false, }) diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index b8b47dba7..f8b77145f 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -398,6 +398,21 @@ local awkward_table = { ["mcl_mobitems:spider_eye"] = "mcl_potions:poison", ["mcl_flowers:wither_rose"] = "mcl_potions:withering", ["mcl_mobitems:rabbit_foot"] = "mcl_potions:leaping", + + ["mcl_flowers:fourleaf_clover"] = "mcl_potions:luck", + ["mcl_farming:potato_item_poison"] = "mcl_potions:nausea", + -- TODO slow falling + -- TODO levitation? + -- TODO darkness? + -- TODO absorption + -- TODO health boost? + -- TODO resistance + -- TODO turtle master? + -- TODO frost + -- TODO blindness? + -- TODO food poisoning? + -- TODO saturation? + -- TODO haste } -- API -- register a potion recipe brewed from awkward potion @@ -416,6 +431,7 @@ end mcl_potions.register_ingredient_potion("mcl_potions:awkward", awkward_table) -- TODO mundane and thick potion recipes +-- TODO glowing out of thick local mod_table = { } @@ -442,6 +458,8 @@ local inversion_table = { ["mcl_potions:leaping"] = "mcl_potions:slowness", ["mcl_potions:night_vision"] = "mcl_potions:invisibility", ["mcl_potions:poison"] = "mcl_potions:harming", + ["mcl_potions:luck"] = "mcl_potions:bad_luck", + ["mcl_potions:haste"] = "mcl_potions:fatigue", } -- API function mcl_potions.register_inversion_recipe(input, output) diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 3ebb3aad8..bd5760455 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -489,7 +489,7 @@ mcl_potions.register_potion({ desc_suffix = S("of Withering"), _tt = nil, _longdesc = S("Applies the withering effect which deals damage at a regular interval and can kill."), - color = "#000000", + color = "#292929", _effect_list = { withering = {dur=mcl_potions.DURATION_POISON}, }, @@ -580,3 +580,229 @@ mcl_potions.register_potion({ has_arrow = true, }) +mcl_potions.register_potion({ + name = "slow_falling", + desc_suffix = S("of Slow Falling"), + _tt = nil, + _longdesc = S("Instead of falling, you descend gracefully."), + color = "#ACCCFF", + _effect_list = { + slow_falling = {}, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "levitation", + desc_suffix = S("of Levitation"), + _tt = nil, + _longdesc = S("Floats body slowly upwards."), + color = "#420E7E", + _effect_list = { + levitation = {}, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "darkness", + desc_suffix = S("of Darkness"), + _tt = nil, + _longdesc = S("Surrounds with darkness."), + color = "#000000", + _effect_list = { + darkness = {}, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "glowing", + desc_suffix = S("of Glowing"), + _tt = nil, + _longdesc = S("Highlights for others to see."), + color = "#FFFF77", + _effect_list = { + glowing = {}, + }, + has_arrow = false, -- TODO add a spectral arrow instead (in mcl_bows?) +}) + +mcl_potions.register_potion({ + name = "health_boost", + desc_suffix = S("of Health Boost"), + _tt = nil, + _longdesc = S("Increases health."), + color = "#FF2222", + _effect_list = { + health_boost = {}, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "absorption", + desc_suffix = S("of Absorption"), + _tt = nil, + _longdesc = S("Absorbs some incoming damage."), + color = "#B59500", + _effect_list = { + absorption = {}, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "resistance", + desc_suffix = S("of Resistance"), + _tt = nil, + _longdesc = S("Descreases damage taken."), + color = "#2552A5", + _effect_list = { + resistance = {}, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "resistance", + desc_suffix = S("of Resistance"), + _tt = nil, + _longdesc = S("Descreases damage taken."), + color = "#2552A5", + _effect_list = { + resistance = {}, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "turtle_master", + desc_suffix = S("of Turtle Master"), + _tt = nil, + _longdesc = S("Descreases damage taken at the cost of speed."), + color = "#255235", + _effect_list = { + resistance = { + level = 3, + dur = 20, + }, + slowness = { + level = 4, + level_scaling = 2, + dur = 20, + }, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "luck", + desc_suffix = S("of Luck"), + _tt = nil, + _longdesc = S("Increases luck."), + color = "#7BFF42", + _effect_list = { + luck = {}, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "bad_luck", + desc_suffix = S("of Bad Luck"), + _tt = nil, + _longdesc = S("Decreases luck."), + color = "#887343", + _effect_list = { + bad_luck = {}, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "frost", + desc_suffix = S("of Frost"), + _tt = nil, + _longdesc = S("Freezes..."), + color = "#5B7DAA", + _effect_list = { + frost = {}, + }, + has_arrow = true, + -- TODO implement effect stacking? +}) + +mcl_potions.register_potion({ + name = "blindness", + desc_suffix = S("of Blindness"), + _tt = nil, + _longdesc = S("Impairs sight."), + color = "#586868", + _effect_list = { + blindness = {}, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "nausea", + desc_suffix = S("of Nausea"), + _tt = nil, + _longdesc = S("Disintegrates senses."), + color = "#715C7F", + _effect_list = { + nausea = {}, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "food_poisoning", + desc_suffix = S("of Food Poisoning"), + _tt = nil, + _longdesc = S("Moves bowels too fast."), + color = "#83A061", + _effect_list = { + food_poisoning = {}, + }, + has_arrow = true, + -- TODO implement effect stacking? +}) + +mcl_potions.register_potion({ + name = "saturation", + desc_suffix = S("of Saturation"), + _tt = nil, + _longdesc = S("Satisfies hunger."), + color = "#CEAE29", + _effect_list = { + saturation = {}, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "haste", + desc_suffix = S("of Haste"), + _tt = nil, + _longdesc = S("Increases digging and attack speed."), + color = "#FFFF00", + _effect_list = { + haste = {}, + }, + has_arrow = true, +}) + +mcl_potions.register_potion({ + name = "fatigue", + desc_suffix = S("of Fatigue"), + _tt = nil, + _longdesc = S("Decreases digging and attack speed."), + color = "#64643D", + _effect_list = { + fatigue = {}, + }, + has_arrow = true, +}) + From b5367a77a748578dc31dd494a4149d92c4b4531a Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Tue, 9 Apr 2024 01:11:31 +0200 Subject: [PATCH 59/91] Expanded brewing recipe API Added recipes using thick or mundane potion --- mods/ITEMS/mcl_potions/init.lua | 39 +++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index f8b77145f..189a014dc 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -430,8 +430,43 @@ function mcl_potions.register_awkward_brew(ingr, potion) end mcl_potions.register_ingredient_potion("mcl_potions:awkward", awkward_table) --- TODO mundane and thick potion recipes --- TODO glowing out of thick +local mundane_table = { + ["mcl_potions:fermented_spider_eye"] = "mcl_potions:weakness", +} +-- API +-- register a potion recipe brewed from mundane potion +function mcl_potions.register_mundane_brew(ingr, potion) + if mundane_table[ingr] then + error("Attempt to register the same ingredient twice!") + end + if type(ingr) ~= "string" then + error("Invalid argument! ingr must be a string") + end + if type(potion) ~= "string" then + error("Invalid argument! potion must be a string") + end + mundane_table[ingr] = potion +end +mcl_potions.register_ingredient_potion("mcl_potions:mundane", mundane_table) + +local thick_table = { + -- TODO glowing from some shining cave flowers +} +-- API +-- register a potion recipe brewed from thick potion +function mcl_potions.register_thick_brew(ingr, potion) + if thick_table[ingr] then + error("Attempt to register the same ingredient twice!") + end + if type(ingr) ~= "string" then + error("Invalid argument! ingr must be a string") + end + if type(potion) ~= "string" then + error("Invalid argument! potion must be a string") + end + thick_table[ingr] = potion +end +mcl_potions.register_ingredient_potion("mcl_potions:thick", thick_table) local mod_table = { } From 7c1f9805e276b792418ebfadfa4ee35f1d443fd8 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Tue, 9 Apr 2024 01:44:52 +0200 Subject: [PATCH 60/91] Tooltip and color fixes --- mods/ITEMS/mcl_potions/functions.lua | 7 ++++--- mods/ITEMS/mcl_potions/potions.lua | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 9a2b760d1..edf1dae5c 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -463,7 +463,7 @@ mcl_potions.register_effect({ name = "darkness", description = S("Darkness"), get_tt = function(factor) - return S("surrounded by darkness\nnot seeing anything beyond @1 nodes", factor) + return S("surrounded by darkness").."\n"..S("not seeing anything beyond @1 nodes", factor) end, res_condition = function(object) return (not object:is_player()) @@ -751,6 +751,7 @@ mcl_potions.register_effect({ on_start = function(object, factor) mcl_burning.extinguish(object) playerphysics.add_physics_factor(object, "speed", "mcl_potions:frost", 1-factor) + if EF.frost[object].vignette then return end EF.frost[object].vignette = object:hud_add({ hud_elem_type = "image", position = {x = 0.5, y = 0.5}, @@ -838,7 +839,7 @@ mcl_potions.register_effect({ name = "nausea", description = S("Nausea"), get_tt = function(factor) - return S("not feeling very well...\nfrequency: @1 / 1 s", factor) + return S("not feeling very well...").."\n"..S("frequency: @1 / 1 s", factor) end, res_condition = function(object) return (not object:is_player()) @@ -1026,7 +1027,7 @@ mcl_potions.register_effect({ name = "conduit_power", description = S("Conduit Power"), get_tt = function(factor) - return S("+@1% mining and attack speed in water\nlimitless breathing under water", math.floor(factor*100)) + return S("+@1% mining and attack speed in water").."\n"..S("limitless breathing under water", math.floor(factor*100)) end, res_condition = function(object) return (not object:is_player()) diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index bd5760455..6199ea5df 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -633,7 +633,7 @@ mcl_potions.register_potion({ desc_suffix = S("of Health Boost"), _tt = nil, _longdesc = S("Increases health."), - color = "#FF2222", + color = "#BE1919", _effect_list = { health_boost = {}, }, From 7c2d74e983b2eea50b717d04eccaa8328ced2a22 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 14 Apr 2024 01:31:04 +0200 Subject: [PATCH 61/91] Typos fixed --- mods/ITEMS/mcl_potions/potions.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 6199ea5df..7e12d9a94 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -656,7 +656,7 @@ mcl_potions.register_potion({ name = "resistance", desc_suffix = S("of Resistance"), _tt = nil, - _longdesc = S("Descreases damage taken."), + _longdesc = S("Decreases damage taken."), color = "#2552A5", _effect_list = { resistance = {}, @@ -668,7 +668,7 @@ mcl_potions.register_potion({ name = "resistance", desc_suffix = S("of Resistance"), _tt = nil, - _longdesc = S("Descreases damage taken."), + _longdesc = S("Decreases damage taken."), color = "#2552A5", _effect_list = { resistance = {}, @@ -680,7 +680,7 @@ mcl_potions.register_potion({ name = "turtle_master", desc_suffix = S("of Turtle Master"), _tt = nil, - _longdesc = S("Descreases damage taken at the cost of speed."), + _longdesc = S("Decreases damage taken at the cost of speed."), color = "#255235", _effect_list = { resistance = { From dcbc9d2398aa1bb1d2363c34300c1a15b20e346a Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 14 Apr 2024 04:04:04 +0200 Subject: [PATCH 62/91] Allowed giving effect without particles ...both with API and the /effect command --- mods/ITEMS/mcl_potions/commands.lua | 20 +++++++++++++++----- mods/ITEMS/mcl_potions/functions.lua | 13 +++++++------ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/mods/ITEMS/mcl_potions/commands.lua b/mods/ITEMS/mcl_potions/commands.lua index 7b420f801..d1280c645 100644 --- a/mods/ITEMS/mcl_potions/commands.lua +++ b/mods/ITEMS/mcl_potions/commands.lua @@ -9,8 +9,8 @@ local S = minetest.get_translator(minetest.get_current_modname()) minetest.register_chatcommand("effect",{ - params = S("|heal|list [] []"), - description = S("Add a status effect to yourself. Arguments: : name of status effect. Passing \"list\" as effect name lists available effects. Passing \"heal\" as effect name heals (or harms) by amount designed by the next parameter. : duration in seconds. (: amount of healing when the effect is \"heal\", passing a negative value subtracts health.) : effect power determinant, bigger level results in more powerful effect for effects that depend on the level (no changes for other effects), defaults to 1, pass F to use low-level factor instead. : effect strength modifier, can mean different things depending on the effect, no changes for effects that do not depend on level/factor."), + params = S("|heal|list [] [] [NOPART]"), + description = S("Add a status effect to yourself. Arguments: : name of status effect. Passing \"list\" as effect name lists available effects. Passing \"heal\" as effect name heals (or harms) by amount designed by the next parameter. : duration in seconds. (: amount of healing when the effect is \"heal\", passing a negative value subtracts health.) : effect power determinant, bigger level results in more powerful effect for effects that depend on the level (no changes for other effects), defaults to 1, pass F to use low-level factor instead. : effect strength modifier, can mean different things depending on the effect, no changes for effects that do not depend on level/factor. NOPART at the end means no particles will be shown for this effect."), privs = {server = true}, func = function(name, params) @@ -45,7 +45,7 @@ minetest.register_chatcommand("effect",{ end elseif not tonumber(P[2]) then return false, S("Missing or invalid duration parameter!") - elseif P[3] and not tonumber(P[3]) and P[3] ~= "F" then + elseif P[3] and not tonumber(P[3]) and P[3] ~= "F" and P[3] ~= "NOPART" then return false, S("Invalid level parameter!") elseif P[3] and P[3] == "F" and not P[4] then return false, S("Missing or invalid factor parameter when level is F!") @@ -54,12 +54,22 @@ minetest.register_chatcommand("effect",{ -- Default level = 1 if not P[3] then P[3] = 1 + elseif P[3] == "NOPART" then + P[3] = 1 + P[4] = "NOPART" + end + + local nopart = false + if P[3] == "F" then + nopart = P[5] == "NOPART" + else + nopart = P[4] == "NOPART" end local def = mcl_potions.registered_effects[P[1]] if def then if P[3] == "F" then - local given = mcl_potions.give_effect(P[1], minetest.get_player_by_name(name), tonumber(P[4]), tonumber(P[2])) + local given = mcl_potions.give_effect(P[1], minetest.get_player_by_name(name), tonumber(P[4]), tonumber(P[2]), nopart) if given then if def.uses_factor then return true, S("@1 effect given to player @2 for @3 seconds with factor of @4.", def.description, name, P[2], P[4]) @@ -70,7 +80,7 @@ minetest.register_chatcommand("effect",{ return false, S("Giving effect @1 to player @2 failed.", def.description, name) end else - local given = mcl_potions.give_effect_by_level(P[1], minetest.get_player_by_name(name), tonumber(P[3]), tonumber(P[2])) + local given = mcl_potions.give_effect_by_level(P[1], minetest.get_player_by_name(name), tonumber(P[3]), tonumber(P[2]), nopart) if given then if def.uses_factor then return true, S("@1 effect on level @2 given to player @3 for @4 seconds.", def.description, P[3], name, P[2]) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index edf1dae5c..7d97df5ee 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -1311,7 +1311,7 @@ minetest.register_globalstep(function(dtime) for object, vals in pairs(EF[name]) do EF[name][object].timer = vals.timer + dtime - if object:get_pos() then mcl_potions._add_spawner(object, effect.particle_color) end + if object:get_pos() and not vals.no_particles 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 @@ -1702,11 +1702,11 @@ local function target_valid(object, name) and registered_effects[name].res_condition(object)) then return true end end -function mcl_potions.give_effect(name, object, factor, duration) +function mcl_potions.give_effect(name, object, factor, duration, no_particles) local edef = registered_effects[name] if not edef or not target_valid(object, name) then return false end if not EF[name][object] then - local vals = {dur = duration, timer = 0,} + local vals = {dur = duration, timer = 0, no_particles = no_particles} if edef.uses_factor then vals.factor = factor end if edef.on_hit_timer then if edef.timer_uses_factor then vals.step = factor @@ -1716,6 +1716,7 @@ function mcl_potions.give_effect(name, object, factor, duration) if edef.on_start then edef.on_start(object, factor) end else local present = EF[name][object] + present.no_particles = no_particles if not edef.uses_factor or (edef.uses_factor and (not edef.inv_factor and factor >= present.factor or edef.inv_factor and factor <= present.factor)) then @@ -1736,13 +1737,13 @@ function mcl_potions.give_effect(name, object, factor, duration) return true end -function mcl_potions.give_effect_by_level(name, object, level, duration) +function mcl_potions.give_effect_by_level(name, object, level, duration, no_particles) if level == 0 then return false end if not registered_effects[name].uses_factor then - return mcl_potions.give_effect(name, object, 0, duration) + return mcl_potions.give_effect(name, object, 0, duration, no_particles) end local factor = registered_effects[name].level_to_factor(level) - return mcl_potions.give_effect(name, object, factor, duration) + return mcl_potions.give_effect(name, object, factor, duration, no_particles) end function mcl_potions.healing_func(object, hp) From 75e5ca8d49f26666e8fbae8f34af9aa45ea4bc3a Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 14 Apr 2024 04:27:09 +0200 Subject: [PATCH 63/91] Added the option to remove and clear effects... ...with the /effect command. Also made the API for clearing effects more robust. --- mods/ITEMS/mcl_potions/commands.lua | 17 +++++++++++++++-- mods/ITEMS/mcl_potions/functions.lua | 17 ++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/mods/ITEMS/mcl_potions/commands.lua b/mods/ITEMS/mcl_potions/commands.lua index d1280c645..c977b8c1c 100644 --- a/mods/ITEMS/mcl_potions/commands.lua +++ b/mods/ITEMS/mcl_potions/commands.lua @@ -9,8 +9,8 @@ local S = minetest.get_translator(minetest.get_current_modname()) minetest.register_chatcommand("effect",{ - params = S("|heal|list [] [] [NOPART]"), - description = S("Add a status effect to yourself. Arguments: : name of status effect. Passing \"list\" as effect name lists available effects. Passing \"heal\" as effect name heals (or harms) by amount designed by the next parameter. : duration in seconds. (: amount of healing when the effect is \"heal\", passing a negative value subtracts health.) : effect power determinant, bigger level results in more powerful effect for effects that depend on the level (no changes for other effects), defaults to 1, pass F to use low-level factor instead. : effect strength modifier, can mean different things depending on the effect, no changes for effects that do not depend on level/factor. NOPART at the end means no particles will be shown for this effect."), + params = S("|heal|list|clear|remove [] [] [NOPART]"), + description = S("Add a status effect to yourself. Arguments: : name of status effect. Passing \"list\" as effect name lists available effects. Passing \"heal\" as effect name heals (or harms) by amount designed by the next parameter. Passing \"clear\" as effect name removes all effects. Passing \"remove\" as effect name removes the effect named by the next parameter. : duration in seconds. (: amount of healing when the effect is \"heal\", passing a negative value subtracts health. : name of a status effect to be removed when using \"remove\" as the previous parameter.) : effect power determinant, bigger level results in more powerful effect for effects that depend on the level (no changes for other effects), defaults to 1, pass F to use low-level factor instead. : effect strength modifier, can mean different things depending on the effect, no changes for effects that do not depend on level/factor. NOPART at the end means no particles will be shown for this effect."), privs = {server = true}, func = function(name, params) @@ -43,6 +43,19 @@ minetest.register_chatcommand("effect",{ return true, S("Player @1 harmed by @2 HP.", name, hp) end end + elseif P[1] == "clear" then + mcl_potions._reset_player_effects(minetest.get_player_by_name(name)) + return true, S("Effects cleared for player @1", name) + elseif P[1] == "remove" then + if not P[2] then + return false, S("Missing effect parameter!") + end + if mcl_potions.registered_effects[P[2]] then + mcl_potions.clear_effect(minetest.get_player_by_name(name), P[2]) + return true, S("Removed effect @1 from player @2", P[2], name) + else + return false, S("@1 is not an available status effect.", P[2]) + end elseif not tonumber(P[2]) then return false, S("Missing or invalid duration parameter!") elseif P[3] and not tonumber(P[3]) and P[3] ~= "F" and P[3] ~= "NOPART" then diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 7d97df5ee..f63ca6e03 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -1385,12 +1385,18 @@ function mcl_potions._reset_player_effects(player, set_hud) return end + local removed_effects = {} for name, effect in pairs(registered_effects) do if EF[name][player] and effect.on_end then effect.on_end(player) end + if effect.after_end then table.insert(removed_effects, effect.after_end) end end mcl_potions._clear_cached_player_data(player) + for i=1, #removed_effects do + removed_effects[i](player) + end + if set_hud ~= false then potions_set_hud(player) end @@ -1535,7 +1541,16 @@ function mcl_potions.get_total_fatigue(object) end function mcl_potions.clear_effect(object, effect) - EF[effect][object] = nil + if not EF[effect] then + minetest.log("warning", "[mcl_potions] Tried to remove an effect that is not registered: " .. dump(effect)) + return false + end + local def = registered_effects[effect] + if EF[effect][object] then + if def.on_end then def.on_end(object) end + EF[effect][object] = nil + if def.after_end then def.after_end(object) end + end if not object:is_player() then return end potions_set_hud(object) end From 9b501bfa7e550d31c1749635516b4ef22ed576d3 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 14 Apr 2024 04:50:24 +0200 Subject: [PATCH 64/91] Allowed infinite effect duration --- mods/ITEMS/mcl_potions/commands.lua | 12 +++++++----- mods/ITEMS/mcl_potions/functions.lua | 27 +++++++++++++++++++++------ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/mods/ITEMS/mcl_potions/commands.lua b/mods/ITEMS/mcl_potions/commands.lua index c977b8c1c..4b4aa0ba7 100644 --- a/mods/ITEMS/mcl_potions/commands.lua +++ b/mods/ITEMS/mcl_potions/commands.lua @@ -9,8 +9,8 @@ local S = minetest.get_translator(minetest.get_current_modname()) minetest.register_chatcommand("effect",{ - params = S("|heal|list|clear|remove [] [] [NOPART]"), - description = S("Add a status effect to yourself. Arguments: : name of status effect. Passing \"list\" as effect name lists available effects. Passing \"heal\" as effect name heals (or harms) by amount designed by the next parameter. Passing \"clear\" as effect name removes all effects. Passing \"remove\" as effect name removes the effect named by the next parameter. : duration in seconds. (: amount of healing when the effect is \"heal\", passing a negative value subtracts health. : name of a status effect to be removed when using \"remove\" as the previous parameter.) : effect power determinant, bigger level results in more powerful effect for effects that depend on the level (no changes for other effects), defaults to 1, pass F to use low-level factor instead. : effect strength modifier, can mean different things depending on the effect, no changes for effects that do not depend on level/factor. NOPART at the end means no particles will be shown for this effect."), + params = S("|heal|list|clear|remove |INF [] [] [NOPART]"), + description = S("Add a status effect to yourself. Arguments: : name of status effect. Passing \"list\" as effect name lists available effects. Passing \"heal\" as effect name heals (or harms) by amount designed by the next parameter. Passing \"clear\" as effect name removes all effects. Passing \"remove\" as effect name removes the effect named by the next parameter. : duration in seconds. Passing \"INF\" as duration makes the effect infinite. (: amount of healing when the effect is \"heal\", passing a negative value subtracts health. : name of a status effect to be removed when using \"remove\" as the previous parameter.) : effect power determinant, bigger level results in more powerful effect for effects that depend on the level (no changes for other effects), defaults to 1, pass F to use low-level factor instead. : effect strength modifier, can mean different things depending on the effect, no changes for effects that do not depend on level/factor. NOPART at the end means no particles will be shown for this effect."), privs = {server = true}, func = function(name, params) @@ -56,7 +56,7 @@ minetest.register_chatcommand("effect",{ else return false, S("@1 is not an available status effect.", P[2]) end - elseif not tonumber(P[2]) then + elseif not tonumber(P[2]) and P[2] ~= "INF" then return false, S("Missing or invalid duration parameter!") elseif P[3] and not tonumber(P[3]) and P[3] ~= "F" and P[3] ~= "NOPART" then return false, S("Invalid level parameter!") @@ -72,6 +72,8 @@ minetest.register_chatcommand("effect",{ P[4] = "NOPART" end + local inf = P[2] == "INF" + local nopart = false if P[3] == "F" then nopart = P[5] == "NOPART" @@ -82,7 +84,7 @@ minetest.register_chatcommand("effect",{ local def = mcl_potions.registered_effects[P[1]] if def then if P[3] == "F" then - local given = mcl_potions.give_effect(P[1], minetest.get_player_by_name(name), tonumber(P[4]), tonumber(P[2]), nopart) + local given = mcl_potions.give_effect(P[1], minetest.get_player_by_name(name), tonumber(P[4]), inf and "INF" or tonumber(P[2]), nopart) if given then if def.uses_factor then return true, S("@1 effect given to player @2 for @3 seconds with factor of @4.", def.description, name, P[2], P[4]) @@ -93,7 +95,7 @@ minetest.register_chatcommand("effect",{ return false, S("Giving effect @1 to player @2 failed.", def.description, name) end else - local given = mcl_potions.give_effect_by_level(P[1], minetest.get_player_by_name(name), tonumber(P[3]), tonumber(P[2]), nopart) + local given = mcl_potions.give_effect_by_level(P[1], minetest.get_player_by_name(name), tonumber(P[3]), inf and "INF" or tonumber(P[2]), nopart) if given then if def.uses_factor then return true, S("@1 effect on level @2 given to player @3 for @4 seconds.", def.description, P[3], name, P[2]) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index f63ca6e03..d36b8db62 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -1272,8 +1272,12 @@ local function potions_set_icons(player) else player:hud_change(label, "text", "") end - local dur = math.round(vals.dur-vals.timer) - player:hud_change(timestamp, "text", math.floor(dur/60)..string.format(":%02d",math.floor(dur % 60))) + if vals.dur == math.huge then + player:hud_change(timestamp, "text", "∞") + else + local dur = math.round(vals.dur-vals.timer) + player:hud_change(timestamp, "text", math.floor(dur/60)..string.format(":%02d",math.floor(dur % 60))) + end EF[effect_name][player].hud_index = i i = i + 1 end @@ -1309,7 +1313,7 @@ end 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 + if vals.dur ~= math.huge then EF[name][object].timer = vals.timer + dtime end if object:get_pos() and not vals.no_particles 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 @@ -1331,9 +1335,14 @@ minetest.register_globalstep(function(dtime) potions_set_hud(object) end elseif object:is_player() then - local dur = math.round(vals.dur-vals.timer) - object:hud_change(icon_ids[object:get_player_name()][vals.hud_index].timestamp, - "text", math.floor(dur/60)..string.format(":%02d",math.floor(dur % 60))) + if vals.dur == math.huge then + object:hud_change(icon_ids[object:get_player_name()][vals.hud_index].timestamp, + "text", "∞") + else + local dur = math.round(vals.dur-vals.timer) + object:hud_change(icon_ids[object:get_player_name()][vals.hud_index].timestamp, + "text", math.floor(dur/60)..string.format(":%02d",math.floor(dur % 60))) + end end end end @@ -1727,6 +1736,9 @@ function mcl_potions.give_effect(name, object, factor, duration, no_particles) if edef.timer_uses_factor then vals.step = factor else vals.step = edef.hit_timer_step end end + if duration == "INF" then + vals.dur = math.huge + end EF[name][object] = vals if edef.on_start then edef.on_start(object, factor) end else @@ -1742,6 +1754,9 @@ function mcl_potions.give_effect(name, object, factor, duration, no_particles) if edef.timer_uses_factor then present.step = factor end if edef.on_start then edef.on_start(object, factor) end end + if duration == "INF" then + present.dur = math.huge + end else return false end From 70d8dfe558fe002464bec564677738dbd53a969a Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 14 Apr 2024 07:45:39 +0200 Subject: [PATCH 65/91] Improved API mob support * various API functions now work with mobs properly * the following effects don't work with mobs at all: water breathing, dolphin's grace, leaping, swiftness, slowness, slow falling, night vision, darkness, frost, health boost, absorption, fire resistance, resistance, luck, bad luck, blindness, nausea, hunger, saturation, haste, fatigue, conduit power * the following effects should work with mobs: invisibility, regeneration, poison, withering, strength, weakness, levitation, glowing * the following effects have no effect on mobs (but can be applied with the API): bad omen, hero of the village --- mods/ITEMS/mcl_campfires/api.lua | 2 +- mods/ITEMS/mcl_mobitems/init.lua | 2 +- mods/ITEMS/mcl_nether/init.lua | 2 +- mods/ITEMS/mcl_potions/commands.lua | 2 +- mods/ITEMS/mcl_potions/functions.lua | 93 +++++++++++++++++----------- 5 files changed, 62 insertions(+), 39 deletions(-) diff --git a/mods/ITEMS/mcl_campfires/api.lua b/mods/ITEMS/mcl_campfires/api.lua index ba6a55960..98318f3f1 100644 --- a/mods/ITEMS/mcl_campfires/api.lua +++ b/mods/ITEMS/mcl_campfires/api.lua @@ -380,7 +380,7 @@ minetest.register_globalstep(function(dtime) etime = 0 for _,pl in pairs(minetest.get_connected_players()) do local armor_feet = pl:get_inventory():get_stack("armor", 5) - if pl and pl:get_player_control().sneak or (minetest.global_exists("mcl_enchanting") and mcl_enchanting.has_enchantment(armor_feet, "frost_walker")) or (minetest.global_exists("mcl_potions") and mcl_potions.has_effect(pl, "fire_proof")) then + if pl and pl:get_player_control().sneak or (minetest.global_exists("mcl_enchanting") and mcl_enchanting.has_enchantment(armor_feet, "frost_walker")) or (minetest.global_exists("mcl_potions") and mcl_potions.has_effect(pl, "fire_resistance")) then return end burn_in_campfire(pl) diff --git a/mods/ITEMS/mcl_mobitems/init.lua b/mods/ITEMS/mcl_mobitems/init.lua index 182bc8ced..01b9a5039 100644 --- a/mods/ITEMS/mcl_mobitems/init.lua +++ b/mods/ITEMS/mcl_mobitems/init.lua @@ -154,7 +154,7 @@ local function drink_milk_delayed(itemstack, player, pointed_thing) ) then mcl_hunger.stop_poison(player) end - mcl_potions._reset_player_effects(player) + mcl_potions._reset_effects(player) end -- Wrapper for handling mcl_hunger delayed eating diff --git a/mods/ITEMS/mcl_nether/init.lua b/mods/ITEMS/mcl_nether/init.lua index 3a57ae427..b69355d5d 100644 --- a/mods/ITEMS/mcl_nether/init.lua +++ b/mods/ITEMS/mcl_nether/init.lua @@ -135,7 +135,7 @@ minetest.register_node("mcl_nether:magma", { -- From walkover mod on_walk_over = function(loc, nodeiamon, player) local armor_feet = player:get_inventory():get_stack("armor", 5) - if player and player:get_player_control().sneak or (minetest.global_exists("mcl_enchanting") and mcl_enchanting.has_enchantment(armor_feet, "frost_walker")) or (minetest.global_exists("mcl_potions") and mcl_potions.has_effect(player, "fire_proof")) then + if player and player:get_player_control().sneak or (minetest.global_exists("mcl_enchanting") and mcl_enchanting.has_enchantment(armor_feet, "frost_walker")) or (minetest.global_exists("mcl_potions") and mcl_potions.has_effect(player, "fire_resistance")) then return end -- Hurt players standing on top of this block diff --git a/mods/ITEMS/mcl_potions/commands.lua b/mods/ITEMS/mcl_potions/commands.lua index 4b4aa0ba7..1c2cd7347 100644 --- a/mods/ITEMS/mcl_potions/commands.lua +++ b/mods/ITEMS/mcl_potions/commands.lua @@ -44,7 +44,7 @@ minetest.register_chatcommand("effect",{ end end elseif P[1] == "clear" then - mcl_potions._reset_player_effects(minetest.get_player_by_name(name)) + mcl_potions._reset_effects(minetest.get_player_by_name(name)) return true, S("Effects cleared for player @1", name) elseif P[1] == "remove" then if not P[2] then diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index d36b8db62..8d85b19b6 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -300,8 +300,10 @@ mcl_potions.register_effect({ get_tt = function(factor) return S("limitless breathing under water") end, + res_condition = function(object) + return (not object:is_player()) -- TODO add support for breath setting for mobs + end, 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 @@ -317,6 +319,9 @@ mcl_potions.register_effect({ get_tt = function(factor) return S("swimming gracefully") end, + res_condition = function(object) + return (not object:is_player()) -- TODO needs mob physics factor API + end, on_hit_timer = function(object, factor, duration) local node = minetest.get_node_or_nil(object:get_pos()) if node and minetest.registered_nodes[node.name] @@ -340,7 +345,7 @@ mcl_potions.register_effect({ return S("-@1% jumping power", math.floor(-factor*100)) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO needs mob physics factor API end, on_start = function(object, factor) playerphysics.add_physics_factor(object, "jump", "mcl_potions:leaping", 1+factor) @@ -361,7 +366,7 @@ mcl_potions.register_effect({ return S("decreases gravity effects") end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO needs mob physics factor API end, on_start = function(object, factor) playerphysics.add_physics_factor(object, "gravity", "mcl_potions:slow_falling", 0.5) @@ -383,7 +388,7 @@ mcl_potions.register_effect({ return S("+@1% running speed", math.floor(factor*100)) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO needs mob physics factor API end, on_start = function(object, factor) playerphysics.add_physics_factor(object, "speed", "mcl_potions:swiftness", 1+factor) @@ -404,7 +409,7 @@ mcl_potions.register_effect({ return S("-@1% running speed", math.floor(factor*100)) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO needs mob physics factor API end, on_start = function(object, factor) playerphysics.add_physics_factor(object, "speed", "mcl_potions:slowness", 1-factor) @@ -441,7 +446,7 @@ mcl_potions.register_effect({ return S("improved vision during the night") end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO what should it do for mobs? end, on_start = function(object, factor) object:get_meta():set_int("night_vision", 1) @@ -466,7 +471,7 @@ mcl_potions.register_effect({ return S("surrounded by darkness").."\n"..S("not seeing anything beyond @1 nodes", factor) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO what should it do for mobs? end, on_start = function(object, factor) object:get_meta():set_int("darkness", 1) @@ -580,7 +585,7 @@ mcl_potions.register_effect({ return S("HP increased by @1", factor) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO needs mob HP modifier API? end, on_start = function(object, factor) object:set_properties({hp_max = minetest.PLAYER_MAX_HP_DEFAULT+factor}) @@ -601,7 +606,7 @@ mcl_potions.register_effect({ return S("absorbs up to @1 incoming damage", factor) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO dmg modifiers don't work for mobs end, on_start = function(object, factor) hb.change_hudbar(object, "absorption", factor, (math.floor(factor/20-0.05)+1)*20) @@ -641,7 +646,7 @@ mcl_potions.register_effect({ return S("resistance to fire damage") end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO dmg modifiers don't work for mobs end, particle_color = "#E49A3A", uses_factor = false, @@ -655,7 +660,7 @@ mcl_potions.register_effect({ return S("resist @1% of incoming damage", math.floor(factor*100)) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO dmg modifiers don't work for mobs end, particle_color = "#2552A5", uses_factor = true, @@ -672,7 +677,7 @@ mcl_potions.register_effect({ description = S("Luck"), particle_color = "#7BFF42", res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO what should it do for mobs? end, on_start = function(object, factor) mcl_luck.apply_luck_modifier(object:get_player_name(), "mcl_potions:luck", factor) @@ -691,7 +696,7 @@ mcl_potions.register_effect({ description = S("Bad Luck"), particle_color = "#887343", res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO what should it do for mobs? end, on_start = function(object, factor) mcl_luck.apply_luck_modifier(object:get_player_name(), "mcl_potions:bad_luck", -factor) @@ -746,7 +751,7 @@ mcl_potions.register_effect({ return S("-1 HP / 1 s, can kill, -@1% running speed", math.floor(factor*100)) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO needs mob physics factor API end, on_start = function(object, factor) mcl_burning.extinguish(object) @@ -799,7 +804,7 @@ mcl_potions.register_effect({ return S("impaired sight") end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO what should it do for mobs? end, on_start = function(object, factor) EF.blindness[object].vignette = object:hud_add({ @@ -842,7 +847,7 @@ mcl_potions.register_effect({ return S("not feeling very well...").."\n"..S("frequency: @1 / 1 s", factor) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO what should it do for mobs? end, on_start = function(object, factor) object:set_lighting({ @@ -891,7 +896,7 @@ mcl_potions.register_effect({ return S("exhausts by @1 per second", factor) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO what should it do for mobs? end, on_start = function(object, factor) hb.change_hudbar(object, "hunger", nil, nil, "mcl_hunger_icon_foodpoison.png", nil, "mcl_hunger_bar_foodpoison.png") @@ -924,7 +929,7 @@ mcl_potions.register_effect({ return S("saturates by @1 per second", factor) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO what should it do for mobs? end, on_step = function(dtime, object, factor, duration) mcl_hunger.set_hunger(object, math.min(mcl_hunger.get_hunger(object)+dtime*factor, 20)) @@ -988,7 +993,7 @@ mcl_potions.register_effect({ return S("+@1% mining and attack speed", math.floor(factor*100)) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO needs mob API support end, on_start = haste_fatigue_hand_update, after_end = function(object) @@ -1009,7 +1014,7 @@ mcl_potions.register_effect({ return S("-@1% mining and attack speed", math.floor((1-factor)*100)) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO needs mob API support end, on_start = haste_fatigue_hand_update, after_end = function(object) @@ -1030,7 +1035,7 @@ mcl_potions.register_effect({ return S("+@1% mining and attack speed in water").."\n"..S("limitless breathing under water", math.floor(factor*100)) end, res_condition = function(object) - return (not object:is_player()) + return (not object:is_player()) -- TODO needs mob API support end, on_start = haste_fatigue_hand_update, on_step = function(dtime, object, factor, duration) @@ -1380,34 +1385,35 @@ function mcl_potions._reset_haste_fatigue_item_meta(player) end mcl_gamemode.register_on_gamemode_change(mcl_potions._reset_haste_fatigue_item_meta) -function mcl_potions._clear_cached_player_data(player) +function mcl_potions._clear_cached_effect_data(object) for name, effect in pairs(EF) do - effect[player] = nil + effect[object] = nil end - - local meta = player:get_meta() + if not object:is_player() then return end + local meta = object: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 +function mcl_potions._reset_effects(object, set_hud) + local set_hud = set_hud + if not object:is_player() then + set_hud = false end local removed_effects = {} for name, effect in pairs(registered_effects) do - if EF[name][player] and effect.on_end then effect.on_end(player) end + if EF[name][object] and effect.on_end then effect.on_end(object) end if effect.after_end then table.insert(removed_effects, effect.after_end) end end - mcl_potions._clear_cached_player_data(player) + mcl_potions._clear_cached_effect_data(object) for i=1, #removed_effects do - removed_effects[i](player) + removed_effects[i](object) end if set_hud ~= false then - potions_set_hud(player) + potions_set_hud(object) end end @@ -1566,17 +1572,17 @@ end minetest.register_on_leaveplayer( function(player) mcl_potions._save_player_effects(player) - mcl_potions._clear_cached_player_data(player) -- clear the buffer to prevent looking for a player not there + mcl_potions._clear_cached_effect_data(player) -- clear the buffer to prevent looking for a player not there icon_ids[player:get_player_name()] = nil end) minetest.register_on_dieplayer( function(player) - mcl_potions._reset_player_effects(player) + mcl_potions._reset_effects(player) potions_set_hud(player) end) minetest.register_on_joinplayer( function(player) - mcl_potions._reset_player_effects(player, false) -- make sure there are no weird holdover effects + mcl_potions._reset_effects(player, false) -- make sure there are no weird holdover effects mcl_potions._load_player_effects(player) mcl_potions._reset_haste_fatigue_item_meta(player) potions_init_icons(player) @@ -1716,12 +1722,29 @@ end -- ██║░░░░░╚██████╔╝██║░╚███║╚█████╔╝░░░██║░░░██║╚█████╔╝██║░╚███║██████╔╝ -- ╚═╝░░░░░░╚═════╝░╚═╝░░╚══╝░╚════╝░░░░╚═╝░░░╚═╝░╚════╝░╚═╝░░╚══╝╚═════╝░ +local registered_res_predicates = {} +-- API +-- This is supposed to add custom resistance functions independent of effects +-- E.g. some entity could be resistant to all (or some) effects under specific conditions +-- predicate - function(object, effect_name) - return true if resists effect +function mcl_potions.register_generic_resistance_predicate(predicate) + if type(predicate) == "function" then + table.insert(registered_res_predicates, predicate) + else + error("Attempted to register non-function as a predicate") + end +end + local function target_valid(object, name) if not object or object:get_hp() <= 0 then return false end local entity = object:get_luaentity() if entity and entity.is_boss then return false end + for i=1, #registered_res_predicates do + if registered_res_predicates[i](object, name) then return false end + end + if not (registered_effects[name].res_condition and registered_effects[name].res_condition(object)) then return true end end From 8f4d5d2e27656bdccb87d1046f3bac70c9afc131 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 17 Apr 2024 21:51:12 +0200 Subject: [PATCH 66/91] Added the ominous potion --- mods/ITEMS/mcl_potions/functions.lua | 3 +++ mods/ITEMS/mcl_potions/potions.lua | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 8d85b19b6..fa524996b 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -713,6 +713,9 @@ mcl_potions.register_effect({ mcl_potions.register_effect({ name = "bad_omen", description = S("Bad Omen"), + get_tt = function(factor) + return S("danger is imminent") + end, particle_color = "#472331", }) diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 7e12d9a94..b651cfbb2 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -806,3 +806,22 @@ mcl_potions.register_potion({ has_arrow = true, }) +mcl_potions.register_potion({ + name = "ominous", + desc_prefix = S("Ominous"), + _tt = nil, + _longdesc = S("Attracts danger."), + image = table.concat({ + "(mcl_potions_potion_overlay.png^[colorize:red:100)", + "^mcl_potions_splash_overlay.png^[colorize:black:100", + "^mcl_potions_potion_bottle.png", + }), + _effect_list = { + bad_omen = { + dur = 6000, + }, + }, + has_splash = false, + has_lingering = false, +}) + From 78ae5ddc26324173433ad901d457a59a5c1361c2 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Wed, 17 Apr 2024 22:52:25 +0200 Subject: [PATCH 67/91] Added some potion recipes Also: * changed the duration of saturation and food poisoning potions * minor code changes --- mods/ITEMS/mcl_potions/init.lua | 34 ++++++++++++++++-------------- mods/ITEMS/mcl_potions/potions.lua | 8 +++---- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index 189a014dc..d70e14f36 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -401,18 +401,14 @@ local awkward_table = { ["mcl_flowers:fourleaf_clover"] = "mcl_potions:luck", ["mcl_farming:potato_item_poison"] = "mcl_potions:nausea", - -- TODO slow falling - -- TODO levitation? - -- TODO darkness? - -- TODO absorption - -- TODO health boost? - -- TODO resistance - -- TODO turtle master? - -- TODO frost - -- TODO blindness? - -- TODO food poisoning? - -- TODO saturation? - -- TODO haste + ["mcl_mobitems:phantom_membrane"] = "mcl_potions:slow_falling", -- TODO add phantom membranes + ["mcl_core:apple_gold"] = "mcl_potions:resistance", + + -- TODO darkness - sculk? + -- TODO absorption - water element? + -- TODO turtle master - earth element? + -- TODO frost - frost element? + -- TODO haste - air element? } -- API -- register a potion recipe brewed from awkward potion @@ -450,7 +446,10 @@ end mcl_potions.register_ingredient_potion("mcl_potions:mundane", mundane_table) local thick_table = { - -- TODO glowing from some shining cave flowers + ["mcl_crimson:shroomlight"] = "mcl_potions:glowing", + ["mcl_mobitems:nether_star"] = "mcl_potions:ominous", + ["mcl_mobitems:ink_sac"] = "mcl_potions:blindness", + ["mcl_farming:carrot_item_gold"] = "mcl_potions:saturation", } -- API -- register a potion recipe brewed from thick potion @@ -495,6 +494,9 @@ local inversion_table = { ["mcl_potions:poison"] = "mcl_potions:harming", ["mcl_potions:luck"] = "mcl_potions:bad_luck", ["mcl_potions:haste"] = "mcl_potions:fatigue", + ["mcl_potions:saturation"] = "mcl_potions:food_poisoning", + ["mcl_potions:slow_falling"] = "mcl_potions:levitation", + ["mcl_potions:absorption"] = "mcl_potions:health_boost", } -- API function mcl_potions.register_inversion_recipe(input, output) @@ -529,9 +531,9 @@ local lingering_table = {} for potion, def in pairs(potions) do if def.has_splash then splash_table[potion] = potion.."_splash" - end - if def.has_lingering then - lingering_table[potion.."_splash"] = potion.."_lingering" + if def.has_lingering then + lingering_table[potion.."_splash"] = potion.."_lingering" + end end end mcl_potions.register_table_modifier("mcl_mobitems:gunpowder", splash_table) diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index b651cfbb2..0d6d1940c 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -764,7 +764,7 @@ mcl_potions.register_potion({ _longdesc = S("Moves bowels too fast."), color = "#83A061", _effect_list = { - food_poisoning = {}, + food_poisoning = {dur=mcl_potions.DURATION_POISON}, }, has_arrow = true, -- TODO implement effect stacking? @@ -777,7 +777,7 @@ mcl_potions.register_potion({ _longdesc = S("Satisfies hunger."), color = "#CEAE29", _effect_list = { - saturation = {}, + saturation = {dur=mcl_potions.DURATION_POISON}, }, has_arrow = true, }) @@ -817,9 +817,7 @@ mcl_potions.register_potion({ "^mcl_potions_potion_bottle.png", }), _effect_list = { - bad_omen = { - dur = 6000, - }, + bad_omen = {dur = 6000}, }, has_splash = false, has_lingering = false, From a4eaaad1a963c77a57134b5e25f1a85bafe3cbf7 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 21 Apr 2024 19:19:42 +0200 Subject: [PATCH 68/91] Remove unused function in mcl_hunger --- mods/PLAYER/mcl_hunger/hunger.lua | 36 ------------------------------- 1 file changed, 36 deletions(-) diff --git a/mods/PLAYER/mcl_hunger/hunger.lua b/mods/PLAYER/mcl_hunger/hunger.lua index c0ba9fb91..2c29e1939 100644 --- a/mods/PLAYER/mcl_hunger/hunger.lua +++ b/mods/PLAYER/mcl_hunger/hunger.lua @@ -99,42 +99,6 @@ function mcl_hunger.reset_bars_poison_hunger(player) end end --- Poison player TODO remove this function -local function poisonp(tick, time, time_left, damage, exhaustion, name) - if not mcl_hunger.active then - return - end - local player = minetest.get_player_by_name(name) - -- First check if player is still there - if not player then - return - end - -- Abort if food poisonings have been stopped - if mcl_hunger.poison_hunger[name] == 0 then - return - end - time_left = time_left + tick - if time_left < time then - minetest.after(tick, poisonp, tick, time, time_left, damage, exhaustion, name) - else - if exhaustion > 0 then - mcl_hunger.poison_hunger [name] = mcl_hunger.poison_hunger[name] - 1 - end - if mcl_hunger.poison_hunger[name] <= 0 then - mcl_hunger.reset_bars_poison_hunger(player) - end - end - - -- Deal damage and exhaust player - -- TODO: Introduce fatal poison at higher difficulties - if player:get_hp()-damage > 0 then - mcl_util.deal_damage(player, damage, {type = "hunger"}) - end - - mcl_hunger.exhaust(name, exhaustion) - -end - local poisonrandomizer = PseudoRandom(os.time()) function mcl_hunger.item_eat(hunger_change, replace_with_item, poisontime, poison, exhaust, poisonchance, sound) From 914e3c6c2a79c643370640ccca0381f0046677e5 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 22 Apr 2024 02:12:54 +0200 Subject: [PATCH 69/91] Effects persist on loads for mobs too --- mods/ENTITIES/mcl_mobs/api.lua | 13 +++++++--- mods/ENTITIES/mcl_mobs/init.lua | 1 + mods/ITEMS/mcl_potions/functions.lua | 37 +++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 8ebdddcac..37db6b46e 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -96,18 +96,20 @@ function mob_class:get_staticdata() local tmp = {} - for _,stat in pairs(self) do + for tag, stat in pairs(self) do local t = type(stat) if t ~= "function" and t ~= "nil" and t ~= "userdata" - and _ ~= "_cmi_components" then - tmp[_] = self[_] + and tag ~= "_cmi_components" then + tmp[tag] = self[tag] end end + tmp._mcl_potions = self._mcl_potions + return minetest.serialize(tmp) end @@ -306,7 +308,10 @@ function mob_class:mob_activate(staticdata, def, dtime) self._run_armor_init = true end - + if not self._mcl_potions then + self._mcl_potions = {} + end + mcl_potions._load_entity_effects(self) if def.after_activate then diff --git a/mods/ENTITIES/mcl_mobs/init.lua b/mods/ENTITIES/mcl_mobs/init.lua index 2b18a6775..3a2e18872 100644 --- a/mods/ENTITIES/mcl_mobs/init.lua +++ b/mods/ENTITIES/mcl_mobs/init.lua @@ -325,6 +325,7 @@ function mcl_mobs.register_mob(name, def) attack_exception = def.attack_exception or function(p) return false end, _spawner = def._spawner, + _mcl_potions = {}, } if minetest.get_modpath("doc_identifier") ~= nil then diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index fa524996b..17323ad7c 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -1339,8 +1339,13 @@ minetest.register_globalstep(function(dtime) if effect.after_end then effect.after_end(object) end if object:is_player() then meta = object:get_meta() - meta:set_string("mcl_potions:"..name, minetest.serialize(EF[name][object])) + meta:set_string("mcl_potions:_EF_"..name, "") potions_set_hud(object) + else + local ent = object:get_luaentity() + if ent then + ent._mcl_potions["_EF_"..name] = nil + end end elseif object:is_player() then if vals.dur == math.huge then @@ -1351,6 +1356,11 @@ minetest.register_globalstep(function(dtime) object:hud_change(icon_ids[object:get_player_name()][vals.hud_index].timestamp, "text", math.floor(dur/60)..string.format(":%02d",math.floor(dur % 60))) end + else + local ent = object:get_luaentity() + if ent then + ent._mcl_potions["_EF_"..name] = EF[name][object] + end end end end @@ -1503,9 +1513,28 @@ function mcl_potions._load_player_effects(player) -- 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:_EF_"..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) + if loaded then + EF[name][player] = loaded + if effect.on_load then + effect.on_load(player, EF[name][player].factor) + end + end + end +end + +function mcl_potions._load_entity_effects(entity) + if not entity or not entity._mcl_potions or entity._mcl_potions == {} then + return + end + local object = entity.object + if not object or not object:get_pos() then return end + for name, effect in pairs(registered_effects) do + local loaded = entity._mcl_potions["_EF_"..name] + if loaded then + EF[name][object] = loaded + if effect.on_load then + effect.on_load(object, EF[name][object].factor) + end end end end From e806d5f3cea9dcb13bf3896d6e5b6b33d854114f Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 22 Apr 2024 02:16:46 +0200 Subject: [PATCH 70/91] Fixed effects still being handled after mob death --- mods/ITEMS/mcl_potions/functions.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 17323ad7c..875d13c7c 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -1333,7 +1333,7 @@ minetest.register_globalstep(function(dtime) end end - if not EF[name][object] or EF[name][object].timer >= vals.dur then + if not object or not EF[name][object] or EF[name][object].timer >= vals.dur or not object:get_pos() then if effect.on_end then effect.on_end(object) end EF[name][object] = nil if effect.after_end then effect.after_end(object) end From 63b2da7aa0cd3a572a728ff3feecff764209dbf9 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 22 Apr 2024 02:26:26 +0200 Subject: [PATCH 71/91] Added on_save_effect support for mobs --- mods/ENTITIES/mcl_mobs/api.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 37db6b46e..873d05bf2 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -109,6 +109,12 @@ function mob_class:get_staticdata() end tmp._mcl_potions = self._mcl_potions + if tmp._mcl_potions then + for name_raw, data in pairs(tmp._mcl_potions) do + local def = mcl_potions.registered_effects[name_raw:match("^_EF_(.+)$")] + if def and def.on_save_effect then def.on_save_effect(self.object) end + end + end return minetest.serialize(tmp) end From 9e9507efeb87f7cfc078447afa4dadbd326178d2 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 22 Apr 2024 03:23:13 +0200 Subject: [PATCH 72/91] Plant placement and drop fixes --- mods/CORE/mcl_util/init.lua | 5 +++-- mods/ITEMS/mcl_flowers/init.lua | 3 ++- mods/ITEMS/mcl_potions/functions.lua | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index 4204e218d..b6fd71673 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -438,10 +438,11 @@ function mcl_util.generate_on_place_plant_function(condition) if not def_under or not def_above then return itemstack end - if def_under.buildable_to then + if def_under.buildable_to and def_under.name ~= itemstack:get_name() then place_pos = pointed_thing.under - elseif def_above.buildable_to then + elseif def_above.buildable_to and def_above.name ~= itemstack:get_name() then place_pos = pointed_thing.above + pointed_thing.under = pointed_thing.above else return itemstack end diff --git a/mods/ITEMS/mcl_flowers/init.lua b/mods/ITEMS/mcl_flowers/init.lua index 7c1fa1de4..85a65a165 100644 --- a/mods/ITEMS/mcl_flowers/init.lua +++ b/mods/ITEMS/mcl_flowers/init.lua @@ -194,8 +194,8 @@ def_clover.mesh = "mcl_clover_3leaf.obj" def_clover.tiles = { "mcl_flowers_clover.png" } def_clover.inventory_image = "mcl_flowers_clover_inv.png" def_clover.wield_image = "mcl_flowers_clover_inv.png" -def_clover.drop = nil def_clover.use_texture_alpha = "clip" +def_clover.drop = "mcl_flowers:clover" def_clover.selection_box = { type = "fixed", fixed = { -4/16, -0.5, -4/16, 4/16, 0, 4/16 }, @@ -212,6 +212,7 @@ def_4l_clover.tiles = { "mcl_flowers_fourleaf_clover.png" } def_4l_clover.inventory_image = "mcl_flowers_fourleaf_clover_inv.png" def_4l_clover.wield_image = "mcl_flowers_fourleaf_clover_inv.png" def_4l_clover.use_texture_alpha = "clip" +def_4l_clover.drop = "mcl_flowers:fourleaf_clover" minetest.register_node("mcl_flowers:fourleaf_clover", def_4l_clover) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 875d13c7c..41c077b81 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -1673,7 +1673,7 @@ function mcl_potions.make_invisible(obj_ref, hide) mcl_player.player_set_visibility(obj_ref, true) obj_ref:set_nametag_attributes({ color = { r = 255, g = 255, b = 255, a = 255 } }) end - else -- TODO make below section (and preferably other effects on mobs) rely on metadata + else if hide then local luaentity = obj_ref:get_luaentity() EF.invisibility[obj_ref].old_size = luaentity.visual_size From 53d640028e2422349307de0e19a1dcf64d5616e9 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Mon, 22 Apr 2024 04:51:01 +0200 Subject: [PATCH 73/91] Added effect stacking option to the potions API Also: * Frost and Food Poisoning potion now stack their effects * fixed a crash related to tipped arrows --- mods/HELP/mcl_tt/snippets_mcl.lua | 1 + mods/ITEMS/mcl_potions/lingering.lua | 5 ++++- mods/ITEMS/mcl_potions/potions.lua | 26 ++++++++++++++++++------- mods/ITEMS/mcl_potions/splash.lua | 7 +++++-- mods/ITEMS/mcl_potions/tipped_arrow.lua | 15 ++++++++------ 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/mods/HELP/mcl_tt/snippets_mcl.lua b/mods/HELP/mcl_tt/snippets_mcl.lua index 7b25f0750..639422295 100644 --- a/mods/HELP/mcl_tt/snippets_mcl.lua +++ b/mods/HELP/mcl_tt/snippets_mcl.lua @@ -171,6 +171,7 @@ tt.register_snippet(function(itemstring, _, itemstack) if effect.uses_factor then factor = effect.level_to_factor(ef_level) end if effect.get_tt then ef_tt = minetest.colorize("grey", effect.get_tt(factor)) else ef_tt = "" end if ef_tt ~= "" then s = s.. ef_tt.. "\n" end + if details.effect_stacks then s = s.. minetest.colorize("grey", S("...stacks")).. "\n" end end end return s:trim() diff --git a/mods/ITEMS/mcl_potions/lingering.lua b/mods/ITEMS/mcl_potions/lingering.lua index ea0d0f36c..0eeb40b50 100644 --- a/mods/ITEMS/mcl_potions/lingering.lua +++ b/mods/ITEMS/mcl_potions/lingering.lua @@ -90,6 +90,9 @@ minetest.register_globalstep(function(dtime) else dur = details.dur end + if details.effect_stacks then + ef_level = ef_level + mcl_potions.get_effect_level(obj, name) + end if mcl_potions.give_effect_by_level(name, obj, ef_level, dur) then applied = true end @@ -97,7 +100,7 @@ minetest.register_globalstep(function(dtime) end if vals.def.custom_effect - and vals.def.custom_effect(obj, (vals.potency+1) * mcl_potions.LINGERING_FACTOR) then + and vals.def.custom_effect(obj, (vals.potency+1) * mcl_potions.LINGERING_FACTOR, plus) then applied = true end diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 0d6d1940c..9ebf64ad2 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -64,7 +64,7 @@ function return_on_use(def, effect, dur) --def.on_use(user, effect, dur) -- Will do effect immediately but not reduce item count until eating delay ends which makes it exploitable by deliberately not finishing delay - -- Wrapper for handling mcl_hunger delayed eating + -- Wrapper for handling mcl_hunger delayed eating TODO migrate to the new function local name = user:get_player_name() mcl_hunger.eat_internal[name]._custom_itemstack = itemstack -- Used as comparison to make sure the custom wrapper executes only when the same item is eaten mcl_hunger.eat_internal[name]._custom_var = { @@ -122,11 +122,14 @@ local function generate_on_use(effects, color, on_use, custom_effect) else dur = details.dur end + if details.effect_stacks then + ef_level = ef_level + mcl_potions.get_effect_level(user, name) + end mcl_potions.give_effect_by_level(name, user, ef_level, dur) end if on_use then on_use(user, potency+1) end - if custom_effect then custom_effect(user, potency+1) end + if custom_effect then custom_effect(user, potency+1, plus) end itemstack = minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) if itemstack then mcl_potions._use_potion(user, color) end @@ -162,6 +165,7 @@ end -- -- -- dur_variable - bool - whether variants of the potion should have the length of this effect changed - -- -- -- - defaults to true -- -- -- - if at least one effect has this set to true, the potion has a "plus" variant +-- -- -- effect_stacks - bool - whether the effect stacks - defaults to false -- uses_level - bool - whether the potion should come at different levels - -- - defaults to true if uses_level is true for at least one effect, else false -- drinkable - bool - defaults to true @@ -172,7 +176,7 @@ end -- default_potent_level - int - potion level used for the default potent variant - defaults to 2 -- default_extend_level - int - extention level (amount of +) used for the default extended variant - defaults to 1 -- custom_on_use - function(user, level) - called when the potion is drunk, returns true on success --- custom_effect - function(object, level) - called when the potion effects are applied, returns true on success +-- custom_effect - function(object, level, plus) - called when the potion effects are applied, returns true on success -- custom_splash_effect - function(pos, level) - called when the splash potion explodes, returns true on success -- custom_linger_effect - function(pos, radius, level) - called on the lingering potion step, returns true on success function mcl_potions.register_potion(def) @@ -195,6 +199,9 @@ function mcl_potions.register_potion(def) pdef.description = S("Strange Potion") end pdef._tt_help = def._tt + if def._tt and def.effect_stacks then + pdef._tt_help = pdef._tt_help .. "\n" .. S("Stacks the effect") + end pdef._dynamic_tt = def._dynamic_tt local potion_longdesc = def._longdesc if def._effect_list then @@ -230,6 +237,7 @@ function mcl_potions.register_potion(def) level_scaling = details.level_scaling or 1, dur = details.dur or mcl_potions.DURATION, dur_variable = durvar, + effect_stacks = details.effect_stacks and true or false } else error("Unable to register potion: effect not registered") @@ -727,10 +735,12 @@ mcl_potions.register_potion({ _longdesc = S("Freezes..."), color = "#5B7DAA", _effect_list = { - frost = {}, + frost = { + dur = mcl_potions.DURATION_POISON, + effect_stacks = true, + }, }, has_arrow = true, - -- TODO implement effect stacking? }) mcl_potions.register_potion({ @@ -764,10 +774,12 @@ mcl_potions.register_potion({ _longdesc = S("Moves bowels too fast."), color = "#83A061", _effect_list = { - food_poisoning = {dur=mcl_potions.DURATION_POISON}, + food_poisoning = { + dur = mcl_potions.DURATION_POISON, + effect_stacks = true, + }, }, has_arrow = true, - -- TODO implement effect stacking? }) mcl_potions.register_potion({ diff --git a/mods/ITEMS/mcl_potions/splash.lua b/mods/ITEMS/mcl_potions/splash.lua index 2fb9f362c..3b9261458 100644 --- a/mods/ITEMS/mcl_potions/splash.lua +++ b/mods/ITEMS/mcl_potions/splash.lua @@ -151,6 +151,9 @@ function mcl_potions.register_splash(name, descr, color, def) else dur = details.dur end + if details.effect_stacks then + ef_level = ef_level + mcl_potions.get_effect_level(obj, name) + end if rad > 0 then mcl_potions.give_effect_by_level(name, obj, ef_level, redux_map[rad]*dur) else @@ -162,9 +165,9 @@ function mcl_potions.register_splash(name, descr, color, def) if def.custom_effect then local power = (potency+1) * mcl_potions.SPLASH_FACTOR if rad > 0 then - def.custom_effect(obj, redux_map[rad] * power) + def.custom_effect(obj, redux_map[rad] * power, plus) else - def.custom_effect(obj, power) + def.custom_effect(obj, power, plus) end end end diff --git a/mods/ITEMS/mcl_potions/tipped_arrow.lua b/mods/ITEMS/mcl_potions/tipped_arrow.lua index a6a1b71bc..1833e7169 100644 --- a/mods/ITEMS/mcl_potions/tipped_arrow.lua +++ b/mods/ITEMS/mcl_potions/tipped_arrow.lua @@ -301,10 +301,14 @@ function mcl_potions.register_arrow(name, desc, color, def) else dur = details.dur end + dur = dur * mcl_potions.SPLASH_FACTOR + if details.effect_stacks then + ef_level = ef_level + mcl_potions.get_effect_level(obj, name) + end mcl_potions.give_effect_by_level(name, obj, ef_level, dur) end end - if def.custom_effect then def.custom_effect(obj, potency+1) end + if def.custom_effect then def.custom_effect(obj, potency+1, plus) end end else obj:punch(self.object, 1.0, { @@ -329,14 +333,13 @@ function mcl_potions.register_arrow(name, desc, color, def) dur = details.dur end dur = dur * mcl_potions.SPLASH_FACTOR - if rad > 0 then - mcl_potions.give_effect_by_level(name, obj, ef_level, redux_map[rad]*dur) - else - mcl_potions.give_effect_by_level(name, obj, ef_level, dur) + if details.effect_stacks then + ef_level = ef_level + mcl_potions.get_effect_level(obj, name) end + mcl_potions.give_effect_by_level(name, obj, ef_level, dur) end end - if def.custom_effect then def.custom_effect(obj, potency+1) end + if def.custom_effect then def.custom_effect(obj, potency+1, plus) end end if is_player then From a039e056a5f8bc86f552bc3741ea4b9d099beb29 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 27 Apr 2024 00:59:22 +0200 Subject: [PATCH 74/91] Support delayed drinking with new potions API --- mods/ITEMS/mcl_potions/potions.lua | 111 +++++++++++------------------ 1 file changed, 43 insertions(+), 68 deletions(-) diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 9ebf64ad2..cc83954c7 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -46,51 +46,6 @@ end -- ╚═╝░░░░░░╚════╝░░░░╚═╝░░░╚═╝░╚════╝░╚═╝░░╚══╝╚═════╝░ -function return_on_use(def, effect, dur) - return function (itemstack, user, pointed_thing) - if pointed_thing.type == "node" then - if user and not user:get_player_control().sneak then - -- Use pointed node's on_rightclick function first, if present - local node = minetest.get_node(pointed_thing.under) - if user and not user:get_player_control().sneak then - if minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name].on_rightclick then - return minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, user, itemstack) or itemstack - end - end - end - elseif pointed_thing.type == "object" then - return itemstack - end - - --def.on_use(user, effect, dur) -- Will do effect immediately but not reduce item count until eating delay ends which makes it exploitable by deliberately not finishing delay - - -- Wrapper for handling mcl_hunger delayed eating TODO migrate to the new function - local name = user:get_player_name() - mcl_hunger.eat_internal[name]._custom_itemstack = itemstack -- Used as comparison to make sure the custom wrapper executes only when the same item is eaten - mcl_hunger.eat_internal[name]._custom_var = { - user = user, - effect = effect, - dur = dur, - } - mcl_hunger.eat_internal[name]._custom_func = def.on_use - mcl_hunger.eat_internal[name]._custom_wrapper = function(name) - - mcl_hunger.eat_internal[name]._custom_func( - mcl_hunger.eat_internal[name]._custom_var.user, - mcl_hunger.eat_internal[name]._custom_var.effect, - mcl_hunger.eat_internal[name]._custom_var.dur - ) - end - - local old_name, old_count = itemstack:get_name(), itemstack:get_count() - itemstack = minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) - if old_name ~= itemstack:get_name() or old_count ~= itemstack:get_count() then - mcl_potions._use_potion(itemstack, user, def.color) - end - return itemstack - end -end - local function generate_on_use(effects, color, on_use, custom_effect) return function(itemstack, user, pointed_thing) if pointed_thing.type == "node" then @@ -104,32 +59,52 @@ local function generate_on_use(effects, color, on_use, custom_effect) return itemstack end - local potency = itemstack:get_meta():get_int("mcl_potions:potion_potent") - local plus = itemstack:get_meta():get_int("mcl_potions:potion_plus") - local ef_level - local dur - for name, details in pairs(effects) do - if details.uses_level then - ef_level = details.level + details.level_scaling * (potency) - else - ef_level = details.level - end - if details.dur_variable then - dur = details.dur * math.pow(mcl_potions.PLUS_FACTOR, plus) - if potency>0 and details.uses_level then - dur = dur / math.pow(mcl_potions.POTENT_FACTOR, potency) + -- Wrapper for handling mcl_hunger delayed eating + local player_name = user:get_player_name() + mcl_hunger.eat_internal[player_name]._custom_itemstack = itemstack -- Used as comparison to make sure the custom wrapper executes only when the same item is eaten + mcl_hunger.eat_internal[player_name]._custom_var = { + user = user, + effects = effects, + on_use = on_use, + custom_effect = custom_effect, + } + mcl_hunger.eat_internal[player_name]._custom_func = function(itemstack, user, effects, on_use, custom_effect) + local potency = itemstack:get_meta():get_int("mcl_potions:potion_potent") + local plus = itemstack:get_meta():get_int("mcl_potions:potion_plus") + local ef_level + local dur + for name, details in pairs(effects) do + if details.uses_level then + ef_level = details.level + details.level_scaling * (potency) + else + ef_level = details.level end - else - dur = details.dur + if details.dur_variable then + dur = details.dur * math.pow(mcl_potions.PLUS_FACTOR, plus) + if potency>0 and details.uses_level then + dur = dur / math.pow(mcl_potions.POTENT_FACTOR, potency) + end + else + dur = details.dur + end + if details.effect_stacks then + ef_level = ef_level + mcl_potions.get_effect_level(user, name) + end + mcl_potions.give_effect_by_level(name, user, ef_level, dur) end - if details.effect_stacks then - ef_level = ef_level + mcl_potions.get_effect_level(user, name) - end - mcl_potions.give_effect_by_level(name, user, ef_level, dur) - end - if on_use then on_use(user, potency+1) end - if custom_effect then custom_effect(user, potency+1, plus) end + if on_use then on_use(user, potency+1) end + if custom_effect then custom_effect(user, potency+1, plus) end + end + mcl_hunger.eat_internal[player_name]._custom_wrapper = function(player_name) + mcl_hunger.eat_internal[player_name]._custom_func( + mcl_hunger.eat_internal[player_name]._custom_itemstack, + mcl_hunger.eat_internal[player_name]._custom_var.user, + mcl_hunger.eat_internal[player_name]._custom_var.effects, + mcl_hunger.eat_internal[player_name]._custom_var.on_use, + mcl_hunger.eat_internal[player_name]._custom_var.custom_effect + ) + end itemstack = minetest.do_item_eat(0, "mcl_potions:glass_bottle", itemstack, user, pointed_thing) if itemstack then mcl_potions._use_potion(user, color) end From bdaff930e0cb53a14601c85019c55be2ebcce82b Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 27 Apr 2024 03:26:01 +0200 Subject: [PATCH 75/91] Documentation update --- mods/ITEMS/mcl_potions/API.md | 318 +++++++++++++++++++++++++++ mods/ITEMS/mcl_potions/functions.lua | 4 +- 2 files changed, 320 insertions(+), 2 deletions(-) create mode 100644 mods/ITEMS/mcl_potions/API.md diff --git a/mods/ITEMS/mcl_potions/API.md b/mods/ITEMS/mcl_potions/API.md new file mode 100644 index 000000000..be0784e22 --- /dev/null +++ b/mods/ITEMS/mcl_potions/API.md @@ -0,0 +1,318 @@ +## Potions and Effects API + + +* [Potions and Effects API](#potions-and-effects-api) + * [Namespace](#namespace) + * [Effects](#effects) + * [Functions](#functions) + * [Deprecated Functions](#deprecated-functions) + * [Tables](#tables) + * [Internally registered effects](#internally-registered-effects) + * [Constants](#constants) + * [Effect Definition](#effect-definition) + * [HP Hudbar Modifiers](#hp-hudbar-modifiers) + * [Functions](#functions) + * [HP Hudbar Modifier Definition](#hp-hudbar-modifier-definition) + * [Potions](#potions) + * [Functions](#functions) + * [Tables](#tables) + * [Internally registered potions](#internally-registered-potions) + * [Constants](#constants) + * [Potion Definition](#potion-definition) + * [Brewing](#brewing) + * [Functions](#functions) + * [Miscellaneous Functions](#miscellaneous-functions) + + +### Namespace +All of the API is defined in the `mcl_potions` namespace. + +### Effects +This section describes parts of the API related to defining and managing effects on players and entities. The mod defines a bunch of effects internally using the same API as described below. + +#### Functions +`mcl_potions.register_effect(def)` – takes an effect definition (`def`) and registers an effect if the definition is valid, and adds the known parts of the definition as well as the outcomes of processing of some parts of the definition to the `mcl_potions.registered_effects` table. This should only be used at load time. + + +`mcl_potions.apply_haste_fatigue(toolcaps, h_fac, f_fac)` – takes a table of tool capabilities (`toolcaps`) and modifies it using the provided haste factor (`h_fac`) and fatigue factor (`f_fac`). The factors default to no-op values. + + +`mcl_potions.hf_update_internal(hand, object)` – returns the `hand` of the `object` updated according to their combined haste and fatigue. **This doesn't change anything by itself!** Manual update of the hand with the hand returned by this function has to be done. This should only be called in situations that are *directly* impacted by haste and/or fatigue, and therefore require an update of the hand. + + +`mcl_potions.update_haste_and_fatigue(player)` – updates haste and fatigue on a `player` (described by an ObjectRef). This should be called whenever an update of the haste-type and fatigue-type effects is desired. + + +`mcl_potions._reset_haste_fatigue_item_meta(player)` – resets the item meta changes caused by haste-type and fatigue-type effects throughout the inventory of the `player` described by an ObjectRef. + + +`mcl_potions._clear_cached_effect_data(object)` – clears cashed effect data for the `object`. This shouldn't be used for resetting effects. + + +`mcl_potions._reset_effects(object, set_hud)` – actually resets the effects for the `object`. It also updates HUD if `set_hud` is `true` or undefined (`nil`). + + +`mcl_potions._save_player_effects(player)` – saves all effects of the `player` described by an ObjectRef to metadata. + + +`mcl_potions._load_player_effects(player)` – loads all effects from the metadata of the `player` described by an ObjectRef. + + +`mcl_potions._load_entity_effects(entity)` – loads all effects from the `entity` (a LuaEntity). + + +`mcl_potions.has_effect(object, effect_name)` – returns `true` if `object` (described by an ObjectRef) has the effect of the ID `effect_name`, `false` otherwise. + + +`mcl_potions.get_effect(object, effect_name)` - returns a table containing values of the effect of the ID `effect_name` on the `object` if the object has the named effect, `false` otherwise. + + +`mcl_potions.get_effect_level(object, effect_name)` – returns the level of the effect of the ID `effect_name` on the `object`. If the effect has no levels, returns `1`. If the object doesn't have the effect, returns `0`. If the effect is not registered, returns `nil`. + + +`mcl_potions.get_total_haste(object)` – returns the total haste of the `object` (from all haste-type effects). + + +`mcl_potions.get_total_fatigue(object)` – returns the total fatigue of the `object` (from all fatigue-type effects). + + +`mcl_potions.clear_effect(object, effect)` – attempts to remove the effect of the ID `effect` from the `object`. If the effect is not registered, logs a warning and returns `false`. Otherwise, returns `nil`. + + +`mcl_potions.make_invisible(obj_ref, hide)` – makes the object going by the `obj_ref` invisible if `hide` is true, visible otherwise. + + +`mcl_potions.register_generic_resistance_predicate(predicate)` – registers an arbitrary effect resistance predicate. This can be used e.g. to make some entity resistant to all (or some) effects under specific conditions. + +* `predicate` – `function(object, effect_name)` - return `true` if `object` resists effect of the ID `effect_name` + + +`mcl_potions.give_effect(name, object, factor, duration, no_particles)` – attempts to give effect of the ID `name` to the `object` with the provided `factor` and `duration`. If `no_particles` is `true`, no particles will be emitted from the object when under the effect. If the effect is not registered, target is invalid (or resistant), or the same effect with more potency is already applied to the target, this function does nothing and returns `false`. On success, this returns `true`. + + +`mcl_potions.give_effect_by_level(name, object, level, duration, no_particles)` – attempts to give effect of the ID `name` to the `object` with the provided `level` and `duration`. If `no_particles` is `true`, no particles will be emitted from the object when under the effect. This converts `level` to factor and calls `mcl_potions.give_effect()` internally, returning the return value of that function. `level` equal to `0` is no-op. + + +`mcl_potions.healing_func(object, hp)` – attempts to heal the `object` by `hp`. Negative `hp` harms magically instead. + + +#### Deprecated functions +**Don't use the following functions, use the above API instead!** The following are only provided for backwards compatibility and will be removed later. They all call `mcl_potions.give_effect()` internally. + +* `mcl_potions.strength_func(object, factor, duration)` +* `mcl_potions.leaping_func(object, factor, duration)` +* `mcl_potions.weakness_func(object, factor, duration)` +* `mcl_potions.swiftness_func(object, factor, duration)` +* `mcl_potions.slowness_func(object, factor, duration)` +* `mcl_potions.withering_func(object, factor, duration)` +* `mcl_potions.poison_func(object, factor, duration)` +* `mcl_potions.regeneration_func(object, factor, duration)` +* `mcl_potions.invisiblility_func(object, null, duration)` +* `mcl_potions.water_breathing_func(object, null, duration)` +* `mcl_potions.fire_resistance_func(object, null, duration)` +* `mcl_potions.night_vision_func(object, null, duration)` +* `mcl_potions.bad_omen_func(object, factor, duration)` + + + +#### Tables +`mcl_potions.registered_effects` – contains all effects that have been registered. You can read from it various data about the effects. You can overwrite the data and alter the effects' definitions too, but this is discouraged, i.e. only do this if you really know what you are doing. You shouldn't add effects directly to this table, as this would skip important setup; instead use the `mcl_potions.register_effect()` function, which is described above. + +#### Internally registered effects +You can't register effects going by these names, because they are already used: +* `invisibility` +* `poison` +* `regeneration` +* `strength` +* `weakness` +* `weakness` +* `dolphin_grace` +* `leaping` +* `slow_falling` +* `swiftness` +* `slowness` +* `levitation` +* `night_vision` +* `darkness` +* `glowing` +* `health_boost` +* `absorption` +* `fire_resistance` +* `resistance` +* `luck` +* `bad_luck` +* `bad_omen` +* `hero_of_village` +* `withering` +* `frost` +* `blindness` +* `nausea` +* `food_poisoning` +* `saturation` +* `haste` +* `fatigue` +* `conduit_power` + +#### Constants +`mcl_potions.LONGEST_MINING_TIME` – longest mining time of one block that can be achieved by slowing down the mining by fatigue-type effects. + +`mcl_potions.LONGEST_PUNCH_INTERVAL` – longest punch interval that can be achieved by slowing down the punching by fatigue-type effects. + +#### Effect Definition +```lua +def = { +-- required parameters in def: + name = string -- effect name in code (unique ID) - can't be one of the reserved words ("list", "heal", "remove", "clear") + description = S(string) -- actual effect name in game +-- optional parameters in def: + get_tt = function(factor) -- returns tooltip description text for use with potions + 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 + after_end = function(object) -- called when the effect wears off, after purging the data of the effect + on_save_effect = function(object -- called when the effect is to be serialized for saving (supposed to do cleanup) + particle_color = string -- colorstring for particles - defaults to #3000EE + uses_factor = bool -- whether factor affects the effect + lvl1_factor = number -- factor for lvl1 effect - defaults to 1 if uses_factor + lvl2_factor = number -- 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, pass empty string for all damage + dmg_mod_is_type = bool -- damage_modifier string is used as type instead of flag of damage, defaults to false + modifier_func = function(damage, effect_vals) -- see damage_modifier, if not defined damage_modifier defaults to 100% resistance + modifier_priority = integer -- priority passed when registering damage_modifier - defaults to -50 + affects_item_speed = table +-- -- if provided, effect gets added to the item_speed_effects table, this should be true if the effect affects item speeds, +-- -- otherwise it won't work properly with other such effects (like haste and fatigue) +-- -- -- factor_is_positive - bool - whether values of factor between 0 and 1 should be considered +factor% or speed multiplier +-- -- -- - obviously +factor% is positive and speed multiplier is negative interpretation +-- -- -- - values of factor higher than 1 will have a positive effect regardless +-- -- -- - values of factor lower than 0 will have a negative effect regardless +} +``` + +### HP Hudbar Modifiers +This part of the API allows complex modification of the HP hudbar. It is mainly required here, so it is defined here. It may be moved to a different mod in the future. + +#### Functions +`mcl_potions.register_hp_hudbar_modifier(def)` – this function takes a modifier definition (`def`, described below) and registers a HP hudbar modifier if the definition is valid. + +#### HP Hudbar Modifier Definition +```lua +def = { +-- required parameters in def: + predicate = function(player) -- returns true if player fulfills the requirements (eg. has the effects) for the hudbar look + icon = string -- name of the icon to which the modifier should change the HP hudbar heart + priority = signed_int -- lower gets checked first, and first fulfilled predicate applies its modifier +} +``` + +### Potions +Magic! + +#### Functions +`mcl_potions.register_potion(def)` – takes a potion definition (`def`) and registers a potion if the definition is valid, and adds the known parts of the definition as well as the outcomes of processing of some parts of the definition to the `mcl_potions.registered_effects` table. This, depending on some fields of the definition, may as well register the corresponding splash potion, lingering potion and tipped arrow. This should only be used at load time. + +`mcl_potions.register_splash(name, descr, color, def)` – registers a splash potion (item and entity when thrown). This is mostly part of the internal API and probably shouldn't be used from outside, therefore not providing exact description. This is used by `mcl_potions.register_potion()`. + +`mcl_potions.register_lingering(name, descr, color, def)` – registers a lingering potion (item and entity when thrown). This is mostly part of the internal API and probably shouldn't be used from outside, therefore not providing exact description. This is used by `mcl_potions.register_potion()`. + +`mcl_potions.register_arrow(name, desc, color, def)` – registers a tipped arrow (item and entity when shot). This is mostly part of the internal API and probably shouldn't be used from outside, therefore not providing exact description. This is used by `mcl_potions.register_potion()`. + +#### Tables +`mcl_potions.registered_potions` – contains all potions that have been registered. You can read from it various data about the potions. You can overwrite the data and alter the definitions too, but this is discouraged, i.e. only do this if you really know what you are doing. You shouldn't add potions directly to this table, because they have to be registered as items too; instead use the `mcl_potions.register_potion()` function, which is described above. Some brewing recipes are autofilled based on this table after the loading of all the mods is done. + +#### Constants +* `mcl_potions.POTENT_FACTOR = 2` +* `mcl_potions.PLUS_FACTOR = 8/3` +* `mcl_potions.INV_FACTOR = 0.50` +* `mcl_potions.DURATION = 180` +* `mcl_potions.DURATION_INV = mcl_potions.DURATION * mcl_potions.INV_FACTOR` +* `mcl_potions.DURATION_POISON = 45` +* `mcl_potions.II_FACTOR = mcl_potions.POTENT_FACTOR` – **DEPRECATED** +* `mcl_potions.DURATION_PLUS = mcl_potions.DURATION * mcl_potions.PLUS_FACTOR` – **DEPRECATED** +* `mcl_potions.DURATION_2 = mcl_potions.DURATION / mcl_potions.II_FACTOR` – **DEPRECATED** +* `mcl_potions.SPLASH_FACTOR = 0.75` +* `mcl_potions.LINGERING_FACTOR = 0.25` + +#### Potion Definition +```lua +def = { +-- required parameters in def: + name = string, -- potion name in code +-- optional parameters in def: + desc_prefix = S(string), -- part of visible potion name, comes before the word "Potion" + desc_suffix = S(string), -- part of visible potion name, comes after the word "Potion" + _tt = S(string), -- custom tooltip text + _dynamic_tt = function(level), -- returns custom tooltip text dependent on potion level + _longdesc = S(string), -- text for in=game documentation + stack_max = int, -- max stack size - defaults to 1 + image = string, -- name of a custom texture of the potion icon + color = string, -- colorstring for potion icon when image is not defined - defaults to #0000FF + groups = table, -- item groups definition for the regular potion, not splash or lingering - +-- - must contain _mcl_potion=1 for tooltip to include dynamic_tt and effects +-- - defaults to {brewitem=1, food=3, can_eat_when_full=1, _mcl_potion=1} + nocreative = bool, -- adds a not_in_creative_inventory=1 group - defaults to false + _effect_list = {, -- all the effects dealt by the potion in the format of tables +-- -- the name of each sub-table should be a name of a registered effect, and fields can be the following: + uses_level = bool, -- whether the level of the potion affects the level of the effect - +-- -- -- - defaults to the uses_factor field of the effect definition + level = int, -- used as the effect level if uses_level is false and for lvl1 potions - defaults to 1 + level_scaling = int, -- used as the number of effect levels added per potion level - defaults to 1 - +-- -- -- - this has no effect if uses_level is false + dur = float, -- duration of the effect in seconds - defaults to mcl_potions.DURATION + dur_variable = bool, -- whether variants of the potion should have the length of this effect changed - +-- -- -- - defaults to true +-- -- -- - if at least one effect has this set to true, the potion has a "plus" variant + effect_stacks = bool, -- whether the effect stacks - defaults to false + } + uses_level = bool, -- whether the potion should come at different levels - +-- - defaults to true if uses_level is true for at least one effect, else false + drinkable = bool, -- defaults to true + has_splash = bool, -- defaults to true + has_lingering = bool, -- defaults to true + has_arrow = bool, -- defaults to false + has_potent = bool, -- whether there is a potent (e.g. II) variant - defaults to the value of uses_level + default_potent_level = int, -- potion level used for the default potent variant - defaults to 2 + default_extend_level = int, -- extention level (amount of +) used for the default extended variant - defaults to 1 + custom_on_use = function(user, level), -- called when the potion is drunk, returns true on success + custom_effect = function(object, level, plus), -- called when the potion effects are applied, returns true on success + custom_splash_effect = function(pos, level), -- called when the splash potion explodes, returns true on success + custom_linger_effect = function(pos, radius, level), -- called on the lingering potion step, returns true on success +} +``` + +### Brewing +Functions supporting brewing potions, used by the `mcl_brewing` module, which calls `mcl_potions.get_alchemy()`. + +#### Functions +`mcl_potions.register_ingredient_potion(input, out_table)` – registers a potion (`input`, item string) that can be combined with multiple ingredients for different outcomes; `out_table` contains the recipes for those outcomes + +`mcl_potions.register_water_brew(ingr, potion)` – registers a `potion` (item string) brewed from water with a specific ingredient (`ingr`) + +`mcl_potions.register_awkward_brew(ingr, potion)` – registers a `potion` (item string) brewed from an awkward potion with a specific ingredient (`ingr`) + +`mcl_potions.register_mundane_brew(ingr, potion)` – registers a `potion` (item string) brewed from a mundane potion with a specific ingredient (`ingr`) + +`mcl_potions.register_thick_brew(ingr, potion)` – registers a `potion` (item string) brewed from a thick potion with a specific ingredient (`ingr`) + +`mcl_potions.register_table_modifier(ingr, modifier)` – registers a brewing recipe altering the potion using a table; this is supposed to substitute one item with another + +`mcl_potions.register_inversion_recipe(input, output)` – what it says + +`mcl_potions.register_meta_modifier(ingr, mod_func)` – registers a brewing recipe altering the potion using a function; this is supposed to be a recipe that changes metadata only + +`mcl_potions.get_alchemy(ingr, pot)` – finds an alchemical recipe for given ingredient and potion; returns outcome + +### Miscellaneous Functions +`mcl_potions._extinguish_nearby_fire(pos, radius)` – attempts to extinguish fires in an area, both on objects and nodes. + +`mcl_potions._add_spawner(obj, color)` – adds a particle spawner denoting an effect being in action. + +`mcl_potions._use_potion(obj, color)` – visual and sound effects of drinking a potion. + +`mcl_potions.is_obj_hit(self, pos)` – determines if an object is hit (by a thrown potion). diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 41c077b81..4ab98491a 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -97,8 +97,8 @@ end -- on_save_effect - function(object - called when the effect is to be serialized for saving (supposed to do cleanup) -- 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 +-- lvl1_factor - number - factor for lvl1 effect - defaults to 1 if uses_factor +-- lvl2_factor - number - 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, pass empty string for all damage From dc7b1869b747f829bd984abc63a441707e8442da Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 27 Apr 2024 04:28:21 +0200 Subject: [PATCH 76/91] Move most of the game to the new API --- mods/ENTITIES/mcl_mobs/physics.lua | 2 +- mods/ENVIRONMENT/mcl_raids/init.lua | 6 +++--- mods/ITEMS/mcl_core/craftitems.lua | 28 ++++++++++++++-------------- mods/ITEMS/mcl_farming/potatoes.lua | 2 +- mods/ITEMS/mcl_fishing/init.lua | 3 ++- mods/ITEMS/mcl_mobitems/init.lua | 2 +- mods/ITEMS/mcl_potions/functions.lua | 1 + mods/ITEMS/mcl_sus_stew/init.lua | 18 +++++++++--------- 8 files changed, 32 insertions(+), 30 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/physics.lua b/mods/ENTITIES/mcl_mobs/physics.lua index 705b22dbb..73aefb509 100644 --- a/mods/ENTITIES/mcl_mobs/physics.lua +++ b/mods/ENTITIES/mcl_mobs/physics.lua @@ -684,7 +684,7 @@ function mob_class:do_env_damage() self.object:set_velocity({x = 0, y = 0, z = 0}) -- wither rose effect elseif self.standing_in == "mcl_flowers:wither_rose" then - mcl_potions.withering_func(self.object, 1, 2) + mcl_potions.give_effect_by_level("withering", self.object, 2, 2) end local nodef = minetest.registered_nodes[self.standing_in] diff --git a/mods/ENVIRONMENT/mcl_raids/init.lua b/mods/ENVIRONMENT/mcl_raids/init.lua index 208ee93e0..1b762b0e9 100644 --- a/mods/ENVIRONMENT/mcl_raids/init.lua +++ b/mods/ENVIRONMENT/mcl_raids/init.lua @@ -104,11 +104,11 @@ function mcl_raids.promote_to_raidcaptain(c) -- object mcl_raids.drop_obanner(pos) if cmi_cause and cmi_cause.type == "punch" and cmi_cause.puncher:is_player() then awards.unlock(cmi_cause.puncher:get_player_name(), "mcl:voluntary_exile") - local lv = mcl_potions.get_effect(cmi_cause.puncher, "bad_omen") + local lv = mcl_potions.get_effect_level(cmi_cause.puncher, "bad_omen") if not lv then lv = 0 else lv = lv.factor end lv = math.max(5,lv + 1) - mcl_potions.bad_omen_func(cmi_cause.puncher,lv,6000) + mcl_potions.give_effect_by_level("bad_omen", cmi_cause.puncher, lv, 6000) end end if old_ondie then return old_ondie(self,pos,cmi_cause) end @@ -310,7 +310,7 @@ mcl_events.register_event("raid",{ self.mobs = {} self.health_max = 1 self.health = 0 - local lv = mcl_potions.get_effect(minetest.get_player_by_name(self.player), "bad_omen") + local lv = mcl_potions.get_effect_level(minetest.get_player_by_name(self.player), "bad_omen") if lv and lv.factor and lv.factor > 1 then self.max_stage = 6 end end, cond_progress = function(self) diff --git a/mods/ITEMS/mcl_core/craftitems.lua b/mods/ITEMS/mcl_core/craftitems.lua index e89fe124a..f95d42ad2 100644 --- a/mods/ITEMS/mcl_core/craftitems.lua +++ b/mods/ITEMS/mcl_core/craftitems.lua @@ -167,17 +167,17 @@ local function eat_gapple(itemstack, placer, pointed_thing) return itemstack end - local regen_duration, absorbtion_factor = 5, 1 + local regen_duration, absorption = 5, 1 if itemstack:get_name() == "mcl_core:apple_gold_enchanted" then - regen_duration, absorbtion_factor = 20, 4 - mcl_potions.fire_resistance_func(placer, 1, 300) - mcl_potions.leaping_func(placer, 1, 300) + regen_duration, absorption = 20, 4 + mcl_potions.give_effect("fire_resistance", placer, 1, 300) + mcl_potions.give_effect_by_level("leaping", placer, 1, 300) if enable_fapples then - mcl_potions.swiftness_func(placer, absorbtion_factor, 120) + mcl_potions.give_effect_by_level("swiftness", placer, absorption, 120) end end - -- TODO: Absorbtion - mcl_potions.regeneration_func(placer, 2, regen_duration) + mcl_potions.give_effect_by_level("absorption", placer, absorption, 120) + mcl_potions.give_effect_by_level("regeneration", placer, 2, regen_duration) return gapple_hunger_restore(itemstack, placer, pointed_thing) end @@ -206,17 +206,17 @@ local function eat_gapple_delayed(itemstack, placer, pointed_thing) return itemstack end - local regen_duration, absorbtion_factor = 5, 1 + local regen_duration, absorption = 5, 1 if itemstack:get_name() == "mcl_core:apple_gold_enchanted" then - regen_duration, absorbtion_factor = 20, 4 - mcl_potions.fire_resistance_func(placer, 1, 300) - mcl_potions.leaping_func(placer, 1, 300) + regen_duration, absorption = 20, 4 + mcl_potions.give_effect("fire_resistance", placer, 1, 300) + mcl_potions.give_effect_by_level("leaping", placer, 1, 300) if enable_fapples then - mcl_potions.swiftness_func(placer, absorbtion_factor, 120) + mcl_potions.give_effect_by_level("swiftness", placer, absorption, 120) end end - -- TODO: Absorbtion - mcl_potions.regeneration_func(placer, 2, regen_duration) + mcl_potions.give_effect_by_level("absorption", placer, absorption, 120) + mcl_potions.give_effect_by_level("regeneration", placer, 2, regen_duration) --return gapple_hunger_restore(itemstack, placer, pointed_thing) end diff --git a/mods/ITEMS/mcl_farming/potatoes.lua b/mods/ITEMS/mcl_farming/potatoes.lua index d3f4e4fc0..66c5169c4 100644 --- a/mods/ITEMS/mcl_farming/potatoes.lua +++ b/mods/ITEMS/mcl_farming/potatoes.lua @@ -142,7 +142,7 @@ minetest.register_on_item_eat(function (hp_change, replace_with_item, itemstack, -- 60% chance of poisoning with poisonous potato if itemstack:get_name() == "mcl_farming:potato_item_poison" then if math.random(1,10) >= 6 then - mcl_potions.poison_func(user, 1, 5) + mcl_potions.give_effect_by_level("poison", user, 1, 5) end end diff --git a/mods/ITEMS/mcl_fishing/init.lua b/mods/ITEMS/mcl_fishing/init.lua index e3bf181f5..163c103a3 100644 --- a/mods/ITEMS/mcl_fishing/init.lua +++ b/mods/ITEMS/mcl_fishing/init.lua @@ -519,7 +519,8 @@ minetest.register_craftitem("mcl_fishing:pufferfish_raw", { minetest.register_on_item_eat(function (hp_change, replace_with_item, itemstack, user, pointed_thing) if itemstack:get_name() == "mcl_fishing:pufferfish_raw" then - mcl_potions.poison_func(user, 1/3, 60) + mcl_potions.give_effect_by_level("poison", user, 3, 60) + mcl_potions.give_effect_by_level("nausea", user, 2, 20) end end ) diff --git a/mods/ITEMS/mcl_mobitems/init.lua b/mods/ITEMS/mcl_mobitems/init.lua index 01b9a5039..f74d254ba 100644 --- a/mods/ITEMS/mcl_mobitems/init.lua +++ b/mods/ITEMS/mcl_mobitems/init.lua @@ -580,6 +580,6 @@ minetest.register_craft({ minetest.register_on_item_eat(function (hp_change, replace_with_item, itemstack, user, pointed_thing) -- poisoning with spider eye if itemstack:get_name() == "mcl_mobitems:spider_eye" then - mcl_potions.poison_func(user, 1, 4) + mcl_potions.give_effect_by_level("poison", user, 1, 4) end end) diff --git a/mods/ITEMS/mcl_potions/functions.lua b/mods/ITEMS/mcl_potions/functions.lua index 4ab98491a..460a1cb8f 100644 --- a/mods/ITEMS/mcl_potions/functions.lua +++ b/mods/ITEMS/mcl_potions/functions.lua @@ -717,6 +717,7 @@ mcl_potions.register_effect({ return S("danger is imminent") end, particle_color = "#472331", + uses_factor = true, }) mcl_potions.register_effect({ diff --git a/mods/ITEMS/mcl_sus_stew/init.lua b/mods/ITEMS/mcl_sus_stew/init.lua index d34dbbf00..a4c3aae31 100644 --- a/mods/ITEMS/mcl_sus_stew/init.lua +++ b/mods/ITEMS/mcl_sus_stew/init.lua @@ -8,8 +8,8 @@ local eat = minetest.item_eat(6, "mcl_core:bowl") --6 hunger points, player rece local flower_effect = { [ "mcl_flowers:allium" ] = "fire_resistance", [ "mcl_flowers:lily_of_the_valley" ] = "poison", - [ "mcl_flowers:blue_orchid" ] = "hunger", - [ "mcl_flowers:dandelion" ] = "hunger", + [ "mcl_flowers:blue_orchid" ] = "food_poisoning", + [ "mcl_flowers:dandelion" ] = "food_poisoning", [ "mcl_flowers:cornflower" ] = "jump", [ "mcl_flowers:oxeye_daisy" ] = "regeneration", [ "mcl_flowers:poppy" ] = "night_vision" @@ -17,31 +17,31 @@ local flower_effect = { local effects = { [ "fire_resistance" ] = function(itemstack, placer, pointed_thing) - mcl_potions.fire_resistance_func(placer, 1, 4) + mcl_potions.give_effect("fire_resistance", placer, 1, 4) return eat(itemstack, placer, pointed_thing) end, [ "poison" ] = function(itemstack, placer, pointed_thing) - mcl_potions.poison_func(placer, 1, 12) + mcl_potions.give_effect_by_level("poison", placer, 1, 12) return eat(itemstack, placer, pointed_thing) end, - [ "hunger" ] = function(itemstack, placer, pointed_thing, player) - mcl_hunger.item_eat(6, "mcl_core:bowl", 3.5, 0, 100) + [ "food_poisoning" ] = function(itemstack, placer, pointed_thing, player) + mcl_potions.give_effect_by_level("food_poisoning", placer, 10, 12) return eat(itemstack, placer, pointed_thing) end, ["jump"] = function(itemstack, placer, pointed_thing) - mcl_potions.leaping_func(placer, 1, 6) + mcl_potions.give_effect_by_level("leaping", placer, 1, 6) return eat(itemstack, placer, pointed_thing) end, ["regeneration"] = function(itemstack, placer, pointed_thing) - mcl_potions.regeneration_func(placer, 1, 8) + mcl_potions.give_effect_by_level("regeneration", placer, 1, 8) return eat(itemstack, placer, pointed_thing) end, ["night_vision"] = function(itemstack, placer, pointed_thing) - mcl_potions.night_vision_func(placer, 1, 5) + mcl_potions.give_effect("night_vision", placer, 1, 5) return eat(itemstack, placer, pointed_thing) end, } From e36b7f413b938e9da6eef42206e89729f372e8e2 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 27 Apr 2024 04:34:27 +0200 Subject: [PATCH 77/91] Strays now use frost arrows --- mods/ENTITIES/mobs_mc/skeleton+stray.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/skeleton+stray.lua b/mods/ENTITIES/mobs_mc/skeleton+stray.lua index f41d57fd3..a84264a83 100644 --- a/mods/ENTITIES/mobs_mc/skeleton+stray.lua +++ b/mods/ENTITIES/mobs_mc/skeleton+stray.lua @@ -113,7 +113,8 @@ local skeleton = { self.object:set_yaw(minetest.dir_to_yaw(vector.direction(self.object:get_pos(), self.attack:get_pos()))) end local dmg = math.random(2, 4) - mcl_bows.shoot_arrow("mcl_bows:arrow", pos, dir, self.object:get_yaw(), self.object, nil, dmg) + local arrow = self.arrow:match("^(.+)_entity$") + mcl_bows.shoot_arrow(arrow, pos, dir, self.object:get_yaw(), self.object, nil, dmg) end end, shoot_interval = 2, @@ -140,10 +141,10 @@ stray.textures = { "mcl_bows_bow_0.png", }, } +stray.arrow = "mcl_potions:frost_arrow_entity" -- TODO: different sound (w/ echo) --- TODO: stray's arrow inflicts slowness status table.insert(stray.drops, { - name = "mcl_potions:slowness_arrow", + name = "mcl_potions:frost_arrow", chance = 2, min = 1, max = 1, From 55ce6f0f4b881dc4e051e1092e14a18f3599f8de Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 27 Apr 2024 05:03:54 +0200 Subject: [PATCH 78/91] Migrated beacons to the new API Also added more effects to them --- mods/ITEMS/mcl_beacons/init.lua | 62 +++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/mods/ITEMS/mcl_beacons/init.lua b/mods/ITEMS/mcl_beacons/init.lua index 9941e9e50..953d036d3 100644 --- a/mods/ITEMS/mcl_beacons/init.lua +++ b/mods/ITEMS/mcl_beacons/init.lua @@ -4,8 +4,12 @@ there are strings in meta, which are being used to see which effect will be give Valid strings: swiftness leaping - strenght + strength regeneration + haste + resistance + slow_falling + absorption ]]-- mcl_beacons = { @@ -122,10 +126,17 @@ local formspec_string= "image[1,4.5;1,1;custom_beacom_symbol_2.png]".. "image[1,6;1,1;custom_beacom_symbol_1.png]".. - "image_button[5.2,1.5;1,1;mcl_potions_effect_swift.png;swiftness;]".. + "image_button[5.2,1.5;1,1;mcl_potions_effect_swiftness.png;swiftness;]".. + "image_button[8.5,1.5;1,1;mcl_potions_effect_haste.png;haste;]".. + "image_button[5.2,3;1,1;mcl_potions_effect_leaping.png;leaping;]".. - "image_button[5.2,4.5;1,1;mcl_potions_effect_strong.png;strenght;]".. - "image_button[5.2,6;1,1;mcl_potions_effect_regenerating.png;regeneration;]".. + "image_button[8.5,3;1,1;mcl_potions_effect_resistance.png;resistance;]".. + + "image_button[5.2,4.5;1,1;mcl_potions_effect_strength.png;strength;]".. + "image_button[8.5,4.5;1,1;mcl_potions_effect_absorption.png;absorption;]".. + + "image_button[5.2,6;1,1;mcl_potions_effect_regeneration.png;regeneration;]".. + "image_button[8.5,6;1,1;mcl_potions_effect_slow_falling.png;slow_falling;]".. "item_image[1,7;1,1;mcl_core:diamond]".. "item_image[2.2,7;1,1;mcl_core:emerald]".. @@ -197,15 +208,7 @@ end local function effect_player(effect,pos,power_level, effect_level,player) local distance = vector.distance(player:get_pos(), pos) if distance > (power_level+1)*10 then return end - if effect == "swiftness" then - mcl_potions.swiftness_func(player,effect_level,16) - elseif effect == "leaping" then - mcl_potions.leaping_func(player, effect_level, 16) - elseif effect == "strenght" then - mcl_potions.strength_func(player, effect_level, 16) - elseif effect == "regeneration" then - mcl_potions.regeneration_func(player, effect_level, 16) - end + mcl_potions.give_effect_by_level(effect, player, effect_level, 16) end local function apply_effects_to_all_players(pos) @@ -254,7 +257,8 @@ minetest.register_node("mcl_beacons:beacon", { remove_beacon_beam(pos) end, on_receive_fields = function(pos, formname, fields, sender) - if fields.swiftness or fields.regeneration or fields.leaping or fields.strenght then + if fields.swiftness or fields.regeneration or fields.leaping or fields.strenght + or fields.haste or fields.resistance or fields.absorption or fields.slow_falling then local sender_name = sender:get_player_name() local power_level = beacon_blockcheck(pos) if minetest.is_protected(pos, sender_name) then @@ -293,6 +297,14 @@ minetest.register_node("mcl_beacons:beacon", { end minetest.get_meta(pos):set_string("effect","swiftness") successful = true + elseif fields.haste then + if power_level == 4 then + minetest.get_meta(pos):set_int("effect_level",2) + else + minetest.get_meta(pos):set_int("effect_level",1) + end + minetest.get_meta(pos):set_string("effect","haste") + successful = true elseif fields.leaping and power_level >= 2 then if power_level == 4 then minetest.get_meta(pos):set_int("effect_level",2) @@ -301,18 +313,38 @@ minetest.register_node("mcl_beacons:beacon", { end minetest.get_meta(pos):set_string("effect","leaping") successful = true + elseif fields.resistance and power_level >= 2 then + if power_level == 4 then + minetest.get_meta(pos):set_int("effect_level",2) + else + minetest.get_meta(pos):set_int("effect_level",1) + end + minetest.get_meta(pos):set_string("effect","resistance") + successful = true elseif fields.strenght and power_level >= 3 then if power_level == 4 then minetest.get_meta(pos):set_int("effect_level",2) else minetest.get_meta(pos):set_int("effect_level",1) end - minetest.get_meta(pos):set_string("effect","strenght") + minetest.get_meta(pos):set_string("effect","strength") + successful = true + elseif fields.absorption and power_level >= 3 then + if power_level == 4 then + minetest.get_meta(pos):set_int("effect_level",2) + else + minetest.get_meta(pos):set_int("effect_level",1) + end + minetest.get_meta(pos):set_string("effect","absorption") successful = true elseif fields.regeneration and power_level == 4 then minetest.get_meta(pos):set_int("effect_level",2) minetest.get_meta(pos):set_string("effect","regeneration") successful = true + elseif fields.slow_falling and power_level == 4 then + minetest.get_meta(pos):set_int("effect_level",2) + minetest.get_meta(pos):set_string("effect","slow_falling") + successful = true end if successful then if power_level == 4 then From 747bf16a9461ddf938f530060ff5190347cb3046 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 27 Apr 2024 05:12:42 +0200 Subject: [PATCH 79/91] Migrated mobs to the new effects API --- mods/ENTITIES/mcl_mobs/combat.lua | 7 ++----- mods/ENTITIES/mobs_mc/skeleton_wither.lua | 2 +- mods/ENTITIES/mobs_mc/spider.lua | 2 +- mods/ENTITIES/mobs_mc/wither.lua | 10 +++++----- mods/ITEMS/mcl_potions/init.lua | 13 ------------- 5 files changed, 9 insertions(+), 25 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/combat.lua b/mods/ENTITIES/mcl_mobs/combat.lua index 99878be2e..d9df817e4 100644 --- a/mods/ENTITIES/mcl_mobs/combat.lua +++ b/mods/ENTITIES/mcl_mobs/combat.lua @@ -21,8 +21,6 @@ local function atan(x) end end -mcl_mobs.effect_functions = {} - -- check if daytime and also if mob is docile during daylight hours function mob_class:day_docile() @@ -1153,9 +1151,8 @@ function mob_class:do_states_attack (dtime) damage_groups = {fleshy = self.damage} }, nil) if self.dealt_effect then - mcl_mobs.effect_functions[self.dealt_effect.name]( - self.attack, self.dealt_effect.factor, self.dealt_effect.dur - ) + mcl_potions.give_effect_by_level(self.dealt_effect.name, self.attack, + self.dealt_effect.level, self.dealt_effect.dur) end end else diff --git a/mods/ENTITIES/mobs_mc/skeleton_wither.lua b/mods/ENTITIES/mobs_mc/skeleton_wither.lua index c39104f4b..b01fb4b96 100644 --- a/mods/ENTITIES/mobs_mc/skeleton_wither.lua +++ b/mods/ENTITIES/mobs_mc/skeleton_wither.lua @@ -98,7 +98,7 @@ mcl_mobs.register_mob("mobs_mc:witherskeleton", { fire_resistant = true, dealt_effect = { name = "withering", - factor = 1, + level = 1, dur = 10, }, }) diff --git a/mods/ENTITIES/mobs_mc/spider.lua b/mods/ENTITIES/mobs_mc/spider.lua index 16f802c09..d01c7afbe 100644 --- a/mods/ENTITIES/mobs_mc/spider.lua +++ b/mods/ENTITIES/mobs_mc/spider.lua @@ -138,7 +138,7 @@ cave_spider.sounds = table.copy(spider.sounds) cave_spider.sounds.base_pitch = 1.25 cave_spider.dealt_effect = { name = "poison", - factor = 2.5, + level = 2, dur = 7, } mcl_mobs.register_mob("mobs_mc:cave_spider", cave_spider) diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index f1e1e6e78..252873629 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -349,7 +349,7 @@ mcl_mobs.register_mob("mobs_mc:wither", { mcl_util.deal_damage(objs[n], 8, {type = "magic"}) hit_some = true end - mcl_mobs.effect_functions["withering"](objs[n], 0.5, 10) + mcl_potions.give_effect("withering", objs[n], 2, 10) end if hit_some then mcl_mobs.effect(pos, 32, "mcl_particles_soul_fire_flame.png", 5, 10, self.reach, 1, 0) @@ -469,7 +469,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { -- direct hit hit_player = function(self, player) local pos = vector.new(self.object:get_pos()) - mcl_mobs.effect_functions["withering"](player, 0.5, 10) + mcl_potions.give_effect("withering", player, 2, 10) player:punch(self.object, 1.0, { full_punch_interval = 0.5, damage_groups = {fleshy = 8}, @@ -484,7 +484,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull", { hit_mob = function(self, mob) local pos = vector.new(self.object:get_pos()) - mcl_mobs.effect_functions["withering"](mob, 0.5, 10) + mcl_potions.give_effect("withering", mob, 2, 10) mob:punch(self.object, 1.0, { full_punch_interval = 0.5, damage_groups = {fleshy = 8}, @@ -522,7 +522,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { -- direct hit hit_player = function(self, player) local pos = vector.new(self.object:get_pos()) - mcl_mobs.effect_functions["withering"](player, 0.5, 10) + mcl_potions.give_effect("withering", player, 2, 10) player:punch(self.object, 1.0, { full_punch_interval = 0.5, damage_groups = {fleshy = 12}, @@ -541,7 +541,7 @@ mcl_mobs.register_arrow("mobs_mc:wither_skull_strong", { hit_mob = function(self, mob) local pos = vector.new(self.object:get_pos()) - mcl_mobs.effect_functions["withering"](mob, 0.5, 10) + mcl_potions.give_effect("withering", mob, 2, 10) mob:punch(self.object, 1.0, { full_punch_interval = 0.5, damage_groups = {fleshy = 12}, diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index d70e14f36..cdc095203 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -633,19 +633,6 @@ function mcl_potions.get_alchemy(ingr, pot) return false end --- TODO replace all calls to the old API with new API calls in other mods --- mcl_mobs.effect_functions["poison"] = mcl_potions.poison_func --- mcl_mobs.effect_functions["regeneration"] = mcl_potions.regeneration_func --- mcl_mobs.effect_functions["invisibility"] = mcl_potions.invisiblility_func --- mcl_mobs.effect_functions["fire_resistance"] = mcl_potions.fire_resistance_func --- mcl_mobs.effect_functions["night_vision"] = mcl_potions.night_vision_func --- mcl_mobs.effect_functions["water_breathing"] = mcl_potions.water_breathing_func --- mcl_mobs.effect_functions["leaping"] = mcl_potions.leaping_func --- mcl_mobs.effect_functions["swiftness"] = mcl_potions.swiftness_func --- mcl_mobs.effect_functions["heal"] = mcl_potions.healing_func --- mcl_mobs.effect_functions["bad_omen"] = mcl_potions.bad_omen_func --- mcl_mobs.effect_functions["withering"] = mcl_potions.withering_func - -- give withering to players in a wither rose local etime = 0 minetest.register_globalstep(function(dtime) From cafa36d0b44ea635568db3ffd1600bb2e7f83b4b Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 27 Apr 2024 05:19:41 +0200 Subject: [PATCH 80/91] Add more sus stew effects --- mods/ITEMS/mcl_sus_stew/init.lua | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/mods/ITEMS/mcl_sus_stew/init.lua b/mods/ITEMS/mcl_sus_stew/init.lua index a4c3aae31..8a88027ae 100644 --- a/mods/ITEMS/mcl_sus_stew/init.lua +++ b/mods/ITEMS/mcl_sus_stew/init.lua @@ -7,12 +7,18 @@ local eat = minetest.item_eat(6, "mcl_core:bowl") --6 hunger points, player rece local flower_effect = { [ "mcl_flowers:allium" ] = "fire_resistance", + [ "mcl_flowers:azure_bluet" ] = "blindness", [ "mcl_flowers:lily_of_the_valley" ] = "poison", - [ "mcl_flowers:blue_orchid" ] = "food_poisoning", - [ "mcl_flowers:dandelion" ] = "food_poisoning", + [ "mcl_flowers:blue_orchid" ] = "saturation", + [ "mcl_flowers:dandelion" ] = "saturation", [ "mcl_flowers:cornflower" ] = "jump", [ "mcl_flowers:oxeye_daisy" ] = "regeneration", - [ "mcl_flowers:poppy" ] = "night_vision" + [ "mcl_flowers:poppy" ] = "night_vision", + [ "mcl_flowers:wither_rose" ] = "withering", + [ "mcl_flowers:tulip_orange" ] = "weakness", + [ "mcl_flowers:tulip_pink" ] = "weakness", + [ "mcl_flowers:tulip_red" ] = "weakness", + [ "mcl_flowers:tulip_white" ] = "weakness", } local effects = { @@ -20,13 +26,19 @@ local effects = { mcl_potions.give_effect("fire_resistance", placer, 1, 4) return eat(itemstack, placer, pointed_thing) end, + + [ "blindness" ] = function(itemstack, placer, pointed_thing) + mcl_potions.give_effect("blindness", placer, 1, 8) + return eat(itemstack, placer, pointed_thing) + end, + [ "poison" ] = function(itemstack, placer, pointed_thing) mcl_potions.give_effect_by_level("poison", placer, 1, 12) return eat(itemstack, placer, pointed_thing) end, - [ "food_poisoning" ] = function(itemstack, placer, pointed_thing, player) - mcl_potions.give_effect_by_level("food_poisoning", placer, 10, 12) + [ "saturation" ] = function(itemstack, placer, pointed_thing, player) + mcl_potions.give_effect_by_level("saturation", placer, 1, 0.5) return eat(itemstack, placer, pointed_thing) end, @@ -40,6 +52,16 @@ local effects = { return eat(itemstack, placer, pointed_thing) end, + ["withering"] = function(itemstack, placer, pointed_thing) + mcl_potions.give_effect_by_level("withering", placer, 1, 8) + return eat(itemstack, placer, pointed_thing) + end, + + ["weakness"] = function(itemstack, placer, pointed_thing) + mcl_potions.give_effect_by_level("weakness", placer, 1, 9) + return eat(itemstack, placer, pointed_thing) + end, + ["night_vision"] = function(itemstack, placer, pointed_thing) mcl_potions.give_effect("night_vision", placer, 1, 5) return eat(itemstack, placer, pointed_thing) From d306260c7e900f75d4dca782559678ea5254abcc Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 27 Apr 2024 05:23:18 +0200 Subject: [PATCH 81/91] Guardian fixes --- mods/ENTITIES/mobs_mc/guardian.lua | 4 +--- mods/ENTITIES/mobs_mc/guardian_elder.lua | 9 ++++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/guardian.lua b/mods/ENTITIES/mobs_mc/guardian.lua index f2addbfa0..473575665 100644 --- a/mods/ENTITIES/mobs_mc/guardian.lua +++ b/mods/ENTITIES/mobs_mc/guardian.lua @@ -99,9 +99,7 @@ mcl_mobs.register_mob("mobs_mc:guardian", { view_range = 16, }) --- Spawning disabled due to size issues --- TODO: Re-enable spawning ---mcl_mobs:spawn_specific("mobs_mc:guardian", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 25000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level - 10) +mcl_mobs:spawn_specific("mobs_mc:guardian", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 25000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level - 10) mcl_mobs:non_spawn_specific("mobs_mc:guardian","overworld",0,minetest.LIGHT_MAX+1) -- spawn eggs mcl_mobs.register_egg("mobs_mc:guardian", S("Guardian"), "#5a8272", "#f17d31", 0) diff --git a/mods/ENTITIES/mobs_mc/guardian_elder.lua b/mods/ENTITIES/mobs_mc/guardian_elder.lua index 094c0513c..47ca568e1 100644 --- a/mods/ENTITIES/mobs_mc/guardian_elder.lua +++ b/mods/ENTITIES/mobs_mc/guardian_elder.lua @@ -105,11 +105,14 @@ mcl_mobs.register_mob("mobs_mc:guardian_elder", { fly_in = { "mcl_core:water_source", "mclx_core:river_water_source" }, jump = false, view_range = 16, + dealt_effect = { + name = "fatigue", + level = 3, + dur = 30, + }, }) --- Spawning disabled due to size issues <- what do you mean? -j4i --- TODO: Re-enable spawning --- mcl_mobs:spawn_specific("mobs_mc:guardian_elder", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 40000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level-18) +mcl_mobs:spawn_specific("mobs_mc:guardian_elder", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 40000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level-18) -- spawn eggs mcl_mobs.register_egg("mobs_mc:guardian_elder", S("Elder Guardian"), "#ceccba", "#747693", 0) From dbea863553a99923b95b0261cc78f892ddfb2cf0 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 27 Apr 2024 06:25:01 +0200 Subject: [PATCH 82/91] Legacy potions converter --- mods/ITEMS/mcl_potions/potions.lua | 49 ++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index cc83954c7..bda47f1e3 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -1,6 +1,8 @@ local S = minetest.get_translator(minetest.get_current_modname()) mcl_potions.registered_potions = {} +-- shorthand +local registered_potions = mcl_potions.registered_potions local function potion_image(colorstring, opacity) if not opacity then @@ -810,3 +812,50 @@ mcl_potions.register_potion({ has_lingering = false, }) + + + +-- COMPAT CODE +local function replace_legacy_potion(itemstack) + local name = itemstack:get_name() + local new_name = name:match("^(.+)_plus$") + local new_stack + if new_name then + new_stack = ItemStack(new_name) + new_stack:get_meta():set_int("mcl_potions:potion_plus", + registered_potions[new_name]._default_extend_level) + tt.reload_itemstack_description(new_stack) + end + new_name = name:match("^(.+)_2$") + if new_name then + new_stack = ItemStack(new_name) + new_stack:get_meta():set_int("mcl_potions:potion_potent", + registered_potions[new_name]._default_potent_level-1) + tt.reload_itemstack_description(new_stack) + end + return new_stack +end +local compat = "mcl_potions:compat_potion" +minetest.register_craftitem(compat, { + description = S("Unknown Potion"), + _tt_help = S("Right-click to identify"), + image = "mcl_potions_dragon_breath.png", + on_secondary_use = replace_legacy_potion, + on_place = replace_legacy_potion, +}) + +local old_potions_plus = { + "fire_resistance", "water_breathing", "invisibility", "regeneration", "poison", + "withering", "leaping", "slowness", "swiftness", "night_vision" +} +local old_potions_2 = { + "healing", "harming", "swiftness", "slowness", "leaping", + "withering", "poison", "regeneration" +} + +for _, name in pairs(old_potions_2) do + minetest.register_alias("mcl_potions:" .. name .. "_2", compat) +end +for _, name in pairs(old_potions_plus) do + minetest.register_alias("mcl_potions:" .. name .. "_plus", compat) +end From 7a4c1ceba52b151f8880bb10e34cc9a11bd1a13a Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 27 Apr 2024 06:47:56 +0200 Subject: [PATCH 83/91] Legacy potion conversion extended --- mods/ITEMS/mcl_potions/potions.lua | 33 ++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index bda47f1e3..545b11876 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -818,19 +818,38 @@ mcl_potions.register_potion({ -- COMPAT CODE local function replace_legacy_potion(itemstack) local name = itemstack:get_name() - local new_name = name:match("^(.+)_plus$") + local suffix = "" + local bare_name = name:match("^(.+)_splash$") + if bare_name then + suffix = "_splash" + else + bare_name = name:match("^(.+)_lingering$") + if bare_name then + suffix = "_lingering" + else + bare_name = name:match("^(.+)_arrow$") + if bare_name then + suffix = "_arrow" + else + bare_name = name + end + end + end + local new_name = bare_name:match("^(.+)_plus$") local new_stack if new_name then - new_stack = ItemStack(new_name) + new_stack = ItemStack(new_name..suffix) new_stack:get_meta():set_int("mcl_potions:potion_plus", registered_potions[new_name]._default_extend_level) + new_stack:set_count(itemstack:get_count()) tt.reload_itemstack_description(new_stack) end - new_name = name:match("^(.+)_2$") + new_name = bare_name:match("^(.+)_2$") if new_name then - new_stack = ItemStack(new_name) + new_stack = ItemStack(new_name..suffix) new_stack:get_meta():set_int("mcl_potions:potion_potent", registered_potions[new_name]._default_potent_level-1) + new_stack:set_count(itemstack:get_count()) tt.reload_itemstack_description(new_stack) end return new_stack @@ -855,7 +874,13 @@ local old_potions_2 = { for _, name in pairs(old_potions_2) do minetest.register_alias("mcl_potions:" .. name .. "_2", compat) + minetest.register_alias("mcl_potions:" .. name .. "_2_splash", compat) + minetest.register_alias("mcl_potions:" .. name .. "_2_lingering", compat) + minetest.register_alias("mcl_potions:" .. name .. "_2_arrow", compat) end for _, name in pairs(old_potions_plus) do minetest.register_alias("mcl_potions:" .. name .. "_plus", compat) + minetest.register_alias("mcl_potions:" .. name .. "_plus_splash", compat) + minetest.register_alias("mcl_potions:" .. name .. "_plus_lingering", compat) + minetest.register_alias("mcl_potions:" .. name .. "_plus_arrow", compat) end From 664993ca7532decc222e47e86efdb2c4058036a2 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 27 Apr 2024 07:37:10 +0200 Subject: [PATCH 84/91] Fixed mob drops not having proper description --- mods/ENTITIES/mcl_item_entity/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index 19e91b460..2cb506450 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -127,6 +127,7 @@ local function try_object_pickup(player, inv, object, checkpos) -- Add what we can to the inventory local itemstack = ItemStack(le.itemstring) + tt.reload_itemstack_description(itemstack) local leftovers = inv:add_item("main", itemstack ) check_pickup_achievements(object, player) From 651fb74be1e5dd5c2f7c31fd5b65dd51352fe72c Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 27 Apr 2024 14:29:00 +0200 Subject: [PATCH 85/91] Fix a crash --- mods/ENTITIES/mcl_mobs/spawning.lua | 3 +++ mods/ENTITIES/mobs_mc/guardian.lua | 2 +- mods/ENTITIES/mobs_mc/guardian_elder.lua | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index b0e6260aa..8a8a42281 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -565,6 +565,9 @@ function mcl_mobs:spawn_specific(name, dimension, type_of_spawning, biomes, min_ return end + assert(min_height) + assert(max_height) + -- chance/spawn number override in minetest.conf for registered mob local numbers = minetest.settings:get(name) diff --git a/mods/ENTITIES/mobs_mc/guardian.lua b/mods/ENTITIES/mobs_mc/guardian.lua index 473575665..ab4051626 100644 --- a/mods/ENTITIES/mobs_mc/guardian.lua +++ b/mods/ENTITIES/mobs_mc/guardian.lua @@ -99,7 +99,7 @@ mcl_mobs.register_mob("mobs_mc:guardian", { view_range = 16, }) -mcl_mobs:spawn_specific("mobs_mc:guardian", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 25000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level - 10) +mcl_mobs:spawn_specific("mobs_mc:guardian", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 25000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level - 10, mobs_mc.water_level) mcl_mobs:non_spawn_specific("mobs_mc:guardian","overworld",0,minetest.LIGHT_MAX+1) -- spawn eggs mcl_mobs.register_egg("mobs_mc:guardian", S("Guardian"), "#5a8272", "#f17d31", 0) diff --git a/mods/ENTITIES/mobs_mc/guardian_elder.lua b/mods/ENTITIES/mobs_mc/guardian_elder.lua index 47ca568e1..be787216c 100644 --- a/mods/ENTITIES/mobs_mc/guardian_elder.lua +++ b/mods/ENTITIES/mobs_mc/guardian_elder.lua @@ -112,7 +112,7 @@ mcl_mobs.register_mob("mobs_mc:guardian_elder", { }, }) -mcl_mobs:spawn_specific("mobs_mc:guardian_elder", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 40000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level-18) +mcl_mobs:spawn_specific("mobs_mc:guardian_elder", { "mcl_core:water_source", "mclx_core:river_water_source" }, { "mcl_core:water_source", "mclx_core:river_water_source" }, 0, minetest.LIGHT_MAX+1, 30, 40000, 2, mcl_vars.mg_overworld_min, mobs_mc.water_level-18, mobs_mc.water_level) -- spawn eggs mcl_mobs.register_egg("mobs_mc:guardian_elder", S("Elder Guardian"), "#ceccba", "#747693", 0) From 551bc99517c8702923698cffdddfb5ad7fe0fe6f Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sat, 27 Apr 2024 21:21:16 +0200 Subject: [PATCH 86/91] Improved compat alias visual --- mods/ITEMS/mcl_potions/potions.lua | 14 +++++++++++--- textures/vl_unknown.png | Bin 0 -> 111 bytes 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 textures/vl_unknown.png diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 545b11876..938fdde6e 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -855,10 +855,18 @@ local function replace_legacy_potion(itemstack) return new_stack end local compat = "mcl_potions:compat_potion" +local compat_arrow = "mcl_potions:compat_arrow" minetest.register_craftitem(compat, { description = S("Unknown Potion"), _tt_help = S("Right-click to identify"), - image = "mcl_potions_dragon_breath.png", + image = "mcl_potions_potion_overlay.png^[colorize:#00F:127^mcl_potions_potion_bottle.png^vl_unknown.png", + on_secondary_use = replace_legacy_potion, + on_place = replace_legacy_potion, +}) +minetest.register_craftitem(compat_arrow, { + description = S("Unknown Tipped Arrow"), + _tt_help = S("Right-click to identify"), + image = "mcl_bows_arrow_inv.png^(mcl_potions_arrow_inv.png^[colorize:#FFF:100)^vl_unknown.png", on_secondary_use = replace_legacy_potion, on_place = replace_legacy_potion, }) @@ -876,11 +884,11 @@ for _, name in pairs(old_potions_2) do minetest.register_alias("mcl_potions:" .. name .. "_2", compat) minetest.register_alias("mcl_potions:" .. name .. "_2_splash", compat) minetest.register_alias("mcl_potions:" .. name .. "_2_lingering", compat) - minetest.register_alias("mcl_potions:" .. name .. "_2_arrow", compat) + minetest.register_alias("mcl_potions:" .. name .. "_2_arrow", compat_arrow) end for _, name in pairs(old_potions_plus) do minetest.register_alias("mcl_potions:" .. name .. "_plus", compat) minetest.register_alias("mcl_potions:" .. name .. "_plus_splash", compat) minetest.register_alias("mcl_potions:" .. name .. "_plus_lingering", compat) - minetest.register_alias("mcl_potions:" .. name .. "_plus_arrow", compat) + minetest.register_alias("mcl_potions:" .. name .. "_plus_arrow", compat_arrow) end diff --git a/textures/vl_unknown.png b/textures/vl_unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..279a4cdb076afa6aa029f2e732fcddb712c8f892 GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7%sgEjLo7}wCoEw7!S8az z;HFfkQO5+OrZ$1sK8yAmTktAqx~*6=bIq29^9;Y(Btj1yP?t(#V9+VaoPK`6NoEEH O1_n=8KbLh*2~7ZMK_Vak literal 0 HcmV?d00001 From 191dd1b95019057e5bd73ee6bd059ef8dca935c2 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 28 Apr 2024 01:00:45 +0200 Subject: [PATCH 87/91] Update template.txt --- mods/ITEMS/mcl_potions/locale/template.txt | 345 ++++++++++++++++----- mods/ITEMS/mcl_potions/potions.lua | 18 +- 2 files changed, 268 insertions(+), 95 deletions(-) diff --git a/mods/ITEMS/mcl_potions/locale/template.txt b/mods/ITEMS/mcl_potions/locale/template.txt index 1420dabee..50c622391 100644 --- a/mods/ITEMS/mcl_potions/locale/template.txt +++ b/mods/ITEMS/mcl_potions/locale/template.txt @@ -1,13 +1,274 @@ # textdomain: mcl_potions - []= +Invisibility= +body is invisible= -Add a status effect to yourself. Arguments: : name of status effect, e.g. poison. : duration in seconds. : effect strength multiplier (1 @= 100%)= +Poison= +-1 HP / @1 s= + +Regeneration= ++1 HP / @1 s= + +Strength= ++@1% melee damage= + +Weakness= +-@1% melee damage= + +Water Breathing= +limitless breathing under water= + +Dolphin's Grace= +swimming gracefully= + +Leaping= ++@1% jumping power= +-@1% jumping power= + +Slow Falling= +decreases gravity effects= + +Swiftness= ++@1% running speed= + +Slowness= +-@1% running speed= + +Levitation= +moves body upwards at @1 nodes/s= + +Night Vision= +improved vision during the night= + +Darkness= +surrounded by darkness= +not seeing anything beyond @1 nodes= + +Glowing= +more visible at all times= + +Health Boost= +HP increased by @1= + +Absorption= +absorbs up to @1 incoming damage= + +Fire Resistance= +resistance to fire damage= + +Resistance= +resist @1% of incoming damage= + +Luck= + +Bad Luck= + +Bad Omen= +danger is imminent= + +Hero of the Village= + +Withering= +-1 HP / @1 s, can kill= + +Frost= +-1 HP / 1 s, can kill, -@1% running speed= + +Blindness= +impaired sight= + +Nausea= +not feeling very well...= +frequency: @1 / 1 s= + +Food Poisoning= +exhausts by @1 per second= + +Saturation= +saturates by @1 per second= + +Haste= ++@1% mining and attack speed= + +Fatigue= +-@1% mining and attack speed= + +Conduit Power= ++@1% mining and attack speed in water= + + +|heal|list|clear|remove |INF [] [] [NOPART]= + +Add a status effect to yourself. Arguments: : name of status effect. Passing "list" as effect name lists available effects. Passing "heal" as effect name heals (or harms) by amount designed by the next parameter. Passing "clear" as effect name removes all effects. Passing "remove" as effect name removes the effect named by the next parameter. : duration in seconds. Passing "INF" as duration makes the effect infinite. (: amount of healing when the effect is "heal", passing a negative value subtracts health. : name of a status effect to be removed when using "remove" as the previous parameter.) : effect power determinant, bigger level results in more powerful effect for effects that depend on the level (no changes for other effects), defaults to 1, pass F to use low-level factor instead. : effect strength modifier, can mean different things depending on the effect, no changes for effects that do not depend on level/factor. NOPART at the end means no particles will be shown for this effect.= Missing effect parameter!= -Missing or invalid duration parameter!= -Invalid factor parameter!= +Missing or invalid heal amount parameter!= +Player @1 healed by @2 HP.= +Player @1 harmed by @2 HP.= +Effects cleared for player @1= +Removed effect @1 from player @2= @1 is not an available status effect.= +Missing or invalid duration parameter!= +Invalid level parameter!= +Missing or invalid factor parameter when level is F!= + +@1 effect given to player @2 for @3 seconds with factor of @4.= +@1 effect given to player @2 for @3 seconds.= +Giving effect @1 to player @2 failed.= +@1 effect on level @2 given to player @3 for @4 seconds.= +@1 effect given to player @2 for @3 seconds.= +Giving effect @1 to player @2 failed.= +@1 is not an available status effect.= + + +A throwable potion that will shatter on impact, where it gives all nearby players and mobs a status effect or a set of status effects.= +Use the “Punch” key to throw it.= + + +A throwable potion that will shatter on impact, where it creates a magic cloud that lingers around for a while. Any player or mob inside the cloud will receive the potion's effect or set of effects, possibly repeatedly.= + + +This particular arrow is tipped and will give an effect when it hits a player or mob.= + + +Use the “Place” key to drink it.= +Drinking a potion gives you a particular effect or set of effects.= + +@1 Potion @2= +@1 Potion= +Potion @1= +Strange Potion= + +Stacks the effect= + +Splash @1= +Lingering @1= +@1 Arrow @2= +@1 Arrow= +Arrow @1= +Strange Tipped Arrow= + +Mighty= +of Trolling= + +Dragon's Breath= +This item is used in brewing and can be combined with splash potions to create lingering potions.= + +Awkward= +No effect= +Has an awkward taste and is used for brewing potions.= + +Mundane= +Has a terrible taste and is not really useful for brewing potions.= + +Thick= +Has a bitter taste and may be useful for brewing potions.= + +of Healing= ++@1 HP= +Instantly heals.= + +of Harming= +-@1 HP= +Instantly deals damage.= + +of Night Vision= +Increases the perceived brightness of light under a dark sky.= + +of Swiftness= +Increases walking speed.= + +of Slowness= +Decreases walking speed.= + +of Leaping= +Increases jump strength.= + +of Withering= +Applies the withering effect which deals damage at a regular interval and can kill.= + +of Poison= +Applies the poison effect which deals damage at a regular interval.= + +of Regeneration= +Regenerates health over time.= + +of Invisibility= +Grants invisibility.= + +of Water Breathing= +Grants limitless breath underwater.= + +of Fire Resistance= +Grants immunity to damage from heat sources like fire.= + +of Strength= +Increases attack power.= + +of Weakness= +Decreases attack power.= + +of Slow Falling= +Instead of falling, you descend gracefully.= + +of Levitation= +Floats body slowly upwards.= + +of Darkness= +Surrounds with darkness.= + +of Glowing= +Highlights for others to see.= + +of Health Boost= +Increases health.= + +of Absorption= +Absorbs some incoming damage.= + +of Resistance= +Decreases damage taken.= + +of Stone Cloak= +Decreases damage taken at the cost of speed.= + +of Luck= +Increases luck.= + +of Bad Luck= +Decreases luck.= + +of Frost= +Freezes...= + +of Blindness= +Impairs sight.= + +of Nausea= +Disintegrates senses.= + +of Food Poisoning= +Moves bowels too fast.= + +of Saturation= +Satisfies hunger.= + +of Haste= +Increases digging and attack speed.= + +of Fatigue= +Decreases digging and attack speed.= + +Ominous= +Attracts danger.= + +Unknown Potion= +Right-click to identify= +Unknown Tipped Arrow= + + Fermented Spider Eye= +Try different combinations to create potions.= + Glass Bottle= Liquid container= @@ -37,79 +298,3 @@ A throwable water bottle that will shatter on impact, where it creates a cloud o Glistering Melon= This shiny melon is full of tiny gold nuggets and would be nice in an item frame. It isn't edible and not useful for anything else.= - -A throwable potion that will shatter on impact, where it creates a magic cloud that lingers around for a while. Any player or mob inside the cloud will receive the potion's effect, possibly repeatedly.= - -Use the “Punch” key to throw it.= -Use the “Place” key to drink it.= -Drinking a potion gives you a particular effect.= -1 HP/@1s | @2= -@1 HP= -@1 Potion= -Splash @1 Potion= -Lingering @1 Potion= -Arrow of @1= - II= - IV= -@1 Potion@2= -Splash @1@2 Potion= -Lingering @1@2 Potion= -Arrow of @1@2= -@1 + Potion= -Splash @1 + Potion= -Lingering @1 + Potion= -Arrow of @1 += -Awkward Potion= -Awkward Splash Potion= -Awkward Lingering Potion= -Has an awkward taste and is used for brewing potions.= -Mundane Potion= -Mundane Splash Potion= -Mundane Lingering Potion= -Has a terrible taste and is not useful for brewing potions.= -Thick Potion= -Thick Splash Potion= -Thick Lingering Potion= -Has a bitter taste and is not useful for brewing potions.= -Dragon's Breath= - -This item is used in brewing and can be combined with splash potions to create lingering potions.= - -Healing= -+4 HP= -+8 HP= -Instantly heals.= -Harming= --6 HP= --12 HP= -Instantly deals damage.= -Night Vision= -Increases the perceived brightness of light under a dark sky.= -Swiftness= -Increases walking speed.= -Slowness= -Decreases walking speed.= -Leaping= -Increases jump strength.= -Poison= -Applies the poison effect which deals damage at a regular interval.= -Regeneration= -Regenerates health over time.= -Invisibility= -Grants invisibility.= -Water Breathing= -Grants limitless breath underwater.= -Fire Resistance= -Grants immunity to damage from heat sources like fire.= -Weakness= -Weakness += -Strength= -Strength II= -Strength += -Try different combinations to create potions.= -No effect= - -A throwable potion that will shatter on impact, where it gives all nearby players and mobs a status effect.= - -This particular arrow is tipped and will give an effect when it hits a player or mob.= - diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 938fdde6e..471c4ad3d 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -386,7 +386,7 @@ mcl_potions.register_potion({ name = "thick", desc_prefix = S("Thick"), _tt = S("No effect"), - _longdesc = S("Has a bitter taste and is not really useful for brewing potions."), + _longdesc = S("Has a bitter taste and may be useful for brewing potions."), color = "#0000FF", }) @@ -650,20 +650,8 @@ mcl_potions.register_potion({ }) mcl_potions.register_potion({ - name = "resistance", - desc_suffix = S("of Resistance"), - _tt = nil, - _longdesc = S("Decreases damage taken."), - color = "#2552A5", - _effect_list = { - resistance = {}, - }, - has_arrow = true, -}) - -mcl_potions.register_potion({ - name = "turtle_master", - desc_suffix = S("of Turtle Master"), + name = "stone_cloak", + desc_suffix = S("of Stone Cloak"), _tt = nil, _longdesc = S("Decreases damage taken at the cost of speed."), color = "#255235", From 496360a1c414f603e39fcb52352166f432dae6f3 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Sun, 28 Apr 2024 03:04:47 +0200 Subject: [PATCH 88/91] Updated Polish translation --- mods/HELP/mcl_tt/locale/mcl_tt.pl.tr | 2 +- mods/HELP/mcl_tt/locale/template.txt | 1 + .../mcl_potions/locale/mcl_potions.pl.tr | 355 +++++++++++++----- mods/ITEMS/mcl_potions/locale/template.txt | 5 - mods/ITEMS/mcl_potions/potions.lua | 3 - 5 files changed, 269 insertions(+), 97 deletions(-) diff --git a/mods/HELP/mcl_tt/locale/mcl_tt.pl.tr b/mods/HELP/mcl_tt/locale/mcl_tt.pl.tr index 7eb8f4c77..912c98ac7 100644 --- a/mods/HELP/mcl_tt/locale/mcl_tt.pl.tr +++ b/mods/HELP/mcl_tt/locale/mcl_tt.pl.tr @@ -45,4 +45,4 @@ Durability: @1=Wytrzymałość: @1 Block breaking strength: @1=Siła niszczenia bloku: @1 @1 uses=@1 użyć Unlimited uses=Nielimitowane użycia - +...stacks=...kumuluje się diff --git a/mods/HELP/mcl_tt/locale/template.txt b/mods/HELP/mcl_tt/locale/template.txt index 3e3b4d300..15076ec24 100644 --- a/mods/HELP/mcl_tt/locale/template.txt +++ b/mods/HELP/mcl_tt/locale/template.txt @@ -45,3 +45,4 @@ Block breaking strength: @1= @1 uses= Unlimited uses= Durability: @1= +...stacks= diff --git a/mods/ITEMS/mcl_potions/locale/mcl_potions.pl.tr b/mods/ITEMS/mcl_potions/locale/mcl_potions.pl.tr index abf61d4d3..db835bd9e 100644 --- a/mods/ITEMS/mcl_potions/locale/mcl_potions.pl.tr +++ b/mods/ITEMS/mcl_potions/locale/mcl_potions.pl.tr @@ -1,115 +1,294 @@ # textdomain: mcl_potions - []= [] +Invisibility=Niewidzialność +body is invisible=ciało jest niewidzialne + +Poison=Trucizna +-1 HP / @1 s=-1 PŻ / @1 s + +Regeneration=Regeneracja ++1 HP / @1 s=+1 PŻ / @1 s + +Strength=Siła ++@1% melee damage=+@1% obrażeń w walce wręcz + +Weakness=Osłabienie +-@1% melee damage=-@1% obrażeń w walce wręcz + +Water Breathing=Oddychanie pod Wodą +limitless breathing under water=nieograniczone oddychanie pod wodą + +Dolphin's Grace=Gracja Delfina +swimming gracefully=pływanie z gracją + +Leaping=Zwiększony Skok ++@1% jumping power=+@1% siły skoku +-@1% jumping power=-@1% siły skoku + +Slow Falling=Powolne Opadanie +decreases gravity effects=zmniejsza skutki grawitacji + +Swiftness=Szybkość ++@1% running speed=+@1% prędkości w biegu + +Slowness=Spowolnienie +-@1% running speed=-@1% prędkości w biegu + +Levitation=Lewitacja +moves body upwards at @1 nodes/s=porusza ciało w górę z prędkością @1 bloków/s + +Night Vision=Noktowizja +improved vision during the night=poprawione widzenie w nocy + +Darkness=Ciemność +surrounded by darkness=otoczony ciemnością +not seeing anything beyond @1 nodes=nie widzi nic poza @1 blokami + +Glowing=Blask +more visible at all times=bardziej widoczny przez cały czas + +Health Boost=Zwiększone Zdrowie +HP increased by @1=PŻ zwiększone o @1 + +Absorption=Absorpcja +absorbs up to @1 incoming damage=pochłania do @1 otrzymywanych obrażeń + +Fire Resistance=Odporność na Ogień +resistance to fire damage=odporność na szkody od ognia + +Resistance=Odporność +resist @1% of incoming damage=zmniejsza otrzymywane obrażenia o @1% + +Luck=Szczęście + +Bad Luck=Pech + +Bad Omen=Zły Omen +danger is imminent=zagrożenie jest blisko + +Hero of the Village=Bohater Wioski + +Withering=Obumieranie +-1 HP / @1 s, can kill=-1 PŻ / @1 s, może zabić + +Frost=Mróz +-1 HP / 1 s, can kill, -@1% running speed=-1 PŻ / 1 s, może zabić, -@1% prędkości w biegu + +Blindness=Ślepota +impaired sight=upośledzony wzrok + +Nausea=Nudności +not feeling very well...=nie czuje się zbyt dobrze +frequency: @1 / 1 s=częstotliwość: @1 / 1 s + +Food Poisoning=Zatrucie Pokarmowe +exhausts by @1 per second=wyczerpuje o @1 na sekundę + +Saturation=Nasycenie +saturates by @1 per second=nasyca o @1 na sekundę + +Haste=Pośpiech ++@1% mining and attack speed=+@1% prędkości kopania i ataku + +Fatigue=Zmęczenie +-@1% mining and attack speed=-@1% prędkości kopania i ataku + +Conduit Power=Moc Przewodni ++@1% mining and attack speed in water=+@1% prędkości kopania i ataku w wodzie + + +|heal|list|clear|remove |INF [] [] [NOPART]=|heal|list|clear|remove |INF [] [] [NOPART] + +Add a status effect to yourself. Arguments: : name of status effect. Passing "list" as effect name lists available effects. Passing "heal" as effect name heals (or harms) by amount designed by the next parameter. Passing "clear" as effect name removes all effects. Passing "remove" as effect name removes the effect named by the next parameter. : duration in seconds. Passing "INF" as duration makes the effect infinite. (: amount of healing when the effect is "heal", passing a negative value subtracts health. : name of a status effect to be removed when using "remove" as the previous parameter.) : effect power determinant, bigger level results in more powerful effect for effects that depend on the level (no changes for other effects), defaults to 1, pass F to use low-level factor instead. : effect strength modifier, can mean different things depending on the effect, no changes for effects that do not depend on level/factor. NOPART at the end means no particles will be shown for this effect.=Nadaj efekt statusu dla samego siebie. Argumenty: : nazwa efektu statusu (po angielsku). Przekazanie "list" jako nazwa efektu wypisuje dostępne nazwy efektów. Przekazanie "heal" jako nazwa efektu leczy (albo krzywdzi) o ilość określoną następnym parametrem. Przekazanie "clear" jako nazwy efektu usuwa wszystkie efekty. Przekazanie "remove" jako nazwy efektu usuwa efekt określony następnym parametrem. : czas trwania w sekundach. Przekazanie "INF" jako czas trwania czyni efekt nieskończonym. (: ilość leczenia kiedy ID-efektu to "heal", przekazanie liczby ujemnej zabiera zdrowie. : nazwa efektu statusu do usunięcia używając "remove" jako poprzedniego parametru.) : wyznacznik siły efektu, wyższy poziom skutkuje potężniejszym efektem prze efektach zależnych od poziomu (brak zmiany przy pozostałych), domyślnie 1, przekaż F żeby użyć niskopoziomowego współczynnika zamiast poziomu. : modyfikator siły efektu, może oznaczać różne rzeczy dla różnych efektów, nie wpływa na efekty, które nie zależą od poziomu/współczynnika. NOPART na końcu oznacza, że cząsteczki nie będą wyświetlane wokół ciebie dla tego efektu. + +Missing effect parameter!=Brakujący ID efektu! +Missing or invalid heal amount parameter!=Brakująca lub niewłaściwa ilość leczenia! +Player @1 healed by @2 HP.=Gracz @1 wyleczony o @2 PŻ. +Player @1 harmed by @2 HP.=Gracz @1 skrzywdzony o @2 PŻ. +Effects cleared for player @1=Efekty wyczyszczone dla gracza @1 +Removed effect @1 from player @2=Usunięto efekt @1 z gracza @2 +@1 is not an available status effect.=@1 nie jest dostępnym efektem. +Missing or invalid duration parameter!=Brakujący lub niewłaściwy czas trwania! +Invalid level parameter!=Niewłaściwy parametr poziomu! +Missing or invalid factor parameter when level is F!=Brakujący lub niewłaściwy współczynnik kiedy poziom to F! + +@1 effect given to player @2 for @3 seconds with factor of @4.=Efekt @1 nadany dla gracza @2 na @3 sekund ze współczynnikiem @4. +@1 effect given to player @2 for @3 seconds.=Efekt @1 nadany dla gracza @2 na #3 sekund. +Giving effect @1 to player @2 failed.=Nadawanie efektu @1 dla gracza @2 nie powiodło się. +@1 effect on level @2 given to player @3 for @4 seconds.=Efekt @1 na poziomie @2 nadany dla gracza @3 na @4 sekund. + + +A throwable potion that will shatter on impact, where it gives all nearby players and mobs a status effect or a set of status effects.=Mikstura, którą można rzucić, a rozbije się przy uderzeniu, wystawiając wszystkich pobliskich graczy i moby na skutki jej działania. +Use the “Punch” key to throw it.=Użyj przycisku "Uderz" by rzucić. + + +A throwable potion that will shatter on impact, where it creates a magic cloud that lingers around for a while. Any player or mob inside the cloud will receive the potion's effect or set of effects, possibly repeatedly.=Mikstura, którą można rzucić, a roztrzaska się przy uderzeniu, tworząc magiczne opary pozostające przez chwilę na ziemi. Jakikolwiek gracz lub mob wewnątrz oparów będzie wystawiony na skutki mikstury, być może wielokrotnie. + + +This particular arrow is tipped and will give an effect when it hits a player or mob.=Czubek tej strzały jest zanurzony w miksturze, co wystawi jej cel na skutki jej działania. + + +Use the “Place” key to drink it.=Użyj przycisku "Postaw" by wypić. +Drinking a potion gives you a particular effect or set of effects.=Wypicie mikstury wywoła u ciebie określone skutki. + +@1 Potion @2=@1 Mikstura @2 +@1 Potion=@1 Mikstura +Potion @1=Mikstura @1 +Strange Potion=Dziwna Mikstura + +Splash @1=Miotana @1 +Lingering @1=Trwała @1 +@1 Arrow @2=@1 Strzała @2 +@1 Arrow=@1 Strzała +Arrow @1=Strzała @1 +Strange Tipped Arrow=Strzała z Dziwnym Grotem + +Mighty=Potężna +of Trolling=Trollowania + +Dragon's Breath=Oddech Smoka +This item is used in brewing and can be combined with splash potions to create lingering potions.=Ten przedmiot jest używany przy warzeniu i może zostać dodany do miotanych mikstur, aby uczynić je trwałymi. + +Awkward=Klarowna +No effect=Brak efektu +Has an awkward taste and is used for brewing potions.=Ma dziwny smak i jest używana do warzenia mikstur. + +Mundane=Mdła +Has a terrible taste and is not really useful for brewing potions.=Ma ohydny smak i nie jest zbyt użyteczna przy warzeniu mikstur. + +Thick=Gęsta +Has a bitter taste and may be useful for brewing potions.=Ma cierpki smak i może być użyteczna przy warzeniu mikstur. + +of Healing=Leczenia ++@1 HP=+@1 PŻ +Instantly heals.=Natychmiast leczy. + +of Harming=Krzywdy +-@1 HP=-@1 PŻ +Instantly deals damage.=Natychmiast zadaje obrażenia. + +of Night Vision=Noktowizji +Increases the perceived brightness of light under a dark sky.=Zwiększa postrzeganą jasność przy ciemnym niebie. + +of Swiftness=Szybkości +Increases walking speed.=Zwiększa prędkość ruchu. + +of Slowness=Spowolnienia +Decreases walking speed.=Zmniejsza prędkość ruchu. + +of Leaping=Zwiększonego Skoku +Increases jump strength.=Zwiększa siłę skoku. + +of Withering=Obumierania +Applies the withering effect which deals damage at a regular interval and can kill.=Zadaje efekt obumierania, zadający obrażenia w regularnych odstępach czasu i mogący zabić. + +of Poison=Trucizny +Applies the poison effect which deals damage at a regular interval.=Zadaje efekt trucizny, zadający obrażenia w regularnych odstępach czasu. + +of Regeneration=Regeneracji +Regenerates health over time.=Regeneruje życie z upływem czasu. + +of Invisibility=Niewidzialności +Grants invisibility.=Daje niewidzialność. + +of Water Breathing=Oddychania pod Wodą +Grants limitless breath underwater.=Daje nieograniczony oddech pod wodą. + +of Fire Resistance=Odporności na Ogień +Grants immunity to damage from heat sources like fire.=Daje odporność na obrażenia od źródeł ciepła takich jak ogień. + +of Strength=Siły +Increases attack power.=Zwiększa siłę ataku. + +of Weakness=Osłabienia +Decreases attack power.=Zmniejsza siłę ataku. + +of Slow Falling=Powolnego Opadania +Instead of falling, you descend gracefully.=Zamiast spadać, zstępujesz delikatnie. + +of Levitation=Lewitacji +Floats body slowly upwards.=Ciało powoli dryfuje w górę. + +of Darkness=Ciemności +Surrounds with darkness.=Otacza ciemnością. + +of Glowing=Blasku +Highlights for others to see.=Podświetla dla innych do dostrzeżenia. + +of Health Boost=Zwiększonego Zdrowia +Increases health.=Zwiększa zdrowie. + +of Absorption=Absorpcji +Absorbs some incoming damage.=Pochłania trochę otrzymywanych obrażeń. + +of Resistance=Odporności +Decreases damage taken.=Zmniejsza otrzymywane obrażenia. + +of Stone Cloak=Kamiennego Płaszcza +Decreases damage taken at the cost of speed.=Zmniejsza otrzymywane obrażenia kosztem prędkości. + +of Luck=Szczęścia +Increases luck.=Zwiększa szczęście. + +of Bad Luck=Pecha +Decreases luck.=Zmniejsza szczęście. + +of Frost=Mrozu +Freezes...=Zamraża... + +of Blindness=Ślepoty +Impairs sight.=Upośledza wzrok. + +of Nausea=Nudności +Disintegrates senses.=Dezintegruje zmysły. + +of Food Poisoning=Zatrucia Pokarmowego +Moves bowels too fast.=Porusza jelitami zbyt szybko. + +of Saturation=Nasycenia +Satisfies hunger.=Zaspokaja głód. + +of Haste=Pośpiechu +Increases digging and attack speed.=Zwiększa prędkość kopania i ataku. + +of Fatigue=Zmęczenia +Decreases digging and attack speed.=Zmniejsza prędkość kopania i ataku. + +Ominous=Złowieszcza +Attracts danger.=Przyciąga zagrożenie. + +Unknown Potion=Nieznana Mikstura +Right-click to identify=Kliknij prawym przyciskiem myszy, aby zidentyfikować +Unknown Tipped Arrow=Strzała z Nieznanym Grotem -Add a status effect to yourself. Arguments: : name of status effect, e.g. poison. : duration in seconds. : effect strength multiplier (1 @= 100%)=Dodaj status na siebie. Argumenty: : nazwa efektu statusu, np. trucizna. : czas trwania w sekundach. : czynnik siły efektu (1 @= 100%) -Missing effect parameter!=Brak parametru efektu! -Missing or invalid duration parameter!=Brak lub nieprawidłowy parametr czasu trwania! -Invalid factor parameter!=Nieprawidłowy parametr czynnika! -@1 is not an available status effect.=@1 nie jest dostępnym efektem statusu. Fermented Spider Eye=Fermentowane oko pająka +Try different combinations to create potions.=Wypróbuj różne kombinacje, by stworzyć mikstury. + Glass Bottle=Szklana butelka -Liquid container=Pojemnik na płyn +Liquid container=Zbiornik na ciecz A glass bottle is used as a container for liquids and can be used to collect water directly.=Szklana butelka jest używana jako pojemnik na płyny i może być wykorzystana bezpośrednio do pozyskiwania wody. - To collect water, use it on a cauldron with water (which removes a level of water) or any water source (which removes no water).=Aby pozyskać wodę użyj jej na kotle z wodą (co usunie jeden poziom wody) lub jakimkolwiek źródle wody (co nie usunie wody). Water Bottle=Butelka wody -Water bottles can be used to fill cauldrons. Drinking water has no effect.=Butelka wody może być wykorzystana do napełniania kotłów. Picie wody nie ma żadnych efektów. +Water bottles can be used to fill cauldrons. Drinking water has no effect.=Butelka wody może być wykorzystana do napełniania kotłów. Picie wody nie ma żadnych skutków. Use the “Place” key to drink. Place this item on a cauldron to pour the water into the cauldron.=Użyj przycisku do stawiania aby pić. Postaw ten przedmiot na kotle aby wylać wodę do kotła. River Water Bottle=Butelka wody rzecznej -River water bottles can be used to fill cauldrons. Drinking it has no effect.=Butelka wody rzecznej może być wykorzystana do napełniania kotłów. Picie jej nie ma żadnego efektu. +River water bottles can be used to fill cauldrons. Drinking it has no effect.=Butelka wody rzecznej może być wykorzystana do napełniania kotłów. Picie jej nie ma żadnego skutku. Use the “Place” key to drink. Place this item on a cauldron to pour the river water into the cauldron.=Użyj przycisku do stawiania aby pić. Postaw ten przedmiot na kotle aby wylać wodę rzeczną do kotła. Splash Water Bottle=Miotana butelka wody Extinguishes fire and hurts some mobs=Gasi ogień i rani niektóre moby -A throwable water bottle that will shatter on impact, where it extinguishes nearby fire and hurts mobs that are vulnerable to water.=Butelka wody którą można rzucać i roztrzaska się przy uderzeniu, gdzie ugasi ogień i rani moby podatne na wodę. +A throwable water bottle that will shatter on impact, where it extinguishes nearby fire and hurts mobs that are vulnerable to water.=Butelka wody, którą można rzucić, a roztrzaska się przy uderzeniu, gdzie ugasi ogień i zrani moby podatne na wodę. Lingering Water Bottle=Trwała miotana butelka wody -A throwable water bottle that will shatter on impact, where it creates a cloud of water vapor that lingers on the ground for a while. This cloud extinguishes fire and hurts mobs that are vulnerable to water.=Butelka wody którą można rzucać i roztrzaska się przy uderzeniu tworząc opary wody pozostające przez chwilę na ziemi. Opary te gaszą ogień i ranią moby podatne na wodę. +A throwable water bottle that will shatter on impact, where it creates a cloud of water vapor that lingers on the ground for a while. This cloud extinguishes fire and hurts mobs that are vulnerable to water.=Butelka wody którą można rzucić, a roztrzaska się przy uderzeniu, tworząc opary wody pozostające przez chwilę na ziemi. Opary te gaszą ogień i ranią moby podatne na wodę. Glistering Melon=Błyszczący arbuz This shiny melon is full of tiny gold nuggets and would be nice in an item frame. It isn't edible and not useful for anything else.=Ten błyszczący arbuz jest pełen tycich odłamków złota i wygląda ładnie w ramkach na przedmioty. Nie jest jadalny ani użyteczny do innych rzeczy. - -A throwable potion that will shatter on impact, where it creates a magic cloud that lingers around for a while. Any player or mob inside the cloud will receive the potion's effect, possibly repeatedly.=Mikstura którą można rzucać i roztrzaska się przy uderzeniu tworząc magiczne opary pozostające przez chwilę na ziemi. Jakikolwiek gracz lub mob wewnątrz oparów będzie wystawiony na efekt mikstury. - -Use the “Punch” key to throw it.=Użyj przycisku "Uderz" by rzucić. -Use the “Place” key to drink it.=Użyj przycisku "Postaw" by wypić. -Drinking a potion gives you a particular effect.=Wypicie mikstury sprawi, że będziesz wystawiona na jej efekty. -1 HP/@1s | @2=1 HP/@1s | @2 -@1 HP=@1 HP -@1 Potion=Mikstura @1 -Splash @1 Potion=Miotana mikstura @1 -Lingering @1 Potion=Trwała miotana mikstura @1 -Arrow of @1=Strzała @1 - II= II - IV= IV -@1 Potion@2=Mikstura @1@2 -Splash @1@2 Potion=Miotana mikstura @1@2 -Lingering @1@2 Potion=Trwała miotana mikstura @1@2 -Arrow of @1@2=Strzała @1@2 -@1 + Potion=Mikstura @1 + -Splash @1 + Potion=Miotana mikstura @1 + -Lingering @1 + Potion=Trwała miotana mikstura @1 + -Arrow of @1 +=Strzała @1 + -Awkward Potion=Klarowna mikstura -Awkward Splash Potion=Klarowna miotana mikstura -Awkward Lingering Potion=Klarowna trwała miotana mikstura -Has an awkward taste and is used for brewing potions.=Ma dziwny smak i jest użyteczna przy warzenia mikstur. -Mundane Potion=Mdła mikstura -Mundane Splash Potion=Mdła miotana mikstura -Mundane Lingering Potion=Mdła trwała miotana mikstura -Has a terrible taste and is not useful for brewing potions.=Ma ohydny smak i nie jest użyteczna przy warzenia mikstur. -Thick Potion=Gęsta mikstura -Thick Splash Potion=Gęsta miotana mikstura -Thick Lingering Potion=Gęsta trwała miotana mikstura -Has a bitter taste and is not useful for brewing potions.=Ma cierpki smak i nie jest użyteczna przy warzenia mikstur. -Dragon's Breath=Oddech smoka - -This item is used in brewing and can be combined with splash potions to create lingering potions.=Ten przedmiot jest używany przy warzeniu i może zostać dodany do miotanych mikstur aby uczynić je trwałymi. - -Healing=leczenia -+4 HP=+4 HP -+8 HP=+8 HP -Instantly heals.=Natychmiastowo leczy. -Harming=obrażeń --6 HP=-6 HP --12 HP=-12 HP -Instantly deals damage.=Natychmiastowo zadaje obrażenia. -Night Vision=widzenia w ciemności -Increases the perceived brightness of light under a dark sky.=Zwiększa postrzeganą jasność przy ciemnym niebie. -Swiftness=prędkości -Increases walking speed.=Zwiększa prędkość poruszania. -Slowness=spowolnienia -Decreases walking speed.=Zmniejsza prędkość poruszania. -Leaping=skakania -Increases jump strength.=Zwiększa siłę skoku. -Poison=trucizny -Applies the poison effect which deals damage at a regular interval.=Aplikuje efekt trucizny zadający obrażenia w regularnych odstępach czasu. -Regeneration=regeneracji -Regenerates health over time.=Regeneruje życie przez pewien czas. -Invisibility=niewidzialności -Grants invisibility.=Sprawia, że cel jest niewidzialny. -Water Breathing=oddychania pod wodą -Grants limitless breath underwater.=Sprawia, że cel może oddychać pod wodą. -Fire Resistance=odporności na ogień -Grants immunity to damage from heat sources like fire.=Sprawia, że cel jest odporny na obrażenia od źródeł ciepła takich jak ogień. -Weakness=słabości -Weakness +=słabości + -Strength=siły -Strength II=siły II -Strength +=siły + -Try different combinations to create potions.=Spróbuj innej kombinacji aby stworzyć miksturę. -No effect=Brak efektu - -A throwable potion that will shatter on impact, where it gives all nearby players and mobs a status effect.=Mikstura, którą można rzucić i rozbije się przy uderzeniu wystawiając wszystkich pobliskich graczy i moby na efekt jej działania. - -This particular arrow is tipped and will give an effect when it hits a player or mob.=Czubek tej strzały jest zanurzony w miksturze co wystawi jej cel na efekt jej działania. - diff --git a/mods/ITEMS/mcl_potions/locale/template.txt b/mods/ITEMS/mcl_potions/locale/template.txt index 50c622391..39cd18f31 100644 --- a/mods/ITEMS/mcl_potions/locale/template.txt +++ b/mods/ITEMS/mcl_potions/locale/template.txt @@ -115,9 +115,6 @@ Missing or invalid factor parameter when level is F!= @1 effect given to player @2 for @3 seconds.= Giving effect @1 to player @2 failed.= @1 effect on level @2 given to player @3 for @4 seconds.= -@1 effect given to player @2 for @3 seconds.= -Giving effect @1 to player @2 failed.= -@1 is not an available status effect.= A throwable potion that will shatter on impact, where it gives all nearby players and mobs a status effect or a set of status effects.= @@ -138,8 +135,6 @@ Drinking a potion gives you a particular effect or set of effects.= Potion @1= Strange Potion= -Stacks the effect= - Splash @1= Lingering @1= @1 Arrow @2= diff --git a/mods/ITEMS/mcl_potions/potions.lua b/mods/ITEMS/mcl_potions/potions.lua index 471c4ad3d..c8de4353e 100644 --- a/mods/ITEMS/mcl_potions/potions.lua +++ b/mods/ITEMS/mcl_potions/potions.lua @@ -176,9 +176,6 @@ function mcl_potions.register_potion(def) pdef.description = S("Strange Potion") end pdef._tt_help = def._tt - if def._tt and def.effect_stacks then - pdef._tt_help = pdef._tt_help .. "\n" .. S("Stacks the effect") - end pdef._dynamic_tt = def._dynamic_tt local potion_longdesc = def._longdesc if def._effect_list then From 018814c362c5ae560d9ad1c2abbeaa18c9ff2ad6 Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Thu, 2 May 2024 04:09:39 +0200 Subject: [PATCH 89/91] Added a few mobitems * one droppable from strays * the rest will get their mobs in a later update * added alternative ways to get the items * added recipes for potions that use these items --- mods/ENTITIES/mobs_mc/skeleton+stray.lua | 9 ++++- mods/ENTITIES/mobs_mc/villager.lua | 2 ++ mods/ITEMS/mcl_fishing/init.lua | 2 ++ mods/ITEMS/mcl_mobitems/init.lua | 40 ++++++++++++++++++++++ mods/ITEMS/mcl_potions/init.lua | 10 +++--- textures/vl_mobitems_aery_charge.png | Bin 0 -> 229 bytes textures/vl_mobitems_crystalline_drop.png | Bin 0 -> 156 bytes textures/vl_mobitems_earthen_ash.png | Bin 0 -> 206 bytes textures/vl_mobitems_ice_crystal.png | Bin 0 -> 341 bytes textures/vl_mobitems_spectre_membrane.png | Bin 0 -> 167 bytes 10 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 textures/vl_mobitems_aery_charge.png create mode 100644 textures/vl_mobitems_crystalline_drop.png create mode 100644 textures/vl_mobitems_earthen_ash.png create mode 100644 textures/vl_mobitems_ice_crystal.png create mode 100644 textures/vl_mobitems_spectre_membrane.png diff --git a/mods/ENTITIES/mobs_mc/skeleton+stray.lua b/mods/ENTITIES/mobs_mc/skeleton+stray.lua index a84264a83..8ea4d9ced 100644 --- a/mods/ENTITIES/mobs_mc/skeleton+stray.lua +++ b/mods/ENTITIES/mobs_mc/skeleton+stray.lua @@ -153,13 +153,20 @@ table.insert(stray.drops, { local chance = 0.5 for i = 1, lvl do if chance > 1 then - return 1 + return 1 -- TODO verify this logic, I think this is not how chance works end chance = chance + (1 - chance) / 2 end return chance end, }) +table.insert(stray.drops, { + name = "mcl_mobitems:shiny_ice_crystal", + chance = 3, + min = 1, + max = 2, + looting = "rare", +}) mcl_mobs.register_mob("mobs_mc:stray", stray) diff --git a/mods/ENTITIES/mobs_mc/villager.lua b/mods/ENTITIES/mobs_mc/villager.lua index 2897650c8..b1e291037 100644 --- a/mods/ENTITIES/mobs_mc/villager.lua +++ b/mods/ENTITIES/mobs_mc/villager.lua @@ -608,6 +608,8 @@ local professions = { { { { "mcl_nether:nether_wart_item", 22, 22 }, E1 }, { { "mcl_core:emerald", 3, 3 }, { "mcl_experience:bottle", 1, 1 } }, + { { "mcl_core:emerald", 15, 15 }, { "mcl_mobitems:aery_charge", 1, 1 } }, -- TODO reconsider + { { "mcl_core:emerald", 15, 15 }, { "mcl_mobitems:earthen_ash", 1, 1 } }, -- TODO reconsider }, }, }, diff --git a/mods/ITEMS/mcl_fishing/init.lua b/mods/ITEMS/mcl_fishing/init.lua index 163c103a3..f381ffefc 100644 --- a/mods/ITEMS/mcl_fishing/init.lua +++ b/mods/ITEMS/mcl_fishing/init.lua @@ -114,6 +114,8 @@ local fish = function(itemstack, player, pointed_thing) { itemstring = "mcl_mobitems:saddle", }, { itemstring = "mcl_flowers:waterlily", }, { itemstring = "mcl_mobitems:nautilus_shell", }, + { itemstring = "mcl_mobitems:spectre_membrane", }, + { itemstring = "mcl_mobitems:crystalline_drop", }, }, stacks_min = 1, stacks_max = 1, diff --git a/mods/ITEMS/mcl_mobitems/init.lua b/mods/ITEMS/mcl_mobitems/init.lua index f74d254ba..4d92c2d43 100644 --- a/mods/ITEMS/mcl_mobitems/init.lua +++ b/mods/ITEMS/mcl_mobitems/init.lua @@ -231,6 +231,46 @@ minetest.register_craftitem("mcl_mobitems:string",{ groups = { craftitem = 1 }, }) +minetest.register_craftitem("mcl_mobitems:spectre_membrane",{ + description = S("Spectre Membrane"), + _doc_items_longdesc = S("This is a crafting component dropped from dead spectres."), + inventory_image = "vl_mobitems_spectre_membrane.png", + groups = { craftitem = 1, brewitem = 1 }, + stack_max = 64, +}) + +minetest.register_craftitem("mcl_mobitems:shiny_ice_crystal",{ + description = S("Shiny Ice Crystal"), + _doc_items_longdesc = S("This item is mainly used for crafting."), + inventory_image = "vl_mobitems_ice_crystal.png", + groups = { craftitem = 1, brewitem = 1 }, + stack_max = 64, +}) + +minetest.register_craftitem("mcl_mobitems:aery_charge",{ + description = S("Aery Charge"), + _doc_items_longdesc = S("This item is mainly used for crafting."), -- TODO shoot? + inventory_image = "vl_mobitems_aery_charge.png", + groups = { craftitem = 1, brewitem = 1 }, + stack_max = 64, +}) + +minetest.register_craftitem("mcl_mobitems:crystalline_drop",{ + description = S("Crystalline Drop"), + _doc_items_longdesc = S("This item is mainly used for crafting."), -- TODO other uses? + inventory_image = "vl_mobitems_crystalline_drop.png", + groups = { craftitem = 1, brewitem = 1 }, + stack_max = 64, +}) + +minetest.register_craftitem("mcl_mobitems:earthen_ash",{ + description = S("Earthen Ash"), + _doc_items_longdesc = S("This item is mainly used for crafting."), -- TODO other uses? + inventory_image = "vl_mobitems_earthen_ash.png", + groups = { craftitem = 1, brewitem = 1 }, + stack_max = 64, +}) + minetest.register_craftitem("mcl_mobitems:blaze_rod", { description = S("Blaze Rod"), _doc_items_longdesc = S("This is a crafting component dropped from dead blazes."), diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index cdc095203..653e3df8c 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -401,14 +401,14 @@ local awkward_table = { ["mcl_flowers:fourleaf_clover"] = "mcl_potions:luck", ["mcl_farming:potato_item_poison"] = "mcl_potions:nausea", - ["mcl_mobitems:phantom_membrane"] = "mcl_potions:slow_falling", -- TODO add phantom membranes + ["mcl_mobitems:spectre_membrane"] = "mcl_potions:slow_falling", ["mcl_core:apple_gold"] = "mcl_potions:resistance", + ["mcl_mobitems:aery_charge"] = "mcl_potions:haste", + ["mcl_mobitems:crystalline_drop"] = "mcl_potions:absorption", + ["mcl_mobitems:earthen_ash"] = "mcl_potions:stone_cloak", + ["mcl_mobitems:shiny_ice_crystal"] = "mcl_potions:frost", -- TODO darkness - sculk? - -- TODO absorption - water element? - -- TODO turtle master - earth element? - -- TODO frost - frost element? - -- TODO haste - air element? } -- API -- register a potion recipe brewed from awkward potion diff --git a/textures/vl_mobitems_aery_charge.png b/textures/vl_mobitems_aery_charge.png new file mode 100644 index 0000000000000000000000000000000000000000..51608d922875d710554c24892a96ada2de4959c2 GIT binary patch literal 229 zcmV^P)VL8f0cqa0e%1deeO>=+lLEn*Jk7;9|7)`oAT%+Cz%_R^ zfi=NskmguVoBz3C?*H)y7|72sO&~T*GuRdQ48f@xq!EZgnve|vVHC|E46_Mr2$Cjr z%^*I8OOTz3iw0>x){No`7=S6lhG9;}8;~#nQ;dv>(l{Uh02!py=Dz{JWDrh|uF~G_BnV)U06^*MbLcT< nGKZ2_&1ClP#O~$K<}B+IdN;my9`(ue00000NkvXXu0mjfKN*)s literal 0 HcmV?d00001 diff --git a/textures/vl_mobitems_spectre_membrane.png b/textures/vl_mobitems_spectre_membrane.png new file mode 100644 index 0000000000000000000000000000000000000000..0819e7532441d6c8ac6233404de127800ae6c20b GIT binary patch literal 167 zcmV;Y09gNtP)o%bJv$x;kr2TwmpoB<$3<>!8b6`Lk?{)cJCYXGuhkY<kt*-BJ6z~UU2t@IBEY%U^bJF>0#yhc_=At@7)0syX% VIrQ3T(76Br002ovPDHLkV1hX)KDht@ literal 0 HcmV?d00001 From 0c57469c6bdfb3dcfafc992414e1162cc78161fa Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Thu, 2 May 2024 04:14:55 +0200 Subject: [PATCH 90/91] Updated Polish translation --- mods/ITEMS/mcl_mobitems/locale/mcl_mobitems.pl.tr | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mods/ITEMS/mcl_mobitems/locale/mcl_mobitems.pl.tr b/mods/ITEMS/mcl_mobitems/locale/mcl_mobitems.pl.tr index a58bfb474..484bc2d61 100644 --- a/mods/ITEMS/mcl_mobitems/locale/mcl_mobitems.pl.tr +++ b/mods/ITEMS/mcl_mobitems/locale/mcl_mobitems.pl.tr @@ -58,6 +58,12 @@ This item is dropped by dead squids. Squid ink can be used to as an ingredient String=Nić Strings are used in crafting.=Nić jest użyteczna w wytwarzaniu. +Spectre Membrane=Błona Widma +This is a crafting component dropped from dead spectres.=Jest to materiał do wytwarzania wypadający z martwych widm. +Shiny Ice Crystal=Lśniący Kryształ Lodu +Aery Charge=Powietrzny Ładunek +Crystalline Drop=Krystaliczna Kropla +Earthen Ash=Ziemny Popiół Blaze Rod=Płomienna różdżka This is a crafting component dropped from dead blazes.=Jest to materiał do wytwarzania wypadający z martwych płomyków. Blaze Powder=Płomienny proszek From 07fac026ddfdf4fb685594d30ec7052b799258eb Mon Sep 17 00:00:00 2001 From: the-real-herowl Date: Thu, 2 May 2024 04:17:16 +0200 Subject: [PATCH 91/91] Added a darkness potion recipe --- mods/ITEMS/mcl_potions/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ITEMS/mcl_potions/init.lua b/mods/ITEMS/mcl_potions/init.lua index 653e3df8c..446f6ef16 100644 --- a/mods/ITEMS/mcl_potions/init.lua +++ b/mods/ITEMS/mcl_potions/init.lua @@ -497,6 +497,7 @@ local inversion_table = { ["mcl_potions:saturation"] = "mcl_potions:food_poisoning", ["mcl_potions:slow_falling"] = "mcl_potions:levitation", ["mcl_potions:absorption"] = "mcl_potions:health_boost", + ["mcl_potions:glowing"] = "mcl_potions:darkness", -- TODO remove after adding a direct recipe? } -- API function mcl_potions.register_inversion_recipe(input, output)