mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 16:47:13 +01:00
[MIRROR] Produce consoles now grey out their buttons if the cost criteria aren't met & have dynamic window sizes. [MDB IGNORE] (#20653)
* Produce consoles now grey out their buttons if the cost criteria aren't met & have dynamic window sizes. (#74773) ## About The Pull Request Fixes #74645 Fixes #72536 If your total order is less than 200 credits/mining points then the purchase button is greyed out telling you just that  Bonus. If your cart is empty then the express button is also greyed out telling you to order atleast 1 item  Even more bonus, the width of the window is dynamically adjusted based on the number of order categories so golem mining console is no longer obscured  Code changes 1. `var/cargo_cost_multiplier` : as the name implies is now the cost applied to all stuff ordered through cargo. it takes top priority(because we assume it will always be cheaper than express) and all item costs are multiplied with this before being displayed on the UI. So mining console has this value as 0.65 as intended 2. `proc/retrive_points()` : is used to retrieve the type of points this console is dealing with from the mobs id card, so for mining it returns the card's mining point's, for others it returns the card's cash, if you want to introduce a new currency type and make your own console for it, make sure you override this proc 3. `proc/subtract_points()` : is used to subtract these points(money, mining points) from the id card after the order is confirmed, return true if it was successful, false otherwise to cancel the order ## Changelog 🆑 fix: order consoles cancelling order's less than 200 but still subtracting money, mining points from the player code: multiplier for all shipments made through cargo refactor: 2 new procs retrive_points() & subtract_points() to dela with different types /🆑 * Produce consoles now grey out their buttons if the cost criteria aren't met & have dynamic window sizes. --------- Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
#define MINING_SHIPPING_MULTIPLIER 0.65
|
||||
#define GET_MINING_SHIPPING_MULTIPLIER(cost) round(cost * MINING_SHIPPING_MULTIPLIER, 5)
|
||||
#define CREDIT_TYPE_MINING "mp"
|
||||
|
||||
/obj/machinery/computer/order_console/mining
|
||||
@@ -10,14 +8,13 @@
|
||||
icon_keyboard = null
|
||||
icon_screen = null
|
||||
circuit = /obj/item/circuitboard/computer/order_console/mining
|
||||
|
||||
cooldown_time = 10 SECONDS //just time to let you know your order went through.
|
||||
cargo_cost_multiplier = 0.65
|
||||
express_cost_multiplier = 1
|
||||
purchase_tooltip = @{"Your purchases will arrive at cargo,
|
||||
and hopefully get delivered by them.
|
||||
35% cheaper than express delivery."}
|
||||
express_tooltip = @{"Sends your purchases instantly."}
|
||||
|
||||
credit_type = CREDIT_TYPE_MINING
|
||||
|
||||
order_categories = list(
|
||||
@@ -28,15 +25,10 @@
|
||||
)
|
||||
blackbox_key = "mining"
|
||||
|
||||
/obj/machinery/computer/order_console/mining/purchase_items(obj/item/card/id/card, express = FALSE)
|
||||
var/final_cost = get_total_cost()
|
||||
var/failure_message = "Sorry, but you do not have enough mining points."
|
||||
if(!express)
|
||||
final_cost = GET_MINING_SHIPPING_MULTIPLIER(final_cost)
|
||||
/obj/machinery/computer/order_console/mining/subtract_points(final_cost, obj/item/card/id/card)
|
||||
if(final_cost <= card.registered_account.mining_points)
|
||||
card.registered_account.mining_points -= final_cost
|
||||
return TRUE
|
||||
say(failure_message)
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/computer/order_console/mining/order_groceries(mob/living/purchaser, obj/item/card/id/card, list/groceries)
|
||||
@@ -67,33 +59,14 @@
|
||||
radio.talk_into(src, "A shaft miner has ordered equipment which will arrive on the cargo shuttle! Please make sure it gets to them as soon as possible!", radio_channel)
|
||||
SSshuttle.shopping_list += new_order
|
||||
|
||||
/obj/machinery/computer/order_console/mining/ui_data(mob/user)
|
||||
var/list/data = ..()
|
||||
var/cost = get_total_cost()
|
||||
data["total_cost"] = "[GET_MINING_SHIPPING_MULTIPLIER(cost)] (Express: [cost]) "
|
||||
if(!isliving(user))
|
||||
return data
|
||||
var/mob/living/living_user = user
|
||||
var/obj/item/card/id/id_card = living_user.get_idcard(TRUE)
|
||||
if(id_card)
|
||||
data["points"] = id_card.registered_account.mining_points
|
||||
|
||||
return data
|
||||
/obj/machinery/computer/order_console/mining/retrive_points(obj/item/card/id/id_card)
|
||||
return FLOOR(id_card.registered_account.mining_points, 1)
|
||||
|
||||
/obj/machinery/computer/order_console/mining/ui_act(action, params)
|
||||
. = ..()
|
||||
if(!.)
|
||||
flick("mining-deny", src)
|
||||
|
||||
/obj/machinery/computer/order_console/mining/ui_static_data(mob/user)
|
||||
var/list/data = ..()
|
||||
for(var/list/order in data["order_datums"])
|
||||
var/cost = order["cost"]
|
||||
if(isnull(cost)) //sanity check
|
||||
continue
|
||||
order["cost"] = GET_MINING_SHIPPING_MULTIPLIER(cost) // change costs to reflect mining shipping instead
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/order_console/mining/attackby(obj/item/weapon, mob/user, params)
|
||||
if(istype(weapon, /obj/item/mining_voucher))
|
||||
redeem_voucher(weapon, user)
|
||||
@@ -215,5 +188,3 @@
|
||||
#undef CREDIT_TYPE_MINING
|
||||
#undef TO_POINT_CARD
|
||||
#undef TO_USER_ID
|
||||
#undef MINING_SHIPPING_MULTIPLIER
|
||||
#undef GET_MINING_SHIPPING_MULTIPLIER
|
||||
|
||||
@@ -28,7 +28,9 @@ GLOBAL_LIST_EMPTY(order_console_products)
|
||||
var/credit_type = CREDIT_TYPE_CREDIT
|
||||
///Whether the console can only use express mode ONLY
|
||||
var/forced_express = FALSE
|
||||
///Multiplied cost to use express mode
|
||||
///Multiplied cost to use for cargo mode
|
||||
var/cargo_cost_multiplier = 1
|
||||
///Multiplied cost to use for express mode
|
||||
var/express_cost_multiplier = 2
|
||||
///The categories of orderable items this console can view and purchase.
|
||||
var/list/order_categories = list()
|
||||
@@ -69,10 +71,17 @@ GLOBAL_LIST_EMPTY(order_console_products)
|
||||
ui = new(user, src, "ProduceConsole", name)
|
||||
ui.open()
|
||||
|
||||
/**
|
||||
* points is any type of currency this machine accepts(money, mining points etc) which is displayed on the ui
|
||||
* Args:
|
||||
* card - The ID card we retrive these points from
|
||||
*/
|
||||
/obj/machinery/computer/order_console/proc/retrive_points(obj/item/card/id/id_card)
|
||||
return FLOOR(id_card.registered_account?.account_balance, 1)
|
||||
|
||||
/obj/machinery/computer/order_console/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/cost = get_total_cost()
|
||||
data["total_cost"] = "[cost] (Express: [cost * express_cost_multiplier])"
|
||||
data["total_cost"] = get_total_cost()
|
||||
data["off_cooldown"] = COOLDOWN_FINISHED(src, order_cooldown)
|
||||
|
||||
if(!isliving(user))
|
||||
@@ -80,7 +89,7 @@ GLOBAL_LIST_EMPTY(order_console_products)
|
||||
var/mob/living/living_user = user
|
||||
var/obj/item/card/id/id_card = living_user.get_idcard(TRUE)
|
||||
if(id_card)
|
||||
data["points"] = id_card.registered_account?.account_balance
|
||||
data["points"] = retrive_points(id_card)
|
||||
for(var/datum/orderable_item/item as anything in GLOB.order_console_products)
|
||||
if(!(item.category_index in order_categories))
|
||||
continue
|
||||
@@ -97,17 +106,21 @@ GLOBAL_LIST_EMPTY(order_console_products)
|
||||
data["express_tooltip"] = express_tooltip
|
||||
data["purchase_tooltip"] = purchase_tooltip
|
||||
data["forced_express"] = forced_express
|
||||
data["cargo_value"] = CARGO_CRATE_VALUE
|
||||
data["cargo_cost_multiplier"] = cargo_cost_multiplier
|
||||
data["express_cost_multiplier"] = express_cost_multiplier
|
||||
data["order_categories"] = order_categories
|
||||
data["order_datums"] = list()
|
||||
for(var/datum/orderable_item/item as anything in GLOB.order_console_products)
|
||||
if(!(item.category_index in order_categories))
|
||||
continue
|
||||
|
||||
data["order_datums"] += list(list(
|
||||
"name" = item.name,
|
||||
"desc" = item.desc,
|
||||
"cat" = item.category_index,
|
||||
"ref" = REF(item),
|
||||
"cost" = item.cost_per_order,
|
||||
"cost" = FLOOR(item.cost_per_order * cargo_cost_multiplier, 1),
|
||||
"product_icon" = icon2base64(getFlatIcon(image(icon = initial(item.item_path.icon), icon_state = initial(item.item_path.icon_state)), no_anim=TRUE))
|
||||
))
|
||||
return data
|
||||
@@ -136,21 +149,20 @@ GLOBAL_LIST_EMPTY(order_console_products)
|
||||
grocery_list[wanted_item] = clamp(params["amt"], 0, 20)
|
||||
if(!grocery_list[wanted_item])
|
||||
grocery_list -= wanted_item
|
||||
if("purchase", "ltsrbt_deliver")
|
||||
if("purchase")
|
||||
if(!grocery_list.len || !COOLDOWN_FINISHED(src, order_cooldown))
|
||||
return
|
||||
if(forced_express)
|
||||
return ui_act(action = "express")
|
||||
//So miners cant spam buy crates for a very low price
|
||||
if(get_total_cost() < CARGO_CRATE_VALUE)
|
||||
return
|
||||
var/obj/item/card/id/used_id_card = living_user.get_idcard(TRUE)
|
||||
if(!used_id_card || !used_id_card.registered_account)
|
||||
say("No bank account detected!")
|
||||
return
|
||||
if(!purchase_items(used_id_card))
|
||||
return
|
||||
//So miners cant spam buy crates for a very low price
|
||||
if(get_total_cost() < CARGO_CRATE_VALUE)
|
||||
say("For the delivery order needs to cost more or equal to [CARGO_CRATE_VALUE] points!")
|
||||
return
|
||||
if(blackbox_key)
|
||||
SSblackbox.record_feedback("tally", "non_express_[blackbox_key]_order", 1, name)
|
||||
order_groceries(living_user, used_id_card, grocery_list)
|
||||
@@ -197,16 +209,30 @@ GLOBAL_LIST_EMPTY(order_console_products)
|
||||
* returns TRUE if we can afford, FALSE otherwise.
|
||||
*/
|
||||
/obj/machinery/computer/order_console/proc/purchase_items(obj/item/card/id/card, express = FALSE)
|
||||
var/final_cost = get_total_cost()
|
||||
var/failure_message = "Sorry, but you do not have enough money."
|
||||
if(express)
|
||||
final_cost *= express_cost_multiplier
|
||||
failure_message += " Remember, Express upcharges the cost!"
|
||||
if(card.registered_account.adjust_money(-final_cost, "[name]: Purchase"))
|
||||
var/final_cost = get_total_cost() * (express ? express_cost_multiplier : cargo_cost_multiplier)
|
||||
var/failure_message = !express ? "Sorry, but you do not have enough [credit_type]." : " Remember, Express upcharges the cost!"
|
||||
if(subtract_points(final_cost, card))
|
||||
return TRUE
|
||||
say(failure_message)
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* whatever type of points was retrived in retrive_points() subtract those type of points from the card upon confirming order
|
||||
* Args:
|
||||
* final_cost - amount of points to subtract from this card
|
||||
* card - The ID card to subtract these points from
|
||||
* returns TRUE if successfull
|
||||
*/
|
||||
/obj/machinery/computer/order_console/proc/subtract_points(final_cost, obj/item/card/id/card)
|
||||
return card.registered_account.adjust_money(-final_cost, "[name]: Purchase")
|
||||
|
||||
/**
|
||||
* start of the shipment of your order
|
||||
* Args:
|
||||
* purchaser - The mob who is making this purchase
|
||||
* card - The card used to place this order
|
||||
* groceries - the list of orders to be placed
|
||||
*/
|
||||
/obj/machinery/computer/order_console/proc/order_groceries(mob/living/purchaser, obj/item/card/id/card, list/groceries)
|
||||
return
|
||||
|
||||
|
||||
+73
-28
@@ -1,3 +1,4 @@
|
||||
import { BooleanLike } from 'common/react';
|
||||
import { capitalize, createSearch } from 'common/string';
|
||||
import { useBackend, useLocalState } from '../backend';
|
||||
import { Box, Button, Dimmer, Divider, Icon, Input, NumberInput, Section, Stack, Tabs } from '../components';
|
||||
@@ -5,6 +6,36 @@ import { Window } from '../layouts';
|
||||
|
||||
const buttonWidth = 2;
|
||||
|
||||
type OrderDatum = {
|
||||
name: string;
|
||||
desc: number;
|
||||
cat: string;
|
||||
ref: string;
|
||||
cost: number;
|
||||
product_icon: string;
|
||||
};
|
||||
|
||||
type Item = {
|
||||
name: string;
|
||||
amt: number;
|
||||
};
|
||||
|
||||
type Data = {
|
||||
credit_type: string;
|
||||
off_cooldown: BooleanLike;
|
||||
points: number;
|
||||
express_tooltip: string;
|
||||
purchase_tooltip: string;
|
||||
forced_express: string;
|
||||
cargo_value: number;
|
||||
cargo_cost_multiplier: number;
|
||||
express_cost_multiplier: number;
|
||||
order_categories: string[];
|
||||
order_datums: OrderDatum[];
|
||||
item_amts: Item[];
|
||||
total_cost: number;
|
||||
};
|
||||
|
||||
const TAB2NAME = [
|
||||
{
|
||||
component: () => ShoppingTab,
|
||||
@@ -20,34 +51,41 @@ const findAmount = (item_amts, name) => {
|
||||
};
|
||||
|
||||
const ShoppingTab = (props, context) => {
|
||||
const { data, act } = useBackend(context);
|
||||
const { data, act } = useBackend<Data>(context);
|
||||
const { credit_type, order_categories, order_datums, item_amts } = data;
|
||||
const [shopIndex, setShopIndex] = useLocalState(context, 'shop-index', 1);
|
||||
const [condensed, setCondensed] = useLocalState(context, 'condensed', false);
|
||||
const [shopCategory, setShopCategory] = useLocalState(
|
||||
context,
|
||||
'shopCategory',
|
||||
order_categories[0]
|
||||
);
|
||||
const [condensed] = useLocalState(context, 'condensed', false);
|
||||
const [searchItem, setSearchItem] = useLocalState(context, 'searchItem', '');
|
||||
const search = createSearch(searchItem, (order_datums) => order_datums.name);
|
||||
const search = createSearch<OrderDatum>(
|
||||
searchItem,
|
||||
(order_datums) => order_datums.name
|
||||
);
|
||||
let goods =
|
||||
searchItem.length > 0
|
||||
? data.order_datums.filter(search)
|
||||
: order_datums.filter((item) => item && item.cat === shopIndex);
|
||||
? order_datums.filter((item) => search(item) && item.cat === shopCategory)
|
||||
: order_datums.filter((item) => item && item.cat === shopCategory);
|
||||
|
||||
return (
|
||||
<Stack fill vertical>
|
||||
<Section mb={-1}>
|
||||
<Stack.Item>
|
||||
<Tabs>
|
||||
{order_categories.map((item, key) => (
|
||||
{order_categories.map((category) => (
|
||||
<Tabs.Tab
|
||||
key={item.id}
|
||||
selected={item === shopIndex}
|
||||
key={category}
|
||||
selected={category === shopCategory}
|
||||
onClick={() => {
|
||||
setShopIndex(item);
|
||||
setShopCategory(category);
|
||||
|
||||
if (searchItem.length > 0) {
|
||||
setSearchItem('');
|
||||
}
|
||||
}}>
|
||||
{item}
|
||||
{category}
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
<Stack.Item grow>
|
||||
@@ -60,10 +98,6 @@ const ShoppingTab = (props, context) => {
|
||||
value={searchItem}
|
||||
onInput={(e, value) => {
|
||||
setSearchItem(value);
|
||||
|
||||
if (value.length > 0) {
|
||||
setShopIndex(1);
|
||||
}
|
||||
}}
|
||||
fluid
|
||||
/>
|
||||
@@ -75,8 +109,8 @@ const ShoppingTab = (props, context) => {
|
||||
<Section fill scrollable>
|
||||
<Stack vertical mt={-2}>
|
||||
<Divider />
|
||||
{goods.map((item) => (
|
||||
<Stack.Item key={item}>
|
||||
{goods.map((item, key) => (
|
||||
<Stack.Item key={key}>
|
||||
<Stack>
|
||||
<span
|
||||
style={{
|
||||
@@ -154,17 +188,20 @@ const ShoppingTab = (props, context) => {
|
||||
};
|
||||
|
||||
const CheckoutTab = (props, context) => {
|
||||
const { data, act } = useBackend(context);
|
||||
const { data, act } = useBackend<Data>(context);
|
||||
const {
|
||||
credit_type,
|
||||
purchase_tooltip,
|
||||
express_tooltip,
|
||||
forced_express,
|
||||
cargo_value,
|
||||
order_datums,
|
||||
total_cost,
|
||||
cargo_cost_multiplier,
|
||||
express_cost_multiplier,
|
||||
item_amts,
|
||||
} = data;
|
||||
|
||||
const total_cargo_cost = Math.floor(total_cost * cargo_cost_multiplier);
|
||||
const checkout_list = order_datums.filter(
|
||||
(food) => food && (findAmount(item_amts, food.name) || 0)
|
||||
);
|
||||
@@ -187,8 +224,8 @@ const CheckoutTab = (props, context) => {
|
||||
</>
|
||||
)}
|
||||
<Stack.Item grow>
|
||||
{checkout_list.map((item) => (
|
||||
<Stack.Item key={item}>
|
||||
{checkout_list.map((item, key) => (
|
||||
<Stack.Item key={key}>
|
||||
<Stack>
|
||||
<Stack.Item>{capitalize(item.name)}</Stack.Item>
|
||||
<Stack.Item grow mt={-1} color="label" fontSize="10px">
|
||||
@@ -228,7 +265,8 @@ const CheckoutTab = (props, context) => {
|
||||
<Section>
|
||||
<Stack>
|
||||
<Stack.Item grow mt={0.5}>
|
||||
Total Cost: {total_cost}
|
||||
Total Cost:{total_cargo_cost}(Express:
|
||||
{total_cost * express_cost_multiplier})
|
||||
</Stack.Item>
|
||||
{!forced_express && (
|
||||
<Stack.Item grow textAlign="center">
|
||||
@@ -236,7 +274,12 @@ const CheckoutTab = (props, context) => {
|
||||
fluid
|
||||
icon="plane-departure"
|
||||
content="Purchase"
|
||||
tooltip={purchase_tooltip}
|
||||
disabled={total_cargo_cost < cargo_value}
|
||||
tooltip={
|
||||
total_cargo_cost < cargo_value
|
||||
? `Total Cost must be above or equal to ${cargo_value}`
|
||||
: purchase_tooltip
|
||||
}
|
||||
tooltipPosition="top"
|
||||
onClick={() => act('purchase')}
|
||||
/>
|
||||
@@ -248,7 +291,10 @@ const CheckoutTab = (props, context) => {
|
||||
icon="parachute-box"
|
||||
color="yellow"
|
||||
content="Express"
|
||||
tooltip={express_tooltip}
|
||||
disabled={total_cost <= 0}
|
||||
tooltip={
|
||||
total_cost <= 0 ? 'Order atleast 1 item' : express_tooltip
|
||||
}
|
||||
tooltipPosition="top-start"
|
||||
onClick={() => act('express')}
|
||||
/>
|
||||
@@ -261,7 +307,6 @@ const CheckoutTab = (props, context) => {
|
||||
};
|
||||
|
||||
const OrderSent = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
return (
|
||||
<Dimmer>
|
||||
<Stack vertical>
|
||||
@@ -277,13 +322,13 @@ const OrderSent = (props, context) => {
|
||||
};
|
||||
|
||||
export const ProduceConsole = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const { points, off_cooldown } = data;
|
||||
const { data } = useBackend<Data>(context);
|
||||
const { points, off_cooldown, order_categories } = data;
|
||||
const [tabIndex, setTabIndex] = useLocalState(context, 'tab-index', 1);
|
||||
const [condensed, setCondensed] = useLocalState(context, 'condensed', false);
|
||||
const TabComponent = TAB2NAME[tabIndex - 1].component();
|
||||
return (
|
||||
<Window width={500} height={400}>
|
||||
<Window width={Math.max(order_categories.length * 125, 500)} height={400}>
|
||||
<Window.Content>
|
||||
{!off_cooldown && <OrderSent />}
|
||||
<Stack vertical fill>
|
||||
Reference in New Issue
Block a user