TGUI Metal Menu (Travis stop it)

This commit is contained in:
ShadowLarkens
2020-09-07 16:52:38 -07:00
parent 3326555eab
commit 735230d642
3 changed files with 251 additions and 88 deletions

View File

@@ -66,63 +66,81 @@
else
. += "There is enough charge for [get_amount()]."
/obj/item/stack/attack_self(mob/user as mob)
list_recipes(user)
/obj/item/stack/attack_self(mob/user)
tgui_interact(user)
/obj/item/stack/proc/list_recipes(mob/user as mob, recipes_sublist)
if (!recipes)
return
if (!src || get_amount() <= 0)
user << browse(null, "window=stack")
user.set_machine(src) //for correct work of onclose
var/list/recipe_list = recipes
if (recipes_sublist && recipe_list[recipes_sublist] && istype(recipe_list[recipes_sublist], /datum/stack_recipe_list))
var/datum/stack_recipe_list/srl = recipe_list[recipes_sublist]
recipe_list = srl.recipes
var/t1 = text("<HTML><HEAD><title>Constructions from []</title></HEAD><body><TT>Amount Left: []<br>", src, src.get_amount())
for(var/i=1;i<=recipe_list.len,i++)
var/E = recipe_list[i]
if (isnull(E))
t1 += "<hr>"
continue
/obj/item/stack/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Stack", name)
ui.open()
if (i>1 && !isnull(recipe_list[i-1]))
t1+="<br>"
/obj/item/stack/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["amount"] = get_amount()
if (istype(E, /datum/stack_recipe_list))
var/datum/stack_recipe_list/srl = E
t1 += "<a href='?src=\ref[src];sublist=[i]'>[srl.title]</a>"
return data
if (istype(E, /datum/stack_recipe))
var/datum/stack_recipe/R = E
var/max_multiplier = round(src.get_amount() / R.req_amount)
var/title as text
var/can_build = 1
can_build = can_build && (max_multiplier>0)
if (R.res_amount>1)
title+= "[R.res_amount]x [R.title]\s"
else
title+= "[R.title]"
title+= " ([R.req_amount] [src.singular_name]\s)"
if (can_build)
t1 += text("<A href='?src=\ref[src];sublist=[recipes_sublist];make=[i];multiplier=1'>[title]</A> ")
else
t1 += text("[]", title)
continue
if (R.max_res_amount>1 && max_multiplier>1)
max_multiplier = min(max_multiplier, round(R.max_res_amount/R.res_amount))
t1 += " |"
var/list/multipliers = list(5,10,25)
for (var/n in multipliers)
if (max_multiplier>=n)
t1 += " <A href='?src=\ref[src];make=[i];multiplier=[n]'>[n*R.res_amount]x</A>"
if (!(max_multiplier in multipliers))
t1 += " <A href='?src=\ref[src];make=[i];multiplier=[max_multiplier]'>[max_multiplier*R.res_amount]x</A>"
/obj/item/stack/tgui_static_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
t1 += "</TT></body></HTML>"
user << browse(t1, "window=stack")
onclose(user, "stack")
return
data["recipes"] = recursively_build_recipes(recipes)
return data
/obj/item/stack/proc/recursively_build_recipes(list/recipe_to_iterate)
var/list/L = list()
for(var/recipe in recipe_to_iterate)
if(istype(recipe, /datum/stack_recipe_list))
var/datum/stack_recipe_list/R = recipe
L["[R.title]"] = recursively_build_recipes(R.recipes)
if(istype(recipe, /datum/stack_recipe))
var/datum/stack_recipe/R = recipe
L["[R.title]"] = build_recipe(R)
return L
/obj/item/stack/proc/build_recipe(datum/stack_recipe/R)
return list(
"res_amount" = R.res_amount,
"max_res_amount" = R.max_res_amount,
"req_amount" = R.req_amount,
"ref" = "\ref[R]",
)
/obj/item/stack/tgui_state(mob/user)
return GLOB.tgui_hands_state
/obj/item/stack/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("make")
if(get_amount() < 1)
qdel(src)
return
var/datum/stack_recipe/R = locate(params["ref"])
if(!is_valid_recipe(R, recipes)) //href exploit protection
return FALSE
var/multiplier = text2num(params["multiplier"])
if(!multiplier || (multiplier <= 0)) //href exploit protection
return
produce_recipe(R, multiplier, usr)
return TRUE
/obj/item/stack/proc/is_valid_recipe(datum/stack_recipe/R, list/recipe_list)
for(var/S in recipe_list)
if(S == R)
return TRUE
if(istype(S, /datum/stack_recipe_list))
var/datum/stack_recipe_list/L = S
if(is_valid_recipe(R, L.recipes))
return TRUE
return FALSE
/obj/item/stack/proc/produce_recipe(datum/stack_recipe/recipe, var/quantity, mob/user)
var/required = quantity*recipe.req_amount
@@ -177,35 +195,6 @@
else
O.color = color
/obj/item/stack/Topic(href, href_list)
..()
if ((usr.restrained() || usr.stat || usr.get_active_hand() != src))
return
if (href_list["sublist"] && !href_list["make"])
list_recipes(usr, text2num(href_list["sublist"]))
if (href_list["make"])
if (src.get_amount() < 1) qdel(src) //Never should happen
var/list/recipes_list = recipes
if (href_list["sublist"])
var/datum/stack_recipe_list/srl = recipes_list[text2num(href_list["sublist"])]
recipes_list = srl.recipes
var/datum/stack_recipe/R = recipes_list[text2num(href_list["make"])]
var/multiplier = text2num(href_list["multiplier"])
if (!multiplier || (multiplier <= 0)) //href exploit protection
return
src.produce_recipe(R, multiplier, usr)
if (src && usr.machine==src) //do not reopen closed window
spawn( 0 )
src.interact(usr)
return
return
//Return 1 if an immediate subsequent call to use() would succeed.
//Ensures that code dealing with stacks uses the same logic
/obj/item/stack/proc/can_use(var/used)

