Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MIRROR] GMM UI & Cargo budget handling tweaks #357

Merged
merged 1 commit into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 165 additions & 70 deletions code/modules/cargo/materials_market.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/// The maximum number of stacks you can place in 1 order
#define MAX_STACK_LIMIT 10
/// The order rank for all galactic material market orders
#define GALATIC_MATERIAL_ORDER "Galactic Materials Market"

/obj/machinery/materials_market
name = "galactic materials market"
desc = "This machine allows the user to buy and sell sheets of minerals \
Expand All @@ -22,8 +27,6 @@
)
/// Are we ordering sheets from our own card balance or the cargo budget?
var/ordering_private = TRUE
/// Currently, can we order sheets from our own card balance or the cargo budget?
var/can_buy_via_budget = FALSE

/obj/machinery/materials_market/update_icon_state()
if(panel_open)
Expand All @@ -36,15 +39,21 @@
return ..()

/obj/machinery/materials_market/wrench_act(mob/living/user, obj/item/tool)
..()
default_unfasten_wrench(user, tool, time = 1.5 SECONDS)
return TOOL_ACT_TOOLTYPE_SUCCESS
. = ..()
if(default_unfasten_wrench(user, tool, time = 1.5 SECONDS) == SUCCESSFUL_UNFASTEN)
return TOOL_ACT_TOOLTYPE_SUCCESS

/obj/machinery/materials_market/screwdriver_act(mob/living/user, obj/item/tool)
. = ..()
if(default_deconstruction_screwdriver(user, "[base_icon_state]_open", "[base_icon_state]", tool))
return TOOL_ACT_TOOLTYPE_SUCCESS

/obj/machinery/materials_market/crowbar_act(mob/living/user, obj/item/tool)
. = ..()
if(default_deconstruction_crowbar(tool))
return TOOL_ACT_TOOLTYPE_SUCCESS

/obj/machinery/materials_market/attackby(obj/item/O, mob/user, params)
if(default_deconstruction_screwdriver(user, "[base_icon_state]_open", "[base_icon_state]", O))
return
else if(default_deconstruction_crowbar(O))
return
if(is_type_in_list(O, exportable_material_items))
var/amount = 0
var/value = 0
Expand All @@ -62,6 +71,7 @@
playsound(src, 'sound/machines/scanbuzz.ogg', 25, FALSE)
return TRUE
qdel(exportable)

var/obj/item/stock_block/new_block = new /obj/item/stock_block(drop_location())
new_block.export_value = amount * value * MARKET_PROFIT_MODIFIER
new_block.export_mat = material_to_export
Expand All @@ -71,6 +81,21 @@
return TRUE
return ..()

/**
* Find the order purchased either privately or by cargo budget
* Arguments
* * [user][mob] - the user who placed this order
* * is_ordering_private - is the player ordering privatly. If FALSE it means they are using cargo budget
*/
/obj/machinery/materials_market/proc/find_order(mob/user, is_ordering_private)
for(var/datum/supply_order/order in SSshuttle.shopping_list)
// Must be a Galactic Materials Market order and payed by the null account(if ordered via cargo budget) or by correct user for private purchase
if(order.orderer_rank == GALATIC_MATERIAL_ORDER && ( \
(!is_ordering_private && isnull(order.paying_account)) || \
(is_ordering_private && !isnull(order.paying_account) && order.orderer == user) \
))
return order
return null

/obj/machinery/materials_market/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
Expand All @@ -81,36 +106,69 @@
ui.open()

/obj/machinery/materials_market/ui_data(mob/user)
var/data = list()
. = list()

//can this player use cargo budget
var/can_buy_via_budget = FALSE
var/obj/item/card/id/used_id_card
if(isliving(user))
var/mob/living/living_user = user
used_id_card = living_user.get_idcard(TRUE)
can_buy_via_budget = (ACCESS_CARGO in used_id_card?.GetAccess())

