diff --git a/.luacheckrc b/.luacheckrc index 8b83ddf..e3b59be 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -31,6 +31,7 @@ read_globals = { "screwdriver", "mcl_crafting_table", "mcl_enchantments", + "stamina", "technic", "hopper", diff --git a/README.md b/README.md index b177b99..264c9c6 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ Dependencies: Minetest Game or MineClone. * In Mineclonia, hoppers can put invalid items into Energy Collectors. * Tools do not show the wear bar (to show the charge level) when first created or crafted. It only appears after changing the range. This will not be fixed. * Unfortunately, caused by the performance improvements to various tool abilities, using the shear ability on sea grass (MCL) will also remove the sand below the sea grass. I can't think of a good way to fix it. +* Dark and Red Matter Armor can make the player invincible. This is an [engine problem](https://github.com/minetest/minetest/issues/14344) that I can't fix. **If you have a suggestion or notice a bug that isn't on this list, visit the [GitHub issues page](https://github.com/thepython10110/exchangeclone/issues).** @@ -89,18 +90,17 @@ You can find the old textures and sounds by going back to previous commits in Gi * [x] Multiple levels of Exchange Orbs (change to Klein Stars, adjust recipes) * [x] Wear bar on Klein Stars for EMC * [x] Fuel storage blocks -* [ ] Divining rods -* [ ] Swiftwolf's Rending Gale (maybe rename?) -* [ ] Mind, Life, Body and Soul Stones (Mind = MCL only) -* [ ] Talisman of Repair (will only work in player inventory, not Alchemical Chests like ProjectE) -* [x] Gem of Eternal Density (will only work on right click, not automatically). -* [ ] Change energy collector recipes to match ProjectE -* [ ] Update screenshots +* [x] Mind, Life, Body and Soul Stones (Mind = MCL only, Body and Life require Stamina mod in MTG) +* [x] Talisman of Repair (will only work in player inventory, not Alchemical Chests like ProjectE) +* [x] Gem of Eternal Density * [x] Update media licenses -* [ ] Edit wiki: - * [ ] Achievements? - * [ ] Divining rods - * [ ] Swiftwolf's Rending Gale +* [ ] Testing + * [ ] Every tool ability in every game + * [ ] Every machine in every game + * [ ] Check new recipes in every game +* [ ] Update screenshots +* [ ] Update wiki: + * [ ] Achievements? Maybe don't belong in wiki... * [ ] Talisman of Repair * [ ] Gem of Eternal Density * [ ] Mind, Life, Body, and Soul Stones @@ -116,9 +116,11 @@ You can find the old textures and sounds by going back to previous commits in Gi #### Overview: * **NOTE: Updating to this version resets tools to their default mode and range (1x1, range 0). Upgrades will not be affected.** +* **OTHER NOTE: In this version... dark and red matter armor are ridiculously overpowered, often making the player invincible. This is an [engine problem](https://github.com/minetest/minetest/issues/14344) that I can't fix.** * Tools' mining speeds, attack damage, and attack speeds now match ProjectE's -* Most tools' abilities are more similar to ProjectE's, and are more efficient in some cases. -* ExchangeClone now uses EE2/ProjectE's textures (I didn't know until recently that EE2's license had been changed to MIT) +* Most tools' abilities are more similar to ProjectE's, and perform better in some cases. +* New items +* ExchangeClone now mostly uses EE2/ProjectE's textures and sounds (I didn't know until recently that EE2's license had been changed to MIT). #### Full changelog: * New features: @@ -126,6 +128,8 @@ You can find the old textures and sounds by going back to previous commits in Gi * Replaced Exchange Orbs with Klein Stars and Magnum Stars * Added storage blocks for Alchemical Coal, Mobius Fuel, and Aeternalis Fuel * Added Gem of Eternal Density + * Added Soul, Body, Life, and Mind Stones (Mind = MCL only, Body/Life require Stamina mod in MTG) + * Added Talisman of Repair * Changes: * Most textures and all sounds are now from ProjectE/EE2. See license section for details. * Several improvements to tools: @@ -138,12 +142,13 @@ You can find the old textures and sounds by going back to previous commits in Gi * Several changes to tool abilities (*mostly* making them closer to the ProjectE versions) * Got rid of `exchangeclone.node_radius_action` function (it was pretty much over-refactoring and made things so much more complicated) * Removed the deprecated PESA. - * Changed "energy" to "EMC" - * Replaced Exchange Orbs with Klein Stars and Magnum Stars + * Changed "energy" to "EMC" (any mods that depend on this will probably have to deal with that, find/replace should work pretty well). + * Replaced Exchange Orbs with Klein Stars and Magnum Stars (any mods that depend on this should find/replace orb with star) * Since Klein Star Omegas have the same capacity as the old Exchange Orbs, they now replace them (meaning players don't lose anything). - * Klein Star Ein->Zwei->Drei->Vier->Sphere->Omega, then the same order for Magnum Stars. + * Klein Star Ein->Zwei->Drei->Vier->Sphere->Omega, then the same order for Magnum Stars, each holding (and costing) 4 times more than the last. * Bugfixes * The Philosopher's Stone no longer fails to transmute logs and leaves in Mineclonia. + * Added energy values for azalea bushes in Mineclonia. ### v6.9 * Fixed a bug where characters were not escaped in the search bar of the Transmutation Table(t) formspec (reported by @programmerjake). @@ -438,9 +443,7 @@ I didn't get to everything I wanted to, mostly because the automatic energy valu ### Features that I plan on adding eventually: -* Achievements * ~~As soon as Minetest 5.8 comes out, better textures for armor...~~ Don't want to limit it to 5.8 -* Divining Rods * Rings (I'll probably add a new PESA-like item for holding rings) * Archangel's Smite (MCL only, arrows will not track targets) * Ring of Ignition @@ -450,8 +453,5 @@ I didn't get to everything I wanted to, mostly because the automatic energy valu * Ring of Arcana (possibly without the Harvest Band) * Gem Armor * Catalytic Lens -* Mind, Life, Body, and Soul Stones * Mercurial Eye -* Talisman of Repair -* Gem of Eternal Density * Probably other things \ No newline at end of file diff --git a/exchangeclone/armor.lua b/exchangeclone/armor.lua index c2a35d6..b634ba0 100644 --- a/exchangeclone/armor.lua +++ b/exchangeclone/armor.lua @@ -288,7 +288,7 @@ else local damage = -hp_change local _, armor_inv = armor:get_valid_player(player, "3d_armor") local blocked = 0 - for i = 1, 6 do + for i = 1, #armor_inv:get_list("armor") do local itemstack = armor_inv:get_stack("armor", i) blocked = blocked + get_blocked_damage(itemstack, damage, reason) end diff --git a/exchangeclone/axes.lua b/exchangeclone/axes.lua index 19ecd1f..36a37f4 100644 --- a/exchangeclone/axes.lua +++ b/exchangeclone/axes.lua @@ -97,6 +97,7 @@ minetest.register_tool("exchangeclone:dark_matter_axe", { _mcl_diggroups = { axey = { speed = 14, level = 5, uses = 0 } }, + wear_represents = "exchangeclone_charge_level" }) exchangeclone.set_charge_type("exchangeclone:dark_matter_axe", "dark_matter") @@ -124,6 +125,7 @@ minetest.register_tool("exchangeclone:red_matter_axe", { _mcl_diggroups = { axey = { speed = 16, level = 6, uses = 0 } }, + wear_represents = "exchangeclone_charge_level" }) exchangeclone.set_charge_type("exchangeclone:red_matter_axe", "red_matter") diff --git a/exchangeclone/baubles.lua b/exchangeclone/baubles.lua deleted file mode 100644 index e742be9..0000000 --- a/exchangeclone/baubles.lua +++ /dev/null @@ -1,162 +0,0 @@ --- Currently none of this stuff actually runs (didn't get to it in v6.0) - -local S = minetest.get_translator() - -local storage = minetest.get_mod_storage() -exchangeclone.bauble_data = minetest.deserialize(storage:get_string("bauble_data")) - ---[[ - -Bauble data format: -{ - action_name = { - player = { - player_name = true, - player_name = true, - } - detached = { - detached_name = true, - detached_name = true, - } - node = { - pos_string = true, - pos_string = true, - } - } -} -For example: -{ - repair = { - player = { - "singleplayer", - "ThePython" - }, - detached = { - "exchangeclone_transmutation_ThePython", - } - node = { - ["(0,0,0)"] = true, - ["(0,999,0)"] = true, - } - } - density = { - player = { - "singleplayer" - } - } -} - -What is done with these values must be handled by the actions themselves. - ---]] - -local time = 0 -local saving_time = 0 - -function exchangeclone.run_bauble_actions() - for _, data in ipairs(exchangeclone.bauble_data) do - for _, action in ipairs(data[2]) do - local func = exchangeclone.bauble_actions[action] - if func then func(data) end - end - end -end - -minetest.register_on_globalstep(function(dtime) - time = time + dtime - saving_time = saving_time + dtime - if time >= 1 then - exchangeclone.run_bauble_actions() - time = 0 - end -end) - -function exchangeclone.show_baubles(player) - local formspec - minetest.show_formspec(player:get_name(), "exchangeclone_baubles", formspec) -end - -minetest.register_tool("exchangeclone:bauble_accessor", { - description = S("Bauble Accessor"), - groups = {disable_repair = 1}, -}) - -minetest.register_tool("exchangeclone:repair_talisman", { - description = S("Repair Talisman"), - groups = {disable_repair = 1, bauble = 1}, - bauble_info = { - action = "repair", - hotbar = true - }, -}) - -minetest.register_tool("exchangeclone:gem_of_eternal_density", { - description = S("Gem of Eternal Density"), - groups = {disable_repair = 1, bauble = 1}, - bauble_info = { - action = "density", - hotbar = true - } -}) - -function exchangeclone.check_baubles(inv, list) - if not inv then return end - list = list or "main" -end - -minetest.register_on_player_inventory_action(function(player, action, inventory, info) - -- Make sure that it's the player owning the inventory, not just the player editing the inventory - player = minetest.get_player_by_name(inventory:get_location().name) - if not player then return end - if action == "move" then - local stack = inventory:get_stack(info.to_list, info.to_index) - if stack:is_empty() then return end - local def = minetest.registered_items[stack:get_name()] - if not (def and def.groups.bauble) then return end - - end -end) - -local function repair_item(stack) - if not stack:is_empty() then - local def = minetest.registered_items[stack:get_name()] - if def - and def.type == "tool" - and (not def.wear_represents or def.wear_represents == "mechanical_wear") - and stack:get_wear() ~= 0 - and ((exchangeclone.mcl and def.durability > 0) or exchangeclone.mtg) then - local uses - if exchangeclone.mcl then - if def.durability then - uses = def.durability - elseif def._mcl_diggroups then - uses = def._mcl_diggroups[1].uses - end - else - if def.tool_capabilities and def.tool_capabilities.groupcaps then - local groupcaps = def.tool_capabilities.groupcaps[1] - uses = groupcaps.uses*math.pow(3, groupcaps.max_level) - elseif def.groups.armor_use then - uses = def.groups.armor_use - end - end - if not uses then uses = 1000 end - if uses then - stack:set_wear(stack:get_wear() + 65535/uses) - end - end - end - - return stack -end - -exchangeclone.bauble_actions = { - repair = function(data) - for _, player in ipairs(data.player) do - local inv = player:get_inventory() - for i = 1, inv:get_size("main") do - inv:set_stack("main", i, repair_item(inv:get_stack("main", i))) - end - end - end -} \ No newline at end of file diff --git a/exchangeclone/covalence_dust.lua b/exchangeclone/covalence_dust.lua index 95c9c8d..7782d0e 100644 --- a/exchangeclone/covalence_dust.lua +++ b/exchangeclone/covalence_dust.lua @@ -81,17 +81,22 @@ local function is_repairable_gear(item) if item:get_wear() <= 0 then return end if minetest.get_item_group(item:get_name(), "disable_repair") > 0 then return end if (exchangeclone.get_item_emc(item) or 0) <= 0 then return end - - local result = 0 - for group, amount in pairs(exchangeclone.tool_types) do - if minetest.get_item_group(item:get_name(), group) > 0 then - result = result + amount + local def = item:get_definition() + if def + and def.type == "tool" + and (not def.wear_represents or def.wear_represents == "mechanical_wear") + and item:get_wear() ~= 0 + and ((exchangeclone.mcl and def.durability > 0) or exchangeclone.mtg) then + local result = 0 + for group, amount in pairs(exchangeclone.tool_types) do + if minetest.get_item_group(item:get_name(), group) > 0 then + result = result + amount + end end + return (result > 0) and result end - return (result > 0) and result end --- Doesn't even get to repairable_gear function minetest.register_allow_player_inventory_action(function(player, action, inventory, info) if action == "take" and listnames[info.listname] then return info.stack:get_count() diff --git a/exchangeclone/gem_of_eternal_density.lua b/exchangeclone/gem_of_eternal_density.lua index b8f6289..2d3a7f9 100644 --- a/exchangeclone/gem_of_eternal_density.lua +++ b/exchangeclone/gem_of_eternal_density.lua @@ -12,29 +12,11 @@ local function get_gem_description(itemstack) local target_message = "Target: "..ItemStack(exchangeclone.density_targets[current_target]):get_short_description() local emc = exchangeclone.get_item_emc(itemstack:get_name()) local stored = exchangeclone.get_item_emc(itemstack) - emc - return "Gem of Eternal Density\n"..target_message.."\nEMC value: "..exchangeclone.format_number(emc).."\nStored EMC: "..exchangeclone.format_number(stored) + return "Gem of Eternal Density\n"..target_message.."\nEMC Value: "..exchangeclone.format_number(emc).."\nStored EMC: "..exchangeclone.format_number(stored) end -local function gem_action(itemstack, player, pointed_thing) - local click_test = exchangeclone.check_on_rightclick(itemstack, player, pointed_thing) - if click_test ~= false then - return click_test - end - +local function condense(player, itemstack) local meta = itemstack:get_meta() - if player:get_player_control().aux1 then - local current_target = math.max(meta:get_int("density_target"), 1) - if player:get_player_control().sneak then - current_target = math.max(1, current_target - 1) - else - current_target = math.min(#exchangeclone.density_targets, current_target + 1) - end - minetest.chat_send_player(player:get_player_name(), "Target: "..ItemStack(exchangeclone.density_targets[current_target]):get_short_description()) - meta:set_int("density_target", current_target) - meta:set_string("description", get_gem_description(itemstack)) - return itemstack - end - local inv = player:get_inventory() local list = inv:get_list("main") -- Don't include hotbar @@ -84,17 +66,51 @@ local function gem_action(itemstack, player, pointed_thing) if remainder > 0 then remainder_emc = remainder_emc + remainder*target_emc end - exchangeclone.play_sound(player, "exchangeclone_enable") + if meta:get_string("exchangeclone_active") ~= "true" then + exchangeclone.play_sound(player, "exchangeclone_enable") + end meta:set_int("exchangeclone_emc_value", exchangeclone.get_item_emc(itemstack:get_name()) + remainder_emc) meta:set_string("description", get_gem_description(itemstack)) return itemstack end +local function gem_action(itemstack, player, pointed_thing) + local click_test = exchangeclone.check_on_rightclick(itemstack, player, pointed_thing) + if click_test ~= false then + return click_test + end + + local meta = itemstack:get_meta() + if player:get_player_control().aux1 then + local current_target = math.max(meta:get_int("density_target"), 1) + if player:get_player_control().sneak then + current_target = math.max(1, current_target - 1) + else + current_target = math.min(#exchangeclone.density_targets, current_target + 1) + end + minetest.chat_send_player(player:get_player_name(), "Target: "..ItemStack(exchangeclone.density_targets[current_target]):get_short_description()) + meta:set_int("density_target", current_target) + meta:set_string("description", get_gem_description(itemstack)) + return itemstack + elseif player:get_player_control().sneak then + return exchangeclone.toggle_active(itemstack, player, pointed_thing) + else + return condense(player, itemstack) + end +end + minetest.register_tool("exchangeclone:gem_of_eternal_density", { description = "Gem of Eternal Density", inventory_image = "exchangeclone_gem_of_eternal_density.png", on_secondary_use = gem_action, - on_place = gem_action + on_place = gem_action, + _exchangeclone_passive = { + hotbar = true, + active_image = "exchangeclone_gem_of_eternal_density_active.png", + func = condense + }, + groups = {disable_repair = 1, exchangeclone_passive = 1}, + _mcl_generate_description = get_gem_description }) minetest.register_craft({ diff --git a/exchangeclone/hammers.lua b/exchangeclone/hammers.lua index dcf3436..d668a6a 100644 --- a/exchangeclone/hammers.lua +++ b/exchangeclone/hammers.lua @@ -72,7 +72,8 @@ minetest.register_tool("exchangeclone:dark_matter_hammer", { pickaxey = { speed = 14, level = 5, uses = 0 } }, on_place = hammer_on_place, - on_secondary_use = hammer_on_place + on_secondary_use = hammer_on_place, + wear_represents = "exchangeclone_charge_level" }) exchangeclone.register_multidig_tool("exchangeclone:dark_matter_hammer", {"group:"..exchangeclone.pickaxe_group}) @@ -101,6 +102,7 @@ minetest.register_tool("exchangeclone:red_matter_hammer", { }, on_place = hammer_on_place, on_secondary_use = hammer_on_place, + wear_represents = "exchangeclone_charge_level" }) exchangeclone.register_multidig_tool("exchangeclone:red_matter_hammer", {"group:"..exchangeclone.pickaxe_group}) diff --git a/exchangeclone/hoes.lua b/exchangeclone/hoes.lua index 49c36de..dcd8582 100644 --- a/exchangeclone/hoes.lua +++ b/exchangeclone/hoes.lua @@ -132,6 +132,7 @@ minetest.register_tool("exchangeclone:dark_matter_hoe", { exchangeclone_dirt = { speed = 14, level = 5, uses = 0 }, hoey = { speed = 14, level = 5, uses = 0 } }, + wear_represents = "exchangeclone_charge_level" }) exchangeclone.register_multidig_tool("exchangeclone:dark_matter_hoe", {"group:exchangeclone_dirt"}) @@ -158,6 +159,7 @@ minetest.register_tool("exchangeclone:red_matter_hoe", { exchangeclone_dirt = { speed = 16, level = 6, uses = 0 }, hoey = { speed = 16, level = 6, uses = 0 } }, + wear_represents = "exchangeclone_charge_level" }) exchangeclone.register_multidig_tool("exchangeclone:red_matter_hoe", {"group:exchangeclone_dirt"}) diff --git a/exchangeclone/init.lua b/exchangeclone/init.lua index e6e1c1a..cc9ac8b 100644 --- a/exchangeclone/init.lua +++ b/exchangeclone/init.lua @@ -107,40 +107,52 @@ end if exchangeclone.mcl2 then mcl_item_id.set_mod_namespace("exchangeclone") end +local files = { + "constructor", + "deconstructor", + "energy_collector", + "klein_stars", + "craftitems", + "tool_upgrades", + "swords", + "pickaxes", + "axes", + "shovels", + "hoes", + "hammers", + "red_matter_multitools", + "covalence_dust", + "philosophers_stone", + "infinite_food", + "alchemical_chests", + "transmutation_table", + "furnaces", + "gem_of_eternal_density", + "talisman_of_repair", + "passive_stones", +} -dofile(modpath.."/constructor.lua") -dofile(modpath.."/deconstructor.lua") -dofile(modpath.."/energy_collector.lua") -dofile(modpath.."/klein_stars.lua") -dofile(modpath.."/craftitems.lua") if exchangeclone.mcl or minetest.get_modpath("3d_armor") then dofile(modpath.."/armor.lua") end + if exchangeclone.mcl then dofile(modpath.."/shears.lua") dofile(modpath.."/tool_upgrades.lua") end -dofile(modpath.."/swords.lua") -dofile(modpath.."/axes.lua") -dofile(modpath.."/hoes.lua") -dofile(modpath.."/pickaxes.lua") -dofile(modpath.."/hammers.lua") -dofile(modpath.."/shovels.lua") -dofile(modpath.."/red_matter_multitools.lua") -dofile(modpath.."/covalence_dust.lua") + if minetest.get_modpath("hopper") then dofile(modpath.."/hopper_compat.lua") end -dofile(modpath.."/philosophers_stone.lua") -dofile(modpath.."/infinite_food.lua") -dofile(modpath.."/alchemical_chests.lua") -dofile(modpath.."/transmutation_table.lua") -dofile(modpath.."/furnaces.lua") -dofile(modpath.."/gem_of_eternal_density.lua") + if minetest.get_modpath("awards") then dofile(modpath.."/awards.lua") end +for _, file in ipairs(files) do + dofile(modpath.."/"..file..".lua") +end + minetest.register_on_mods_loaded(function() local emc_start_time = minetest.get_us_time() minetest.log("action", "[ExchangeClone] Registering EMC values") diff --git a/exchangeclone/passive_stones.lua b/exchangeclone/passive_stones.lua new file mode 100644 index 0000000..faea700 --- /dev/null +++ b/exchangeclone/passive_stones.lua @@ -0,0 +1,191 @@ +local function heal(player, amount) + local hp_max = player:get_properties().hp_max + local current_hp = player:get_hp() + if current_hp < hp_max then + player:set_hp(math.min(current_hp + amount, hp_max), { type = "set_hp", other = "healing" }) + return true + end +end + +local function satiate() end + +if exchangeclone.mcl and mcl_hunger.active then + satiate = function(player, amount) + local hunger = mcl_hunger.get_hunger(player) + if hunger < 20 then + mcl_hunger.set_hunger(player, hunger + amount) + mcl_hunger.set_saturation(player, hunger + amount) + return true + end + end +elseif exchangeclone.mtg and minetest.get_modpath("stamina") then + satiate = function(player, amount) + if stamina.get_saturation(player) < stamina.settings.visual_max then + stamina.change_saturation(player, amount) + return true + end + end +end + +minetest.register_tool("exchangeclone:soul_stone", { + description = "Soul Stone", + inventory_image = "exchangeclone_soul_stone.png", + _exchangeclone_passive = { + func = function(player) + if exchangeclone.get_player_emc(player) >= 64 then + if heal(player, 2) then + exchangeclone.add_player_emc(player, -64) + end + end + end, + hotbar = true, + active_image = "exchangeclone_soul_stone_active.png", + exclude = {"exchangeclone:life_stone"} + }, + on_secondary_use = exchangeclone.toggle_active, + on_place = exchangeclone.toggle_active, + groups = {exchangeclone_passive = 1, disable_repair = 1} +}) +minetest.register_craft({ + output = "exchangeclone:soul_stone", + recipe = { + {exchangeclone.itemstrings.glowstoneworth, exchangeclone.itemstrings.glowstoneworth, exchangeclone.itemstrings.glowstoneworth}, + {"exchangeclone:red_matter", exchangeclone.itemstrings.lapisworth, "exchangeclone:red_matter"}, + {exchangeclone.itemstrings.glowstoneworth, exchangeclone.itemstrings.glowstoneworth, exchangeclone.itemstrings.glowstoneworth}, + } +}) + +if (exchangeclone.mcl and mcl_hunger.active) or (exchangeclone.mtg and minetest.get_modpath("stamina")) then + minetest.register_tool("exchangeclone:body_stone", { + description = "Body Stone", + inventory_image = "exchangeclone_body_stone.png", + _exchangeclone_passive = { + func = function(player) + if exchangeclone.get_player_emc(player) >= 64 then + if satiate(player, 2) then + exchangeclone.add_player_emc(player, -64) + end + end + end, + hotbar = true, + active_image = "exchangeclone_body_stone_active.png", + exclude = {"exchangeclone:life_stone"} + }, + on_secondary_use = exchangeclone.toggle_active, + on_place = exchangeclone.toggle_active, + groups = {exchangeclone_passive = 1, disable_repair = 1} + }) + + local sugar_ingredient = exchangeclone.mcl and "mcl_core:sugar" or "default:papyrus" + minetest.register_craft({ + output = "exchangeclone:body_stone", + recipe = { + {sugar_ingredient, sugar_ingredient, sugar_ingredient}, + {"exchangeclone:red_matter", exchangeclone.itemstrings.lapisworth, "exchangeclone:red_matter"}, + {sugar_ingredient, sugar_ingredient, sugar_ingredient}, + } + }) + + minetest.register_tool("exchangeclone:life_stone", { + description = "Life Stone", + inventory_image = "exchangeclone_life_stone.png", + _exchangeclone_passive = { + func = function(player) + if exchangeclone.get_player_emc(player) >= 64 then + local changed + if heal(player, 2) then + changed = true + end + if satiate(player, 2) then + changed = true + end + if changed then + exchangeclone.add_player_emc(player, -64) + end + end + end, + hotbar = true, + active_image = "exchangeclone_life_stone_active.png", + exclude = {"exchangeclone:body_stone", "exchangeclone:soul_stone"} + }, + on_secondary_use = exchangeclone.toggle_active, + on_place = exchangeclone.toggle_active, + groups = {exchangeclone_passive = 1, disable_repair = 1}, + }) + minetest.register_craft({ + output = "exchangeclone:life_stone", + type = "shapeless", + recipe = {"exchangeclone:soul_stone", "exchangeclone:body_stone"} + }) +end + +if exchangeclone.mcl then + + local function get_mind_description(itemstack) + local meta = itemstack:get_meta() + local emc = exchangeclone.get_item_emc(itemstack) or 0 + local stored = meta:get_int("exchangeclone_stored_xp") or 0 + return "Mind Stone\nEMC Value: "..exchangeclone.format_number(emc).."\nStored XP: "..exchangeclone.format_number(stored) + end + + local function drain_xp(player, itemstack) + local meta = itemstack:get_meta() + local stored = meta:get_int("exchangeclone_stored_xp") or 0 + local player_xp = mcl_experience.get_xp(player) + meta:set_int("exchangeclone_stored_xp", stored + player_xp) + mcl_experience.set_xp(player, 0) + meta:set_string("description", get_mind_description(itemstack)) + return itemstack + end + + local function mind_action(itemstack, player, pointed_thing) + local click_test = exchangeclone.check_on_rightclick(itemstack, player, pointed_thing) + if click_test ~= false then + return click_test + end + + local meta = itemstack:get_meta() + local stored = meta:get_int("exchangeclone_stored_xp") or 0 + if player:get_player_control().aux1 then + return exchangeclone.toggle_active(itemstack, player, pointed_thing) + elseif player:get_player_control().sneak then + local player_xp = mcl_experience.get_xp(player) + local amount_to_take = math.min(100, player_xp) + mcl_experience.set_xp(player, player_xp - amount_to_take) + meta:set_int("exchangeclone_stored_xp", stored + amount_to_take) + meta:set_string("description", get_mind_description(itemstack)) + return itemstack + else + local player_xp = mcl_experience.get_xp(player) + local amount_to_take = math.min(100, stored) + mcl_experience.set_xp(player, player_xp + amount_to_take) + meta:set_int("exchangeclone_stored_xp", stored - amount_to_take) + meta:set_string("description", get_mind_description(itemstack)) + return itemstack + end + end + + minetest.register_tool("exchangeclone:mind_stone", { + description = "Mind Stone", + inventory_image = "exchangeclone_mind_stone.png", + _exchangeclone_passive = { + func = drain_xp, + hotbar = true, + active_image = "exchangeclone_mind_stone_active.png", + }, + on_secondary_use = mind_action, + on_place = mind_action, + groups = {exchangeclone_passive = 1, disable_repair = 1}, + _mcl_generate_description = get_mind_description + }) + + local book = "mcl_books:book" + minetest.register_craft({ + output = "exchangeclone:mind_stone", + recipe = { + {book, book, book}, + {"exchangeclone:red_matter", exchangeclone.itemstrings.lapisworth, "exchangeclone:red_matter"}, + {book, book, book}, + } + }) +end \ No newline at end of file diff --git a/exchangeclone/philosophers_stone.lua b/exchangeclone/philosophers_stone.lua index 576a983..141da09 100644 --- a/exchangeclone/philosophers_stone.lua +++ b/exchangeclone/philosophers_stone.lua @@ -111,7 +111,8 @@ minetest.register_tool("exchangeclone:philosophers_stone", { on_use = on_left_click, on_place = on_right_click, on_secondary_use = on_right_click, - groups = {philosophers_stone = 1, disable_repair = 1, fire_immune = 1} + groups = {philosophers_stone = 1, disable_repair = 1, fire_immune = 1}, + wear_represents = "exchangeclone_charge_level" }) exchangeclone.set_charge_type("exchangeclone:philosophers_stone", "phil") diff --git a/exchangeclone/pickaxes.lua b/exchangeclone/pickaxes.lua index fd12c00..562aa54 100644 --- a/exchangeclone/pickaxes.lua +++ b/exchangeclone/pickaxes.lua @@ -97,6 +97,7 @@ minetest.register_tool("exchangeclone:dark_matter_pickaxe", { }, on_secondary_use = pickaxe_on_use, on_place = pickaxe_on_use, + wear_represents = "exchangeclone_charge_level" }) exchangeclone.register_multidig_tool("exchangeclone:dark_matter_pickaxe", {"group:"..exchangeclone.pickaxe_group}) @@ -124,6 +125,7 @@ minetest.register_tool("exchangeclone:red_matter_pickaxe", { }, on_secondary_use = pickaxe_on_use, on_place = pickaxe_on_use, + wear_represents = "exchangeclone_charge_level" }) exchangeclone.register_multidig_tool("exchangeclone:red_matter_pickaxe", {"group:"..exchangeclone.pickaxe_group}) diff --git a/exchangeclone/shears.lua b/exchangeclone/shears.lua index 0b590d4..e118532 100644 --- a/exchangeclone/shears.lua +++ b/exchangeclone/shears.lua @@ -81,6 +81,7 @@ minetest.register_tool("exchangeclone:dark_matter_shears", { shearsy_wool = { speed = 14, level = 5, uses = 0 }, shearsy_cobweb = { speed = 14, level = 5, uses = 0 } }, + wear_represents = "exchangeclone_charge_level" }) @@ -106,6 +107,7 @@ minetest.register_tool("exchangeclone:red_matter_shears", { shearsy_wool = { speed = 16, level = 6, uses = 0 }, shearsy_cobweb = { speed = 16, level = 6, uses = 0 } }, + wear_represents = "exchangeclone_charge_level" }) exchangeclone.set_charge_type("exchangeclone:red_matter_shears", "red_matter") diff --git a/exchangeclone/shovels.lua b/exchangeclone/shovels.lua index 30751dd..363eb5a 100644 --- a/exchangeclone/shovels.lua +++ b/exchangeclone/shovels.lua @@ -135,6 +135,7 @@ minetest.register_tool("exchangeclone:dark_matter_shovel", { _mcl_diggroups = { shovely = { speed = 14, level = 5, uses = 0 } }, + wear_represents = "exchangeclone_charge_level" }) exchangeclone.set_charge_type("exchangeclone:dark_matter_shovel", "dark_matter") @@ -161,6 +162,7 @@ minetest.register_tool("exchangeclone:red_matter_shovel", { _mcl_diggroups = { shovely = { speed = 16, level = 6, uses = 0 } }, + wear_represents = "exchangeclone_charge_level" }) exchangeclone.set_charge_type("exchangeclone:red_matter_shovel", "red_matter") diff --git a/exchangeclone/swords.lua b/exchangeclone/swords.lua index 8f29e43..fbef6bf 100644 --- a/exchangeclone/swords.lua +++ b/exchangeclone/swords.lua @@ -186,6 +186,7 @@ minetest.register_tool("exchangeclone:dark_matter_sword", { _mcl_diggroups = { swordy = { speed = 14, level = 5, uses = 0 } }, + wear_represents = "exchangeclone_charge_level" }) minetest.register_tool("exchangeclone:red_matter_sword", { @@ -211,6 +212,7 @@ minetest.register_tool("exchangeclone:red_matter_sword", { _mcl_diggroups = { swordy = { speed = 16, level = 6, uses = 0 } }, + wear_represents = "exchangeclone_charge_level" }) minetest.register_craft({ diff --git a/exchangeclone/talisman_of_repair.lua b/exchangeclone/talisman_of_repair.lua new file mode 100644 index 0000000..bbfc6b9 --- /dev/null +++ b/exchangeclone/talisman_of_repair.lua @@ -0,0 +1,73 @@ +local function repair_items(inv, listname) + local list = inv:get_list(listname) + for i = 1, #list do + local stack = inv:get_stack(listname, i) + if not stack:is_empty() then + local def = stack:get_definition() + if def + and def.type == "tool" + and (not def.wear_represents or def.wear_represents == "mechanical_wear") + and stack:get_wear() > 0 then + local uses + if exchangeclone.mcl then + local armor_uses = minetest.get_item_group(stack:get_name(), "mcl_armor_uses") + if armor_uses > 0 then + uses = armor_uses + elseif def._mcl_diggroups then + for name, data in pairs(def._mcl_diggroups) do + uses = data.uses + break -- Just the simplest way to do it... + end + end + else + if def.tool_capabilities and def.tool_capabilities.groupcaps then + local groupcaps + for name, data in pairs(def.tool_capabilities.groupcaps) do + groupcaps = data + break -- Just the simplest way to do it... + end + uses = groupcaps.uses*math.pow(3, groupcaps.maxlevel-1) + elseif def.groups.armor_use then + uses = 65535/def.groups.armor_use + end + end + if uses and uses > 0 then + minetest.log(uses) + stack:set_wear(math.max(0, stack:get_wear() - 65535/uses)) + inv:set_stack(listname, i, stack) + end + end + end + end +end + +minetest.register_tool("exchangeclone:talisman_of_repair", { + description = "Talisman of Repair", + inventory_image = "exchangeclone_talisman_of_repair.png", + _exchangeclone_passive = { + func = function(player) + local inv = player:get_inventory() + repair_items(inv, "main") + if exchangeclone.mcl then + repair_items(inv, "offhand") + repair_items(inv, "armor") + elseif minetest.get_modpath("3d_armor") then + local _, armor_inv = armor:get_valid_player(player, "3d_armor") + repair_items(armor_inv, "armor") + end + end, + always_active = true + }, + groups = {exchangeclone_passive = 1, disable_repair = 1} +}) + +local string = exchangeclone.mcl and "mcl_mobitems:string" or "farming:string" + +minetest.register_craft({ + output = "exchangeclone:talisman_of_repair", + recipe = { + {"exchangeclone:low_covalence_dust", "exchangeclone:medium_covalence_dust", "exchangeclone:high_covalence_dust"}, + {string, exchangeclone.mcl and "mcl_core:paper" or "default:paper", string}, + {"exchangeclone:high_covalence_dust", "exchangeclone:medium_covalence_dust", "exchangeclone:low_covalence_dust"} + } +}) \ No newline at end of file diff --git a/exchangeclone/textures/exchangeclone_alchemical_tome.png b/exchangeclone/textures/exchangeclone_alchemical_tome.png index a80baec..a893e9c 100644 Binary files a/exchangeclone/textures/exchangeclone_alchemical_tome.png and b/exchangeclone/textures/exchangeclone_alchemical_tome.png differ diff --git a/exchangeclone/textures/exchangeclone_body_stone.png b/exchangeclone/textures/exchangeclone_body_stone.png new file mode 100644 index 0000000..7efcbda Binary files /dev/null and b/exchangeclone/textures/exchangeclone_body_stone.png differ diff --git a/exchangeclone/textures/exchangeclone_body_stone_active.png b/exchangeclone/textures/exchangeclone_body_stone_active.png new file mode 100644 index 0000000..77a351a Binary files /dev/null and b/exchangeclone/textures/exchangeclone_body_stone_active.png differ diff --git a/exchangeclone/textures/exchangeclone_gem_of_eternal_density_active.png b/exchangeclone/textures/exchangeclone_gem_of_eternal_density_active.png new file mode 100644 index 0000000..df3d53c Binary files /dev/null and b/exchangeclone/textures/exchangeclone_gem_of_eternal_density_active.png differ diff --git a/exchangeclone/textures/exchangeclone_life_stone.png b/exchangeclone/textures/exchangeclone_life_stone.png new file mode 100644 index 0000000..15ec781 Binary files /dev/null and b/exchangeclone/textures/exchangeclone_life_stone.png differ diff --git a/exchangeclone/textures/exchangeclone_life_stone_active.png b/exchangeclone/textures/exchangeclone_life_stone_active.png new file mode 100644 index 0000000..41aaf09 Binary files /dev/null and b/exchangeclone/textures/exchangeclone_life_stone_active.png differ diff --git a/exchangeclone/textures/exchangeclone_mind_stone.png b/exchangeclone/textures/exchangeclone_mind_stone.png new file mode 100644 index 0000000..de6c3a1 Binary files /dev/null and b/exchangeclone/textures/exchangeclone_mind_stone.png differ diff --git a/exchangeclone/textures/exchangeclone_mind_stone_active.png b/exchangeclone/textures/exchangeclone_mind_stone_active.png new file mode 100644 index 0000000..3e33320 Binary files /dev/null and b/exchangeclone/textures/exchangeclone_mind_stone_active.png differ diff --git a/exchangeclone/textures/exchangeclone_soul_stone.png b/exchangeclone/textures/exchangeclone_soul_stone.png new file mode 100644 index 0000000..cdefde0 Binary files /dev/null and b/exchangeclone/textures/exchangeclone_soul_stone.png differ diff --git a/exchangeclone/textures/exchangeclone_soul_stone_active.png b/exchangeclone/textures/exchangeclone_soul_stone_active.png new file mode 100644 index 0000000..dc93aec Binary files /dev/null and b/exchangeclone/textures/exchangeclone_soul_stone_active.png differ diff --git a/exchangeclone/textures/exchangeclone_talisman_of_repair.png b/exchangeclone/textures/exchangeclone_talisman_of_repair.png new file mode 100644 index 0000000..51f9cf2 Binary files /dev/null and b/exchangeclone/textures/exchangeclone_talisman_of_repair.png differ diff --git a/zzzz_exchangeclone_init/lib.lua b/zzzz_exchangeclone_init/lib.lua index 9e9e661..7a939fd 100644 --- a/zzzz_exchangeclone_init/lib.lua +++ b/zzzz_exchangeclone_init/lib.lua @@ -68,9 +68,14 @@ function exchangeclone.get_item_emc(item) return cheapest end + -- Only check metadata for ItemStacks if type(item) == "userdata" then - local meta_emc_value = tonumber(item:get_meta():get_string("exchangeclone_emc_value")) - if meta_emc_value then minetest.log(dump(meta_emc_value)) return math.max(0, meta_emc_value) end + local meta_emc_value = item:get_meta():get_string("exchangeclone_emc_value") + if meta_emc_value == "none" then + return 0 + elseif tonumber(meta_emc_value) then + return math.max(0, tonumber(meta_emc_value)) + end end -- handle items/itemstacks @@ -355,6 +360,7 @@ exchangeclone.itemstrings = { redstoneworth = exchangeclone.mcl and "mesecons:redstone" or "default:obsidian", obsidian = exchangeclone.mcl and "mcl_core:obsidian" or "default:obsidian", glowstoneworth = exchangeclone.mcl and "mcl_nether:glowstone_dust" or "default:tin_ingot", + lapisworth = exchangeclone.mcl and "mcl_core:lapis" or "bucket:bucket_lava", coal = exchangeclone.mcl and "mcl_core:coal_lump" or "default:coal_lump", iron = exchangeclone.mcl and "mcl_core:iron_ingot" or "default:steel_ingot", copper = exchangeclone.mcl and "mcl_copper:copper_ingot" or "default:copper_ingot", @@ -1205,4 +1211,67 @@ function exchangeclone.place_torch(player, pointed_thing) if torch_on_place then torch_on_place(ItemStack(exchangeclone.itemstrings.torch), player, pointed_thing) end +end + +do + local hb_max = exchangeclone.mcl and 9 or 8 + local timer = 0 + + minetest.register_globalstep(function(dtime) + timer = timer + dtime + if timer >= 1 then + timer = 0 + for _, player in pairs(minetest.get_connected_players()) do + local inv = player:get_inventory() + local processed_already = {} + for i, stack in ipairs(inv:get_list("main")) do + if minetest.get_item_group(stack:get_name(), "exchangeclone_passive") then + local passive_data = stack:get_definition()._exchangeclone_passive + if passive_data + and not processed_already[stack:get_name()] + and (stack:get_meta():get_string("exchangeclone_active") == "true" or passive_data.always_active) + and (not passive_data.hotbar or (passive_data.hotbar and i <= hb_max)) then + local found + if passive_data.exclude then + for _, itemstring in pairs(passive_data.exclude) do + if processed_already[itemstring] then + found = true + break + end + end + end + if not found then + processed_already[stack:get_name()] = true + local result = passive_data.func(player, stack) + if result then inv:set_stack("main", i, result) end + end + end + end + end + end + end + end) +end + +function exchangeclone.toggle_active(itemstack, player, pointed_thing) + local click_test = exchangeclone.check_on_rightclick(itemstack, player, pointed_thing) + if click_test ~= false then + return click_test + end + + local meta = itemstack:get_meta() + local def = itemstack:get_definition() + if meta:get_string("exchangeclone_active") ~= "true" then + exchangeclone.play_sound(player, "exchangeclone_enable") + meta:set_string("exchangeclone_active", "true") + local active_image = def._exchangeclone_passive.active_image + if active_image then + meta:set_string("inventory_image", active_image) + end + else + exchangeclone.play_sound(player, "exchangeclone_charge_down") + meta:set_string("exchangeclone_active", "") + meta:set_string("inventory_image", "") + end + return itemstack end \ No newline at end of file