Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Commit 59725c5

Browse files
Added food tab to cart UI
1 parent d1b8fc2 commit 59725c5

File tree

2 files changed

+320
-0
lines changed

2 files changed

+320
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/obj/machinery/food_cart_TGUI
2+
name = "food cart"
3+
desc = "New generation hot dog stand."
4+
icon = 'icons/obj/kitchen.dmi'
5+
icon_state = "foodcart"
6+
density = TRUE
7+
anchored = FALSE
8+
use_power = NO_POWER_USE
9+
//Max amount of items that can be in cart's storage
10+
var/storage_capacity = 80
11+
//Sound made when an item is dispensed
12+
var/dispense_sound = 'sound/machines/click.ogg'
13+
//List for items to be shown in UI
14+
var/list/ui_list = list()
15+
16+
/obj/machinery/food_cart_TGUI/ui_interact(mob/user, datum/tgui/ui)
17+
ui = SStgui.try_update_ui(user, src, ui)
18+
if(!ui)
19+
ui = new(user, src, "FoodCart", name)
20+
ui.open()
21+
ui.set_autoupdate(TRUE)
22+
23+
/obj/machinery/food_cart_TGUI/ui_data(mob/user)
24+
//Define variables from UI
25+
var/list/data = list()
26+
data["food"] = list()
27+
data["storage"] = list()
28+
29+
//Loop through starting list for data to send to main tab
30+
for(var/item_detail in ui_list)
31+
32+
//Create needed list and variable for geting data for UI
33+
var/list/details = list()
34+
var/obj/item/reagent_containers/food/item = new item_detail
35+
36+
//Get information for UI
37+
details["item_name"] = item.name
38+
details["item_quantity"] = find_amount(item)
39+
details["item_type_path"] = item.type
40+
41+
//Get an image for the UI
42+
var/icon/item_pic = getFlatIcon(item)
43+
var/md5 = md5(fcopy_rsc(item_pic))
44+
if(!SSassets.cache["photo_[md5]_[item.name]_icon.png"])
45+
SSassets.transport.register_asset("photo_[md5]_[item.name]_icon.png", item_pic)
46+
SSassets.transport.send_assets(user, list("photo_[md5]_[item.name]_icon.png" = item_pic))
47+
details["item_image"] = SSassets.transport.get_asset_url("photo_[md5]_[item.name]_icon.png")
48+
49+
//Add to food list
50+
data["food"] += list(details)
51+
52+
//Get content and capacity data
53+
data["contents_length"] = contents.len
54+
data["storage_capacity"] = storage_capacity
55+
56+
//Send stored information to UI
57+
return data
58+
59+
/obj/machinery/food_cart_TGUI/ui_act(action, list/params)
60+
. = ..()
61+
if(.)
62+
63+
return
64+
65+
switch(action)
66+
if("dispense")
67+
var/itemPath = text2path(params["itemPath"])
68+
dispense_item(itemPath)
69+
70+
//For adding items to storage
71+
/obj/machinery/food_cart_TGUI/attackby(obj/item/A, mob/user, params)
72+
//Check to make sure it is a food item
73+
if(istype(A, /obj/item/reagent_containers/food))
74+
storage_single(A)
75+
76+
/obj/machinery/food_cart_TGUI/proc/dispense_item(received_item, mob/user = usr)
77+
78+
//Make a variable for checking the type of the selected item
79+
var/obj/item/reagent_containers/food/ui_item = new received_item
80+
81+
//If the vat has some of the desired item, dispense it
82+
if(find_amount(ui_item) > 0)
83+
//Select the last(most recent) of desired item
84+
var/obj/item/reagent_containers/food/snacks/dispensed_item = LAZYACCESS(contents, last_index(ui_item))
85+
//Drop it on the floor and then move it into the user's hands
86+
dispensed_item.forceMove(loc)
87+
user.put_in_hands(dispensed_item)
88+
user.visible_message(span_notice("[user] dispenses [ui_item.name] from [src]."), span_notice("You dispense [ui_item.name] from [src]."))
89+
playsound(src, dispense_sound, 25, TRUE, extrarange = -3)
90+
//If the last one was dispenced, remove from UI
91+
if(find_amount(ui_item) == 0)
92+
LAZYREMOVE(ui_list, received_item)
93+
else
94+
//For Alt click and because UI buttons are slow to disable themselves
95+
user.balloon_alert(user, "All out!")
96+
97+
/obj/machinery/food_cart_TGUI/proc/storage_single(obj/item/target_item, mob/user = usr)
98+
//Check if there is room
99+
if(contents.len < storage_capacity)
100+
//If item's typepath is not already in ui_list, add it
101+
if(!LAZYFIND(ui_list, target_item.type))
102+
LAZYADD(ui_list, target_item.type)
103+
//Move item to content
104+
target_item.forceMove(src)
105+
user.visible_message(span_notice("[user] inserts [target_item] into [src]."), span_notice("You insert [target_item] into [src]."))
106+
playsound(src, 'sound/effects/rustle2.ogg', 50, TRUE, extrarange = -3)
107+
108+
return
109+
else
110+
//Warn about full capacity
111+
user.balloon_alert(user, "No space!")
112+
113+
/obj/machinery/food_cart_TGUI/proc/find_amount(obj/item/counting_item, target_name = null, list/target_list = null)
114+
var/amount = 0
115+
116+
//If target_list is null, search contents for type paths
117+
if(!target_list)
118+
//Loop through contents, counting every instance of the given target
119+
for(var/obj/item/list_item in contents)
120+
if(list_item.type == counting_item.type)
121+
amount += 1
122+
//Else, search target_list
123+
else
124+
for(var/list_item in target_list)
125+
if(list_item == target_name)
126+
amount += 1
127+
128+
return amount
129+
130+
/obj/machinery/food_cart_TGUI/proc/last_index(obj/item/search_item)
131+
132+
var/obj/item/reagent_containers/food/snacks/item_index = null
133+
134+
//Search for the same item path in storage
135+
for(var/i in 1 to LAZYLEN(contents))
136+
//Loop through entire list to get last/most recent item
137+
if(contents[i].type == search_item.type)
138+
item_index = i
139+
140+
return item_index
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import { storage } from 'common/storage';
2+
import { capitalize } from 'common/string';
3+
import { useBackend, useLocalState } from '../backend';
4+
import { Button, Section, Table, Tabs, Box, TextArea, Stack, Tooltip } from '../components';
5+
import { Window } from '../layouts';
6+
import { resolveAsset } from './../assets';
7+
8+
// Store data for cones and scoops within Data
9+
type Data = {
10+
tabs: Tab[];
11+
}
12+
13+
type Tab = {
14+
food: FoodStats[];
15+
storage: StorageStats[];
16+
}
17+
18+
// Stats for food item
19+
type FoodStats = {
20+
item_image: string;
21+
item_name: string;
22+
item_quantity: number;
23+
item_type_path: string;
24+
selected_item: string;
25+
}
26+
27+
type StorageStats = {
28+
contents_length: number;
29+
storage_capacity: number;
30+
}
31+
32+
export const FoodCart = (props, context) => {
33+
// Get information from backend code
34+
const { data } = useBackend<Data>(context);
35+
// Make a variable for storing a number that represents the current selected tab
36+
const [selectedMainTab, setMainTab] = useLocalState(context, 'selectedMainTab', 0);
37+
38+
return(
39+
// Create window for ui
40+
<Window width={620} height={500} resizable>
41+
{/* Add constants to window and make it scrollable */}
42+
<Window.Content
43+
scrollable>
44+
{/* Create tabs for better organization */}
45+
<Tabs fluid>
46+
<Tabs.Tab
47+
icon="burger"
48+
bold
49+
// Show the food tab when the selectedMainTab is 0
50+
selected={selectedMainTab === 0}
51+
// Set selectedMainTab to 0 when the food tab is clicked
52+
onClick={() => setMainTab(0)}>
53+
{/* Put 'Food' in the tab to differentiate it from other tabs */}
54+
Food
55+
</Tabs.Tab>
56+
</Tabs>
57+
{/* If selectedMainTab is 0, show the UI elements in FoodTab */}
58+
{selectedMainTab === 0 && <FoodTab />}
59+
</Window.Content>
60+
</Window>
61+
);
62+
};
63+
64+
const FoodTab = (props, context) => {
65+
66+
// For organizing the food tab's information
67+
return (
68+
<Stack vertical>
69+
<Stack.Item>
70+
<Section
71+
title="Storage Capacity"
72+
textAlign="center">
73+
<CapacityRow />
74+
</Section>
75+
</Stack.Item>
76+
<Stack.Item>
77+
<Section
78+
title="Food Selection"
79+
textAlign="center">
80+
<FoodRow />
81+
</Section>
82+
</Stack.Item>
83+
</Stack>
84+
);
85+
};
86+
87+
const CapacityRow = (props, context) => {
88+
// Get data from ui_data in backend code
89+
const { data } = useBackend<StorageStats>(context);
90+
// Get needed variables from StorageStats
91+
const { contents_length } = data;
92+
const { storage_capacity } = data;
93+
94+
// Return a section with the tab's section_text
95+
return(
96+
<Table>
97+
<Table.Row>
98+
<Table.Cell
99+
fontSize="14px"
100+
textAlign="center"
101+
bold>
102+
{/* Show the vat's current contents and its max contents */}
103+
{contents_length}/{storage_capacity}
104+
</Table.Cell>
105+
</Table.Row>
106+
</Table>
107+
);
108+
};
109+
110+
const FoodRow = (props, context) => {
111+
// Get data from ui_data in backend code
112+
const { act, data } = useBackend<Tab>(context);
113+
// Get cones information from data
114+
const { food = [] } = data;
115+
116+
if(food.length > 0) {
117+
return (
118+
// Create Table for horizontal format
119+
<Table>
120+
{/* Use map to create dynamic rows based on the contents of food, with item being the individual item and its stats */}
121+
{food.map(item => (
122+
// Start row for holding ui elements and given data
123+
<Table.Row
124+
key={item.item_name}
125+
fontSize="14px">
126+
<Table.Cell>
127+
{/* Get image and then add it to the ui */}
128+
<Box
129+
as="img"
130+
src={resolveAsset(item.item_image)}
131+
height="32px"
132+
style={{
133+
'-ms-interpolation-mode': 'nearest-neighbor',
134+
'image-rendering': 'pixelated' }} />
135+
</Table.Cell>
136+
<Table.Cell
137+
bold>
138+
{/* Get name */}
139+
{capitalize(item.item_name)}
140+
</Table.Cell>
141+
<Table.Cell
142+
textAlign="right">
143+
{/* Get amount of item in storage */}
144+
{item.item_quantity} in storage
145+
</Table.Cell>
146+
<Table.Cell>
147+
{/* Make dispense button */}
148+
<Button
149+
fluid
150+
content="Dispense"
151+
textAlign="center"
152+
fontSize="16px"
153+
// Dissable if there is none of the item in storage
154+
disabled={(
155+
item.item_quantity === 0
156+
)}
157+
onClick={() => act("dispense", {
158+
itemPath: item.item_type_path,
159+
})}
160+
/>
161+
</Table.Cell>
162+
</Table.Row>
163+
))}
164+
</Table>
165+
);
166+
} else {
167+
return (
168+
<Table>
169+
<Table.Row>
170+
<Table.Cell
171+
fontSize="14px"
172+
textAlign="center"
173+
bold>
174+
Put something in you daft fool!
175+
</Table.Cell>
176+
</Table.Row>
177+
</Table>
178+
);
179+
}
180+
};

0 commit comments

Comments
 (0)