mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-06-24 07:34:56 +01:00
9fb7c20daa
## About The Pull Request Last Christmas we had and resolved this bug #88595 where via the mechanic of buying random trash, Cargo could roll on the roulette to try and get random Christmas presents and open them for random items. This was removed because it's not supposed to work that way and was a way of exploiting Christmas cheer for personal gain, which is grinchsome behaviour. That said, being able to order Christmas presents is also kind of soulful, so this PR brings that mechanic back but on purpose this time. During the Christmas season _only_, Cargo can spend 3000 credits of their budget to order a "Surplus Christmas Gifts" crate which contains 4-6 presents _with pre-assigned recipients_. In a similar system to addressed mail, only the person written on the gift tag can open the present, so unless you're sufficiently scroogeous to collect a huge pile of presents on the cargo room floor in hopes of getting a couple with your name on (in my testing these contained raw unbaked croissant dough, and a piece of paper from a space ruin) you should mostly be using this to deliver generalised holiday cheer to the crew rather than just yourself. This PR also contains (maybe as more lines than the actual feature) a refactor changing a bunch of boolean vars on `/datum/supply_pack` into bitflags, because I needed to add one more and it seemed silly to have so many booleans. ## Why It's Good For The Game It allows those with the yuletide spirit to deliver some christmas cheer to their fellow man, isn't that the season's reason? ## Changelog 🆑 add: When the game considers it to be Christmas, Cargo can order additional Christmas gifts pre-addressed to random crew members. /🆑
345 lines
14 KiB
Plaintext
345 lines
14 KiB
Plaintext
/datum/computer_file/program/budgetorders
|
|
filename = "orderapp"
|
|
filedesc = "NT Shopping Network"
|
|
downloader_category = PROGRAM_CATEGORY_SUPPLY
|
|
program_open_overlay = "request"
|
|
extended_desc = "Nanotrasen Shopping Network interface for purchasing supplies from the cargo catalogue using a department budget account."
|
|
program_flags = PROGRAM_ON_NTNET_STORE | PROGRAM_REQUIRES_NTNET
|
|
can_run_on_flags = PROGRAM_LAPTOP | PROGRAM_PDA
|
|
size = 10
|
|
tgui_id = "NtosCargo"
|
|
program_icon = FA_ICON_CART_FLATBED
|
|
///Are you actually placing orders with it?
|
|
var/requestonly = TRUE
|
|
///Can the tablet see or buy illegal stuff?
|
|
var/contraband = FALSE
|
|
///Is it being bought from a personal account, or is it being done via a budget/cargo?
|
|
var/self_paid = FALSE
|
|
///Can this console approve purchase requests?
|
|
var/can_approve_requests = FALSE
|
|
///What do we say when the shuttle moves with living beings on it.
|
|
var/safety_warning = "For safety and ethical reasons, the automated supply shuttle cannot transport live organisms, \
|
|
human remains, classified nuclear weaponry, mail, undelivered departmental order crates, syndicate bombs, \
|
|
homing beacons, unstable eigenstates, or machinery housing any form of artificial intelligence."
|
|
///If you're being raided by pirates, what do you tell the crew?
|
|
var/blockade_warning = "Bluespace instability detected. Shuttle movement impossible."
|
|
///The name of the shuttle template being used as the cargo shuttle. 'cargo' is default and contains critical code. Don't change this unless you know what you're doing.
|
|
var/cargo_shuttle = "cargo"
|
|
///The docking port called when returning to the station.
|
|
var/docking_home = "cargo_home"
|
|
///The docking port called when leaving the station.
|
|
var/docking_away = "cargo_away"
|
|
///If this console can loan the cargo shuttle. Set to false to disable.
|
|
var/stationcargo = TRUE
|
|
///The account this console processes and displays. Independent from the account the shuttle processes.
|
|
var/cargo_account = ACCOUNT_CAR
|
|
|
|
/datum/computer_file/program/budgetorders/proc/is_visible_pack(mob/user, paccess_to_check, list/access, contraband)
|
|
if(HAS_SILICON_ACCESS(user)) //Borgs can't buy things.
|
|
return FALSE
|
|
if(computer.obj_flags & EMAGGED)
|
|
return TRUE
|
|
else if(contraband) //Hide contrband when non-emagged.
|
|
return FALSE
|
|
if(!paccess_to_check) // No required_access, allow it.
|
|
return TRUE
|
|
if(isAdminGhostAI(user))
|
|
return TRUE
|
|
|
|
//Aquire access from the inserted ID card.
|
|
if(!length(access))
|
|
var/obj/item/card/id/D = computer?.stored_id?.GetID()
|
|
if(!D)
|
|
return FALSE
|
|
access = D.GetAccess()
|
|
|
|
if(paccess_to_check in access)
|
|
return TRUE
|
|
|
|
return FALSE
|
|
|
|
/datum/computer_file/program/budgetorders/ui_data(mob/user)
|
|
var/list/data = list()
|
|
data["location"] = SSshuttle.supply.getStatusText()
|
|
data["department"] = "Cargo"
|
|
|
|
var/datum/bank_account/buyer = SSeconomy.get_dep_account(cargo_account)
|
|
var/obj/item/card/id/id_card = computer.stored_id?.GetID()
|
|
if(id_card?.registered_account)
|
|
buyer = SSeconomy.get_dep_account(id_card?.registered_account.account_job.paycheck_department)
|
|
if((ACCESS_COMMAND in id_card.access))
|
|
requestonly = FALSE
|
|
can_approve_requests = TRUE
|
|
// If buyer is a departmental budget, replaces "Cargo" with that budget - we're not using the cargo budget here
|
|
data["department"] = "[buyer.account_holder] Requisitions"
|
|
else
|
|
requestonly = TRUE
|
|
can_approve_requests = FALSE
|
|
else
|
|
requestonly = TRUE
|
|
if(buyer)
|
|
data["points"] = buyer.account_balance
|
|
// To recap above because it's kind of a mess, here's all the options:
|
|
//Head of staff ID card: Can approve, buy, and make purchases using their own departmental budgets.
|
|
//ID card, not a head of staff: can request items from cargo using departmental budget.
|
|
//No ID card, can request items from cargo using the cargo budget.
|
|
|
|
//Otherwise static data, that is being applied in ui_data as the crates visible and buyable are not static, and are determined by inserted ID.
|
|
data["requestonly"] = requestonly
|
|
data["supplies"] = list()
|
|
for(var/pack in SSshuttle.supply_packs)
|
|
var/datum/supply_pack/P = SSshuttle.supply_packs[pack]
|
|
if(P.order_flags & ORDER_INVISIBLE)
|
|
continue
|
|
if(!is_visible_pack(user, P.access_view , null, (P.order_flags & ORDER_CONTRABAND)) || (P.order_flags & ORDER_EMAG_ONLY))
|
|
continue
|
|
if(!data["supplies"][P.group])
|
|
data["supplies"][P.group] = list(
|
|
"name" = P.group,
|
|
"packs" = list()
|
|
)
|
|
if(((P.order_flags & ORDER_EMAG_ONLY) && ((P.order_flags & ORDER_CONTRABAND) && !contraband) || ((P.order_flags & ORDER_SPECIAL) && !(P.order_flags & ORDER_SPECIAL_ENABLED)) || (P.order_flags & ORDER_POD_ONLY)))
|
|
continue
|
|
|
|
var/obj/item/first_item = length(P.contains) > 0 ? P.contains[1] : null
|
|
data["supplies"][P.group]["packs"] += list(list(
|
|
"name" = P.name,
|
|
"cost" = P.get_cost(),
|
|
"id" = pack,
|
|
"desc" = P.desc || P.name, // If there is a description, use it. Otherwise use the pack's name.
|
|
"first_item_icon" = first_item?.icon,
|
|
"first_item_icon_state" = first_item?.icon_state,
|
|
"goody" = P.order_flags & ORDER_GOODY,
|
|
"access" = P.access,
|
|
"contains" = P.get_contents_ui_data(),
|
|
))
|
|
|
|
//Data regarding the User's capability to buy things.
|
|
data["away"] = SSshuttle.supply.getDockedId() == docking_away
|
|
data["self_paid"] = self_paid
|
|
data["docked"] = SSshuttle.supply.mode == SHUTTLE_IDLE
|
|
data["loan"] = !!SSshuttle.shuttle_loan
|
|
data["loan_dispatched"] = SSshuttle.shuttle_loan && SSshuttle.shuttle_loan.dispatched
|
|
data["can_send"] = FALSE //There is no situation where I want the app to be able to send the shuttle AWAY from the station, but conversely is fine.
|
|
data["can_approve_requests"] = can_approve_requests
|
|
data["app_cost"] = TRUE
|
|
var/message = "Remember to stamp and send back the supply manifests."
|
|
if(SSshuttle.centcom_message)
|
|
message = SSshuttle.centcom_message
|
|
if(SSshuttle.supply_blocked)
|
|
message = blockade_warning
|
|
data["message"] = message
|
|
var/cart_list = list()
|
|
for(var/datum/supply_order/order in SSshuttle.shopping_list)
|
|
if(cart_list[order.pack.name])
|
|
cart_list[order.pack.name][1]["amount"]++
|
|
cart_list[order.pack.name][1]["cost"] += order.get_final_cost()
|
|
if(order.department_destination)
|
|
cart_list[order.pack.name][1]["dep_order"]++
|
|
if(!isnull(order.paying_account))
|
|
cart_list[order.pack.name][1]["paid"]++
|
|
continue
|
|
|
|
cart_list[order.pack.name] = list(list(
|
|
"cost_type" = order.cost_type,
|
|
"object" = order.pack.name,
|
|
"cost" = order.get_final_cost(),
|
|
"id" = order.id,
|
|
"amount" = 1,
|
|
"orderer" = order.orderer,
|
|
"paid" = !isnull(order.paying_account), //number of orders purchased privatly
|
|
"dep_order" = !!order.department_destination, //number of orders purchased by a department
|
|
"can_be_cancelled" = order.can_be_cancelled,
|
|
))
|
|
data["cart"] = list()
|
|
for(var/item_id in cart_list)
|
|
data["cart"] += cart_list[item_id]
|
|
|
|
|
|
data["requests"] = list()
|
|
for(var/datum/supply_order/order in SSshuttle.request_list)
|
|
var/datum/supply_pack/pack = order.pack
|
|
data["requests"] += list(list(
|
|
"object" = pack.name,
|
|
"cost" = pack.get_cost(),
|
|
"orderer" = order.orderer,
|
|
"reason" = order.reason,
|
|
"id" = order.id,
|
|
"account" = order.paying_account ? order.paying_account.account_holder : "Cargo Department"
|
|
))
|
|
|
|
return data
|
|
|
|
/datum/computer_file/program/budgetorders/ui_static_data(mob/user)
|
|
var/list/data = list()
|
|
data["max_order"] = CARGO_MAX_ORDER
|
|
return data
|
|
|
|
/datum/computer_file/program/budgetorders/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
|
. = ..()
|
|
var/mob/user = ui.user
|
|
switch(action)
|
|
if("send")
|
|
if(!SSshuttle.supply.canMove())
|
|
computer.say(safety_warning)
|
|
return
|
|
if(SSshuttle.supply_blocked)
|
|
computer.say(blockade_warning)
|
|
return
|
|
if(SSshuttle.supply.getDockedId() == docking_home)
|
|
SSshuttle.moveShuttle(cargo_shuttle, docking_away, TRUE)
|
|
computer.say("The supply shuttle is departing.")
|
|
user.investigate_log("sent the supply shuttle away.", INVESTIGATE_CARGO)
|
|
else
|
|
user.investigate_log("called the supply shuttle.", INVESTIGATE_CARGO)
|
|
computer.say("The supply shuttle has been called and will arrive in [SSshuttle.supply.timeLeft(600)] minute\s.")
|
|
SSshuttle.moveShuttle(cargo_shuttle, docking_home, TRUE)
|
|
. = TRUE
|
|
if("loan")
|
|
if(!SSshuttle.shuttle_loan)
|
|
return
|
|
if(SSshuttle.supply_blocked)
|
|
computer.say(blockade_warning)
|
|
return
|
|
else if(SSshuttle.supply.mode != SHUTTLE_IDLE)
|
|
return
|
|
else if(SSshuttle.supply.getDockedId() != docking_away)
|
|
return
|
|
else if(stationcargo != TRUE)
|
|
return
|
|
else
|
|
SSshuttle.shuttle_loan.loan_shuttle()
|
|
computer.say("The supply shuttle has been loaned to CentCom.")
|
|
user.investigate_log("accepted a shuttle loan event.", INVESTIGATE_CARGO)
|
|
user.log_message("accepted a shuttle loan event.", LOG_GAME)
|
|
. = TRUE
|
|
if("add")
|
|
var/id = text2path(params["id"])
|
|
var/datum/supply_pack/pack = SSshuttle.supply_packs[id]
|
|
if(!istype(pack))
|
|
return
|
|
if((pack.order_flags & (ORDER_EMAG_ONLY | ORDER_POD_ONLY | ORDER_CONTRABAND)) || ((pack.order_flags & ORDER_SPECIAL) && !(pack.order_flags & ORDER_SPECIAL_ENABLED)))
|
|
return
|
|
|
|
var/name = "*None Provided*"
|
|
var/rank = "*None Provided*"
|
|
var/ckey = user.ckey
|
|
var/mob/living/carbon/human/hwoman
|
|
if(ishuman(user))
|
|
hwoman = user
|
|
rank = hwoman.get_assignment(hand_first = TRUE)
|
|
else if(issilicon(user))
|
|
name = user.real_name
|
|
rank = "Silicon"
|
|
|
|
// Our account that we want to end up paying with.
|
|
var/datum/bank_account/account
|
|
// Our ID card that we want to pull from for identification. Modifies either name, account, or neither depending on function.
|
|
var/obj/item/card/id/id_card_customer = computer.stored_id?.GetID()
|
|
if(!id_card_customer)
|
|
id_card_customer = hwoman?.get_idcard(TRUE) //Grab from hands/mob if there's no id_card slot to prioritize.
|
|
name = id_card_customer?.registered_account.account_holder
|
|
|
|
if(self_paid)
|
|
if(!istype(id_card_customer))
|
|
computer.say("No ID card detected.")
|
|
return
|
|
if(IS_DEPARTMENTAL_CARD(id_card_customer))
|
|
computer.say("[id_card_customer] cannot be used to make purchases.")
|
|
return
|
|
account = id_card_customer.registered_account
|
|
name = id_card_customer.registered_account.account_holder
|
|
if(!istype(account))
|
|
computer.say("Invalid bank account.")
|
|
return
|
|
|
|
var/reason = ""
|
|
var/datum/bank_account/personal_department
|
|
if((requestonly && !self_paid) || !(computer.stored_id?.GetID()))
|
|
reason = tgui_input_text(user, "Reason", name, max_length = MAX_MESSAGE_LEN)
|
|
if(isnull(reason) || ..())
|
|
return
|
|
|
|
if(id_card_customer?.registered_account?.account_job && !self_paid) //Find a budget to pull from
|
|
personal_department = SSeconomy.get_dep_account(id_card_customer.registered_account.account_job.paycheck_department)
|
|
if(!(personal_department.account_holder == "Cargo Budget"))
|
|
var/dept_choice = tgui_alert(user, "Which department are you requesting this for?", "Choose request department", list("Cargo Budget", "[personal_department.account_holder]"))
|
|
if(!dept_choice)
|
|
return
|
|
if(dept_choice == "Cargo Budget")
|
|
personal_department = null
|
|
|
|
if((pack.order_flags & ORDER_GOODY) && !self_paid)
|
|
playsound(computer, 'sound/machines/buzz/buzz-sigh.ogg', 50, FALSE)
|
|
computer.say("ERROR: Small crates may only be purchased by private accounts.")
|
|
return
|
|
|
|
if(SSshuttle.supply.get_order_count(pack) == OVER_ORDER_LIMIT)
|
|
playsound(computer, 'sound/machines/buzz/buzz-sigh.ogg', 50, FALSE)
|
|
computer.say("ERROR: No more then [CARGO_MAX_ORDER] of any pack may be ordered at once")
|
|
return
|
|
|
|
if(!self_paid)
|
|
account = personal_department
|
|
|
|
var/turf/T = get_turf(computer)
|
|
var/datum/supply_order/SO = new(pack, name, rank, ckey, reason, account)
|
|
SO.generateRequisition(T)
|
|
if((requestonly && !self_paid) || !(computer.stored_id?.GetID()))
|
|
SSshuttle.request_list += SO
|
|
else
|
|
SSshuttle.shopping_list += SO
|
|
if(self_paid)
|
|
computer.say("Order processed. The price will be charged to [account.account_holder]'s bank account on delivery.")
|
|
playsound(computer, 'sound/effects/coin2.ogg', 40, TRUE)
|
|
. = TRUE
|
|
if("remove")
|
|
var/id = text2num(params["id"])
|
|
for(var/datum/supply_order/SO in SSshuttle.shopping_list)
|
|
if(SO.id == id)
|
|
SSshuttle.shopping_list -= SO
|
|
. = TRUE
|
|
break
|
|
if("clear")
|
|
for(var/datum/supply_order/cancelled_order in SSshuttle.shopping_list)
|
|
if(cancelled_order.department_destination || cancelled_order.can_be_cancelled)
|
|
continue //don't cancel other department's orders or orders that can't be cancelled
|
|
SSshuttle.shopping_list -= cancelled_order
|
|
. = TRUE
|
|
if("approve")
|
|
var/id = text2num(params["id"])
|
|
for(var/datum/supply_order/SO in SSshuttle.request_list)
|
|
if(SO.id == id)
|
|
var/obj/item/card/id/id_card = computer.stored_id?.GetID()
|
|
if(id_card && id_card?.registered_account)
|
|
SO.paying_account = SSeconomy.get_dep_account(id_card?.registered_account?.account_job.paycheck_department)
|
|
SSshuttle.request_list -= SO
|
|
SSshuttle.shopping_list += SO
|
|
. = TRUE
|
|
break
|
|
if("deny")
|
|
var/id = text2num(params["id"])
|
|
for(var/datum/supply_order/SO in SSshuttle.request_list)
|
|
if(SO.id == id)
|
|
SSshuttle.request_list -= SO
|
|
. = TRUE
|
|
break
|
|
if("denyall")
|
|
SSshuttle.request_list.Cut()
|
|
. = TRUE
|
|
if("toggleprivate")
|
|
self_paid = !self_paid
|
|
. = TRUE
|
|
if(.)
|
|
post_signal(cargo_shuttle)
|
|
|
|
/datum/computer_file/program/budgetorders/proc/post_signal(command)
|
|
|
|
var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS)
|
|
|
|
if(!frequency)
|
|
return
|
|
|
|
var/datum/signal/status_signal = new(list("command" = command))
|
|
frequency.post_signal(src, status_signal)
|