diff --git a/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm b/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm
index 2ce78a09a71..193c1938477 100644
--- a/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm
+++ b/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm
@@ -3162,9 +3162,9 @@
/turf/open/floor/iron/dark,
/area/service/hydroponics)
"rN" = (
-/obj/structure/closet/crate/freezer,
/obj/machinery/power/apc/auto_name/east,
/obj/structure/cable,
+/obj/structure/closet/crate/secure/freezer/pizza,
/turf/open/floor/iron,
/area/cargo/warehouse)
"rS" = (
diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm
index a6f64518d82..2d3b9865d2d 100644
--- a/code/__HELPERS/_lists.dm
+++ b/code/__HELPERS/_lists.dm
@@ -203,6 +203,7 @@
//2. Gets a number between 1 and that total
//3. For each element in the list, subtracts its weighting from that number
//4. If that makes the number 0 or less, return that element.
+//Will output null sometimes if you use decimals (e.g. 0.1 instead of 10) as rand() uses integers, not floats
/proc/pickweight(list/L)
var/total = 0
var/item
diff --git a/code/game/objects/items/food/pizza.dm b/code/game/objects/items/food/pizza.dm
index 537faaa292e..6072923b769 100644
--- a/code/game/objects/items/food/pizza.dm
+++ b/code/game/objects/items/food/pizza.dm
@@ -8,6 +8,8 @@
foodtypes = GRAIN | DAIRY | VEGETABLES
/// type is spawned 6 at a time and replaces this pizza when processed by cutting tool
var/obj/item/food/pizzaslice/slice_type
+ ///What label pizza boxes use if this pizza spawns in them.
+ var/boxtag = ""
/obj/item/food/pizza/MakeProcessable()
if (slice_type)
@@ -35,9 +37,9 @@
icon_state = "pizzamargherita"
food_reagents = list(/datum/reagent/consumable/nutriment = 25, /datum/reagent/consumable/nutriment/protein = 8, /datum/reagent/consumable/tomatojuice = 6, /datum/reagent/consumable/nutriment/vitamin = 5)
tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1)
- tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1)
foodtypes = GRAIN | VEGETABLES | DAIRY
slice_type = /obj/item/food/pizzaslice/margherita
+ boxtag = "Margherita Deluxe"
/obj/item/food/pizza/margherita/robo
food_reagents = list(/datum/reagent/nanomachines = 70, /datum/reagent/consumable/nutriment = 25, /datum/reagent/consumable/nutriment/protein = 8, /datum/reagent/consumable/tomatojuice = 6, /datum/reagent/consumable/nutriment/vitamin = 5)
@@ -60,6 +62,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 25, /datum/reagent/consumable/nutriment/protein = 8, /datum/reagent/consumable/tomatojuice = 6, /datum/reagent/consumable/nutriment/vitamin = 8)
foodtypes = GRAIN | VEGETABLES| DAIRY | MEAT
slice_type = /obj/item/food/pizzaslice/meat
+ boxtag = "Meatlovers' Supreme"
/obj/item/food/pizzaslice/meat
name = "meatpizza slice"
@@ -77,6 +80,7 @@
tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "mushroom" = 1)
foodtypes = GRAIN | VEGETABLES | DAIRY
slice_type = /obj/item/food/pizzaslice/mushroom
+ boxtag = "Mushroom Special"
/obj/item/food/pizzaslice/mushroom
name = "mushroom pizza slice"
@@ -94,6 +98,7 @@
tastes = list("crust" = 1, "tomato" = 2, "cheese" = 1, "carrot" = 1)
foodtypes = GRAIN | VEGETABLES | DAIRY
slice_type = /obj/item/food/pizzaslice/vegetable
+ boxtag = "Gourmet Vegetable"
/obj/item/food/pizzaslice/vegetable
name = "vegetable pizza slice"
@@ -111,6 +116,7 @@
tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "meat" = 1, "laziness" = 1)
foodtypes = GRAIN | VEGETABLES | DAIRY | MEAT | JUNKFOOD
slice_type = /obj/item/food/pizzaslice/donkpocket
+ boxtag = "Bangin' Donk"
/obj/item/food/pizzaslice/donkpocket
name = "donkpocket pizza slice"
@@ -128,6 +134,7 @@
tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "meat" = 1)
foodtypes = GRAIN | VEGETABLES | DAIRY
slice_type = /obj/item/food/pizzaslice/dank
+ boxtag = "Fresh Herb"
/obj/item/food/pizzaslice/dank
name = "dank pizza slice"
@@ -139,12 +146,13 @@
/obj/item/food/pizza/sassysage
name = "sassysage pizza"
- desc = "You can really smell the sassiness."
+ desc = "You can almost taste the sassiness."
icon_state = "sassysagepizza"
food_reagents = list(/datum/reagent/consumable/nutriment = 20, /datum/reagent/consumable/nutriment/protein = 15, /datum/reagent/consumable/tomatojuice = 6, /datum/reagent/consumable/nutriment/vitamin = 6)
tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "meat" = 1)
foodtypes = GRAIN | VEGETABLES | DAIRY
slice_type = /obj/item/food/pizzaslice/sassysage
+ boxtag = "Sausage Lovers"
/obj/item/food/pizzaslice/sassysage
name = "sassysage pizza slice"
@@ -162,6 +170,7 @@
tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "pineapple" = 2, "ham" = 2)
foodtypes = GRAIN | VEGETABLES | DAIRY | MEAT | FRUIT | PINEAPPLE
slice_type = /obj/item/food/pizzaslice/pineapple
+ boxtag = "Honolulu Chew"
/obj/item/food/pizzaslice/pineapple
name = "\improper Hawaiian pizza slice"
@@ -195,6 +204,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 25, /datum/reagent/consumable/nutriment/protein = 9, /datum/reagent/consumable/nutriment/vitamin = 6, /datum/reagent/iron = 10, /datum/reagent/medicine/omnizine = 30)
tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "pepperoni" = 2, "9 millimeter bullets" = 2)
slice_type = /obj/item/food/pizzaslice/arnold
+ boxtag = "9mm Pepperoni"
//fuck it, i will leave this at the food level for now.
/obj/item/food/proc/try_break_off(mob/living/M, mob/living/user) //maybe i give you a pizza maybe i break off your arm
diff --git a/code/game/objects/structures/crates_lockers/crates/secure.dm b/code/game/objects/structures/crates_lockers/crates/secure.dm
index d12b5944c45..82439bb13a4 100644
--- a/code/game/objects/structures/crates_lockers/crates/secure.dm
+++ b/code/game/objects/structures/crates_lockers/crates/secure.dm
@@ -54,6 +54,21 @@
name = "secure hydroponics crate"
icon_state = "hydrosecurecrate"
+/obj/structure/closet/crate/secure/freezer //for consistency with other "freezer" closets/crates
+ desc = "An insulated crate with a lock on it, used to secure perishables."
+ name = "secure kitchen crate"
+ icon_state = "kitchen_secure_crate"
+
+/obj/structure/closet/crate/secure/freezer/pizza
+ name = "secure pizza crate"
+ desc = "An insulated crate with a lock on it, used to secure pizza."
+ req_access = list(28)
+ tamperproof = 10
+
+/obj/structure/closet/crate/secure/freezer/pizza/PopulateContents()
+ . = ..()
+ new /obj/effect/spawner/lootdrop/pizzaparty(src)
+
/obj/structure/closet/crate/secure/engineering
desc = "A crate with a lock on it, painted in the scheme of the station's engineers."
name = "secure engineering crate"
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index 0a5d4ec5c66..b1a8e307c0a 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -1801,7 +1801,8 @@
/datum/supply_pack/organic/pizza
name = "Pizza Crate"
- desc = "Best prices on this side of the galaxy. All deliveries are guaranteed to be 99% anomaly-free!"
+ desc = "Why visit the kitchen when you can have five random pizzas in a fraction of the time? \
+ Best prices this side of the galaxy! All deliveries are guaranteed to be 99% anomaly-free."
cost = CARGO_CRATE_VALUE * 10 // Best prices this side of the galaxy.
contains = list(/obj/item/pizzabox/margherita,
/obj/item/pizzabox/mushroom,
@@ -1809,15 +1810,37 @@
/obj/item/pizzabox/vegetable,
/obj/item/pizzabox/pineapple)
crate_name = "pizza crate"
+ ///Whether we've provided an infinite pizza box already this shift or not.
var/static/anomalous_box_provided = FALSE
+ ///The percentage chance (per pizza) of this supply pack to spawn an anomalous pizza box.
+ var/anna_molly_box_chance = 1
+ ///Total tickets in our figurative lottery (per pizza) to decide if we create a bomb box, and if so what type. 1 to 3 create a bomb. The rest do nothing.
+ var/boombox_tickets = 100
+ ///Whether we've provided a bomb pizza box already this shift or not.
+ var/boombox_provided = FALSE
/datum/supply_pack/organic/pizza/fill(obj/structure/closet/crate/C)
. = ..()
- if(!anomalous_box_provided)
- for(var/obj/item/pizzabox/P in C)
- if(prob(1)) //1% chance for each box, so 4% total chance per order
+
+ var/list/pizza_types = list(
+ /obj/item/food/pizza/margherita = 10,
+ /obj/item/food/pizza/meat = 10,
+ /obj/item/food/pizza/mushroom = 10,
+ /obj/item/food/pizza/vegetable = 10,
+ /obj/item/food/pizza/donkpocket = 10,
+ /obj/item/food/pizza/dank = 7,
+ /obj/item/food/pizza/sassysage = 10,
+ /obj/item/food/pizza/pineapple = 10,
+ /obj/item/food/pizza/arnold = 3
+ ) //weighted by chance to disrupt eaters' rounds
+
+ for(var/obj/item/pizzabox/P in C)
+ if(!anomalous_box_provided)
+ if(prob(anna_molly_box_chance)) //1% chance for each box, so 4% total chance per order
var/obj/item/pizzabox/infinite/fourfiveeight = new(C)
fourfiveeight.boxtag = P.boxtag
+ fourfiveeight.boxtag_set = TRUE
+ fourfiveeight.update_icon()
qdel(P)
anomalous_box_provided = TRUE
log_game("An anomalous pizza box was provided in a pizza crate at during cargo delivery")
@@ -1825,7 +1848,34 @@
addtimer(CALLBACK(src, .proc/anomalous_pizza_report), rand(300, 1800))
else
message_admins("An anomalous pizza box was silently created with no command report in a pizza crate delivery.")
- break
+ continue
+
+ if(!boombox_provided)
+ var/boombox_lottery = rand(1,boombox_tickets)
+ var/boombox_type
+ switch(boombox_lottery)
+ if(1 to 2)
+ boombox_type = /obj/item/pizzabox/bomb/armed //explodes after opening
+ if(3)
+ boombox_type = /obj/item/pizzabox/bomb //free bomb
+
+ if(boombox_type)
+ new boombox_type(C)
+ qdel(P)
+ boombox_provided = TRUE
+ log_game("A bomb pizza box was created by a pizza crate delivery.")
+ message_admins("A bomb pizza box has arrived in a pizza crate delivery.")
+ continue
+
+ //here we randomly replace our pizzas for a chance at the full range
+ var/obj/item/food/pizza/replacement_type = pickweight(pizza_types)
+ pizza_types -= replacement_type
+ if(replacement_type && !istype(P.pizza, replacement_type))
+ QDEL_NULL(P.pizza)
+ P.pizza = new replacement_type
+ P.boxtag = P.pizza.boxtag
+ P.boxtag_set = TRUE
+ P.update_icon()
/datum/supply_pack/organic/pizza/proc/anomalous_pizza_report()
print_command_report("[station_name()], our anomalous materials divison has reported a missing object that is highly likely to have been sent to your station during a routine cargo \
diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm
index 0492ba1db27..99b8f6c38ab 100644
--- a/code/modules/food_and_drinks/pizzabox.dm
+++ b/code/modules/food_and_drinks/pizzabox.dm
@@ -19,6 +19,8 @@
var/open = FALSE
var/can_open_on_fall = TRUE //if FALSE, this pizza box will never open if it falls from a stack
var/boxtag = ""
+ ///Used to make sure artisinal box tags aren't overwritten.
+ var/boxtag_set = FALSE
var/list/boxes = list()
var/obj/item/food/pizza/pizza
@@ -34,6 +36,8 @@
/obj/item/pizzabox/Initialize()
. = ..()
+ if(pizza)
+ pizza = new pizza
update_icon()
@@ -44,6 +48,9 @@
/obj/item/pizzabox/update_icon()
// Description
desc = initial(desc)
+ if(pizza && pizza.boxtag && !boxtag_set)
+ boxtag = pizza.boxtag
+ boxtag_set = TRUE
if(open)
if(pizza)
desc = "[desc] It appears to have \a [pizza] inside. Use your other hand to take it out."
@@ -211,6 +218,7 @@
if(!user.canUseTopic(src, BE_CLOSE))
return
to_chat(user, "You write with [I] on [src].")
+ boxtag_set = TRUE
update_icon()
return
else if(is_wire_tool(I))
@@ -245,6 +253,14 @@
if(boxes.len >= 2 && prob(20 * boxes.len))
disperse_pizzas()
+/obj/item/pizzabox/examine(mob/user)
+ . = ..()
+ if(isobserver(user))
+ if(bomb)
+ . += "This pizza box contains [bomb_defused ? "an unarmed bomb" : "an armed bomb"]."
+ if(pizza && istype(pizza, /obj/item/food/pizza/margherita/robo))
+ . += "The pizza in this pizza box contains nanomachines."
+
/obj/item/pizzabox/proc/disperse_pizzas()
visible_message("The pizzas fall everywhere!")
for(var/V in boxes)
@@ -272,56 +288,54 @@
/obj/item/pizzabox/bomb/Initialize()
. = ..()
- var/randompizza = pick(subtypesof(/obj/item/food/pizza))
- pizza = new randompizza(src)
+ if(!pizza)
+ var/randompizza = pick(subtypesof(/obj/item/food/pizza))
+ pizza = new randompizza(src)
bomb = new(src)
wires = new /datum/wires/explosive/pizza(src)
-/obj/item/pizzabox/margherita/Initialize()
- . = ..()
- AddPizza()
- boxtag = "Margherita Deluxe"
+/obj/item/pizzabox/bomb/armed
+ bomb_timer = 5
+ bomb_defused = FALSE
+ boxtag = "Meat Explosion"
+ boxtag_set = TRUE
+ pizza = /obj/item/food/pizza/meat
-/obj/item/pizzabox/margherita/proc/AddPizza()
- pizza = new /obj/item/food/pizza/margherita(src)
+/obj/item/pizzabox/margherita
+ pizza = /obj/item/food/pizza/margherita
-/obj/item/pizzabox/margherita/robo/AddPizza()
- pizza = new /obj/item/food/pizza/margherita/robo(src)
+/obj/item/pizzabox/margherita/robo
+ pizza = /obj/item/food/pizza/margherita/robo
-/obj/item/pizzabox/vegetable/Initialize()
- . = ..()
- pizza = new /obj/item/food/pizza/vegetable(src)
- boxtag = "Gourmet Vegatable"
+/obj/item/pizzabox/vegetable
+ pizza = /obj/item/food/pizza/vegetable
-/obj/item/pizzabox/mushroom/Initialize()
- . = ..()
- pizza = new /obj/item/food/pizza/mushroom(src)
- boxtag = "Mushroom Special"
+/obj/item/pizzabox/mushroom
+ pizza = /obj/item/food/pizza/mushroom
-/obj/item/pizzabox/meat/Initialize()
- . = ..()
- pizza = new /obj/item/food/pizza/meat(src)
- boxtag = "Meatlover's Supreme"
+/obj/item/pizzabox/meat
+ pizza = /obj/item/food/pizza/meat
-/obj/item/pizzabox/pineapple/Initialize()
- . = ..()
- pizza = new /obj/item/food/pizza/pineapple(src)
- boxtag = "Honolulu Chew"
+/obj/item/pizzabox/pineapple
+ pizza = /obj/item/food/pizza/pineapple
//An anomalous pizza box that, when opened, produces the opener's favorite kind of pizza.
/obj/item/pizzabox/infinite
resistance_flags = FIRE_PROOF | LAVA_PROOF | ACID_PROOF //hard to destroy
can_open_on_fall = FALSE
+ boxtag = "Your Favourite" //used to give it a tag overlay, shouldn't be seen by players
+ ///List of pizzas this box can spawn. Weighted by chance to be someone's favorite.
var/list/pizza_types = list(
- /obj/item/food/pizza/meat = 1,
- /obj/item/food/pizza/mushroom = 1,
- /obj/item/food/pizza/margherita = 1,
- /obj/item/food/pizza/sassysage = 0.8,
- /obj/item/food/pizza/vegetable = 0.8,
- /obj/item/food/pizza/pineapple = 0.5,
- /obj/item/food/pizza/donkpocket = 0.3,
- /obj/item/food/pizza/dank = 0.1,
- ) //pizzas here are weighted by chance to be someone's favorite
+ /obj/item/food/pizza/meat = 10,
+ /obj/item/food/pizza/mushroom = 10,
+ /obj/item/food/pizza/margherita = 10,
+ /obj/item/food/pizza/sassysage = 8,
+ /obj/item/food/pizza/vegetable = 8,
+ /obj/item/food/pizza/pineapple = 5,
+ /obj/item/food/pizza/donkpocket = 3,
+ /obj/item/food/pizza/dank = 1,
+ )
+ ///List of ckeys and their favourite pizzas. e.g. pizza_preferences[ckey] = /obj/item/food/pizza/meat
var/static/list/pizza_preferences
/obj/item/pizzabox/infinite/Initialize()
@@ -330,28 +344,43 @@
pizza_preferences = list()
/obj/item/pizzabox/infinite/examine(mob/user)
+ if(!open && ishuman(user))
+ attune_pizza(user) //pizza tag changes based on examiner
. = ..()
if(isobserver(user))
. += "This pizza box is anomalous, and will produce infinite pizza."
/obj/item/pizzabox/infinite/attack_self(mob/living/user)
- QDEL_NULL(pizza)
if(ishuman(user))
attune_pizza(user)
- . = ..()
+ return ..()
-/obj/item/pizzabox/infinite/proc/attune_pizza(mob/living/carbon/human/noms) //tonight on "proc names I never thought I'd type"
- if(!pizza_preferences[noms.ckey])
- pizza_preferences[noms.ckey] = pickweight(pizza_types)
- if(noms.has_quirk(/datum/quirk/pineapple_liker))
- pizza_preferences[noms.ckey] = /obj/item/food/pizza/pineapple
- else if(noms.has_quirk(/datum/quirk/pineapple_hater))
+/obj/item/pizzabox/infinite/proc/attune_pizza(mob/living/carbon/human/nommer) //tonight on "proc names I never thought I'd type"
+ if(!nommer.ckey)
+ return
+
+ //list our ckey and assign it a favourite pizza
+ if(!pizza_preferences[nommer.ckey])
+ if(nommer.has_quirk(/datum/quirk/pineapple_liker))
+ pizza_preferences[nommer.ckey] = /obj/item/food/pizza/pineapple
+ else if(nommer.has_quirk(/datum/quirk/pineapple_hater))
var/list/pineapple_pizza_liker = pizza_types.Copy()
pineapple_pizza_liker -= /obj/item/food/pizza/pineapple
- pizza_preferences[noms.ckey] = pickweight(pineapple_pizza_liker)
- else if(noms.mind && noms.mind.assigned_role == "Botanist")
- pizza_preferences[noms.ckey] = /obj/item/food/pizza/dank
+ pizza_preferences[nommer.ckey] = pickweight(pineapple_pizza_liker)
+ else if(nommer.mind && nommer.mind.assigned_role == "Botanist")
+ pizza_preferences[nommer.ckey] = /obj/item/food/pizza/dank
+ else
+ pizza_preferences[nommer.ckey] = pickweight(pizza_types)
+ if(pizza)
+ //if the pizza isn't our favourite, delete it
+ if(pizza.type != pizza_preferences[nommer.ckey])
+ QDEL_NULL(pizza)
+ else
+ pizza.foodtypes = nommer.dna.species.liked_food //make sure it's our favourite
+ return
- var/obj/item/pizza_type = pizza_preferences[noms.ckey]
- pizza = new pizza_type (src)
- pizza.foodtypes = noms.dna.species.liked_food //it's our favorite!
+ var/obj/item/food/pizza/favourite_pizza_type = pizza_preferences[nommer.ckey]
+ pizza = new favourite_pizza_type
+ boxtag_set = FALSE
+ update_icon() //update our boxtag to match our new pizza
+ pizza.foodtypes = nommer.dna.species.liked_food //it's our favorite!
diff --git a/code/modules/ruins/lavalandruin_code/pizzaparty.dm b/code/modules/ruins/lavalandruin_code/pizzaparty.dm
index a7776f4e6a8..590994451b5 100644
--- a/code/modules/ruins/lavalandruin_code/pizzaparty.dm
+++ b/code/modules/ruins/lavalandruin_code/pizzaparty.dm
@@ -5,5 +5,5 @@
loot = list(/obj/item/pizzabox/margherita = 3,
/obj/item/pizzabox/meat = 3,
/obj/item/pizzabox/mushroom = 3,
- /obj/item/pizzabox/bomb = 1)
+ /obj/item/pizzabox/bomb/armed = 1)
lootdoubles = FALSE
diff --git a/icons/obj/crates.dmi b/icons/obj/crates.dmi
index 3f15cc67b22..98ccc6b2ff1 100644
Binary files a/icons/obj/crates.dmi and b/icons/obj/crates.dmi differ