//if no cargo access then force private purchase
var/is_ordering_private = ordering_private || !can_buy_via_budget

//find current order based on ordering mode & player
var/datum/supply_order/current_order = find_order(user, is_ordering_private)

var/material_data
var/trend_string
var/color_string
var/sheet_to_buy
var/requested_amount
for(var/datum/material/traded_mat as anything in SSstock_market.materials_prices)
var/trend_string = ""
if(SSstock_market.materials_trends[traded_mat] == 0)
trend_string = "neutral"
else if(SSstock_market.materials_trends[traded_mat] == 1)
trend_string = "up"
else if(SSstock_market.materials_trends[traded_mat] == -1)
trend_string = "down"
var/color_string = ""
if (initial(traded_mat.greyscale_colors))
color_string = splicetext(initial(traded_mat.greyscale_colors), 7, length(initial(traded_mat.greyscale_colors)), "") //slice it to a standard 6 char hex
else if(initial(traded_mat.color))
color_string = initial(traded_mat.color)
//convert trend into text
switch(SSstock_market.materials_trends[traded_mat])
if(0)
trend_string = "neutral"
if(1)
trend_string = "up"
else
trend_string = "down"

//get mat color
var/initial_colors = initial(traded_mat.greyscale_colors)
if(initial_colors)
color_string = splicetext(initial_colors, 7, length(initial_colors), "") //slice it to a standard 6 char hex
else
initial_colors = initial(traded_mat.color)
if(initial_colors)
color_string = initial_colors
else
color_string = COLOR_CYAN

//get sheet type from material
sheet_to_buy = initial(traded_mat.sheet_type)
if(!sheet_to_buy)
CRASH("Material with no sheet type being sold on materials market!")

//get the ordered amount from the order
requested_amount = 0
if(!isnull(current_order))
requested_amount = current_order.pack.contains[sheet_to_buy]

//send data
material_data += list(list(
"name" = initial(traded_mat.name),
"price" = SSstock_market.materials_prices[traded_mat],
"quantity" = SSstock_market.materials_quantity[traded_mat],
"trend" = trend_string,
"color" = color_string,
"requested" = requested_amount
))

can_buy_via_budget = FALSE
var/obj/item/card/id/used_id_card
if(isliving(user))
var/mob/living/living_user = user
used_id_card = living_user.get_idcard(TRUE)
can_buy_via_budget = (ACCESS_CARGO in used_id_card?.GetAccess())

//get account balance
var/balance = 0
if(!ordering_private)
var/datum/bank_account/dept = SSeconomy.get_dep_account(ACCOUNT_CAR)
Expand All @@ -119,16 +177,23 @@
else
balance = used_id_card?.registered_account?.account_balance

//is market crashing
var/market_crashing = FALSE
if(HAS_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING))
market_crashing = TRUE

data["catastrophe"] = market_crashing
data["materials"] = material_data
data["creditBalance"] = balance
data["orderingPrive"] = ordering_private
data["canOrderCargo"] = can_buy_via_budget
return data
//get final order cost
var/current_cost = 0
if(!isnull(current_order))
current_cost = current_order.get_final_cost()

//pack data
.["catastrophe"] = market_crashing
.["materials"] = material_data
.["creditBalance"] = balance
.["orderBalance"] = current_cost
.["orderingPrive"] = ordering_private
.["canOrderCargo"] = can_buy_via_budget

/obj/machinery/materials_market/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
. = ..()
Expand All @@ -141,12 +206,19 @@
if(isnull(used_id_card))
say("No ID Found")
return
var/can_buy_via_budget = (ACCESS_CARGO in used_id_card?.GetAccess())

//if multiple users open the UI some of them may not have the required access so we recheck
var/is_ordering_private = ordering_private
if(!can_buy_via_budget) //no cargo access then force private purchase
is_ordering_private = TRUE

