Cargo can buy more presents at Christmas time (#94251)

## 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.
/🆑
This commit is contained in:
Jacquerel
2025-12-11 15:10:31 +00:00
committed by GitHub
parent 9c430648c6
commit 9fb7c20daa
29 changed files with 190 additions and 119 deletions
+22
View File
@@ -41,6 +41,28 @@
///Used by coupons to define that they're cursed
#define COUPON_OMEN "omen"
// Supply pack flags determining ordering properties
/// Order is literally never visible, presumably it's an abstract type or something
#define ORDER_INVISIBLE (1 << 0)
/// Only orderable on emagged consoles
#define ORDER_EMAG_ONLY (1 << 1)
/// Only orderable on consoles with doctored boards
#define ORDER_CONTRABAND (1 << 2)
/// Can only be ordered privately, can use discount coupons, and arrives in a bag instead of a crate
#define ORDER_GOODY (1 << 3)
/// Can only be ordered via the express order console
#define ORDER_POD_ONLY (1 << 4)
/// Can only be ordered if the following flag is also enabled, for conditionally provided options
#define ORDER_SPECIAL (1 << 5)
/// If present then a special order can be ordered
#define ORDER_SPECIAL_ENABLED (1 << 6)
/// Unavailable to departmental order consoles even if it is in an appropriate category
#define ORDER_NOT_DEPARTMENTAL (1 << 7)
/// This will notify admins when it is purchased
#define ORDER_DANGEROUS (1 << 8)
/// This is set when something is created by an admin to make sure its contents is also marked as such
#define ORDER_ADMIN_SPAWNED (1 << 9)
///Discount categories for coupons. This one is for anything that isn't discountable.
#define SUPPLY_PACK_NOT_DISCOUNTABLE null
///Discount category for the standard stuff, mostly goodies.
@@ -594,7 +594,7 @@
//Let people order more nebula shielding
var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/engineering/rad_nebula_shielding_kit]
pack.special_enabled = TRUE
pack.order_flags |= ORDER_SPECIAL_ENABLED
//Give robotics some radiation protection modules for modsuits
var/datum/supply_pack/supply_pack_modsuits = new /datum/supply_pack/engineering/rad_protection_modules()
+24
View File
@@ -106,6 +106,8 @@
/obj/item/gift/anything
name = "christmas gift"
desc = "It could be anything!"
/// Weak reference to who this gift is for and who can open it, if that's nobody then anyone can
var/datum/weakref/recipient_ref = null
/obj/item/gift/anything/get_gift_type()
var/static/list/obj/item/possible_gifts = null
@@ -115,3 +117,25 @@
var/gift_type = pick(possible_gifts)
return gift_type
/obj/item/gift/anything/attack_self(mob/user)
if (isnull(recipient_ref))
return ..()
var/datum/mind/recipient = recipient_ref.resolve()
if(recipient && recipient != user?.mind)
to_chat(user, span_notice("This gift isn't for you, and you don't want to get on Santa's bad side!"))
return FALSE
return ..()
/// Assign the mind of someone as the person this gift is for
/obj/item/gift/anything/proc/assign_recipient(datum/mind/recipient)
if (ismob(recipient)) // You're presumably at this point because you are an admin who fucked up but I will save you
var/mob/recipient_mob = recipient
recipient = recipient_mob.mind
if (isnull(recipient))
return
name = "[initial(name)] for [recipient.name] ([recipient.assigned_role.title])"
recipient_ref = WEAKREF(recipient)
+1 -1
View File
@@ -99,7 +99,7 @@ ADMIN_VERB(spawn_cargo, R_SPAWN, "Spawn Cargo", "Spawn a cargo crate.", ADMIN_CA
if(!chosen)
return
var/datum/supply_pack/S = new chosen
S.admin_spawned = TRUE
S.order_flags |= ORDER_ADMIN_SPAWNED
S.generate(get_turf(user.mob))
log_admin("[key_name(user)] spawned cargo pack [chosen] at [AREACOORD(user.mob)]")
+1 -1
View File
@@ -72,7 +72,7 @@
/datum/supply_pack/bitrunning
name = "bitrunning order"
hidden = TRUE
order_flags = ORDER_INVISIBLE
crate_name = "bitrunning delivery crate"
access = list(ACCESS_BIT_DEN)
test_ignored = TRUE
+1 -1
View File
@@ -2,7 +2,7 @@
/datum/supply_pack/goody
access = NONE
group = "Goodies"
goody = TRUE
order_flags = ORDER_GOODY
crate_type = null
discountable = SUPPLY_PACK_STD_DISCOUNTABLE
+2 -2
View File
@@ -98,7 +98,7 @@
var/cost = pack.get_cost()
if(applied_coupon) //apply discount price
cost *= (1 - applied_coupon.discount_pct_off)
if(paying_account?.add_to_accounts && !pack.goody) //privately purchased and not a goody means 1.1x the cost
if(paying_account?.add_to_accounts && !(pack.order_flags & ORDER_GOODY)) //privately purchased and not a goody means 1.1x the cost
cost *= 1.1
return round(cost)
@@ -189,7 +189,7 @@
else
account_holder = "Cargo"
var/obj/structure/closet/crate/crate = pack.generate(A, paying_account)
if(pack.contraband)
if(pack.order_flags & ORDER_CONTRABAND)
for(var/atom/movable/item_within as anything in crate.get_all_contents())
ADD_TRAIT(item_within, TRAIT_CONTRABAND, INNATE_TRAIT)
if(department_destination)
+12 -8
View File
@@ -174,14 +174,17 @@
if(pack.group != group)
continue
if(pack.order_flags & ORDER_INVISIBLE)
continue
// Express console packs check
if(express && (pack.hidden || pack.special))
if(express && (pack.order_flags & (ORDER_EMAG_ONLY | ORDER_SPECIAL)))
continue
if(!express && ((pack.hidden && !(obj_flags & EMAGGED)) || (pack.special && !pack.special_enabled) || pack.drop_pod_only))
if(!express && (((pack.order_flags & ORDER_EMAG_ONLY) && !(obj_flags & EMAGGED)) || ((pack.order_flags & ORDER_SPECIAL) && !(pack.order_flags & ORDER_SPECIAL_ENABLED)) || (pack.order_flags & ORDER_POD_ONLY)))
continue
if(pack.contraband && !contraband)
if((pack.order_flags & ORDER_CONTRABAND) && !contraband)
continue
var/obj/item/first_item = length(pack.contains) > 0 ? pack.contains[1] : null
@@ -192,9 +195,9 @@
"desc" = pack.desc || pack.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" = pack.goody,
"goody" = (pack.order_flags & ORDER_GOODY),
"access" = pack.access,
"contraband" = pack.contraband,
"contraband" = (pack.order_flags & ORDER_CONTRABAND),
"contains" = pack.get_contents_ui_data(),
))
@@ -222,7 +225,8 @@
CRASH("Unknown supply pack id given by order console ui. ID: [id]")
if(amount > CARGO_MAX_ORDER || amount < 1) // Holy shit fuck off
CRASH("Invalid amount passed into add_item")
if((pack.hidden && !(obj_flags & EMAGGED)) || (pack.contraband && !contraband) || pack.drop_pod_only || (pack.special && !pack.special_enabled))
if(((pack.order_flags & ORDER_EMAG_ONLY) && !(obj_flags & EMAGGED)) || ((pack.order_flags & ORDER_CONTRABAND) && !contraband) || (pack.order_flags & ORDER_POD_ONLY) || ((pack.order_flags & ORDER_SPECIAL) && !(pack.order_flags & ORDER_SPECIAL_ENABLED)))
return
var/name = "*None Provided*"
@@ -260,7 +264,7 @@
var/list/working_list = SSshuttle.shopping_list
var/reason = ""
var/datum/bank_account/personal_department
if(requestonly && !self_paid && !pack.goody)
if(requestonly && !self_paid && !(pack.order_flags & ORDER_GOODY))
working_list = SSshuttle.request_list
reason = tgui_input_text(user, "Reason", name, max_length = MAX_MESSAGE_LEN)
if(isnull(reason))
@@ -276,7 +280,7 @@
if(dept_choice == "Cargo Budget")
personal_department = null
if(pack.goody && !self_paid)
if((pack.order_flags & ORDER_GOODY) && !self_paid)
playsound(src, 'sound/machines/buzz/buzz-sigh.ogg', 50, FALSE)
say("ERROR: Small crates may only be purchased by private accounts.")
return
+5 -19
View File
@@ -3,10 +3,6 @@
var/name = "Crate"
/// The group that the supply pack is sorted into within the cargo purchasing UI.
var/group = ""
/// Is this cargo supply pack visible to the cargo purchasing UI.
var/hidden = FALSE
/// Is this supply pack purchasable outside of the standard purchasing band? Contraband is available by multitooling the cargo purchasing board.
var/contraband = FALSE
/// Cost of the crate. DO NOT GO ANY LOWER THAN X1.4 the "CARGO_CRATE_VALUE" value if using regular crates, or infinite profit will be possible!
var/cost = CARGO_CRATE_VALUE * 1.4
/// What access is required to open the crate when spawned?
@@ -25,24 +21,14 @@
var/desc = ""
/// What typepath of crate do you spawn?
var/crate_type = /obj/structure/closet/crate
/// Should we message admins?
var/dangerous = FALSE
/// Event/Station Goals/Admin enabled packs
var/special = FALSE
/// When a cargo pack can be unlocked by special events (as seen in special), this toggles if it's been enabled in the round yet (For example, after the station alert, we can now enable buying the station goal pack).
var/special_enabled = FALSE
/// Only usable by the Bluespace Drop Pod via the express cargo console
var/drop_pod_only = FALSE
/// If this pack comes shipped in a specific pod when launched from the express console
var/special_pod
/// Was this spawned through an admin proc?
var/admin_spawned = FALSE
/// Goodies can only be purchased by private accounts and can have coupons apply to them. They also come in a lockbox instead of a full crate, so the crate price min doesn't apply
var/goody = FALSE
/// Can coupons target this pack? If so, how rarely?
var/discountable = SUPPLY_PACK_NOT_DISCOUNTABLE
/// Is this supply pack considered unpredictable for the purposes of testing unit testing? Examples include the stock market, or miner supply crates. If true, exempts from unit testing
var/test_ignored = FALSE
/// Various properties for cargo order mostly used to determine which consoles can see it
var/order_flags = NONE
/datum/supply_pack/New()
id = type
@@ -95,7 +81,7 @@
contains[item] = 1
for(var/iteration = 1 to contains[item])
var/atom/A = new item(C)
if(!admin_spawned)
if(!(order_flags & ORDER_ADMIN_SPAWNED))
continue
A.flags_1 |= ADMIN_SPAWNED_1
@@ -126,7 +112,7 @@
*/
/datum/supply_pack/custom
name = "mining order"
hidden = TRUE
order_flags = ORDER_INVISIBLE
crate_name = "shaft mining delivery crate"
access = ACCESS_MINING
test_ignored = TRUE
@@ -186,6 +172,6 @@
while(sheets_to_spawn)
var/spawn_quantity = min(sheets_to_spawn, MAX_STACK_SIZE)
var/obj/item/stack/sheet/ordered_stack = new possible_stack(C, spawn_quantity)
if(admin_spawned)
if(order_flags & ORDER_ADMIN_SPAWNED)
ordered_stack.flags_1 |= ADMIN_SPAWNED_1
sheets_to_spawn -= spawn_quantity
+38 -2
View File
@@ -74,7 +74,7 @@
name = "Hilarious Firing Pin Crate"
desc = "I uh... I'm not really sure what this does. Wanna buy it?"
cost = CARGO_CRATE_VALUE * 10
contraband = TRUE
order_flags = ORDER_CONTRABAND
contains = list(/obj/item/firing_pin/clown)
crate_name = "toy crate" // It's /technically/ a toy. For the clown, at least.
crate_type = /obj/structure/closet/crate/wooden
@@ -110,7 +110,7 @@
name = "Laser Tag Firing Pins Crate"
desc = "Three laser tag firing pins used in laser-tag units to ensure users are wearing their vests."
cost = CARGO_CRATE_VALUE * 3.5
contraband = TRUE
order_flags = ORDER_CONTRABAND
contains = list(/obj/item/storage/box/lasertagpins)
crate_name = "laser tag crate"
@@ -281,3 +281,39 @@
crate_name = "long balloons kit"
crate_type = /obj/structure/closet/crate/wooden
discountable = SUPPLY_PACK_STD_DISCOUNTABLE
/datum/supply_pack/costumes_toys/christmas
name = "Surplus Christmas Gifts"
desc = "This crate contains pre-wrapped gifts addressed to station employees, sourced at random from Nanotrasen surplus as part of a morale boosting initiative."
cost = CARGO_CRATE_VALUE * 30
contains = list()
order_flags = ORDER_SPECIAL
crate_type = /obj/structure/closet/crate/mail
discountable = SUPPLY_PACK_NOT_DISCOUNTABLE
/datum/supply_pack/costumes_toys/christmas/fill(obj/structure/closet/crate/crate)
var/list/mail_recipients = list()
for(var/mob/living/carbon/human/human in GLOB.player_list)
if(human.stat == DEAD || !human.mind)
continue
// Skip wizards, nuke ops, cyborgs; They're not written down as employees
if(!(human.mind.assigned_role.job_flags & JOB_CREW_MEMBER))
continue
mail_recipients += human.mind
for (var/i in 1 to rand(4, 6))
var/obj/item/gift/anything/gift = new(crate)
var/datum/mind/recipient = pick_n_take(mail_recipients)
if(recipient)
gift.assign_recipient(recipient)
else
qdel(gift)
break
var/obj/item/delivery/big/parcel = new(crate.loc)
parcel.base_icon_state = crate.delivery_icon
parcel.giftwrapped = TRUE
parcel.update_icon()
parcel.drag_slowdown = crate.drag_slowdown
crate.forceMove(parcel)
parcel.name = "christmas gifts"
+8 -8
View File
@@ -160,7 +160,7 @@
devastating feat of human engineering and testament to wartime determination. \
Highly advanced research is required for proper construction."
cost = CARGO_CRATE_VALUE * 30
special = TRUE
order_flags = ORDER_SPECIAL
access_view = ACCESS_COMMAND
contains = list(/obj/item/paper/guides/jobs/engineering/bsa,
/obj/item/circuitboard/machine/bsa/front,
@@ -176,7 +176,7 @@
library of scientific knowledge, capable of granting superhuman powers and abilities. \
Highly advanced research is required for proper construction. Also contains five DNA probes."
cost = CARGO_CRATE_VALUE * 24
special = TRUE
order_flags = ORDER_SPECIAL
access_view = ACCESS_COMMAND
contains = list(/obj/item/circuitboard/machine/dna_vault,
/obj/item/dna_probe = 5,
@@ -187,7 +187,7 @@
name = "DNA Vault Samplers"
desc = "Contains five DNA probes for use in the DNA vault."
cost = CARGO_CRATE_VALUE * 6
special = TRUE
order_flags = ORDER_SPECIAL
access_view = ACCESS_COMMAND
contains = list(/obj/item/dna_probe = 5)
crate_name= "dna samplers crate"
@@ -236,7 +236,7 @@
contains = list(/obj/machinery/power/emitter = 2)
crate_name = "emitter crate"
crate_type = /obj/structure/closet/crate/secure/engineering
dangerous = TRUE
order_flags = ORDER_DANGEROUS
/datum/supply_pack/engine/field_gen
name = "Field Generator Crate"
@@ -276,7 +276,7 @@
contains = list(/obj/machinery/power/supermatter_crystal/shard)
crate_name = "supermatter shard crate"
crate_type = /obj/structure/closet/crate/secure/radiation
dangerous = TRUE
order_flags = ORDER_DANGEROUS
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
/datum/supply_pack/engine/tesla_coils
@@ -302,12 +302,12 @@
)
crate_name = "HFR crate"
crate_type = /obj/structure/closet/crate/secure/engineering/atmos
dangerous = TRUE
order_flags = ORDER_DANGEROUS
/datum/supply_pack/engineering/rad_protection_modules
name = "Radiation Protection Modules"
desc = "Contains multiple radiation protections modules for MODsuits."
hidden = TRUE
order_flags = ORDER_INVISIBLE
contains = list(/obj/item/mod/module/rad_protection = 3)
crate_name = "modsuit radiation modules"
crate_type = /obj/structure/closet/crate/engineering
@@ -317,7 +317,7 @@
desc = "Contains circuitboards and radiation modules for constructing radioactive nebula shielding."
cost = CARGO_CRATE_VALUE * 2
special = TRUE
order_flags = ORDER_SPECIAL
contains = list(
/obj/item/mod/module/rad_protection = 5,
/obj/item/circuitboard/machine/radioactive_nebula_shielding = 5,
+1 -1
View File
@@ -1,7 +1,7 @@
/// Exploration drone unlockables ///
/datum/supply_pack/exploration
special = TRUE
order_flags = ORDER_SPECIAL
group = "Outsourced"
/datum/supply_pack/exploration/scrapyard
+2 -2
View File
@@ -156,7 +156,7 @@
Call today and we'll shoot over a demo unit for just 300 credits!"
cost = CARGO_CRATE_VALUE * 0.6 //Empty pod, so no crate refund
contains = list()
drop_pod_only = TRUE
order_flags = ORDER_POD_ONLY
crate_type = null
special_pod = /obj/structure/closet/supplypod/bluespacepod
@@ -211,7 +211,7 @@
/datum/supply_pack/misc/syndicate
name = "Assorted Syndicate Gear"
desc = "Contains a random assortment of syndicate gear."
special = TRUE //Cannot be ordered via cargo
order_flags = ORDER_SPECIAL //Cannot be ordered via cargo
contains = list()
crate_name = "syndicate gear crate"
crate_type = /obj/structure/closet/crate
+17 -18
View File
@@ -24,7 +24,7 @@
name = "Foam Force Pistols Crate"
desc = "Psst.. hey bud... remember those old foam force pistols that got discontinued for being too cool? \
Well I got two of those right here with your name on em. I'll even throw in a spare mag for each, waddya say?"
contraband = TRUE
order_flags = ORDER_CONTRABAND
cost = CARGO_CRATE_VALUE * 3
contains = list(
/obj/item/gun/ballistic/automatic/pistol/toy = 2,
@@ -56,7 +56,7 @@
desc = "Wait, is this the right crate? It has a frowny face, what does that mean?"
cost = CARGO_CRATE_VALUE * 4
contains = list(/mob/living/basic/spider/giant/hunter)
contraband = TRUE
order_flags = ORDER_CONTRABAND
/datum/supply_pack/imports/bamboo50
name = "50 Bamboo Cuttings"
@@ -125,7 +125,7 @@
name = "NULL_ENTRY"
desc = "(*!&@#OKAY, OPERATIVE, WE SEE HOW MUCH MONEY YOU'RE FLAUNTING. FINE. HAVE THIS, AND GOOD LUCK PUTTING IT TOGETHER!#@*$"
cost = CARGO_CRATE_VALUE * 100
hidden = TRUE
order_flags = ORDER_EMAG_ONLY
contains = list(/obj/item/book/granter/crafting_recipe/regal_condor)
/datum/supply_pack/imports/mafia
@@ -133,7 +133,7 @@
desc = "This crate contains everything you need to set up your own ethnicity-based racketeering operation."
cost = CARGO_CRATE_VALUE * 4
contains = list()
contraband = TRUE
order_flags = ORDER_CONTRABAND
/datum/supply_pack/imports/mafia/fill(obj/structure/closet/crate/our_crate)
for(var/items in 1 to 4)
@@ -148,7 +148,7 @@
name = "'Contraband' Crate"
desc = "Psst.. bud... want some contraband? I can get you a poster, some nice cigs, dank, even some \
sponsored items...you know, the good stuff. Just keep it away from the cops, kay?"
contraband = TRUE
order_flags = ORDER_CONTRABAND
cost = CARGO_CRATE_VALUE * 20
contains = list(
/obj/effect/spawner/random/contraband = 5,
@@ -162,7 +162,7 @@
SMUGGLING THIS CRATE THROUGH A FEW OUTDATED CUSTOMS CHECKPOINTS, WE'VE THE NEXT BEST THING! \
SERVICE AUTORIFLES. DON'T WORRY, THE RUMORS ABOUT THE GUN MELTING YOU ARE JUST THAT! RUMORS! \
THESE THINGS WORK FINE! MIGHT BE SLIGHTLY DIRTY.!#@*$"
hidden = TRUE
order_flags = ORDER_EMAG_ONLY
cost = CARGO_CRATE_VALUE * 7
contains = list(
/obj/item/gun/ballistic/automatic/wt550 = 2,
@@ -173,7 +173,7 @@
/datum/supply_pack/imports/wt550ammo
name = "Smuggled WT-550 Ammo Crate"
desc = "(*!&@#OPERATIVE, YOU LIKE THAT WT-550? THEN WHY NOT EQUIP YOURSELF WITH SOME MORE AMMO!!#@*$"
hidden = TRUE
order_flags = ORDER_EMAG_ONLY
cost = CARGO_CRATE_VALUE * 4
contains = list(
/obj/item/ammo_box/magazine/wt550m9 = 2,
@@ -187,7 +187,7 @@
name = "Shocktrooper Crate"
desc = "(*!&@#WANT TO PUT THE FEAR OF DEATH INTO YOUR ENEMIES? THIS CRATE OF GOODIES CAN HELP MAKE THAT A REALITY. \
CONTAINS AN ARMOR VEST AND HELMET, A BOX OF FIVE EMP GRENADES, THREE SMOKEBOMBS, TWO GLUON GRENADES AND TWO FRAG GRENADES!#@*$"
hidden = TRUE
order_flags = ORDER_EMAG_ONLY
cost = CARGO_CRATE_VALUE * 10
contains = list(
/obj/item/storage/box/emps,
@@ -203,7 +203,7 @@
name = "Special Ops Crate"
desc = "(*!&@#THE PIGS ON YOUR TAIL? MAYBE YOU CAN BUY SOME TIME WITH THIS CRATE! \
CONTAINS A CHAMELEON MASK, BELT AND JUMPSUIT, MIRAGE GRENADES AND AN AGENT CARD! AND A KNIFE!!#@*$"
hidden = TRUE
order_flags = ORDER_EMAG_ONLY
cost = CARGO_CRATE_VALUE * 10
contains = list(
/obj/item/clothing/mask/chameleon,
@@ -220,7 +220,7 @@
desc = "Hello <;~insert appropriate greeting here: 'Comrade'|'Imperalist Scum'|'Quartermaster of Reputable Station'~;>, \
we have the most modern russian military equipment the black market can offer, for the right price of course. \
No lock, best price."
contraband = TRUE
order_flags = ORDER_CONTRABAND
cost = CARGO_CRATE_VALUE * 12
contains = list(
/obj/item/food/rationpack,
@@ -252,7 +252,7 @@
Then we have the perfect weapon for you! Special price for good friends! \
We don't have enough spare ammo, so you'll have to pick up the weapon of \
dead comrade when you run out."
hidden = TRUE
order_flags = ORDER_EMAG_ONLY
cost = CARGO_CRATE_VALUE * 6
contains = list(/obj/item/gun/ballistic/rifle/boltaction = 6)
@@ -261,7 +261,7 @@
desc = "TUNNEL SNAKES OWN THIS TOWN. Contains an unbranded All Terrain Vehicle, and a \
complete gang outfit -- consists of black gloves, a menacing skull bandanna, and a SWEET leather overcoat!"
cost = CARGO_CRATE_VALUE * 4
contraband = TRUE
order_flags = ORDER_CONTRABAND
contains = list(
/obj/vehicle/ridden/atv,
/obj/item/key/atv,
@@ -280,8 +280,7 @@
contains = list()
crate_type = /obj/structure/closet/crate/secure/loot
crate_name = "abandoned crate"
contraband = TRUE
dangerous = TRUE //these are literally bombs so....
order_flags = ORDER_CONTRABAND | ORDER_DANGEROUS //these are literally bombs so....
discountable = SUPPLY_PACK_RARE_DISCOUNTABLE
/datum/supply_pack/imports/shambler_evil
@@ -290,7 +289,7 @@
cost = CARGO_CRATE_VALUE * 50
contains = list(/obj/item/reagent_containers/cup/soda_cans/shamblers/eldritch = 1)
crate_name = "illegal shambler's juice crate"
contraband = TRUE
order_flags = ORDER_CONTRABAND
/datum/supply_pack/imports/hide
name = "Animal Hide Crate"
@@ -312,7 +311,7 @@
name = "Big Slappy parts"
desc = "Illegal Big Slappy parts. The fastest and statistically most dangerous wrench."
cost = CARGO_CRATE_VALUE * 22
contraband = TRUE
order_flags = ORDER_CONTRABAND
contains = list(/obj/item/weaponcrafting/giant_wrench)
crate_name = "unknown parts crate"
@@ -337,7 +336,7 @@
espionage uniform used by the very best. Providing the best \
flexibility, with our latest Camo-tech threads. Perfect for \
risky espionage hallway operations. Enjoy our product!"
contraband = TRUE
order_flags = ORDER_CONTRABAND
cost = CARGO_CRATE_VALUE * 6
contains = list(
/obj/item/clothing/under/syndicate/floortilecamo = 3,
@@ -359,7 +358,7 @@
station? Fear not, the Long-To-Short-Range-Bluespace-Transceiver (LTSRBT for short) \
is here to help. Contains a LTSRBT circuit, two bluespace crystals, and one ansible."
cost = CARGO_CRATE_VALUE * 10
contraband = TRUE
order_flags = ORDER_CONTRABAND
contains = list(
/obj/item/circuitboard/machine/ltsrbt,
/obj/item/stack/ore/bluespace_crystal/artificial = 2,
+3 -3
View File
@@ -17,7 +17,7 @@
/datum/supply_pack/critter/butterfly
name = "Butterflies Crate"
desc = "Not a very dangerous insect, but they do give off a better image than, say, flies or cockroaches."//is that a motherfucking worm reference
contraband = TRUE
order_flags = ORDER_CONTRABAND
cost = CARGO_CRATE_VALUE * 5
contains = list(/mob/living/basic/butterfly)
crate_name = "entomology samples crate"
@@ -113,7 +113,7 @@
cost = CARGO_CRATE_VALUE * 8
contains = list(/mob/living/basic/crab)
crate_name = "look sir free crabs"
drop_pod_only = TRUE
order_flags = ORDER_POD_ONLY
/datum/supply_pack/critter/crab/generate()
. = ..()
@@ -218,7 +218,7 @@
/datum/supply_pack/critter/garden_gnome
name = "Garden Gnome Crate"
desc = "Collect them all for your garden. Comes with three!"
hidden = TRUE
order_flags = ORDER_EMAG_ONLY
cost = CARGO_CRATE_VALUE * 15
contains = list(/mob/living/basic/garden_gnome)
crate_name = "garden gnome crate"
+1 -1
View File
@@ -176,7 +176,7 @@
)
crate_name = "virus crate"
crate_type = /obj/structure/closet/crate/secure/plasma
dangerous = TRUE
order_flags = ORDER_DANGEROUS
/datum/supply_pack/medical/cmoturtlenecks
name = "Chief Medical Officer Turtlenecks"
+2 -2
View File
@@ -139,7 +139,7 @@
cost = CARGO_CRATE_VALUE * 12
contains = list(/obj/item/storage/backpack/duffelbag/clown/cream_pie)
crate_name = "party equipment crate"
contraband = TRUE
order_flags = ORDER_CONTRABAND
access = ACCESS_THEATRE
access_view = ACCESS_THEATRE
crate_type = /obj/structure/closet/crate/secure
@@ -360,7 +360,7 @@
crate_type = /obj/structure/closet/crate/cardboard
/datum/supply_pack/organic/syrup_contraband
contraband = TRUE
order_flags = ORDER_CONTRABAND
name = "Contraband Syrups Box"
desc = "A packaged box containing illegal coffee syrups. Possession of these carries a penalty established in the galactic penal code."
cost = CARGO_CRATE_VALUE * 6
+1 -1
View File
@@ -155,7 +155,7 @@
contains = list(/obj/item/transfer_valve = 2)
crate_name = "tank transfer valves crate"
crate_type = /obj/structure/closet/crate/secure/science
dangerous = TRUE
order_flags = ORDER_DANGEROUS
/datum/supply_pack/science/monkey_helmets
name = "Monkey Mind Magnification Helmet crate"
+3 -3
View File
@@ -144,7 +144,7 @@
The Alpha and the Omega of security headwear. Guaranteed to strike fear into the hearts \
of each and every criminal aboard the station. Also comes with a security gasmask."
cost = CARGO_CRATE_VALUE * 6 //justice comes at a price. An expensive, noisy price.
contraband = TRUE
order_flags = ORDER_CONTRABAND
contains = list(/obj/item/clothing/head/helmet/toggleable/justice,
/obj/item/clothing/mask/gas/sechailer,
)
@@ -171,7 +171,7 @@
desc = "Spare equipment found in a warehouse. Contains a constable's outfit, \
whistle, and conversion kit."
cost = CARGO_CRATE_VALUE * 2.2
contraband = TRUE
order_flags = ORDER_CONTRABAND
contains = list(/obj/item/clothing/under/rank/security/constable,
/obj/item/clothing/head/costume/constable,
/obj/item/clothing/gloves/color/white,
@@ -308,7 +308,7 @@
)
crate_name = "incendiary weapons crate"
crate_type = /obj/structure/closet/crate/secure/plasma
dangerous = TRUE
order_flags = ORDER_DANGEROUS
/datum/supply_pack/security/armory/mindshield
name = "Mindshield Implants Crate"
+1 -1
View File
@@ -713,7 +713,7 @@
var/datum/supply_order/SO = single_order
if (SO.pack.crate_type)
SO.generate(pod)
else if (SO.pack.goody) //Goody orders lack a crate_type and need special handling
else if (SO.pack.order_flags & ORDER_GOODY) //Goody orders lack a crate_type and need special handling
SO.generateCombo(pod, SO.orderer, SO.pack.contains, SO.pack.cost)
else if (istype(single_order, /atom/movable))
var/atom/movable/O = single_order
+1 -1
View File
@@ -64,7 +64,7 @@
stray_spawnable_supply_packs = SSshuttle.supply_packs.Copy()
for(var/pack in stray_spawnable_supply_packs)
var/datum/supply_pack/pack_type = pack
if(initial(pack_type.special))
if(initial(pack_type.order_flags) & ORDER_SPECIAL)
stray_spawnable_supply_packs -= pack
///Spawns a random supply pack, puts it in a pod, and spawns it on a random tile of the selected area
+3 -3
View File
@@ -45,7 +45,7 @@ GLOBAL_LIST_INIT(adventure_loot_generator_index,generate_generator_index())
var/list/still_locked_packs = list()
for(var/pack_type in unlockable_packs)
var/datum/supply_pack/pack_singleton = SSshuttle.supply_packs[pack_type]
if(!pack_singleton.special_enabled)
if(!(pack_singleton.order_flags & ORDER_SPECIAL_ENABLED))
still_locked_packs += pack_type
if(!length(still_locked_packs)) // Just give out some cash instead.
var/datum/adventure_loot_generator/simple/cash/replacement = new
@@ -133,10 +133,10 @@ GLOBAL_LIST_INIT(adventure_loot_generator_index,generate_generator_index())
/obj/item/trade_chip/proc/try_to_unlock_contract(mob/user)
var/datum/supply_pack/pack_singleton = SSshuttle.supply_packs[unlocked_pack_type]
if(!unlocked_pack_type || !pack_singleton || !pack_singleton.special)
if(!unlocked_pack_type || !pack_singleton || !(pack_singleton.order_flags & ORDER_SPECIAL))
to_chat(user,span_danger("This chip is invalid!"))
return
pack_singleton.special_enabled = TRUE
pack_singleton.order_flags |= ORDER_SPECIAL_ENABLED
to_chat(user,span_notice("Contract accepted into nanotrasen supply database."))
qdel(src)
+21 -21
View File
@@ -876,6 +876,27 @@ GLOBAL_LIST_INIT(holiday_mail, list())
/datum/holiday/xmas/greet()
return "Have a merry Christmas!"
/datum/holiday/xmas/celebrate()
. = ..()
SSticker.OnRoundstart(CALLBACK(src, PROC_REF(roundstart_celebrate)))
GLOB.maintenance_loot += list(
list(
/obj/item/clothing/head/costume/santa = 1,
/obj/item/gift/anything = 1,
/obj/item/toy/xmas_cracker = 3,
) = maint_holiday_weight,
)
/datum/holiday/xmas/proc/roundstart_celebrate()
for(var/obj/machinery/computer/security/telescreen/entertainment/Monitor as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/computer/security/telescreen/entertainment))
Monitor.icon_state_on = "entertainment_xmas"
for(var/mob/living/basic/pet/dog/corgi/ian/Ian in GLOB.mob_living_list)
Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian))
var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/costumes_toys/christmas]
pack.order_flags |= ORDER_SPECIAL_ENABLED
/datum/holiday/boxing
name = "Boxing Day"
begin_day = 26
@@ -984,27 +1005,6 @@ GLOBAL_LIST_INIT(holiday_mail, list())
/datum/holiday/hebrew/passover/getStationPrefix()
return pick("Matzah", "Moses", "Red Sea")
// HOLIDAY ADDONS
/datum/holiday/xmas/celebrate()
. = ..()
SSticker.OnRoundstart(CALLBACK(src, PROC_REF(roundstart_celebrate)))
GLOB.maintenance_loot += list(
list(
/obj/item/clothing/head/costume/santa = 1,
/obj/item/gift/anything = 1,
/obj/item/toy/xmas_cracker = 3,
) = maint_holiday_weight,
)
/datum/holiday/xmas/proc/roundstart_celebrate()
for(var/obj/machinery/computer/security/telescreen/entertainment/Monitor as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/computer/security/telescreen/entertainment))
Monitor.icon_state_on = "entertainment_xmas"
for(var/mob/living/basic/pet/dog/corgi/ian/Ian in GLOB.mob_living_list)
Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian))
// EASTER (this having its own spot should be understandable)
/datum/holiday/easter
@@ -89,14 +89,16 @@
data["supplies"] = list()
for(var/pack in SSshuttle.supply_packs)
var/datum/supply_pack/P = SSshuttle.supply_packs[pack]
if(!is_visible_pack(user, P.access_view , null, P.contraband) || P.hidden)
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.hidden && (P.contraband && !contraband) || (P.special && !P.special_enabled) || P.drop_pod_only))
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
@@ -107,7 +109,7 @@
"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.goody,
"goody" = P.order_flags & ORDER_GOODY,
"access" = P.access,
"contains" = P.get_contents_ui_data(),
))
@@ -216,7 +218,7 @@
var/datum/supply_pack/pack = SSshuttle.supply_packs[id]
if(!istype(pack))
return
if(pack.hidden || pack.contraband || pack.drop_pod_only || (pack.special && !pack.special_enabled))
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*"
@@ -267,7 +269,7 @@
if(dept_choice == "Cargo Budget")
personal_department = null
if(pack.goody && !self_paid)
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
@@ -105,13 +105,11 @@ GLOBAL_VAR(department_cd_override)
/// Checks if we can "see" the passed supply pack
/datum/computer_file/program/department_order/proc/can_see_pack(datum/supply_pack/to_check)
PROTECTED_PROC(TRUE)
if(to_check.hidden && !(computer.obj_flags & EMAGGED))
if((to_check.order_flags & ORDER_EMAG_ONLY) && !(computer.obj_flags & EMAGGED))
return FALSE
if(to_check.special && !to_check.special_enabled)
if((to_check.order_flags & ORDER_SPECIAL) && !(to_check.order_flags & ORDER_SPECIAL_ENABLED))
return FALSE
if(to_check.drop_pod_only)
return FALSE
if(to_check.goody)
if(to_check.order_flags & (ORDER_INVISIBLE | ORDER_POD_ONLY | ORDER_GOODY | ORDER_NOT_DEPARTMENTAL))
return FALSE
return TRUE
@@ -192,7 +192,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
if(spawning_order.paying_account) //Someone paid out of pocket
paying_for_this = spawning_order.paying_account
// 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
if(spawning_order.pack.goody)
if(spawning_order.pack.order_flags & ORDER_GOODY)
var/list/current_buyer_orders = goodies_by_buyer[spawning_order.paying_account]
if(LAZYLEN(current_buyer_orders) == GOODY_FREE_SHIPPING_MAX)
price = round(price + CRATE_TAX)
@@ -212,7 +212,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
pack_cost = spawning_order.pack.get_cost()
if(spawning_order.paying_account)
paying_for_this = spawning_order.paying_account
if(spawning_order.pack.goody)
if(spawning_order.pack.order_flags & ORDER_GOODY)
LAZYADD(goodies_by_buyer[spawning_order.paying_account], spawning_order)
var/receiver_message = "Cargo order #[spawning_order.id] has shipped."
if(spawning_order.charge_on_purchase)
@@ -223,7 +223,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
cargo.adjust_money(price - pack_cost) //Cargo gets the handling fee
value += pack_cost
if(!spawning_order.pack.goody) //we handle goody crates below
if(!(spawning_order.pack.order_flags & ORDER_GOODY)) //we handle goody crates below
var/obj/structure/closet/crate = spawning_order.generate(pick_n_take(empty_turfs))
crate.name += " - #[spawning_order.id]"
@@ -231,7 +231,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
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)
if(spawning_order.pack.order_flags & ORDER_DANGEROUS)
message_admins("\A [spawning_order.pack.name] ordered by [ADMIN_LOOKUPFLW(spawning_order.orderer_ckey)], paid by [from_whom] has shipped.")
purchases++
+1 -1
View File
@@ -21,7 +21,7 @@ GLOBAL_VAR_INIT(bsa_unlock, FALSE)
/datum/station_goal/bluespace_cannon/on_report()
//Unlock BSA parts
var/datum/supply_pack/engineering/bsa/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/bsa]
P.special_enabled = TRUE
P.order_flags |= ORDER_SPECIAL_ENABLED
/datum/station_goal/bluespace_cannon/check_completion()
if(..())
+2 -2
View File
@@ -47,10 +47,10 @@
/datum/station_goal/dna_vault/on_report()
var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/dna_vault]
P.special_enabled = TRUE
P.order_flags |= ORDER_SPECIAL_ENABLED
P = SSshuttle.supply_packs[/datum/supply_pack/engineering/dna_probes]
P.special_enabled = TRUE
P.order_flags |= ORDER_SPECIAL_ENABLED
/datum/station_goal/dna_vault/check_completion()
if(..())
+2 -2
View File
@@ -30,10 +30,10 @@
/datum/station_goal/station_shield/on_report()
//Unlock
var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shield_sat]
P.special_enabled = TRUE
P.order_flags |= ORDER_SPECIAL_ENABLED
P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shield_sat_control]
P.special_enabled = TRUE
P.order_flags |= ORDER_SPECIAL_ENABLED
/datum/station_goal/station_shield/check_completion()
if(..())