Merge pull request #14489 from LetterN/amogus

Fixes NIRM
This commit is contained in:
Lin
2021-03-22 15:37:56 -05:00
committed by GitHub
4 changed files with 98 additions and 47 deletions
@@ -80,16 +80,25 @@
name = "private crate"
desc = "A crate cover designed to only open for who purchased its contents."
icon_state = "privatecrate"
///Account of the person buying the crate if private purchasing.
var/datum/bank_account/buyer_account
///Department of the person buying the crate if buying via the NIRN app.
var/datum/bank_account/department/department_account
///Is the secure crate opened or closed?
var/privacy_lock = TRUE
///Is the crate being bought by a person, or a budget card?
var/department_purchase = FALSE
/obj/structure/closet/crate/secure/owned/examine(mob/user)
. = ..()
to_chat(user, "<span class='notice'>It's locked with a privacy lock, and can only be unlocked by the buyer's ID.</span>")
. += "<span class='notice'>It's locked with a privacy lock, and can only be unlocked by the buyer's ID.</span>"
/obj/structure/closet/crate/secure/owned/Initialize(mapload, datum/bank_account/_buyer_account)
. = ..()
buyer_account = _buyer_account
if(istype(buyer_account, /datum/bank_account/department))
department_purchase = TRUE
department_account = buyer_account
/obj/structure/closet/crate/secure/owned/togglelock(mob/living/user, silent)
if(privacy_lock)
@@ -97,7 +106,7 @@
var/obj/item/card/id/id_card = user.get_idcard(TRUE)
if(id_card)
if(id_card.registered_account)
if(id_card.registered_account == buyer_account)
if(id_card.registered_account == buyer_account || (department_purchase && (id_card.registered_account?.account_job?.paycheck_department) == (department_account.department_id)))
if(iscarbon(user))
add_fingerprint(user)
locked = !locked
+20 -8
View File
@@ -16,7 +16,7 @@
errors |= MANIFEST_ERROR_ITEM
/obj/item/paper/fluff/jobs/cargo/manifest/proc/is_approved()
return stamped && stamped.len && !is_denied()
return stamped?.len && !is_denied()
/obj/item/paper/fluff/jobs/cargo/manifest/proc/is_denied()
return stamped && ("stamp-deny" in stamped)
@@ -49,6 +49,7 @@
P.info += "<h2>[station_name()] Supply Requisition</h2>"
P.info += "<hr/>"
P.info += "Order #[id]<br/>"
P.info += "Time of Order: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]<br/>"
P.info += "Item: [pack.name]<br/>"
P.info += "Access Restrictions: [get_access_desc(pack.access)]<br/>"
P.info += "Requested by: [orderer]<br/>"
@@ -68,10 +69,10 @@
P.name = "shipping manifest - [packname?"#[id] ([pack.name])":"(Grouped Item Crate)"]"
P.info += "<h2>[command_name()] Shipping Manifest</h2>"
P.info += "<hr/>"
if(id && !(id == "Cargo"))
if(owner && !(owner == "Cargo"))
P.info += "Direct purchase from [owner]<br/>"
P.name += " - Purchased by [owner]"
P.info += "Order #[id]<br/>"
P.info += "Order[packname?"":"s"]: [id]<br/>"
P.info += "Destination: [station_name]<br/>"
if(packname)
P.info += "Item: [packname]<br/>"
@@ -82,8 +83,11 @@
var/obj/structure/closet/C = container
ignore_this += C.lockerelectronics
for(var/atom/movable/AM in container.contents - ignore_this)
if((P.errors & MANIFEST_ERROR_CONTENTS) && prob(50))
continue
if((P.errors & MANIFEST_ERROR_CONTENTS))
if(prob(50))
P.info += "<li>[AM.name]</li>"
else
continue
P.info += "<li>[AM.name]</li>"
P.info += "</ul>"
P.info += "<h4>Stamp below to confirm receipt of goods:</h4>"
@@ -94,7 +98,7 @@
/obj/structure/closet/crate/large,
/obj/structure/closet/secure_closet/goodies
))
if(blacklisted_error[container.type])
if(is_type_in_list(container, blacklisted_error))
P.errors &= ~MANIFEST_ERROR_ITEM
else
var/lost = max(round(container.contents.len / 10), 1)
@@ -108,15 +112,23 @@
var/obj/structure/closet/crate/C = container
C.manifest = P
C.update_icon()
else
// manifest goes in if it's not a crate
container.contents += P
return P
/datum/supply_order/proc/generate(atom/A)
var/account_holder
if(paying_account)
account_holder = paying_account.account_holder
else
account_holder = "Cargo"
var/obj/structure/closet/crate/C = pack.generate(A, paying_account)
generateManifest(C, paying_account, pack)
generateManifest(C, account_holder, pack)
return C
/datum/supply_order/proc/generateCombo(var/miscbox, var/misc_own, var/misc_contents)
/datum/supply_order/proc/generateCombo(miscbox, misc_own, misc_contents)
for (var/I in misc_contents)
new I(miscbox)
generateManifest(miscbox, misc_own, "")
@@ -1,8 +1,9 @@
/datum/computer_file/program/budgetorders
filename = "orderapp"
filedesc = "Nanotrasen Internal Requisition Network (NIRN)"
filedesc = "NT IRN"
// category = PROGRAM_CATEGORY_SUPL
program_icon_state = "request"
extended_desc = "A request network that utilizes the Nanotrasen Ordering network to purchase supplies using a department budget account."
extended_desc = "Nanotrasen Internal Requisition Network interface for supply purchasing using a department budget account."
requires_ntnet = TRUE
transfer_access = ACCESS_HEADS
usage_flags = PROGRAM_LAPTOP | PROGRAM_TABLET
@@ -79,7 +80,6 @@
data["supplies"] = list()
for(var/pack in SSshuttle.supply_packs)
var/datum/supply_pack/P = SSshuttle.supply_packs[pack]
// todo: replace to P.access_view
if(!is_visible_pack(usr, P.access , null, P.contraband) || P.hidden)
continue
if(!data["supplies"][P.group])
@@ -105,7 +105,7 @@
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_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."
+63 -33
View File
@@ -25,7 +25,14 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
/obj/item/shared_storage,
/obj/structure/extraction_point,
/obj/machinery/syndicatebomb,
/obj/item/hilbertshotel
/obj/item/hilbertshotel,
/obj/machinery/launchpad,
/obj/machinery/disposal,
/obj/structure/disposalpipe,
/obj/item/hilbertshotel,
/obj/machinery/camera,
/obj/item/gps,
/obj/structure/checkoutmachine
)))
GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
@@ -33,6 +40,11 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
/mob/living/simple_animal/slaughter
)))
/// 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"
id = "supply"
@@ -58,6 +70,7 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
return check_blacklist(shuttle_areas, GLOB.blacklisted_cargo_types - GLOB.cargo_shuttle_leave_behind_typecache)
return ..()
// fuc off
/obj/docking_port/mobile/supply/enterTransit()
var/list/leave_behind = list()
for(var/i in check_blacklist(shuttle_areas, GLOB.cargo_shuttle_leave_behind_typecache))
@@ -98,12 +111,11 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
sell()
/obj/docking_port/mobile/supply/proc/buy()
if(!SSshuttle.shoppinglist.len)
return
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
if(!SSshuttle.shoppinglist.len)
return
var/list/empty_turfs = list()
for(var/place in shuttle_areas)
@@ -113,30 +125,39 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
continue
empty_turfs += T
var/datum/bank_account/cargo_budget = SSeconomy.get_dep_account(ACCOUNT_CAR)
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
for(var/datum/supply_order/SO in SSshuttle.shoppinglist)
if(!empty_turfs.len)
break
var/price = SO.pack.cost
if(SO.applied_coupon)
price *= (1 - SO.applied_coupon.discount_pct_off)
var/datum/bank_account/D
if(SO.paying_account) //Someone paid out of pocket
D = SO.paying_account
var/list/current_buyer_orders = goodies_by_buyer[SO.paying_account] // so we can access the length a few lines down
if(!SO.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
D.bank_card_talk("Goody order size exceeds free shipping limit: Assessing [CRATE_TAX] credit S&H fee.")
else
D = cargo_budget
D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
if(!D.adjust_money(-SO.pack.cost))
if(!D.adjust_money(-price))
if(SO.paying_account)
D.bank_card_talk("Cargo order #[SO.id] rejected due to lack of funds. Credits required: [price]")
continue
if(SO.paying_account)
if(SO.pack.goody)
LAZYADD(goodies_by_buyer[SO.paying_account], SO)
D.bank_card_talk("Cargo order #[SO.id] has shipped. [price] credits have been charged to your bank account.")
var/datum/bank_account/department/cargo = SSeconomy.get_dep_account(ACCOUNT_CAR)
cargo.adjust_money(price - SO.pack.cost) //Cargo gets the handling fee
@@ -145,30 +166,7 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
SSshuttle.orderhistory += SO
QDEL_NULL(SO.applied_coupon)
if(SO.pack.goody) //goody means it gets piled in the miscbox
if(SO.paying_account)
if(!miscboxes.len || !miscboxes[D.account_holder]) //if there's no miscbox for this person
miscboxes[D.account_holder] = new /obj/item/storage/lockbox/order(pick_n_take(empty_turfs))
var/obj/item/storage/lockbox/order/our_box = miscboxes[D.account_holder]
our_box.buyer_account = SO.paying_account
miscboxes[D.account_holder].name = "small items case - purchased by [D.account_holder]"
misc_contents[D.account_holder] = list()
for (var/item in SO.pack.contains)
misc_contents[D.account_holder] += item
misc_order_num[D.account_holder] = "[misc_order_num[D.account_holder]]#[SO.id] "
else //No private payment, so we just stuff it all into a generic crate
if(!miscboxes.len || !miscboxes["Cargo"])
miscboxes["Cargo"] = new /obj/structure/closet/secure_closet/goodies(pick_n_take(empty_turfs))
miscboxes["Cargo"].name = "small items closet"
misc_contents["Cargo"] = list()
miscboxes["Cargo"].req_access = list()
for (var/item in SO.pack.contains)
misc_contents["Cargo"] += item
//new item(miscboxes["Cargo"])
if(SO.pack.access)
miscboxes["Cargo"].req_access += SO.pack.access
misc_order_num["Cargo"] = "[misc_order_num["Cargo"]]#[SO.id] "
else
if(!SO.pack.goody) //we handle goody crates below
SO.generate(pick_n_take(empty_turfs))
SSblackbox.record_feedback("nested tally", "cargo_imports", 1, list("[SO.pack.cost]", "[SO.pack.name]"))
@@ -177,16 +175,43 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
message_admins("\A [SO.pack.name] ordered by [ADMIN_LOOKUPFLW(SO.orderer_ckey)], paid by [D.account_holder] 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/O in buying_account_orders)
var/datum/supply_order/our_order = O
for (var/item in our_order.pack.contains)
misc_contents[buyer] += item
misc_order_num[buyer] = "[misc_order_num[buyer]]#[our_order.id] "
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])
qdel(SO)
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
var/gain = 0
if(!GLOB.exports_list.len) // No exports list? Generate it!
@@ -204,6 +229,8 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
continue
if(bounty_ship_item_and_contents(AM, dry_run = FALSE))
matched_bounty = TRUE
// ignore mech checks because the mech is ONLY for bounty
continue
if(!AM.anchored || istype(AM, /obj/mecha))
export_item_and_contents(AM, export_categories , dry_run = FALSE, external_report = ex)
@@ -230,4 +257,7 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list(
msg = copytext_char(msg, 1, MAX_MESSAGE_LEN)
SSshuttle.centcom_message = msg
investigate_log("Shuttle contents sold for [gain] credits. Contents: [ex.exported_atoms || "none."] Message: [SSshuttle.centcom_message || "none."]", INVESTIGATE_CARGO)
investigate_log("Shuttle 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)
#undef GOODY_FREE_SHIPPING_MAX
#undef CRATE_TAX