switch(action)
if("buy")
var/material_str = params["material"]
var/quantity = text2num(params["quantity"])

//find material from it's name
var/datum/material/material_bought
var/obj/item/stack/sheet/sheet_to_buy
for(var/datum/material/mat as anything in SSstock_market.materials_prices)
Expand All @@ -155,12 +227,11 @@
break
if(!material_bought)
CRASH("Invalid material name passed to materials market!")
sheet_to_buy = initial(material_bought.sheet_type)
if(!sheet_to_buy)
CRASH("Material with no sheet type being sold on materials market!")

//if multiple users open the UI some of them may not have the required access so we recheck
var/is_ordering_private = ordering_private
if(!(ACCESS_CARGO in used_id_card.GetAccess())) //no cargo access then force private purchase
is_ordering_private = TRUE

//get available bank account for purchasing
var/datum/bank_account/account_payable
if(is_ordering_private)
account_payable = used_id_card.registered_account
Expand All @@ -170,59 +241,81 @@
say("No bank account detected!")
return

sheet_to_buy = initial(material_bought.sheet_type)
if(!sheet_to_buy)
CRASH("Material with no sheet type being sold on materials market!")
//sanity checks for available quantity & budget
if(quantity > SSstock_market.materials_quantity[material_bought])
say("Not enough materials on the market to purchase!")
return

var/cost = SSstock_market.materials_prices[material_bought] * quantity
if(cost > account_payable.account_balance)
to_chat(living_user, span_warning("You don't have enough money to buy that!"))
say("Not enough money to start purchase!")
return

var/list/things_to_order = list()
things_to_order += (sheet_to_buy)
things_to_order[sheet_to_buy] = quantity

// We want to count how many stacks of all sheets we're ordering to make sure they don't exceed the limit of 10
// If we already have a custom order on SSshuttle, we should add the things to order to that order
for(var/datum/supply_order/order in SSshuttle.shopping_list)
// Must be a Galactic Materials Market order and payed by the null account(if ordered via cargo budget) or by correct user for private purchase
if(order.orderer_rank == "Galactic Materials Market" && ( \
(!is_ordering_private && order.paying_account == null) || \
(is_ordering_private && order.paying_account != null && order.orderer == living_user) \
))
// Check if this order exceeded its limit
var/prior_stacks = 0
for(var/obj/item/stack/sheet/sheet as anything in order.pack.contains)
prior_stacks += ROUND_UP(order.pack.contains[sheet] / 50)
if(prior_stacks >= 10)
to_chat(usr, span_notice("You already have 10 stacks of sheets on order! Please wait for them to arrive before ordering more."))
playsound(usr, 'sound/machines/synth_no.ogg', 35, FALSE)
return
// Append to this order
order.append_order(things_to_order, cost)
var/datum/supply_order/current_order = find_order(living_user, is_ordering_private)
if(!isnull(current_order))
// Check if this order exceeded the market limit
var/prior_sheets = current_order.pack.contains[sheet_to_buy]
if(prior_sheets + quantity > SSstock_market.materials_quantity[material_bought] )
say("There aren't enough sheets on the market! Please wait for more sheets to be traded before adding more.")
playsound(usr, 'sound/machines/synth_no.ogg', 35, FALSE)
return

// Check if the order exceeded the purchase limit
var/prior_stacks = ROUND_UP(prior_sheets / MAX_STACK_SIZE)
if(prior_stacks >= MAX_STACK_LIMIT)
say("There are already 10 stacks of sheets on order! Please wait for them to arrive before ordering more.")
playsound(usr, 'sound/machines/synth_no.ogg', 35, FALSE)
return

// Prevents you from ordering more than the available budget
var/datum/bank_account/paying_account = account_payable
if(!isnull(current_order.paying_account)) //order is already being paid by another account
paying_account = current_order.paying_account
if(current_order.get_final_cost() + cost > paying_account.account_balance)
say("Order exceeds available budget! Please send it before purchasing more.")
return

