mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-26 01:22:03 +00:00
* Minor improvements to mining order console * merge * Mining orders can no longer error and don't say they charge you (#71676) - Mining orders now show the amount of mining points spent as the 'Cost' instead of a flat 240 credits - Mining orders now no longer have errors (including nothing being in the crate at all) because they can't be sent back for a full refund. - Mining orders no longer say they charged you if they haven't. Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Co-authored-by: Tastyfish <crazychris32@gmail.com>
307 lines
13 KiB
Plaintext
307 lines
13 KiB
Plaintext
GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
|
|
/mob/living,
|
|
/obj/structure/blob,
|
|
/obj/effect/rune,
|
|
/obj/structure/spider/spiderling,
|
|
/obj/item/disk/nuclear,
|
|
/obj/machinery/nuclearbomb,
|
|
/obj/item/beacon,
|
|
/obj/narsie,
|
|
/obj/tear_in_reality,
|
|
/obj/machinery/teleport/station,
|
|
/obj/machinery/teleport/hub,
|
|
/obj/machinery/quantumpad,
|
|
/obj/effect/mob_spawn,
|
|
/obj/effect/hierophant,
|
|
/obj/structure/receiving_pad,
|
|
/obj/item/warp_cube,
|
|
/obj/machinery/rnd/production, //print tracking beacons, send shuttle
|
|
/obj/machinery/autolathe, //same
|
|
/obj/projectile/beam/wormhole,
|
|
/obj/effect/portal,
|
|
/obj/item/shared_storage,
|
|
/obj/structure/extraction_point,
|
|
/obj/machinery/syndicatebomb,
|
|
/obj/item/hilbertshotel,
|
|
/obj/item/swapper,
|
|
/obj/docking_port,
|
|
/obj/machinery/launchpad,
|
|
/obj/machinery/disposal,
|
|
/obj/structure/disposalpipe,
|
|
/obj/item/mail,
|
|
/obj/machinery/camera,
|
|
/obj/item/gps,
|
|
/obj/structure/checkoutmachine,
|
|
/obj/machinery/fax
|
|
)))
|
|
|
|
/// How many goody orders we can fit in a lockbox before we upgrade to a crate
|
|
#define GOODY_FREE_SHIPPING_MAX 5
|
|
/// How much to charge oversized goody orders
|
|
#define CRATE_TAX 700
|
|
|
|
/obj/docking_port/mobile/supply
|
|
name = "supply shuttle"
|
|
shuttle_id = "cargo"
|
|
callTime = 600
|
|
|
|
dir = WEST
|
|
port_direction = EAST
|
|
movement_force = list("KNOCKDOWN" = 0, "THROW" = 0)
|
|
|
|
//Export categories for this run, this is set by console sending the shuttle.
|
|
var/export_categories = EXPORT_CARGO
|
|
|
|
/obj/docking_port/mobile/supply/register()
|
|
. = ..()
|
|
SSshuttle.supply = src
|
|
|
|
/obj/docking_port/mobile/supply/canMove()
|
|
if(is_station_level(z))
|
|
return check_blacklist(shuttle_areas)
|
|
return ..()
|
|
|
|
/obj/docking_port/mobile/supply/proc/check_blacklist(areaInstances)
|
|
for(var/place in areaInstances)
|
|
var/area/shuttle/shuttle_area = place
|
|
for(var/turf/shuttle_turf in shuttle_area)
|
|
for(var/atom/passenger in shuttle_turf.get_all_contents())
|
|
if((is_type_in_typecache(passenger, GLOB.blacklisted_cargo_types) || HAS_TRAIT(passenger, TRAIT_BANNED_FROM_CARGO_SHUTTLE)) && !istype(passenger, /obj/docking_port))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/obj/docking_port/mobile/supply/request(obj/docking_port/stationary/S)
|
|
if(mode != SHUTTLE_IDLE)
|
|
return 2
|
|
return ..()
|
|
|
|
/obj/docking_port/mobile/supply/initiate_docking()
|
|
if(getDockedId() == "cargo_away") // Buy when we leave home.
|
|
buy()
|
|
create_mail()
|
|
. = ..() // Fly/enter transit.
|
|
if(. != DOCKING_SUCCESS)
|
|
return
|
|
if(getDockedId() == "cargo_away") // Sell when we get home
|
|
sell()
|
|
|
|
/obj/docking_port/mobile/supply/proc/buy()
|
|
SEND_SIGNAL(SSshuttle, COMSIG_SUPPLY_SHUTTLE_BUY)
|
|
var/list/obj/miscboxes = list() //miscboxes are combo boxes that contain all goody orders grouped
|
|
var/list/misc_order_num = list() //list of strings of order numbers, so that the manifest can show all orders in a box
|
|
var/list/misc_contents = list() //list of lists of items that each box will contain
|
|
var/list/misc_costs = list() //list of overall costs sustained by each buyer.
|
|
|
|
var/list/empty_turfs = list()
|
|
for(var/area/shuttle/shuttle_area as anything in shuttle_areas)
|
|
for(var/turf/open/floor/T in shuttle_area)
|
|
if(T.is_blocked_turf())
|
|
continue
|
|
empty_turfs += T
|
|
|
|
//quickly and greedily handle chef's grocery runs first, there are a few reasons why this isn't attached to the rest of cargo...
|
|
//but the biggest reason is that the chef requires produce to cook and do their job, and if they are using this system they
|
|
//already got let down by the botanists. So to open a new chance for cargo to also screw them over any more than is necessary is bad.
|
|
if(SSshuttle.chef_groceries.len)
|
|
var/obj/structure/closet/crate/freezer/grocery_crate = new(pick_n_take(empty_turfs))
|
|
grocery_crate.name = "kitchen produce freezer"
|
|
investigate_log("Chef's [SSshuttle.chef_groceries.len] sized produce order arrived. Cost was deducted from orderer, not cargo.", INVESTIGATE_CARGO)
|
|
for(var/datum/orderable_item/item as anything in SSshuttle.chef_groceries)//every order
|
|
for(var/amt in 1 to SSshuttle.chef_groceries[item])//every order amount
|
|
new item.item_path(grocery_crate)
|
|
SSshuttle.chef_groceries.Cut() //This lets the console know it can order another round.
|
|
|
|
if(!SSshuttle.shopping_list.len)
|
|
return
|
|
|
|
var/value = 0
|
|
var/purchases = 0
|
|
var/list/goodies_by_buyer = list() // if someone orders more than GOODY_FREE_SHIPPING_MAX goodies, we upcharge to a normal crate so they can't carry around 20 combat shotties
|
|
var/list/forced_briefcases = list() //SKYRAT EDIT
|
|
|
|
for(var/datum/supply_order/spawning_order in SSshuttle.shopping_list)
|
|
if(!empty_turfs.len)
|
|
break
|
|
var/price = spawning_order.pack.get_cost()
|
|
if(spawning_order.applied_coupon)
|
|
price *= (1 - spawning_order.applied_coupon.discount_pct_off)
|
|
|
|
var/datum/bank_account/paying_for_this
|
|
|
|
//department orders EARN money for cargo, not the other way around
|
|
//Skyrat Edit Add
|
|
if(!spawning_order.department_destination && spawning_order.charge_on_purchase)
|
|
//Skyrat Edit End
|
|
if(spawning_order.paying_account) //Someone paid out of pocket
|
|
paying_for_this = spawning_order.paying_account
|
|
var/list/current_buyer_orders = goodies_by_buyer[spawning_order.paying_account] // so we can access the length a few lines down
|
|
if(!spawning_order.pack.goody)
|
|
price *= 1.1 //TODO make this customizable by the quartermaster
|
|
|
|
// note this is before we increment, so this is the GOODY_FREE_SHIPPING_MAX + 1th goody to ship. also note we only increment off this step if they successfully pay the fee, so there's no way around it
|
|
else if(LAZYLEN(current_buyer_orders) == GOODY_FREE_SHIPPING_MAX)
|
|
price += CRATE_TAX
|
|
paying_for_this.bank_card_talk("Goody order size exceeds free shipping limit: Assessing [CRATE_TAX] credit S&H fee.")
|
|
else
|
|
paying_for_this = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
|
if(paying_for_this)
|
|
if(!paying_for_this.adjust_money(-price, "Cargo: [spawning_order.pack.name]"))
|
|
if(spawning_order.paying_account)
|
|
paying_for_this.bank_card_talk("Cargo order #[spawning_order.id] rejected due to lack of funds. Credits required: [price]")
|
|
continue
|
|
//Skyrat Edit Add
|
|
if(spawning_order.paying_account && spawning_order.charge_on_purchase)
|
|
//Skyrat Edit End
|
|
paying_for_this = spawning_order.paying_account
|
|
if(spawning_order.pack.goody)
|
|
LAZYADD(goodies_by_buyer[spawning_order.paying_account], spawning_order)
|
|
var/reciever_message = "Cargo order #[spawning_order.id] has shipped."
|
|
if(spawning_order.charge_on_purchase)
|
|
reciever_message += " [price] credits have been charged to your bank account"
|
|
paying_for_this.bank_card_talk(reciever_message)
|
|
SSeconomy.track_purchase(paying_for_this, price, spawning_order.pack.name)
|
|
var/datum/bank_account/department/cargo = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
|
cargo.adjust_money(price - spawning_order.pack.get_cost()) //Cargo gets the handling fee
|
|
value += spawning_order.pack.get_cost()
|
|
SSshuttle.shopping_list -= spawning_order
|
|
SSshuttle.order_history += spawning_order
|
|
QDEL_NULL(spawning_order.applied_coupon)
|
|
|
|
spawning_order.on_spawn() //SKYRAT EDIT
|
|
if(!spawning_order.pack.goody && !(spawning_order?.paying_account in forced_briefcases)) //we handle goody crates below //SKYRAT EDIT
|
|
spawning_order.generate(pick_n_take(empty_turfs))
|
|
|
|
SSblackbox.record_feedback("nested tally", "cargo_imports", 1, list("[spawning_order.pack.get_cost()]", "[spawning_order.pack.name]"))
|
|
|
|
var/from_whom = paying_for_this?.account_holder || "nobody (department order)"
|
|
|
|
investigate_log("Order #[spawning_order.id] ([spawning_order.pack.name], placed by [key_name(spawning_order.orderer_ckey)]), paid by [from_whom] has shipped.", INVESTIGATE_CARGO)
|
|
if(spawning_order.pack.dangerous)
|
|
message_admins("\A [spawning_order.pack.name] ordered by [ADMIN_LOOKUPFLW(spawning_order.orderer_ckey)], paid by [from_whom] has shipped.")
|
|
purchases++
|
|
|
|
// we handle packing all the goodies last, since the type of crate we use depends on how many goodies they ordered. If it's more than GOODY_FREE_SHIPPING_MAX
|
|
// then we send it in a crate (including the CRATE_TAX cost), otherwise send it in a free shipping case
|
|
for(var/D in goodies_by_buyer)
|
|
var/list/buying_account_orders = goodies_by_buyer[D]
|
|
var/datum/bank_account/buying_account = D
|
|
var/buyer = buying_account.account_holder
|
|
|
|
if(buying_account_orders.len > GOODY_FREE_SHIPPING_MAX) // no free shipping, send a crate
|
|
var/obj/structure/closet/crate/secure/owned/our_crate = new /obj/structure/closet/crate/secure/owned(pick_n_take(empty_turfs))
|
|
our_crate.buyer_account = buying_account
|
|
our_crate.name = "goody crate - purchased by [buyer]"
|
|
miscboxes[buyer] = our_crate
|
|
else //free shipping in a case
|
|
miscboxes[buyer] = new /obj/item/storage/lockbox/order(pick_n_take(empty_turfs))
|
|
var/obj/item/storage/lockbox/order/our_case = miscboxes[buyer]
|
|
our_case.buyer_account = buying_account
|
|
miscboxes[buyer].name = "goody case - purchased by [buyer]"
|
|
misc_contents[buyer] = list()
|
|
|
|
for(var/datum/supply_order/our_order as anything in buying_account_orders)
|
|
for (var/item in our_order.pack.contains)
|
|
misc_contents[buyer] += item
|
|
misc_costs[buyer] += our_order.pack.cost
|
|
misc_order_num[buyer] = "[misc_order_num[buyer]]#[our_order.id] "
|
|
//SKYRAT EDIT START
|
|
for(var/briefcase_order in forced_briefcases)
|
|
var/list/buying_account_orders = forced_briefcases[briefcase_order]
|
|
var/datum/bank_account/buying_account = briefcase_order
|
|
var/buyer = buying_account.account_holder
|
|
var/buying_acc_order_num = length(buying_account_orders)
|
|
for(var/datum/supply_order/company_import/the_order in buying_account_orders)
|
|
if(!the_order.item_amount || (the_order.item_amount == 1))
|
|
continue
|
|
buying_acc_order_num += the_order.item_amount - 1
|
|
|
|
if(buying_acc_order_num > 2) // no free shipping, send a crate
|
|
var/obj/structure/closet/crate/secure/owned/our_crate = new /obj/structure/closet/crate/secure/owned(pick_n_take(empty_turfs))
|
|
our_crate.buyer_account = buying_account
|
|
our_crate.name = "special import crate - purchased by [buyer]"
|
|
miscboxes[buyer] = our_crate
|
|
else //free shipping in a case
|
|
miscboxes[buyer] = new /obj/item/storage/lockbox/order(pick_n_take(empty_turfs))
|
|
var/obj/item/storage/lockbox/order/our_case = miscboxes[buyer]
|
|
our_case.buyer_account = buying_account
|
|
if(istype(our_case.buyer_account, /datum/bank_account/department))
|
|
our_case.department_purchase = TRUE
|
|
our_case.department_account = our_case.buyer_account
|
|
miscboxes[buyer].name = "special import case - purchased by [buyer]"
|
|
misc_contents[buyer] = list()
|
|
|
|
for(var/datum/supply_order/order in buying_account_orders)
|
|
for (var/item in order.pack.contains)
|
|
misc_contents[buyer] += item
|
|
misc_costs[buyer] += order.pack.cost
|
|
misc_order_num[buyer] = "[misc_order_num[buyer]]#[order.id] "
|
|
//SKYRAT EDIT END
|
|
|
|
for(var/I in miscboxes)
|
|
var/datum/supply_order/SO = new/datum/supply_order()
|
|
SO.id = misc_order_num[I]
|
|
SO.generateCombo(miscboxes[I], I, misc_contents[I], misc_costs[I])
|
|
qdel(SO)
|
|
|
|
SSeconomy.import_total += value
|
|
var/datum/bank_account/cargo_budget = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
|
investigate_log("[purchases] orders in this shipment, worth [value] credits. [cargo_budget.account_balance] credits left.", INVESTIGATE_CARGO)
|
|
|
|
/obj/docking_port/mobile/supply/proc/sell()
|
|
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
|
|
var/presale_points = D.account_balance
|
|
|
|
if(!GLOB.exports_list.len) // No exports list? Generate it!
|
|
setupExports()
|
|
|
|
var/msg = ""
|
|
|
|
var/datum/export_report/ex = new
|
|
|
|
for(var/area/shuttle/shuttle_area as anything in shuttle_areas)
|
|
for(var/atom/movable/AM in shuttle_area)
|
|
if(iscameramob(AM))
|
|
continue
|
|
if(AM.anchored)
|
|
continue
|
|
export_item_and_contents(AM, export_categories, dry_run = FALSE, external_report = ex)
|
|
|
|
if(ex.exported_atoms)
|
|
ex.exported_atoms += "." //ugh
|
|
|
|
for(var/datum/export/E in ex.total_amount)
|
|
var/export_text = E.total_printout(ex)
|
|
if(!export_text)
|
|
continue
|
|
|
|
msg += export_text + "\n"
|
|
D.adjust_money(ex.total_value[E])
|
|
|
|
SSeconomy.export_total += (D.account_balance - presale_points)
|
|
SSshuttle.centcom_message = msg
|
|
investigate_log("contents sold for [D.account_balance - presale_points] credits. Contents: [ex.exported_atoms ? ex.exported_atoms.Join(",") + "." : "none."] Message: [SSshuttle.centcom_message || "none."]", INVESTIGATE_CARGO)
|
|
|
|
/*
|
|
Generates a box of mail depending on our exports and imports.
|
|
Applied in the cargo shuttle sending/arriving, by building the crate if the round is ready to introduce mail based on the economy subsystem.
|
|
Then, fills the mail crate with mail, by picking applicable crew who can recieve mail at the time to sending.
|
|
*/
|
|
/obj/docking_port/mobile/supply/proc/create_mail()
|
|
//Early return if there's no mail waiting to prevent taking up a slot. We also don't send mails on sundays or holidays.
|
|
if(!SSeconomy.mail_waiting || SSeconomy.mail_blocked)
|
|
return
|
|
|
|
//spawn crate
|
|
var/list/empty_turfs = list()
|
|
for(var/place as anything in shuttle_areas)
|
|
var/area/shuttle/shuttle_area = place
|
|
for(var/turf/open/floor/shuttle_floor in shuttle_area)
|
|
if(shuttle_floor.is_blocked_turf())
|
|
continue
|
|
empty_turfs += shuttle_floor
|
|
|
|
new /obj/structure/closet/crate/mail/economy(pick(empty_turfs))
|
|
|
|
#undef GOODY_FREE_SHIPPING_MAX
|
|
#undef CRATE_TAX
|