374 lines
12 KiB
Lua
374 lines
12 KiB
Lua
-- idea: explore button + require lot of essence to 'discover' certain items: sapling, iron, copper, tin, gold, mese, diamond, mithril
|
|
|
|
-- ALCHEMY by rnd (2017)
|
|
|
|
-- combine ingredients into new outputs
|
|
|
|
|
|
alchemy = {};
|
|
|
|
dofile(minetest.get_modpath("alchemy").."/items.lua")
|
|
|
|
|
|
local get_change = function( money ) -- returns change in greedy way
|
|
local values = alchemy.essence;
|
|
local p = {};
|
|
for i = #values,1,-1 do
|
|
p[i] = math.floor(money/values[i][2]);
|
|
money = money - p[i]*values[i][2]
|
|
end
|
|
|
|
return p
|
|
end
|
|
|
|
|
|
local lab_make = function(pos) --try to 'make' more material in 1st slot of 'in' using essences in 'out'
|
|
local meta = minetest.get_meta(pos);
|
|
local inv = meta:get_inventory();
|
|
local stack = inv:get_stack("in", 1);
|
|
local item = stack:get_name();
|
|
if item == "" then return end
|
|
local essence = 0;
|
|
for i = 1,4 do
|
|
local stack = inv:get_stack("out", i);
|
|
local count = stack:get_count()
|
|
local eitem = stack:get_name();
|
|
--how much essence
|
|
essence = essence + (alchemy.essence_values[eitem] or 0)*count;
|
|
end
|
|
|
|
local cost = alchemy.items[item]; if not cost then return end
|
|
--adjust cost depending on upgrades
|
|
local upgrade = 0
|
|
if inv:get_stack("upgrade", 1):get_name() == "alchemy:essence_upgrade" then
|
|
upgrade = inv:get_stack("upgrade", 1):get_count();
|
|
end
|
|
cost = cost*math.max(1,(0.2 + 4.8/(1 + 0.05*upgrade))) -- 1 for upgrade 100, 5 for upgrade 0
|
|
|
|
local out_count = math.floor(essence/cost);
|
|
if out_count < 1 then return end
|
|
|
|
local remainder = essence - cost*out_count;
|
|
|
|
inv:add_item("in",ItemStack(item.. " " .. out_count))
|
|
local p = get_change( remainder );
|
|
|
|
-- set inventory to containt remainder of essence
|
|
local values = alchemy.essence;
|
|
for i = 1, #values do
|
|
if p[i]>0 then
|
|
inv:set_stack("out",i,ItemStack(values[i][1].. " " .. p[i]))
|
|
else
|
|
inv:set_stack("out",i,ItemStack(""))
|
|
end
|
|
end
|
|
|
|
for i = #values+1,4 do
|
|
inv:set_stack("out",i,ItemStack(""))
|
|
end
|
|
|
|
|
|
end
|
|
|
|
|
|
local lab_break = function(pos) -- break down materials in 'in'
|
|
local meta = minetest.get_meta(pos);
|
|
local inv = meta:get_inventory();
|
|
for j = 1,4 do
|
|
local stack = inv:get_stack("in", j);
|
|
local item = stack:get_name();
|
|
if item~="" then
|
|
local essence = (alchemy.items[item] or 1)*stack:get_count();
|
|
local p = get_change(essence ); -- essence of item in spot j
|
|
-- require 1 energy to break 1 gold (250 essence)
|
|
local fuel_cost = math.floor(essence/250); if fuel_cost<1 then fuel_cost = 1 end
|
|
local fuel_stack = ItemStack("alchemy:essence_energy " .. fuel_cost);
|
|
if not inv:contains_item("fuel", fuel_stack) then
|
|
local text = "not enough energy, need " .. fuel_cost .. " cells."
|
|
meta:set_string("infotext", text)
|
|
minetest.show_formspec(
|
|
meta:get_string("owner"),"alchemy_help","size[5.5,5]".."textarea[0.,0;6.1,6;alchemy_help;ALCHEMY;" .. minetest.formspec_escape(text) .. "]"
|
|
)
|
|
return
|
|
else
|
|
inv:remove_item("fuel", fuel_stack)
|
|
meta:set_string("infotext","")
|
|
end
|
|
|
|
inv:set_stack("in",j,ItemStack(""))
|
|
|
|
local values = alchemy.essence;
|
|
for i = 1, #values do
|
|
if p[i]>0 then
|
|
inv:add_item("out",ItemStack(values[i][1].. " " .. p[i]))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
minetest.register_abm({ -- very slowly create energy
|
|
nodenames = {"alchemy:lab"},
|
|
neighbors = {""},
|
|
interval = 30,
|
|
chance = 1,
|
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
|
local meta = minetest.get_meta(pos);
|
|
|
|
local inv = meta:get_inventory();
|
|
local upgrade = 0;
|
|
if inv:get_stack("upgrade", 1):get_name() == "alchemy:essence_upgrade" then
|
|
upgrade = inv:get_stack("upgrade", 1):get_count();
|
|
end
|
|
|
|
local count = 1 + upgrade
|
|
local stack = ItemStack("alchemy:essence_energy " .. count)
|
|
inv:add_item("fuel", stack)
|
|
end
|
|
})
|
|
|
|
|
|
local lab_update_meta = function(pos)
|
|
local meta = minetest.get_meta(pos);
|
|
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
|
|
|
|
local form =
|
|
"size[8,6.75]"..
|
|
"button[0,2;2.,0.75;ibreak;BREAK]"..
|
|
"button[6,2;2.,0.75;fuel;FUEL]"..
|
|
"button[3,2;2.,0.75;make;MAKE]"..
|
|
"label[0,-0.4.;MATERIAL]"..
|
|
"list[" .. list_name .. ";in;0,0;2,2;]"..
|
|
"label[3,-0.4.;ESSENCE]"..
|
|
"list[" .. list_name .. ";out;3,0;2,2;]"..
|
|
"image[2,0.;1,1;gui_furnace_arrow_bg.png^[transformR270]"..
|
|
"image[2,1.;1,1;gui_furnace_arrow_bg.png^[transformR90]"..
|
|
"label[6,-0.4.;UPGRADE]"..
|
|
"list[" .. list_name .. ";upgrade;6,0;1,1;]"..
|
|
"button[6.,1;2,1;upgrade;".. minetest.colorize("red","HELP") .. "]"..
|
|
"list[current_player;main;0,3;8,4;]"..
|
|
"listring[context;in]"..
|
|
"listring[current_player;main]"..
|
|
"listring[context;out]"..
|
|
"listring[current_player;main]"
|
|
meta:set_string("formspec", form);
|
|
end
|
|
|
|
|
|
minetest.register_node("alchemy:lab", {
|
|
description = "Alchemy laboratory",
|
|
tiles = {"default_steel_block.png","default_steel_block.png","alchemy_lab.png","alchemy_lab.png","alchemy_lab.png","alchemy_lab.png"},
|
|
groups = {cracky=3, mesecon_effector_on = 1},
|
|
sounds = default.node_sound_wood_defaults(),
|
|
after_place_node = function(pos, placer)
|
|
local meta = minetest.get_meta(pos);
|
|
meta:set_string("infotext", "Alchemy: To operate it insert materials or essences.")
|
|
meta:set_string("owner", placer:get_player_name());
|
|
local inv = meta:get_inventory();
|
|
inv:set_size("in",4);
|
|
inv:set_size("out",4); -- dusts here
|
|
inv:set_size("upgrade",1);
|
|
inv:set_size("fuel",32);
|
|
end,
|
|
|
|
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
|
|
local meta = minetest.get_meta(pos);
|
|
local privs = minetest.get_player_privs(player:get_player_name());
|
|
if minetest.is_protected(pos, player:get_player_name()) and not privs.privs then return end -- only owner can interact with recycler
|
|
lab_update_meta(pos);
|
|
end,
|
|
|
|
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
local meta = minetest.get_meta(pos);
|
|
local privs = minetest.get_player_privs(player:get_player_name());
|
|
if meta:get_string("owner")~=player:get_player_name() and not privs.privs then return 0 end
|
|
return stack:get_count();
|
|
end,
|
|
|
|
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
local privs = minetest.get_player_privs(player:get_player_name());
|
|
if minetest.is_protected(pos, player:get_player_name()) and not privs.privs then return 0 end
|
|
return stack:get_count();
|
|
end,
|
|
|
|
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
|
return 0;
|
|
end,
|
|
|
|
mesecons = {effector = {
|
|
action_on = function (pos, node,ttl)
|
|
if type(ttl)~="number" then ttl = 1 end
|
|
if ttl<0 then return end -- machines_TTL prevents infinite recursion
|
|
local meta = minetest.get_meta(pos);
|
|
if meta:get_int("mode") == 2 then
|
|
lab_make(pos)
|
|
else
|
|
lab_break(pos)
|
|
end
|
|
end
|
|
}
|
|
},
|
|
|
|
on_receive_fields = function(pos, formname, fields, sender)
|
|
|
|
if minetest.is_protected(pos, sender:get_player_name()) then return end
|
|
local meta = minetest.get_meta(pos);
|
|
|
|
if fields.make then
|
|
lab_make(pos);
|
|
meta:set_int("mode",2)
|
|
return
|
|
end
|
|
|
|
if fields.ibreak then
|
|
lab_break(pos);
|
|
meta:set_int("mode",2)
|
|
return
|
|
end
|
|
|
|
if fields.fuel then
|
|
local meta = minetest.get_meta(pos);
|
|
local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z
|
|
|
|
local form =
|
|
"size[8,8]"..
|
|
"label[0,-0.4;INSERT ENERGY ESSENCE AS FUEL]"..
|
|
"list[" .. list_name .. ";fuel;0,0;8,4;]"..
|
|
"list[current_player;main;0,4.25;8,4;]"..
|
|
"listring[context;fuel]"..
|
|
"listring[current_player;main]"..
|
|
"listring[context;fuel]"
|
|
|
|
minetest.show_formspec(
|
|
sender:get_player_name(),"alchemy_fuel",form
|
|
)
|
|
return
|
|
end
|
|
|
|
if fields.upgrade then
|
|
local text = minetest.colorize("yellow","1.BREAK") .."\nPlace items in left window (MATERIALS) and use 'break' to transmute them into essences.\n\n"..
|
|
minetest.colorize("yellow","2.MADE") .."\nPlace essences in right window (ESSENCES), place item to be created in left window (1st position) and use 'make'.\n\n"..
|
|
minetest.colorize("red","3.DISCOVER") .."\nif you insert enough essence you can discover new materials.\n\n"..
|
|
"Make process will be more effective if you place upgrade essences in upgrade window. cost factor is 0.2 + 4.8/(1 + 0.05*upgrade)\n\n" ..
|
|
"To break materials you need 1 energy essence for every 250 essence. Energy essence is produced at rate (1+upgrade) by alchemy lab every 1/2 minute\n\n"..
|
|
"There are 4 kinds of essences: low (1), medium (50), high(2500) and upgrade(125000)."
|
|
|
|
local meta = minetest.get_meta(pos);
|
|
local level = meta:get_int("level");-- discovery level
|
|
local discovery = alchemy.discoveries[level] or alchemy.discoveries[0]
|
|
|
|
minetest.show_formspec(
|
|
sender:get_player_name(),"alchemy_help:" .. minetest.pos_to_string(pos), "size[5.5,5]".."textarea[0.,0;6.1,5.5;alchemy_help;ALCHEMY HELP;" .. minetest.formspec_escape(text) .. "]"..
|
|
"button_exit[0,4.75;5.5,0.75;discover;" .. minetest.colorize("red","DISCOVER " .. level .. " : ".. discovery.item .. " (cost " .. discovery.cost .. ")") .."]"
|
|
)
|
|
return
|
|
end
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
|
|
minetest.register_on_player_receive_fields(
|
|
function(player, formname, fields)
|
|
|
|
--minetest.chat_send_all("D " .. formname .. " " .. minetest.serialize(fields))
|
|
local fname = "alchemy_help:";
|
|
if string.sub(formname,1, string.len(fname)) ~= fname then return end
|
|
|
|
if fields.discover then
|
|
local pos = minetest.string_to_pos(string.sub(formname, string.len(fname)+1));
|
|
local meta = minetest.get_meta(pos);
|
|
local level = meta:get_int("level") or 0;-- discovery level
|
|
local discovery = alchemy.discoveries[level] or alchemy.discoveries[0];
|
|
local cost = discovery.cost;
|
|
|
|
|
|
local inv = meta:get_inventory();
|
|
local item = discovery.item;
|
|
|
|
local essence = 0;
|
|
for i = 1,4 do
|
|
local stack = inv:get_stack("out", i);
|
|
local count = stack:get_count()
|
|
local eitem = stack:get_name();
|
|
--how much essence
|
|
essence = essence + (alchemy.essence_values[eitem] or 0)*count;
|
|
end
|
|
|
|
if essence<cost then
|
|
minetest.chat_send_player(player:get_player_name(),"#ALCHEMY: you need at least " .. cost .. " essence, you have only " .. essence)
|
|
return
|
|
end
|
|
|
|
local remainder = essence - cost;
|
|
|
|
inv:add_item("in",ItemStack(item))
|
|
level = level+1;
|
|
if alchemy.discoveries[level] then meta:set_int("level",level);minetest.chat_send_player(player:get_player_name(),"#ALCHEMY: successfuly discovered " .. item .. "!") end
|
|
|
|
local p = get_change( remainder );
|
|
|
|
-- set inventory to containt remainder of essence
|
|
local values = alchemy.essence;
|
|
for i = 1, #values do
|
|
if p[i]>0 then
|
|
inv:set_stack("out",i,ItemStack(values[i][1].. " " .. p[i]))
|
|
else
|
|
inv:set_stack("out",i,ItemStack(""))
|
|
end
|
|
end
|
|
|
|
for i = #values+1,4 do
|
|
inv:set_stack("out",i,ItemStack(""))
|
|
end
|
|
|
|
return;
|
|
end
|
|
end)
|
|
|
|
|
|
minetest.register_craft({
|
|
output = "alchemy:lab",
|
|
recipe = {
|
|
{"default:steel_ingot","default:goldblock","default:steel_ingot"},
|
|
{"default:steel_ingot","default:diamondblock","default:steel_ingot"},
|
|
{"default:steel_ingot","default:steel_ingot","default:steel_ingot"},
|
|
|
|
}
|
|
})
|
|
|
|
|
|
|
|
-- ESSENCES
|
|
|
|
minetest.register_craftitem("alchemy:essence_low", {
|
|
description = "Low essence",
|
|
inventory_image = "alchemy_essence_base.png^[colorize:#0000FF:180",
|
|
stack_max = 30000,
|
|
})
|
|
|
|
minetest.register_craftitem("alchemy:essence_medium", {
|
|
description = "Medium essence",
|
|
inventory_image = "alchemy_essence_base.png^[colorize:#00FF00:180",
|
|
stack_max = 30000,
|
|
})
|
|
|
|
minetest.register_craftitem("alchemy:essence_high", {
|
|
description = "High essence",
|
|
inventory_image = "alchemy_essence_base.png^[colorize:#FF0000:180",
|
|
stack_max = 30000,
|
|
})
|
|
|
|
minetest.register_craftitem("alchemy:essence_upgrade", {
|
|
description = "Upgrade essence",
|
|
inventory_image = "alchemy_essence_base.png^[colorize:#FFFF00:180",
|
|
stack_max = 30000,
|
|
})
|
|
|
|
minetest.register_craftitem("alchemy:essence_energy", {
|
|
description = "energy essence",
|
|
inventory_image = "energy_essence.png",
|
|
stack_max = 64000,
|
|
}) |