//Now we need to add a cargo order for quantity sheets of material_bought.sheet_type
// Finally Append to this order
current_order.append_order(things_to_order, cost)
return TRUE

//Place a new order
var/datum/supply_pack/custom/minerals/mineral_pack = new(
purchaser = is_ordering_private ? living_user : "Cargo", \
cost = cost, \
contains = things_to_order, \
)
var/datum/supply_order/new_order = new(
var/datum/supply_order/materials/new_order = new(
pack = mineral_pack,
orderer = living_user,
orderer_rank = "Galactic Materials Market",
orderer_rank = GALATIC_MATERIAL_ORDER,
orderer_ckey = living_user.ckey,
paying_account = is_ordering_private ? account_payable : null,
cost_type = "credit",
cost_type = "cr",
can_be_cancelled = FALSE
)
say("Thank you for your purchase! It will arrive on the next cargo shuttle!")
SSshuttle.shopping_list += new_order
return
return TRUE

if("toggle_budget")
if(!can_buy_via_budget)
return
ordering_private = !ordering_private
return TRUE

if("clear")
var/datum/supply_order/current_order = find_order(living_user, is_ordering_private)
if(!isnull(current_order))
SSshuttle.shopping_list -= current_order
qdel(current_order)
return TRUE

/obj/item/stock_block
name = "stock block"
Expand All @@ -238,6 +331,11 @@
/// Is this stock block currently updating it's value with the market (aka fluid)?
var/fluid = FALSE

/obj/item/stock_block/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(value_warning)), 2.5 MINUTES, TIMER_DELETE_ME)
addtimer(CALLBACK(src, PROC_REF(update_value)), 5 MINUTES, TIMER_DELETE_ME)

/obj/item/stock_block/examine(mob/user)
. = ..()
. += span_notice("\The [src] is worth [export_value] cr, from selling [quantity] sheets of [initial(export_mat?.name)].")
Expand All @@ -246,11 +344,6 @@
else
. += span_notice("\The [src]'s value is still [span_boldnotice("locked in")]. [span_boldnotice("Sell it")] before it's value becomes liquid!")

/obj/item/stock_block/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(value_warning)), 2.5 MINUTES)
addtimer(CALLBACK(src, PROC_REF(update_value)), 5 MINUTES)

/obj/item/stock_block/proc/value_warning()
visible_message(span_warning("\The [src] is starting to become liquid!"))
icon_state = "stock_block_fluid"
Expand All @@ -266,3 +359,5 @@
update_appearance(UPDATE_ICON_STATE)
visible_message(span_warning("\The [src] becomes liquid!"))

#undef MAX_STACK_LIMIT
#undef GALATIC_MATERIAL_ORDER
12 changes: 9 additions & 3 deletions code/modules/cargo/order.dm
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@
/datum/supply_order/proc/get_final_cost()
var/cost = pack.get_cost()
if(applied_coupon) //apply discount price
cost -= (cost * applied_coupon.discount_pct_off)
if(!isnull(paying_account)) //privately purchased means 1.1x the cost
cost *= (1 - applied_coupon.discount_pct_off)
if(paying_account && !pack.goody) //privately purchased and not a goody means 1.1x the cost
cost *= 1.1
return cost
return round(cost)

/datum/supply_order/proc/generateRequisition(turf/T)
var/obj/item/paper/requisition_paper = new(T)
Expand Down Expand Up @@ -201,6 +201,12 @@
pack.contains[i] = new_contents[i]
pack.cost += cost_increase

//To append cargo crate value to final order cost
/datum/supply_order/materials

/datum/supply_order/materials/get_final_cost()
return (..() + CARGO_CRATE_VALUE)

#undef MANIFEST_ERROR_CHANCE
#undef MANIFEST_ERROR_NAME
#undef MANIFEST_ERROR_CONTENTS
Expand Down
Loading