mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-18 21:15:21 +00:00
## About The Pull Request This is a followup on my previous PR involving cargo imports. I've made a number of changes and new additions to cargo's imports and contraband. But I've also changed how Smuggler's Satchels generate loot as well. ### New: **Abandoned Crates:** You can now order in abandoned crates at a steep price. Obviously these are just your standard fare abandoned crates, so they've got a pretty long list of potential contents. Some great, some utterly not worth the price you paid for the crate. Since they're quite pricey, you can't order very many quickly. But this does allow cargo techs the opportunity to spend the round solving puzzles to get interesting loot. **Dumpster of Maint Garbage:** This dumpster (similarly named to another dumpster you can order) is filled with maint trash and potential maint random spawns. This list is extensive enough that anything spawned in this crate is likely to be mostly garbage. But, it is more affordable than abandoned crates. I'd consider this the literally trashier version of the abandoned crate. **Shamber's Juice Eldritch Energy! Crate:** A crate with one can of the extremely rare, short run edition of Shambler's Juice, Eldritch Energy! This contains 5 units of eldritch essence. Heals heretics, hurts everyone else! This is a VERY potent poison, but it also happens to be a handy way for a Cargonian heretic to get a potent healing item without having to waste knowledge points. **Animal Hide Crate:** It's a cargo crate full of animal hides! This can include fairly rare hides and some icebox creature hides as well, like polar bear hides and wolf sinew. It's not too expensive, and mostly spits out leather. **Dreadnog Carton Crate:** A carton full of the worst eggnog imaginable. This is just something to troll people with. Drink it and you'll get a massive mood penalty. Dreadnog! May or may not contain space cola! ### Updated: **Contraband Crate and Smuggler's Satchels:** This has had it's price increased considerably. But, for good reason. It now contains some more controlled random items, but also some more valuable contraband as well as a very rare spawn. The upper end on his contraband can be extremely valuable, but the majority of the items gained from contraband crates will probably be either what you can get now (quite weak), or something a bit more middle of the road (some more unique narcotics). As a consequence, I've also passed this change onto smuggler's satchels, as they used the crate to generate its contents. (it literally spawned and then deleted a contraband crate to generate the contents hoo haa). I've also increased the number of items in the smuggler's satchel. Since the randomly spawned smuggler's satchels are quite a bit rarer now there is only ever two spawned in the map, and spending actual TC on these is somewhat counterproductive, I don't imagine this will be more beneficial for scavenger hunters hoping for some interesting goodies. **Russian Crate (the normal one):** The mosins now spawn in ancient gun cases. These determine what kind of mosin you can get. 79% of the time, you get the crap mosin. 20% of the time, you get a good mosin. And 1% of the time, you get rations. This more tightly controls how many good mosins are entering into the round and how much of a value purchase the Russian crate actually is for getting ballistics. Since the process is even more unlikely than before, it isn't necessarily as guaranteed that you will get a good mosin. Hell, you might not even get a gun if you're that unlucky. **Shocktrooper Crate:** It now has an armor vest and helmet. So, not only do you get some grenades, you get some protection as well. Since this is the 'loud' crate, I felt it appropriate to make it slightly more useful for enabling that. **Special Ops Crate:** It now contains five mirage grenades and a chameleon belt, and has had the survival knife improved to a switchblade. This is probably the weakest of the two crates STILL, but hopefully these make them a little more interesting and novel by giving them pretty fun grenade to toy with. ## Why It's Good For The Game My initial PR hoped to add in a few more interesting purchases for cargo. I think currently cargo has a slight issue of not having enough valuable or interesting uses for their money. I think it still has that problem, but by including more unique crates that allow cargo to provide some oddities into the round, that might slowly work itself out. This PR hopes to provide another way to waste their money if they have an excess amount. Landfill Trash Gambling. Spending it away on complete junk, which I think is absolutely hilarious when it doesn't work out, as it is soulful in its design. Definitely not inspired by my recent thrift shop excursions this month buying and scrounging for furniture and interesting clothing. [Relevant](https://www.youtube.com/watch?v=QK8mJJJvaes) Also, I wanted to buff some of the crates I introduced a bit last time, and nerf the mosin production somewhat via a more controllable method that I can actually adjust as necessary down the line. ## Changelog 🆑 fix: Stops manifest generation runtiming when a cargo crate is empty. add: Abandoned crates are now available via cargo imports. add: Dumpsters full of maintenance trash are now available via cargo imports. add: An ultra-rare can of Shambler's Juice is now available via cargo imports. add: Animal hides and leathers can be (unreliably) ordered via cargo imports. add: The Dreadnog has entered this realm. To consume, purchase it via cargo imports. balance: Contraband Crates (and as a consequence, smuggler's satchels) now generate more varied goods. Mostly the same, but sometimes you get something quite different or even valuable. balance: Mosins generated via the Russian supply crate are a bit more random, weighing more heavily towards bad mosins than good mosins. balance: Buffed both the shocktrooper and special op crate. Shocktrooper now has an armored helmet and vest, and special op now has 5 mirage grenades and a chameleon belt. The survival knife in the special op crate is now a switchblade. /🆑
195 lines
7.0 KiB
Plaintext
195 lines
7.0 KiB
Plaintext
/// The chance for a manifest or crate to be created with errors
|
|
#define MANIFEST_ERROR_CHANCE 5
|
|
|
|
// MANIFEST BITFLAGS
|
|
/// Determines if the station name will be incorrect on the manifest
|
|
#define MANIFEST_ERROR_NAME (1 << 0)
|
|
/// Determines if contents will be deleted from the manifest but still be present in the crate
|
|
#define MANIFEST_ERROR_CONTENTS (1 << 1)
|
|
/// Determines if contents will be deleted from the crate but still be present in the manifest
|
|
#define MANIFEST_ERROR_ITEM (1 << 2)
|
|
|
|
/obj/item/paper/fluff/jobs/cargo/manifest
|
|
var/order_cost = 0
|
|
var/order_id = 0
|
|
var/errors = 0
|
|
|
|
/obj/item/paper/fluff/jobs/cargo/manifest/Initialize(mapload, id, cost, manifest_can_fail = TRUE)
|
|
. = ..()
|
|
order_id = id
|
|
order_cost = cost
|
|
if(!manifest_can_fail)
|
|
return
|
|
|
|
if(prob(MANIFEST_ERROR_CHANCE))
|
|
errors |= MANIFEST_ERROR_NAME
|
|
investigate_log("Supply order #[order_id] generated a manifest with an incorrect station name.", INVESTIGATE_CARGO)
|
|
if(prob(MANIFEST_ERROR_CHANCE))
|
|
errors |= MANIFEST_ERROR_CONTENTS
|
|
investigate_log("Supply order #[order_id] generated a manifest missing listed contents.", INVESTIGATE_CARGO)
|
|
if(prob(MANIFEST_ERROR_CHANCE))
|
|
errors |= MANIFEST_ERROR_ITEM
|
|
investigate_log("Supply order #[order_id] generated with incorrect contents shipped.", INVESTIGATE_CARGO)
|
|
|
|
/obj/item/paper/fluff/jobs/cargo/manifest/proc/is_approved()
|
|
return LAZYLEN(stamp_cache) && !is_denied()
|
|
|
|
/obj/item/paper/fluff/jobs/cargo/manifest/proc/is_denied()
|
|
return LAZYLEN(stamp_cache) && ("stamp-deny" in stamp_cache)
|
|
|
|
/datum/supply_order
|
|
var/id
|
|
var/cost_type
|
|
var/orderer
|
|
var/orderer_rank
|
|
var/orderer_ckey
|
|
var/reason
|
|
var/discounted_pct
|
|
///If set to FALSE, we won't charge when the cargo shuttle arrives with this.
|
|
var/charge_on_purchase = TRUE
|
|
///area this order wants to reach, if not null then it will come with the deliver_first component set to this area
|
|
var/department_destination
|
|
var/datum/supply_pack/pack
|
|
var/datum/bank_account/paying_account
|
|
var/obj/item/coupon/applied_coupon
|
|
///Boolean on whether the manifest can fail or not.
|
|
var/manifest_can_fail = TRUE
|
|
///Boolean on whether the manifest can be cancelled through cargo consoles.
|
|
var/can_be_cancelled = TRUE
|
|
|
|
/datum/supply_order/New(
|
|
datum/supply_pack/pack,
|
|
orderer,
|
|
orderer_rank,
|
|
orderer_ckey,
|
|
reason,
|
|
paying_account,
|
|
department_destination,
|
|
coupon,
|
|
charge_on_purchase = TRUE,
|
|
manifest_can_fail = TRUE,
|
|
cost_type = "cr",
|
|
can_be_cancelled = TRUE,
|
|
)
|
|
id = SSshuttle.order_number++
|
|
src.cost_type = cost_type
|
|
src.pack = pack
|
|
src.orderer = orderer
|
|
src.orderer_rank = orderer_rank
|
|
src.orderer_ckey = orderer_ckey
|
|
src.reason = reason
|
|
src.paying_account = paying_account
|
|
src.department_destination = department_destination
|
|
src.applied_coupon = coupon
|
|
src.charge_on_purchase = charge_on_purchase
|
|
src.manifest_can_fail = manifest_can_fail
|
|
src.can_be_cancelled = can_be_cancelled
|
|
|
|
//returns the total cost of this order. Its not the total price paid by cargo but the total value of this order
|
|
/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.1
|
|
return cost
|
|
|
|
/datum/supply_order/proc/generateRequisition(turf/T)
|
|
var/obj/item/paper/requisition_paper = new(T)
|
|
|
|
requisition_paper.name = "requisition form - #[id] ([pack.name])"
|
|
var/requisition_text = "<h2>[station_name()] Supply Requisition</h2>"
|
|
requisition_text += "<hr/>"
|
|
requisition_text += "Order #[id]<br/>"
|
|
requisition_text+= "Time of Order: [station_time_timestamp()]<br/>"
|
|
requisition_text += "Item: [pack.name]<br/>"
|
|
requisition_text += "Access Restrictions: [SSid_access.get_access_desc(pack.access)]<br/>"
|
|
requisition_text += "Requested by: [orderer]<br/>"
|
|
if(paying_account)
|
|
requisition_text += "Paid by: [paying_account.account_holder]<br/>"
|
|
requisition_text += "Rank: [orderer_rank]<br/>"
|
|
requisition_text += "Comment: [reason]<br/>"
|
|
|
|
requisition_paper.add_raw_text(requisition_text)
|
|
requisition_paper.update_appearance()
|
|
return requisition_paper
|
|
|
|
/datum/supply_order/proc/generateManifest(obj/container, owner, packname, cost) //generates-the-manifests.
|
|
var/obj/item/paper/fluff/jobs/cargo/manifest/manifest_paper = new(null, id, cost, manifest_can_fail)
|
|
|
|
var/station_name = (manifest_paper.errors & MANIFEST_ERROR_NAME) ? new_station_name() : station_name()
|
|
|
|
manifest_paper.name = "shipping manifest - [packname?"#[id] ([pack.name])":"(Grouped Item Crate)"]"
|
|
|
|
var/manifest_text = "<h2>[command_name()] Shipping Manifest</h2>"
|
|
manifest_text += "<hr/>"
|
|
if(owner && !(owner == "Cargo"))
|
|
manifest_text += "Direct purchase from [owner]<br/>"
|
|
manifest_paper.name += " - Purchased by [owner]"
|
|
manifest_text += "Order[packname?"":"s"]: [id]<br/>"
|
|
manifest_text += "Destination: [station_name]<br/>"
|
|
if(packname)
|
|
manifest_text += "Item: [packname]<br/>"
|
|
manifest_text += "Contents: <br/>"
|
|
manifest_text += "<ul>"
|
|
var/container_contents = list() // Associative list with the format (item_name = nº of occurences, ...)
|
|
for(var/atom/movable/AM in container.contents - manifest_paper)
|
|
container_contents[AM.name]++
|
|
if((manifest_paper.errors & MANIFEST_ERROR_CONTENTS) && container_contents)
|
|
for(var/i = 1 to rand(1, round(container.contents.len * 0.5))) // Remove anywhere from one to half of the items
|
|
var/missing_item = pick(container_contents)
|
|
container_contents[missing_item]--
|
|
if(container_contents[missing_item] == 0) // To avoid 0s and negative values on the manifest
|
|
container_contents -= missing_item
|
|
|
|
for(var/item in container_contents)
|
|
manifest_text += "<li> [container_contents[item]] [item][container_contents[item] == 1 ? "" : "s"]</li>"
|
|
manifest_text += "</ul>"
|
|
manifest_text += "<h4>Stamp below to confirm receipt of goods:</h4>"
|
|
|
|
manifest_paper.add_raw_text(manifest_text)
|
|
|
|
if(manifest_paper.errors & MANIFEST_ERROR_ITEM)
|
|
if(HAS_TRAIT(container, TRAIT_NO_MISSING_ITEM_ERROR))
|
|
manifest_paper.errors &= ~MANIFEST_ERROR_ITEM
|
|
else
|
|
var/lost = max(round(container.contents.len / 10), 1)
|
|
while(--lost >= 0)
|
|
qdel(pick(container.contents))
|
|
|
|
|
|
manifest_paper.update_appearance()
|
|
manifest_paper.forceMove(container)
|
|
|
|
if(istype(container, /obj/structure/closet/crate))
|
|
var/obj/structure/closet/crate/C = container
|
|
C.manifest = manifest_paper
|
|
C.update_appearance()
|
|
else
|
|
container.contents += manifest_paper
|
|
|
|
return manifest_paper
|
|
|
|
/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/crate = pack.generate(A, paying_account)
|
|
if(department_destination)
|
|
crate.AddElement(/datum/element/deliver_first, department_destination, pack.cost)
|
|
generateManifest(crate, account_holder, pack, pack.cost)
|
|
return crate
|
|
|
|
/datum/supply_order/proc/generateCombo(miscbox, misc_own, misc_contents, misc_cost)
|
|
for (var/I in misc_contents)
|
|
new I(miscbox)
|
|
generateManifest(miscbox, misc_own, "", misc_cost)
|
|
return
|
|
|
|
#undef MANIFEST_ERROR_CHANCE
|
|
#undef MANIFEST_ERROR_NAME
|
|
#undef MANIFEST_ERROR_CONTENTS
|
|
#undef MANIFEST_ERROR_ITEM
|