'Disable' table buttons when an action is invalid

This commit is contained in:
Hugues Ross 2020-04-19 18:23:28 -04:00
parent 913cd03594
commit 59c359a3a3
2 changed files with 68 additions and 60 deletions

View File

@ -41,6 +41,7 @@ cartographer.skin = {
},
button = {
font_color = "#694a3a",
disabled_font_color = "#606060",
texture = "cartographer_simple_table_button",
selected_texture = "cartographer_simple_table_button_pressed",
hovered_texture = "cartographer_simple_table_button_hovered",
@ -84,6 +85,7 @@ cartographer.skin = {
},
button = {
font_color = "#694a3a",
disabled_font_color = "#606060",
texture = "cartographer_simple_table_button",
selected_texture = "cartographer_simple_table_button_pressed",
hovered_texture = "cartographer_simple_table_button_hovered",
@ -127,6 +129,7 @@ cartographer.skin = {
},
button = {
font_color = "#1f2533",
disabled_font_color = "#606060",
texture = "cartographer_advanced_table_button",
selected_texture = "cartographer_advanced_table_button_pressed",
hovered_texture = "cartographer_advanced_table_button_hovered",

117
table.lua
View File

@ -48,21 +48,34 @@ end
-- Get the material cost of the craft settings from the given table metadata
-- meta: The metadata to read
--
-- Returns a table with the material costs
-- Returns a table with the material costs, and a boolean indicating if the
-- costs were positive or negative before clamping.
local function get_craft_material_cost(meta)
local cost = get_material_cost(meta:get_int("size") or SIZE_SMALL, meta:get_int("detail") or 0);
local stack = meta:get_inventory():get_stack("output", 1);
local is_positive = true;
if stack:get_name() == "cartographer:map" then
local smeta = stack:get_meta();
local sub_cost = get_material_cost(smeta:get_int("cartographer:size") or SIZE_SMALL, (smeta:get_int("cartographer:detail") or 1) - 1);
is_positive = cost.paper >= sub_cost.paper and cost.pigment >= sub_cost.pigment;
cost.paper = math.max(cost.paper - sub_cost.paper, 0);
cost.pigment = math.max(cost.pigment - sub_cost.pigment, 0);
end
return cost;
return cost, is_positive;
end
-- Check if the given table metadata has enough materials to cover the given
-- cost table.
-- cost: A table of material costs
-- meta: The metadata
--
-- Returns true if the table's materials can cover the cost
local function can_afford(cost, meta)
return cost.paper + cost.pigment > 0
and cost.paper <= meta:get_int("paper")
and cost.pigment <= meta:get_int("pigment");
end
-- Get the material cost of the copy settings from the given table metadata
@ -123,6 +136,24 @@ end
local fs = {};
-- Draw a button, with support for enabled/disabled states
-- x: The x position of the button
-- y: The y position of the button
-- w: The width of the button
-- h: The height of the button
-- id: The element id
-- text: The text to display in the button
-- enabled: Whether or not the button is enabled
--
-- Returns a formspec string
function fs.button(x, y, w, h, id, text, enabled)
if enabled then
return string.format("button[%f,%f;%f,%f;%s;%s]", x, y, w, h, id, text);
end
return string.format("button[%f,%f;%f,%f;disabled_button;%s]", x, y, w, h, text);
end
-- Draw a 1px thick horizontal separator formspec element
-- y: The y position of the separator
-- skin: A 9-slice background skin table
@ -154,7 +185,8 @@ function fs.header(w, h, rank, tab, skin)
data = data .. string.format("button[3.25,-0.425;1.5,0.55;tab3;Copy Map]", tab);
end
return data .. string.format("style_type[button;border=false;bgimg=%s.png;bgimg_hovered=%s.png;bgimg_pressed=%s.png;bgimg_middle=%s;textcolor=%s]", skin.button.texture, skin.button.hovered_texture, skin.button.pressed_texture, tostring(skin.button.radius), skin.button.font_color);
return data .. string.format("style_type[button;border=false;bgimg=%s.png;bgimg_hovered=%s.png;bgimg_pressed=%s.png;bgimg_middle=%s;textcolor=%s]", skin.button.texture, skin.button.hovered_texture, skin.button.pressed_texture, tostring(skin.button.radius), skin.button.font_color)
.. string.format("style[disabled_button;bgimg=;bgimg_hovered=;bgimg_pressed=;textcolor=%s]", skin.button.disabled_font_color);
end
-- Draw material counters from a table's metadata
@ -205,13 +237,14 @@ end
-- Returns a formspec string
function fs.convert(x, y, pos, skin)
local meta = minetest.get_meta(pos);
local value = cartographer.get_material_value(meta:get_inventory():get_stack("input", 1));
return string.format("container[%f,%f]", x, y)
.. "formspec_version[3]"
.. inventory_bg(0, 0, 1, 1, skin.slot)
.. string.format("list[nodemeta:%d,%d,%d;input;0,0;1,1;]", pos.x, pos.y, pos.z)
.. "button[1.25,0.5;2,0.5;convert;Convert Materials]"
.. fs.cost(1.25, 0.125, cartographer.get_material_value(meta:get_inventory():get_stack("input", 1)), skin)
.. fs.button(1.25, 0.5, 2, 0.5, "convert", "Convert Materials", value.paper + value.pigment > 0)
.. fs.cost(1.25, 0.125, value, skin)
.. "container_end[]";
end
@ -225,12 +258,13 @@ end
--
-- Returns a formspec string
function fs.craft(x, y, pos, rank, meta, skin)
local cost, is_positive = get_craft_material_cost(meta);
local data = string.format("container[%f,%f]", x, y)
.. "formspec_version[3]"
.. inventory_bg(0, 0.75, 1, 1, skin.slot)
.. string.format("list[nodemeta:%d,%d,%d;output;0,0.75;1,1;]", pos.x, pos.y, pos.z)
.. "button[1.25,1.25;2,0.5;craft;Craft Map]"
.. fs.cost(1.25, 0.875, get_craft_material_cost(meta), skin);
.. fs.button(1.25, 1.25, 2, 0.5, "craft", "Craft Map", is_positive and can_afford(cost, meta))
.. fs.cost(1.25, 0.875, cost, skin);
if rank > 1 then
local size = "s";
@ -276,13 +310,14 @@ end
-- Returns a formspec string
function fs.copy(x, y, pos, skin)
local meta = minetest.get_meta(pos);
local costs = get_copy_material_cost(meta);
return string.format("container[%f,%f]", x, y)
.. "formspec_version[3]"
.. inventory_bg(0, 0, 1, 1, skin.slot)
.. string.format("list[nodemeta:%d,%d,%d;copy_input;0,0;1,1;]", pos.x, pos.y, pos.z)
.. "button[1.25,0.5;2,0.5;copy;Copy Map]"
.. fs.cost(1.25, 0.125, get_copy_material_cost(meta), skin)
.. fs.button(1.25, 0.5, 2, 0.5, "copy", "Copy Map", can_afford(costs, meta))
.. fs.cost(1.25, 0.125, costs, skin)
.. inventory_bg(8.75, 0, 1, 1, skin.slot)
.. string.format("list[nodemeta:%d,%d,%d;copy_output;8.75,0;1,1;]", pos.x, pos.y, pos.z)
.. "container_end[]";
@ -367,7 +402,6 @@ end
-- fields: A table containing the input
minetest.register_on_player_receive_fields(function(player, name, fields)
if name == "simple_table" then
minetest.chat_send_all(name..": ");
local meta = minetest.get_meta(player_tables[player:get_player_name()].pos);
if fields["convert"] then
@ -385,35 +419,19 @@ minetest.register_on_player_receive_fields(function(player, name, fields)
local size = meta:get_int("size");
local detail = meta:get_int("detail");
local scale = meta:get_int("scale");
local paper = meta:get_int("paper");
local pigment = meta:get_int("pigment");
local cost, is_positive = get_craft_material_cost(meta);
if is_positive and can_afford(cost, meta) then
meta:set_int("paper", meta:get_int("paper") - cost.paper);
meta:set_int("pigment", meta:get_int("paper") - cost.pigment);
local inv = meta:get_inventory();
local stack = inv:get_stack("output", 1);
local cost = get_craft_material_cost(meta);
if stack:is_empty() then
if paper >= cost.paper and pigment >= cost.pigment then
paper = paper - cost.paper;
pigment = pigment - cost.pigment;
meta:set_int("paper", paper);
meta:set_int("pigment", pigment);
cartographer.map_sound("cartographer_write", player);
inv:set_stack("output", 1, cartographer.create_map_item(size, 1 + detail, scale));
end
else
local smeta = stack:get_meta();
local old_size = smeta:get_int("cartographer:size");
local old_detail = smeta:get_int("cartographer:detail") - 1;
if old_detail <= detail and old_size <= size and not (old_detail == detail and old_size == size) and paper >= cost.paper and pigment >= cost.pigment then
paper = paper - cost.paper;
pigment = pigment - cost.pigment;
meta:set_int("paper", paper);
meta:set_int("pigment", pigment);
smeta:set_int("cartographer:detail", 1 + detail);
cartographer.resize_map_item(smeta, size);
@ -421,34 +439,21 @@ minetest.register_on_player_receive_fields(function(player, name, fields)
if map then
map.detail = 1 + detail;
end
cartographer.map_sound("cartographer_write", player);
inv:set_stack("output", 1, stack);
end
end
elseif fields["copy"] then
local paper = meta:get_int("paper");
local pigment = meta:get_int("pigment");
local inv = meta:get_inventory();
local in_stack = inv:get_stack("copy_input", 1);
local out_stack = inv:get_stack("copy_output", 1);
if out_stack:is_empty() and in_stack:get_name() == "cartographer:map" then
local smeta = in_stack:get_meta();
local size = smeta:get_int("cartographer:size") or SIZE_SMALL;
local detail = smeta:get_int("cartographer:detail") or 1;
local cost = get_material_cost(size, detail - 1);
if paper >= cost.paper and pigment >= cost.pigment then
paper = paper - cost.paper;
pigment = pigment - cost.pigment;
meta:set_int("paper", paper);
meta:set_int("pigment", pigment);
cartographer.map_sound("cartographer_write", player);
inv:set_stack("copy_output", 1, cartographer.copy_map_item(in_stack));
end
elseif fields["copy"] then
local cost = get_copy_material_cost(meta);
if can_afford(cost, meta) then
meta:set_int("paper", meta:get_int("paper") - cost.paper);
meta:set_int("pigment", meta:get_int("paper") - cost.pigment);
cartographer.map_sound("cartographer_write", player);
local inv = meta:get_inventory();
inv:set_stack("copy_output", 1, cartographer.copy_map_item(inv:get_stack("copy_input", 1)));
end
elseif fields["s"] then
meta:set_int("size", SIZE_SMALL);