View File

@@ -0,0 +1,174 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, Collapsible, Table, Divider } from "../components";
import { Window } from "../layouts";
import { logger } from '../logging';
export const Stack = (props, context) => {
const { act, data } = useBackend(context);
const {
amount,
recipes,
} = data;
return (
<Window width={400} height={600} resizable>
<Window.Content scrollable>
<Section title={"Amount: " + amount}>
<RecipeList recipes={recipes} />
</Section>
</Window.Content>
</Window>
);
};
const RecipeList = (props, context) => {
const { act, data } = useBackend(context);
const {
recipes,
} = props;
let sortedKeys = Object.keys(recipes).sort();
// Shunt all categories to the top.
// We're not using this for now, keeping it here in case someone really hates color coding later.
// let nonCategories = sortedKeys.filter(item => recipes[item].ref !== undefined);
// let categories = sortedKeys.filter(item => recipes[item].ref === undefined);
// categories.unshift("--DIVIDER--");
// let newSortedKeys = nonCategories.concat(categories);
return sortedKeys.map(title => {
// if (title === "--DIVIDER--") {
// return (
// <Box mt={1} mb={1}>
// <Divider />
// </Box>
// );
// }
let recipe = recipes[title];
if (recipe.ref === undefined) {
return (
<Collapsible ml={1} mb={-0.7} color="label" title={title}>
<Box ml={1}>
<RecipeList recipes={recipe} />
</Box>
</Collapsible>
);
} else {
return (
<Recipe title={title} recipe={recipe} />
);
}
});
};
const buildMultiplier = (recipe, amount) => {
if (recipe.req_amount > amount) {
return 0;
}
return Math.floor(amount / recipe.req_amount);
};
const Multipliers = (props, context) => {
const { act, data } = useBackend(context);
const {
recipe,
maxMultiplier,
} = props;
let maxM = Math.min(maxMultiplier, Math.floor(recipe.max_res_amount / recipe.res_amount));
let multipliers = [5, 10, 25];
let finalResult = [];
for (let multiplier of multipliers) {
if (maxM >= multiplier) {
finalResult.push((
<Button
content={multiplier * recipe.res_amount + "x"}
onClick={() => act("make", {
ref: recipe.ref,
multiplier: multiplier,
})} />
));
}
}
if (multipliers.indexOf(maxM) === -1) {
finalResult.push((
<Button
content={maxM * recipe.res_amount + "x"}
onClick={() => act("make", {
ref: recipe.ref,
multiplier: maxM,
})} />
));
}
return finalResult;
};
const Recipe = (props, context) => {
const { act, data } = useBackend(context);
const {
amount,
} = data;
const {
recipe,
title,
} = props;
const {
res_amount,
max_res_amount,
req_amount,
ref,
} = recipe;
let buttonName = title;
buttonName += " (";
buttonName += req_amount + " ";
buttonName += ("sheet" + (req_amount > 1 ? "s" : ""));
buttonName += ")";
if (res_amount > 1) {
buttonName = res_amount + "x " + buttonName;
}
let maxMultiplier = buildMultiplier(recipe, amount);
return (
<Box>
<Table>
<Table.Row>
<Table.Cell>
<Button
fluid
disabled={!maxMultiplier}
icon="wrench"
content={buttonName}
onClick={() => act("make", {
ref: recipe.ref,
multiplier: 1,
})} />
</Table.Cell>
{max_res_amount > 1 && maxMultiplier > 1 && (
<Table.Cell collapsing>
<Multipliers recipe={recipe} maxMultiplier={maxMultiplier} />
</Table.Cell>
)}
</Table.Row>
</Table>
</Box>
);
};

File diff suppressed because one or more lines are too long